| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424 |
- #ifdef __APPLE__
- #include "Base.h"
- #include "Platform.h"
- #include "FileSystem.h"
- #include "Game.h"
- #include "Form.h"
- #include "ScriptController.h"
- #include <unistd.h>
- #include <IOKit/hid/IOHIDLib.h>
- #import <Cocoa/Cocoa.h>
- #import <QuartzCore/CVDisplayLink.h>
- #import <OpenGL/OpenGL.h>
- #import <mach/mach_time.h>
- #import <Foundation/Foundation.h>
- #import <GameKit/GameKit.h>
- // These should probably be moved to a platform common file
- #define SONY_USB_VENDOR_ID 0x054c
- #define SONY_USB_PS3_PRODUCT_ID 0x0268
- #define MICROSOFT_VENDOR_ID 0x045e
- #define MICROSOFT_XBOX360_PRODUCT_ID 0x028e
- #define STEELSERIES_VENDOR_ID 0x1038
- #define STEELSERIES_FREE_PRODUCT_ID 0x1412
- #define FRUCTEL_VENDOR_ID 0x25B6
- #define FRUCTEL_GAMETEL_PRODUCT_ID 0x0001
- using namespace std;
- using namespace gameplay;
- @class View;
- @class HIDGamepad;
- int __argc = 0;
- char** __argv = 0;
- // Default to 720p
- static int __width = 1280;
- static int __height = 720;
- static double __timeStart;
- static double __timeAbsolute;
- static bool __vsync = WINDOW_VSYNC;
- static bool __hasMouse = false;
- static bool __leftMouseDown = false;
- static bool __rightMouseDown = false;
- static bool __otherMouseDown = false;
- static bool __shiftDown = false;
- static char* __title = NULL;
- static bool __fullscreen = false;
- static bool __resizable = false;
- static bool __mouseCaptured = false;
- static bool __mouseCapturedFirstPass = false;
- static CGPoint __mouseCapturePoint;
- static bool __multiSampling = false;
- static bool __cursorVisible = true;
- static View* __view = NULL;
- static NSMutableDictionary *__activeGamepads = NULL;
- static NSMutableArray *__gamepads = NULL;
- static IOHIDManagerRef __hidManagerRef = NULL;
- // Gamepad Helper Function
- HIDGamepad *gamepadForLocationID(NSNumber *locationID);
- HIDGamepad *gamepadForLocationIDValue(unsigned int locationIDValue);
- HIDGamepad *gamepadForGameHandle(int gameHandle);
- // IOHid Helper Functions
- CFMutableDictionaryRef IOHIDCreateDeviceMatchingDictionary(UInt32 inUsagePage, UInt32 inUsage);
- CFStringRef IOHIDDeviceGetStringProperty(IOHIDDeviceRef deviceRef, CFStringRef key);
- int IOHIDDeviceGetIntProperty(IOHIDDeviceRef deviceRef, CFStringRef key);
- // IOHid Callbacks
- static void hidDeviceDiscoveredCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef);
- static void hidDeviceRemovalCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef);
- static void hidDeviceValueAvailableCallback(void *inContext, IOReturn inResult, void *inSender);
- double getMachTimeInMilliseconds()
- {
- static const double kOneMillion = 1000 * 1000;
- static mach_timebase_info_data_t s_timebase_info;
-
- if (s_timebase_info.denom == 0)
- (void) mach_timebase_info(&s_timebase_info);
-
- // mach_absolute_time() returns billionth of seconds, so divide by one million to get milliseconds
- GP_ASSERT(s_timebase_info.denom);
- return ((double)mach_absolute_time() * (double)s_timebase_info.numer) / (kOneMillion * (double)s_timebase_info.denom);
- }
- @interface HIDGamepadAxis : NSObject
- {
- IOHIDElementRef e;
- CFIndex v;
- CFIndex logMin;
- CFIndex logMax;
- }
- + gamepadAxisWithAxisElement:(IOHIDElementRef)element;
- - initWithAxisElement:(IOHIDElementRef)element;
- - (IOHIDElementRef)element;
- - (IOHIDElementCookie)cookie;
- - (uint32_t)usage;
- - (uint32_t)usagePage;
- - (CFIndex)logicalMinimum;
- - (CFIndex)logicalMaximum;
- - (float)calibratedValue;
- - (CFIndex)value;
- - (void)setValue:(CFIndex)value;
- @end
- @implementation HIDGamepadAxis
- + gamepadAxisWithAxisElement:(IOHIDElementRef)element
- {
- return [[[[self class] alloc] initWithAxisElement:element] autorelease];
- }
- - initWithAxisElement:(IOHIDElementRef)element
- {
- if((self = [super init]))
- {
- e = (IOHIDElementRef)CFRetain(element);
- }
- return self;
- }
- - (void)dealloc
- {
- CFRelease(e);
- [super dealloc];
- }
- - (IOHIDElementRef)element
- {
- return e;
- }
- - (IOHIDElementCookie)cookie
- {
- return IOHIDElementGetCookie(e);
- }
- - (bool)isHatSwitch {
- return (IOHIDElementGetUsage(e) == kHIDUsage_GD_Hatswitch);
- }
- - (uint32_t)usage
- {
- return IOHIDElementGetUsage(e);
- }
- - (uint32_t)usagePage
- {
- return IOHIDElementGetUsagePage(e);
- }
- - (CFIndex)logicalMinimum
- {
- return IOHIDElementGetLogicalMin(e);
- }
- - (CFIndex)logicalMaximum
- {
- return IOHIDElementGetLogicalMax(e);
- }
- - (float)calibratedValue
- {
- float cmax = 2.0f;
- float cmin = 0.0f;
- return ((((v - [self logicalMinimum]) * (cmax - cmin)) / ([self logicalMaximum] - [self logicalMinimum])) + cmin - 1.0f);
- }
- - (CFIndex)value
- {
- return v;
- }
- - (void)setValue:(CFIndex)value
- {
- v = value;
- }
- @end
- @interface HIDGamepadButton : NSObject
- {
- IOHIDElementRef e;
- IOHIDElementRef te;
- bool state;
- int triggerValue;
- }
- + gamepadButtonWithButtonElement:(IOHIDElementRef)element;
- - initWithButtonElement:(IOHIDElementRef)element;
- - (void)setTriggerElement:(IOHIDElementRef)element;
- - (IOHIDElementRef)element;
- - (IOHIDElementCookie)cookie;
- - (IOHIDElementRef)triggerElement;
- - (IOHIDElementCookie)triggerCookie;
- - (bool)isTriggerButton;
- - (uint32_t)usage;
- - (uint32_t)usagePage;
- - (int)stateValue;
- - (float)calibratedStateValue;
- - (void)setStateValue:(int)value;
- - (bool)state;
- - (void)setState:(bool)state;
- @end
- @implementation HIDGamepadButton
- + gamepadButtonWithButtonElement:(IOHIDElementRef)element
- {
- return [[[[self class] alloc] initWithButtonElement:element] autorelease];
- }
- - initWithButtonElement:(IOHIDElementRef)element
- {
- if((self = [super init]))
- {
- e = (IOHIDElementRef)CFRetain(element);
- te = NULL;
- state = false;
- }
- return self;
- }
- - (void)dealloc
- {
- CFRelease(e);
- if(te != NULL) CFRelease(te);
- [super dealloc];
- }
- - (void)setTriggerElement:(IOHIDElementRef)element {
- if(te)
- {
- CFRelease(te);
- te = NULL;
- }
- if(element)
- {
- te = (IOHIDElementRef)CFRetain(element);
- }
- }
- - (IOHIDElementRef)element
- {
- return e;
- }
- - (IOHIDElementCookie)cookie
- {
- return IOHIDElementGetCookie(e);
- }
- - (IOHIDElementRef)triggerElement
- {
- return te;
- }
- - (IOHIDElementCookie)triggerCookie
- {
- return IOHIDElementGetCookie(te);
- }
- - (bool)isTriggerButton
- {
- return (te != NULL);
- }
- - (uint32_t)usage
- {
- return IOHIDElementGetUsage(e);
- }
- - (uint32_t)usagePage
- {
- return IOHIDElementGetUsagePage(e);
- }
- - (void)setStateValue:(int)value {
- triggerValue = value;
- }
- - (int)stateValue
- {
- return triggerValue;
- }
- - (float)calibratedStateValue
- {
- return (float)triggerValue / 255.0f;
- }
- - (bool)state
- {
- return state;
- }
- - (void)setState:(bool)s
- {
- state = s;
- }
- @end
- @interface HIDGamepad : NSObject
- {
- IOHIDDeviceRef hidDeviceRef;
- IOHIDQueueRef queueRef;
- NSMutableArray* buttons;
- NSMutableArray* triggerButtons;
- NSMutableArray* axes;
- HIDGamepadAxis* hatSwitch;
- }
- @property (assign) IOHIDDeviceRef hidDeviceRef;
- @property (assign) IOHIDQueueRef queueRef;
- @property (retain) NSMutableArray* buttons;
- @property (retain) NSMutableArray* triggerButtons;
- @property (retain) NSMutableArray* axes;
- @property (retain) HIDGamepadAxis* hatSwitch;
- - initWithDevice:(IOHIDDeviceRef)rawDevice;
- - (IOHIDDeviceRef)rawDevice;
- - (NSNumber*)locationID;
- - (void)initializeGamepadElements;
- - (HIDGamepadButton*)buttonWithCookie:(IOHIDElementCookie)cookie;
- - (bool)startListening;
- - (void)stopListening;
- - (NSString*)identifierName;
- - (NSString*)productName;
- - (NSString*)manufacturerName;
- - (NSString*)serialNumber;
- - (int)versionNumber;
- - (int)vendorID;
- - (int)productID;
- - (NSUInteger)numberOfAxes;
- - (NSUInteger)numberOfSticks;
- - (NSUInteger)numberOfButtons;
- - (NSUInteger)numberOfTriggerButtons;
- - (HIDGamepadAxis*)axisAtIndex:(NSUInteger)index;
- - (HIDGamepadButton*)buttonAtIndex:(NSUInteger)index;
- - (HIDGamepadButton*)triggerButtonAtIndex:(NSUInteger)index;
- - (HIDGamepadAxis*)getHatSwitch;
- @end
- @implementation HIDGamepad
- @synthesize hidDeviceRef;
- @synthesize queueRef;
- @synthesize buttons;
- @synthesize triggerButtons;
- @synthesize axes;
- @synthesize hatSwitch;
- - initWithDevice:(IOHIDDeviceRef)rawDevice
- {
- if((self = [super init]))
- {
- [self setButtons:[NSMutableArray array]];
- [self setTriggerButtons:[NSMutableArray array]];
- [self setAxes:[NSMutableArray array]];
- hatSwitch = NULL;
- CFRetain(rawDevice);
- IOHIDQueueRef queue = IOHIDQueueCreate(CFAllocatorGetDefault(), rawDevice, 10, kIOHIDOptionsTypeNone);
- [self setHidDeviceRef:rawDevice];
- [self setQueueRef:queue];
-
- [self initializeGamepadElements];
- [self startListening];
- }
- return self;
- }
- - (void)dealloc
- {
- [self stopListening];
-
- CFRelease([self rawDevice]);
- CFRelease([self queueRef]);
- [self setQueueRef:NULL];
- [self setHidDeviceRef:NULL];
-
- [self setButtons:NULL];
- [self setTriggerButtons:NULL];
- [self setAxes:NULL];
- if (hatSwitch != NULL)
- {
- [hatSwitch dealloc];
- }
-
- [super dealloc];
- }
- - (IOHIDDeviceRef)rawDevice
- {
- return [self hidDeviceRef];
- }
- - (NSNumber*)locationID
- {
- return (NSNumber*)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDLocationIDKey));
- }
- - (void)initializeGamepadElements
- {
- uint32_t vendorID = [self vendorID];
- uint32_t productID = [self productID];
-
- CFArrayRef elements = IOHIDDeviceCopyMatchingElements([self rawDevice], NULL, kIOHIDOptionsTypeNone);
- for(int i = 0; i < CFArrayGetCount(elements); i++)
- {
- IOHIDElementRef hidElement = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
- IOHIDElementType type = IOHIDElementGetType(hidElement);
- if (type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis)
- {
- uint32_t pageUsage = IOHIDElementGetUsage(hidElement);
- IOHIDElementCookie cookie = IOHIDElementGetCookie(hidElement);
- switch(pageUsage)
- {
- case kHIDUsage_GD_X:
- case kHIDUsage_GD_Y:
- case kHIDUsage_GD_Rx:
- case kHIDUsage_GD_Ry:
- case kHIDUsage_GD_Z:
- case kHIDUsage_GD_Rz:
- {
- if (vendorID == MICROSOFT_VENDOR_ID &&
- productID == MICROSOFT_XBOX360_PRODUCT_ID &&
- (pageUsage == kHIDUsage_GD_Z || pageUsage == kHIDUsage_GD_Rz))
- {
- HIDGamepadButton* triggerButton = [HIDGamepadButton gamepadButtonWithButtonElement:hidElement];
- [triggerButton setTriggerElement:hidElement];
- [[self triggerButtons] addObject:triggerButton];
- }
- else
- {
- HIDGamepadAxis* axis = [HIDGamepadAxis gamepadAxisWithAxisElement:hidElement];
- [[self axes] addObject:axis];
- }
- break;
- }
- case kHIDUsage_GD_Hatswitch:
- {
- HIDGamepadAxis* hat = [[HIDGamepadAxis alloc] initWithAxisElement:hidElement];
- [hat setValue: -1];
- hatSwitch = hat;
- }
- default:
- // Ignore the pointers
- // Note: Some of the pointers are for the 6-axis accelerometer in a PS3 controller
- // Note: L2/R2 triggers are at cookie 39 and 40 base 10 tied to 9 and 10 button elements
- break;
- }
- }
- if(type == kIOHIDElementTypeInput_Button)
- {
- HIDGamepadButton *button = [HIDGamepadButton gamepadButtonWithButtonElement:hidElement];
- [[self buttons] addObject:button];
- }
- }
- // Go back and get proprietary information (e.g. triggers) and associate with appropriate values
- // Example for other trigger buttons
- for(int i = 0; i < CFArrayGetCount(elements); i++)
- {
- IOHIDElementRef hidElement = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
- IOHIDElementType type = IOHIDElementGetType(hidElement);
- IOHIDElementCookie cookie = IOHIDElementGetCookie(hidElement);
-
- // Gamepad specific code
- if(vendorID == SONY_USB_VENDOR_ID && productID == SONY_USB_PS3_PRODUCT_ID)
- {
- if((unsigned long)cookie == 39)
- {
- HIDGamepadButton *leftTriggerButton = [self buttonWithCookie:(IOHIDElementCookie)9];
- if(leftTriggerButton)
- {
- [leftTriggerButton setTriggerElement:hidElement];
- [[self triggerButtons] addObject:leftTriggerButton];
- }
- }
- if((unsigned long)cookie == 40)
- {
- HIDGamepadButton *rightTriggerButton = [self buttonWithCookie:(IOHIDElementCookie)10];
- if(rightTriggerButton)
- {
- [rightTriggerButton setTriggerElement:hidElement];
- [[self triggerButtons] addObject:rightTriggerButton];
- }
- }
- }
- }
- }
- - (HIDGamepadButton*)buttonWithCookie:(IOHIDElementCookie)cookie {
- for(HIDGamepadButton *b in [self buttons]) {
- if([b cookie] == cookie)
- return b;
- }
- return NULL;
- }
- - (bool)startListening
- {
- IOReturn kr = IOHIDDeviceOpen([self hidDeviceRef], kIOHIDOptionsTypeNone);
- if(kr != 0) {
- return false;
- }
- IOHIDDeviceScheduleWithRunLoop([self hidDeviceRef], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
-
- IOHIDQueueStart([self queueRef]);
- IOHIDQueueRegisterValueAvailableCallback([self queueRef], hidDeviceValueAvailableCallback, self);
-
- CFArrayRef elements = (CFArrayRef)[self watchedElements];
- for(int i = 0; i < CFArrayGetCount(elements); i++)
- {
- IOHIDElementRef hidElement = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
- IOHIDQueueAddElement([self queueRef], hidElement);
- }
-
- IOHIDQueueScheduleWithRunLoop([self queueRef], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
-
- return true;
- }
- - (void)stopListening
- {
- IOHIDQueueUnscheduleFromRunLoop([self queueRef], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
- IOHIDQueueStop([self queueRef]);
-
- IOHIDDeviceUnscheduleFromRunLoop([self hidDeviceRef], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
- IOHIDDeviceClose([self hidDeviceRef], kIOHIDOptionsTypeNone);
- }
- - (NSString*)identifierName
- {
- NSString* idName = NULL;
- if(idName == NULL) idName = [self productName];
- if(idName == NULL) idName = [self manufacturerName];
- if(idName == NULL) idName = [self serialNumber];
- if(idName == NULL) idName = [NSString stringWithFormat:@"%d-%d", [self vendorID], [self productID]];
- return idName;
- }
- - (NSString*)productName
- {
- CFStringRef productName = (CFStringRef)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDProductKey));
- if(productName == NULL || CFGetTypeID(productName) != CFStringGetTypeID())
- {
- return NULL;
- }
- return (NSString*)productName;
- }
- - (NSString*)manufacturerName
- {
- CFStringRef manufacturerName = (CFStringRef)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDManufacturerKey));
- if(manufacturerName == NULL || CFGetTypeID(manufacturerName) != CFStringGetTypeID())
- {
- return NULL;
- }
- return (NSString*)manufacturerName;
- }
- - (NSString*)serialNumber
- {
- CFStringRef serialNumber = (CFStringRef)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDSerialNumberKey));
- if(serialNumber == NULL || CFGetTypeID(serialNumber) != CFStringGetTypeID())
- {
- return NULL;
- }
- return (NSString*)serialNumber;
- }
- - (int)versionNumber
- {
- return IOHIDDeviceGetIntProperty([self rawDevice], CFSTR(kIOHIDVersionNumberKey));
- }
- - (int)vendorID
- {
- return IOHIDDeviceGetIntProperty([self rawDevice], CFSTR(kIOHIDVendorIDKey));
- }
- - (int)productID
- {
- return IOHIDDeviceGetIntProperty([self rawDevice], CFSTR(kIOHIDProductIDKey));
- }
- - (NSUInteger)numberOfAxes
- {
- return [[self axes] count];
- }
- - (NSUInteger)numberOfSticks
- {
- return ([[self axes] count] / 2);
- }
- - (NSUInteger)numberOfButtons
- {
- return [[self buttons] count];
- }
- - (NSUInteger)numberOfTriggerButtons
- {
- return [[self triggerButtons] count];
- }
- - (HIDGamepadButton*)triggerButtonAtIndex:(NSUInteger)index
- {
- HIDGamepadButton *b = NULL;
- if(index < [[self triggerButtons] count])
- {
- b = [[self triggerButtons] objectAtIndex:index];
- }
- return b;
- }
- - (HIDGamepadAxis*)axisAtIndex:(NSUInteger)index
- {
- HIDGamepadAxis *a = NULL;
- if(index < [[self axes] count])
- {
- a = [[self axes] objectAtIndex:index];
- }
- return a;
- }
- - (HIDGamepadButton*)buttonAtIndex:(NSUInteger)index
- {
- HIDGamepadButton *b = NULL;
- if(index < [[self buttons] count])
- {
- b = [[self buttons] objectAtIndex:index];
- }
- return b;
- }
- - (HIDGamepadAxis*)getHatSwitch
- {
- if (hatSwitch != NULL)
- {
- return hatSwitch;
- }
- return NULL;
- }
- - (NSArray*)watchedElements
- {
- NSMutableArray *r = [NSMutableArray array];
- for(HIDGamepadButton *b in [self buttons])
- {
- [r addObject:(id)[b element]];
- }
- for(HIDGamepadAxis *a in [self axes])
- {
- [r addObject:(id)[a element]];
- }
- for(HIDGamepadButton* t in [self triggerButtons])
- {
- [r addObject:(id)[t triggerElement]];
- }
- if (hatSwitch)
- {
- [r addObject:(id)[hatSwitch element]];
- }
- return [NSArray arrayWithArray:r];
- }
- - (void)hidValueAvailable:(IOHIDValueRef)value
- {
- IOHIDElementRef element = IOHIDValueGetElement(value);
- IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
-
- if(IOHIDValueGetLength(value) > 4) return; // saftey precaution for PS3 cotroller
- CFIndex integerValue = IOHIDValueGetIntegerValue(value);
-
- for(HIDGamepadAxis *a in [self axes])
- {
- if([a cookie] == cookie)
- {
- [a setValue:integerValue];
- }
- }
-
- for(HIDGamepadButton *b in [self buttons])
- {
- if([b cookie] == cookie)
- {
- [b setState:(bool)integerValue];
- break;
- }
- }
-
- for(HIDGamepadButton *b in [self triggerButtons])
- {
- if([b triggerCookie] == cookie)
- {
- [b setStateValue:integerValue];
- break;
- }
- }
- if (hatSwitch && [hatSwitch cookie] == cookie)
- {
- [hatSwitch setValue:integerValue];
- }
- }
- @end
- @interface View : NSOpenGLView <NSWindowDelegate>
- {
- @public
- CVDisplayLinkRef displayLink;
- NSRecursiveLock* gameLock;
- @protected
- Game* _game;
- unsigned int _gestureEvents;
- }
- - (void) detectGamepads: (Game*) game;
- @end
- @implementation View
- -(void)windowWillClose:(NSNotification*)note
- {
- [gameLock lock];
- _game->exit();
- [gameLock unlock];
- [[NSApplication sharedApplication] terminate:self];
- }
- - (void)windowDidResize:(NSNotification*)notification
- {
- [gameLock lock];
- NSSize size = [ [ _window contentView ] frame ].size;
- gameplay::Platform::resizeEventInternal((unsigned int)size.width, (unsigned int)size.height);
- [gameLock unlock];
- }
- - (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime
- {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
- [self update];
-
- [pool release];
-
- return kCVReturnSuccess;
- }
- - (void) detectGamepads: (Game*) game
- {
- // Locate any newly connected devices
- for(HIDGamepad* gamepad in __gamepads)
- {
- NSNumber* locationID = [gamepad locationID];
- if([__activeGamepads objectForKey:locationID] == NULL)
- {
- // Gameplay::add is friended to Platform, but we're not in Platform right now.
- Platform::gamepadEventConnectedInternal((unsigned int)[locationID intValue],
- [gamepad numberOfButtons],
- [gamepad numberOfSticks],
- [gamepad numberOfTriggerButtons],
- [gamepad vendorID],
- [gamepad productID],
- [[gamepad manufacturerName] cStringUsingEncoding:NSASCIIStringEncoding],
- [[gamepad productName] cStringUsingEncoding:NSASCIIStringEncoding]);
- [__activeGamepads setObject:locationID forKey:locationID];
- }
- }
-
- // Detect any disconnected gamepads
- NSMutableArray* deadGamepads = [NSMutableArray array];
- for(NSNumber* locationID in __activeGamepads)
- {
- HIDGamepad* gamepad = gamepadForLocationID(locationID);
- if(gamepad == NULL)
- {
- NSNumber* gameHandle = [__activeGamepads objectForKey:locationID];
- Platform::gamepadEventDisconnectedInternal((unsigned int)[locationID intValue]);
- [deadGamepads addObject:locationID];
- }
- }
- [__activeGamepads removeObjectsForKeys:deadGamepads];
- }
- -(void) update
- {
- [gameLock lock];
- [[self openGLContext] makeCurrentContext];
- CGLLockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
- if (_game)
- {
- [self detectGamepads: _game];
-
- _game->frame();
- }
- CGLFlushDrawable((CGLContextObj)[[self openGLContext] CGLContextObj]);
- CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]);
- [gameLock unlock];
- }
- static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime,
- CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
- {
- CVReturn result = [(View*)displayLinkContext getFrameForTime:outputTime];
- return result;
- }
- - (id) initWithFrame: (NSRect) frame
- {
- _game = Game::getInstance();
-
- Properties* config = _game->getConfig()->getNamespace("window", true);
- int samples = config ? config->getInt("samples") : 0;
- if (samples < 0)
- samples = 0;
-
- // Note: Keep multisampling attributes at the start of the attribute lists since code below
- // assumes they are array elements 0 through 4.
- NSOpenGLPixelFormatAttribute windowedAttrs[] =
- {
- NSOpenGLPFAMultisample,
- NSOpenGLPFASampleBuffers, samples ? 1 : 0,
- NSOpenGLPFASamples, samples,
- NSOpenGLPFAAccelerated,
- NSOpenGLPFADoubleBuffer,
- NSOpenGLPFAColorSize, 32,
- NSOpenGLPFADepthSize, 24,
- NSOpenGLPFAAlphaSize, 8,
- NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
- 0
- };
- NSOpenGLPixelFormatAttribute fullscreenAttrs[] =
- {
- NSOpenGLPFAMultisample,
- NSOpenGLPFASampleBuffers, samples ? 1 : 0,
- NSOpenGLPFASamples, samples,
- NSOpenGLPFADoubleBuffer,
- NSOpenGLPFAScreenMask, (NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()),
- NSOpenGLPFAFullScreen,
- NSOpenGLPFAColorSize, 32,
- NSOpenGLPFADepthSize, 24,
- NSOpenGLPFAAlphaSize, 8,
- NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
- 0
- };
- NSOpenGLPixelFormatAttribute* attrs = __fullscreen ? fullscreenAttrs : windowedAttrs;
-
- __multiSampling = samples > 0;
- // Try to choose a supported pixel format
- NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
- if (!pf)
- {
- bool valid = false;
- while (!pf && samples > 0)
- {
- samples /= 2;
- attrs[2] = samples ? 1 : 0;
- attrs[4] = samples;
- pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
- if (pf)
- {
- valid = true;
- break;
- }
- }
- __multiSampling = samples > 0;
-
- if (!valid)
- {
- NSLog(@"OpenGL pixel format not supported.");
- GP_ERROR("Failed to create a valid OpenGL pixel format.");
- return nil;
- }
- }
-
- if ((self = [super initWithFrame:frame pixelFormat:[pf autorelease]]))
- {
- gameLock = [[NSRecursiveLock alloc] init];
- __timeStart = getMachTimeInMilliseconds();
- }
-
- return self;
- }
- - (void) prepareOpenGL
- {
- [super prepareOpenGL];
-
- _game->run();
-
- if (__fullscreen)
- {
- [[self window] setLevel: NSMainMenuWindowLevel+1];
- [[self window] setHidesOnDeactivate:YES];
- }
- else
- {
- [[self window] setLevel: NSNormalWindowLevel];
- }
- [[self window] makeKeyAndOrderFront: self];
- [[self window] setTitle: [NSString stringWithUTF8String: __title ? __title : ""]];
-
- // Make all the OpenGL calls to setup rendering and build the necessary rendering objects
- [[self openGLContext] makeCurrentContext];
- // Synchronize buffer swaps with vertical refresh rate
- GLint swapInt = __vsync ? 1 : 0;
- [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
-
- // Create a display link capable of being used with all active displays
- CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
-
- // Set the renderer output callback function
- CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
-
- CGLContextObj cglContext = (CGLContextObj)[[self openGLContext] CGLContextObj];
- CGLPixelFormatObj cglPixelFormat = (CGLPixelFormatObj)[[self pixelFormat] CGLPixelFormatObj];
- CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat);
-
- GLint dim[2] = {__width, __height};
- CGLSetParameter(cglContext, kCGLCPSurfaceBackingSize, dim);
- CGLEnable(cglContext, kCGLCESurfaceBackingSize);
-
- // Activate the display link
- CVDisplayLinkStart(displayLink);
- }
- - (void) dealloc
- {
- [gameLock lock];
-
- // Release the display link
- CVDisplayLinkStop(displayLink);
- CVDisplayLinkRelease(displayLink);
- _game->exit();
-
- [gameLock unlock];
- [super dealloc];
- }
- - (void)resumeDisplayRenderer
- {
- [gameLock lock];
- CVDisplayLinkStop(displayLink);
- [gameLock unlock];
- }
- - (void)haltDisplayRenderer
- {
- [gameLock lock];
- CVDisplayLinkStop(displayLink);
- [gameLock unlock];
- }
- - (void) mouse: (Mouse::MouseEvent) mouseEvent orTouchEvent: (Touch::TouchEvent) touchEvent x: (float) x y: (float) y s: (int) s
- {
- [__view->gameLock lock];
- if (!gameplay::Platform::mouseEventInternal(mouseEvent, x, y, s))
- {
- gameplay::Platform::touchEventInternal(touchEvent, x, y, 0);
- }
- [__view->gameLock unlock];
- }
- - (void) mouseDown: (NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- __leftMouseDown = true;
- [self mouse: Mouse::MOUSE_PRESS_LEFT_BUTTON orTouchEvent: Touch::TOUCH_PRESS x: point.x y: __height - point.y s: 0];
- }
- - (void) mouseUp: (NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- __leftMouseDown = false;
- [self mouse: Mouse::MOUSE_RELEASE_LEFT_BUTTON orTouchEvent: Touch::TOUCH_RELEASE x: point.x y: __height - point.y s: 0];
- }
- // helper function to handle mouse capture
- bool getMousePointForEvent(NSPoint& point, NSEvent* event)
- {
- if (__mouseCaptured)
- {
- if (__mouseCapturedFirstPass)
- {
- // Discard the first mouseMoved event following transition into capture
- // since it contains bogus x,y data.
- __mouseCapturedFirstPass = false;
- return false;
- }
-
- point.x = [event deltaX];
- point.y = [event deltaY];
-
- NSWindow* window = __view.window;
- NSRect rect = window.frame;
- CGPoint centerPoint;
- centerPoint.x = rect.origin.x + (rect.size.width / 2);
- centerPoint.y = rect.origin.y + (rect.size.height / 2);
- CGDisplayMoveCursorToPoint(CGDisplayPrimaryDisplay(NULL), centerPoint);
- }
- else
- {
- point.y = __height - point.y;
- }
- return true;
- }
- - (void)mouseMoved:(NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-
- if (!getMousePointForEvent(point, event))
- {
- return;
- }
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, point.x, point.y, 0);
- [__view->gameLock unlock];
- }
- - (void) mouseDragged: (NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- if (__leftMouseDown)
- {
- if (__mouseCaptured)
- {
- if (!getMousePointForEvent(point, event))
- {
- return;
- }
-
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, point.x, point.y, 0);
- [__view->gameLock unlock];
- }
- else
- {
- [self mouse: Mouse::MOUSE_MOVE orTouchEvent: Touch::TOUCH_MOVE x: point.x y: __height - point.y s: 0];
- }
- }
- }
- - (void) rightMouseDown: (NSEvent*) event
- {
- __rightMouseDown = true;
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_PRESS_RIGHT_BUTTON, point.x, __height - point.y, 0);
- [__view->gameLock unlock];
- }
- - (void) rightMouseUp: (NSEvent*) event
- {
- __rightMouseDown = false;
- NSPoint point = [event locationInWindow];
-
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_RELEASE_RIGHT_BUTTON, point.x, __height - point.y, 0);
- [__view->gameLock unlock];
- }
- - (void) rightMouseDragged: (NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-
- if (!getMousePointForEvent(point, event))
- {
- return;
- }
-
- // In right-mouse case, whether __rightMouseDown is true or false
- // this should not matter, mouse move is still occuring
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, point.x, point.y, 0);
- [__view->gameLock unlock];
- }
- - (void)otherMouseDown: (NSEvent*) event
- {
- __otherMouseDown = true;
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_PRESS_MIDDLE_BUTTON, point.x, __height - point.y, 0);
- [__view->gameLock unlock];
- }
- - (void)otherMouseUp: (NSEvent*) event
- {
- __otherMouseDown = false;
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_RELEASE_MIDDLE_BUTTON, point.x, __height - point.y, 0);
- [__view->gameLock unlock];
- }
- - (void)otherMouseDragged: (NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, point.x, __height - point.y, 0);
- [__view->gameLock unlock];
- }
- - (void) mouseEntered: (NSEvent*)event
- {
- __hasMouse = true;
- }
- - (void)scrollWheel: (NSEvent*) event
- {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
- [__view->gameLock lock];
- gameplay::Platform::mouseEventInternal(Mouse::MOUSE_WHEEL, point.x, __height - point.y, (int)([event deltaY] * 10.0f));
- [__view->gameLock unlock];
- }
- - (void) mouseExited: (NSEvent*)event
- {
- __leftMouseDown = false;
- __rightMouseDown = false;
- __otherMouseDown = false;
- __hasMouse = false;
- }
- - (BOOL)acceptsFirstResponder
- {
- return YES;
- }
- int getKey(unsigned short keyCode, unsigned int modifierFlags)
- {
- __shiftDown = (modifierFlags & NSShiftKeyMask);
- unsigned int caps = (__shiftDown ? 1 : 0) ^ ((modifierFlags & NSAlphaShiftKeyMask) ? 1 : 0);
- switch(keyCode)
- {
- case 0x69:
- return Keyboard::KEY_PRINT;
- case 0x35:
- return Keyboard::KEY_ESCAPE;
- case 0x33:
- return Keyboard::KEY_BACKSPACE;
- case 0x30:
- return Keyboard::KEY_TAB;
- case 0x24:
- return Keyboard::KEY_RETURN;
- case 0x72:
- return Keyboard::KEY_INSERT;
- case 0x73:
- return Keyboard::KEY_HOME;
- case 0x74:
- return Keyboard::KEY_PG_UP;
- case 0x79:
- return Keyboard::KEY_PG_DOWN;
- case 0x75:
- return Keyboard::KEY_DELETE;
- case 0x77:
- return Keyboard::KEY_END;
- case 0x7B:
- return Keyboard::KEY_LEFT_ARROW;
- case 0x7C:
- return Keyboard::KEY_RIGHT_ARROW;
- case 0x7E:
- return Keyboard::KEY_UP_ARROW;
- case 0x7D:
- return Keyboard::KEY_DOWN_ARROW;
- case 0x47:
- return Keyboard::KEY_NUM_LOCK;
- case 0x45:
- return Keyboard::KEY_KP_PLUS;
- case 0x4E:
- return Keyboard::KEY_KP_MINUS;
- case 0x43:
- return Keyboard::KEY_KP_MULTIPLY;
- case 0x4B:
- return Keyboard::KEY_KP_DIVIDE;
- case 0x59:
- return Keyboard::KEY_KP_HOME;
- case 0x5B:
- return Keyboard::KEY_KP_UP;
- case 0x5C:
- return Keyboard::KEY_KP_PG_UP;
- case 0x56:
- return Keyboard::KEY_KP_LEFT;
- case 0x57:
- return Keyboard::KEY_KP_FIVE;
- case 0x58:
- return Keyboard::KEY_KP_RIGHT;
- case 0x53:
- return Keyboard::KEY_KP_END;
- case 0x54:
- return Keyboard::KEY_KP_DOWN;
- case 0x55:
- return Keyboard::KEY_KP_PG_DOWN;
- case 0x52:
- return Keyboard::KEY_KP_INSERT;
- case 0x41:
- return Keyboard::KEY_KP_DELETE;
- case 0x7A:
- return Keyboard::KEY_F1;
- case 0x78:
- return Keyboard::KEY_F2;
- case 0x63:
- return Keyboard::KEY_F3;
- case 0x76:
- return Keyboard::KEY_F4;
- case 0x60:
- return Keyboard::KEY_F5;
- case 0x61:
- return Keyboard::KEY_F6;
- case 0x62:
- return Keyboard::KEY_F7;
- case 0x64:
- return Keyboard::KEY_F8;
- case 0x65:
- return Keyboard::KEY_F9;
- case 0x6D:
- return Keyboard::KEY_F10;
-
- // MACOS reserved:
- // return Keyboard::KEY_F11;
- // return Keyboard::KEY_F12;
- // return Keyboard::KEY_PAUSE;
- // return Keyboard::KEY_SCROLL_LOCK;
-
- case 0x31:
- return Keyboard::KEY_SPACE;
- case 0x1D:
- return __shiftDown ? Keyboard::KEY_RIGHT_PARENTHESIS : Keyboard::KEY_ZERO;
- case 0x12:
- return __shiftDown ? Keyboard::KEY_EXCLAM : Keyboard::KEY_ONE;
- case 0x13:
- return __shiftDown ? Keyboard::KEY_AT : Keyboard::KEY_TWO;
- case 0x14:
- return __shiftDown ? Keyboard::KEY_NUMBER : Keyboard::KEY_THREE;
- case 0x15:
- return __shiftDown ? Keyboard::KEY_DOLLAR : Keyboard::KEY_FOUR;
- case 0x17:
- return __shiftDown ? Keyboard::KEY_PERCENT : Keyboard::KEY_FIVE;
- case 0x16:
- return __shiftDown ? Keyboard::KEY_CIRCUMFLEX : Keyboard::KEY_SIX;
- case 0x1A:
- return __shiftDown ? Keyboard::KEY_AMPERSAND : Keyboard::KEY_SEVEN;
- case 0x1C:
- return __shiftDown ? Keyboard::KEY_ASTERISK : Keyboard::KEY_EIGHT;
- case 0x19:
- return __shiftDown ? Keyboard::KEY_LEFT_PARENTHESIS : Keyboard::KEY_NINE;
- case 0x18:
- return __shiftDown ? Keyboard::KEY_EQUAL : Keyboard::KEY_PLUS;
- case 0x2B:
- return __shiftDown ? Keyboard::KEY_LESS_THAN : Keyboard::KEY_COMMA;
- case 0x1B:
- return __shiftDown ? Keyboard::KEY_UNDERSCORE : Keyboard::KEY_MINUS;
- case 0x2F:
- return __shiftDown ? Keyboard::KEY_GREATER_THAN : Keyboard::KEY_PERIOD;
- case 0x29:
- return __shiftDown ? Keyboard::KEY_COLON : Keyboard::KEY_SEMICOLON;
- case 0x2C:
- return __shiftDown ? Keyboard::KEY_QUESTION : Keyboard::KEY_SLASH;
- case 0x32:
- return __shiftDown ? Keyboard::KEY_GRAVE : Keyboard::KEY_TILDE;
- case 0x21:
- return __shiftDown ? Keyboard::KEY_LEFT_BRACE : Keyboard::KEY_LEFT_BRACKET;
- case 0x2A:
- return __shiftDown ? Keyboard::KEY_BAR : Keyboard::KEY_BACK_SLASH;
- case 0x1E:
- return __shiftDown ? Keyboard::KEY_RIGHT_BRACE : Keyboard::KEY_RIGHT_BRACKET;
- case 0x27:
- return __shiftDown ? Keyboard::KEY_QUOTE : Keyboard::KEY_APOSTROPHE;
-
- case 0x00:
- return caps ? Keyboard::KEY_CAPITAL_A : Keyboard::KEY_A;
- case 0x0B:
- return caps ? Keyboard::KEY_CAPITAL_B : Keyboard::KEY_B;
- case 0x08:
- return caps ? Keyboard::KEY_CAPITAL_C : Keyboard::KEY_C;
- case 0x02:
- return caps ? Keyboard::KEY_CAPITAL_D : Keyboard::KEY_D;
- case 0x0E:
- return caps ? Keyboard::KEY_CAPITAL_E : Keyboard::KEY_E;
- case 0x03:
- return caps ? Keyboard::KEY_CAPITAL_F : Keyboard::KEY_F;
- case 0x05:
- return caps ? Keyboard::KEY_CAPITAL_G : Keyboard::KEY_G;
- case 0x04:
- return caps ? Keyboard::KEY_CAPITAL_H : Keyboard::KEY_H;
- case 0x22:
- return caps ? Keyboard::KEY_CAPITAL_I : Keyboard::KEY_I;
- case 0x26:
- return caps ? Keyboard::KEY_CAPITAL_J : Keyboard::KEY_J;
- case 0x28:
- return caps ? Keyboard::KEY_CAPITAL_K : Keyboard::KEY_K;
- case 0x25:
- return caps ? Keyboard::KEY_CAPITAL_L : Keyboard::KEY_L;
- case 0x2E:
- return caps ? Keyboard::KEY_CAPITAL_M : Keyboard::KEY_M;
- case 0x2D:
- return caps ? Keyboard::KEY_CAPITAL_N : Keyboard::KEY_N;
- case 0x1F:
- return caps ? Keyboard::KEY_CAPITAL_O : Keyboard::KEY_O;
- case 0x23:
- return caps ? Keyboard::KEY_CAPITAL_P : Keyboard::KEY_P;
- case 0x0C:
- return caps ? Keyboard::KEY_CAPITAL_Q : Keyboard::KEY_Q;
- case 0x0F:
- return caps ? Keyboard::KEY_CAPITAL_R : Keyboard::KEY_R;
- case 0x01:
- return caps ? Keyboard::KEY_CAPITAL_S : Keyboard::KEY_S;
- case 0x11:
- return caps ? Keyboard::KEY_CAPITAL_T : Keyboard::KEY_T;
- case 0x20:
- return caps ? Keyboard::KEY_CAPITAL_U : Keyboard::KEY_U;
- case 0x09:
- return caps ? Keyboard::KEY_CAPITAL_V : Keyboard::KEY_V;
- case 0x0D:
- return caps ? Keyboard::KEY_CAPITAL_W : Keyboard::KEY_W;
- case 0x07:
- return caps ? Keyboard::KEY_CAPITAL_X : Keyboard::KEY_X;
- case 0x10:
- return caps ? Keyboard::KEY_CAPITAL_Y : Keyboard::KEY_Y;
- case 0x06:
- return caps ? Keyboard::KEY_CAPITAL_Z : Keyboard::KEY_Z;
- default:
- return Keyboard::KEY_NONE;
- }
- }
- /**
- * Returns the unicode value for the given keycode or zero if the key is not a valid printable character.
- */
- int getUnicode(int key)
- {
-
- switch (key)
- {
- case Keyboard::KEY_BACKSPACE:
- return 0x0008;
- case Keyboard::KEY_TAB:
- return 0x0009;
- case Keyboard::KEY_RETURN:
- case Keyboard::KEY_KP_ENTER:
- return 0x000A;
- case Keyboard::KEY_ESCAPE:
- return 0x001B;
- case Keyboard::KEY_SPACE:
- case Keyboard::KEY_EXCLAM:
- case Keyboard::KEY_QUOTE:
- case Keyboard::KEY_NUMBER:
- case Keyboard::KEY_DOLLAR:
- case Keyboard::KEY_PERCENT:
- case Keyboard::KEY_CIRCUMFLEX:
- case Keyboard::KEY_AMPERSAND:
- case Keyboard::KEY_APOSTROPHE:
- case Keyboard::KEY_LEFT_PARENTHESIS:
- case Keyboard::KEY_RIGHT_PARENTHESIS:
- case Keyboard::KEY_ASTERISK:
- case Keyboard::KEY_PLUS:
- case Keyboard::KEY_COMMA:
- case Keyboard::KEY_MINUS:
- case Keyboard::KEY_PERIOD:
- case Keyboard::KEY_SLASH:
- case Keyboard::KEY_ZERO:
- case Keyboard::KEY_ONE:
- case Keyboard::KEY_TWO:
- case Keyboard::KEY_THREE:
- case Keyboard::KEY_FOUR:
- case Keyboard::KEY_FIVE:
- case Keyboard::KEY_SIX:
- case Keyboard::KEY_SEVEN:
- case Keyboard::KEY_EIGHT:
- case Keyboard::KEY_NINE:
- case Keyboard::KEY_COLON:
- case Keyboard::KEY_SEMICOLON:
- case Keyboard::KEY_LESS_THAN:
- case Keyboard::KEY_EQUAL:
- case Keyboard::KEY_GREATER_THAN:
- case Keyboard::KEY_QUESTION:
- case Keyboard::KEY_AT:
- case Keyboard::KEY_CAPITAL_A:
- case Keyboard::KEY_CAPITAL_B:
- case Keyboard::KEY_CAPITAL_C:
- case Keyboard::KEY_CAPITAL_D:
- case Keyboard::KEY_CAPITAL_E:
- case Keyboard::KEY_CAPITAL_F:
- case Keyboard::KEY_CAPITAL_G:
- case Keyboard::KEY_CAPITAL_H:
- case Keyboard::KEY_CAPITAL_I:
- case Keyboard::KEY_CAPITAL_J:
- case Keyboard::KEY_CAPITAL_K:
- case Keyboard::KEY_CAPITAL_L:
- case Keyboard::KEY_CAPITAL_M:
- case Keyboard::KEY_CAPITAL_N:
- case Keyboard::KEY_CAPITAL_O:
- case Keyboard::KEY_CAPITAL_P:
- case Keyboard::KEY_CAPITAL_Q:
- case Keyboard::KEY_CAPITAL_R:
- case Keyboard::KEY_CAPITAL_S:
- case Keyboard::KEY_CAPITAL_T:
- case Keyboard::KEY_CAPITAL_U:
- case Keyboard::KEY_CAPITAL_V:
- case Keyboard::KEY_CAPITAL_W:
- case Keyboard::KEY_CAPITAL_X:
- case Keyboard::KEY_CAPITAL_Y:
- case Keyboard::KEY_CAPITAL_Z:
- case Keyboard::KEY_LEFT_BRACKET:
- case Keyboard::KEY_BACK_SLASH:
- case Keyboard::KEY_RIGHT_BRACKET:
- case Keyboard::KEY_UNDERSCORE:
- case Keyboard::KEY_GRAVE:
- case Keyboard::KEY_A:
- case Keyboard::KEY_B:
- case Keyboard::KEY_C:
- case Keyboard::KEY_D:
- case Keyboard::KEY_E:
- case Keyboard::KEY_F:
- case Keyboard::KEY_G:
- case Keyboard::KEY_H:
- case Keyboard::KEY_I:
- case Keyboard::KEY_J:
- case Keyboard::KEY_K:
- case Keyboard::KEY_L:
- case Keyboard::KEY_M:
- case Keyboard::KEY_N:
- case Keyboard::KEY_O:
- case Keyboard::KEY_P:
- case Keyboard::KEY_Q:
- case Keyboard::KEY_R:
- case Keyboard::KEY_S:
- case Keyboard::KEY_T:
- case Keyboard::KEY_U:
- case Keyboard::KEY_V:
- case Keyboard::KEY_W:
- case Keyboard::KEY_X:
- case Keyboard::KEY_Y:
- case Keyboard::KEY_Z:
- case Keyboard::KEY_LEFT_BRACE:
- case Keyboard::KEY_BAR:
- case Keyboard::KEY_RIGHT_BRACE:
- case Keyboard::KEY_TILDE:
- return key;
- default:
- return 0;
- }
- }
- - (void)flagsChanged: (NSEvent*)event
- {
- unsigned int keyCode = [event keyCode];
- unsigned int flags = [event modifierFlags];
- [__view->gameLock lock];
- switch (keyCode)
- {
- case 0x39:
- gameplay::Platform::keyEventInternal((flags & NSAlphaShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_CAPS_LOCK);
- break;
- case 0x38:
- gameplay::Platform::keyEventInternal((flags & NSShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_SHIFT);
- break;
- case 0x3C:
- gameplay::Platform::keyEventInternal((flags & NSShiftKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_SHIFT);
- break;
- case 0x3A:
- gameplay::Platform::keyEventInternal((flags & NSAlternateKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_ALT);
- break;
- case 0x3D:
- gameplay::Platform::keyEventInternal((flags & NSAlternateKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_ALT);
- break;
- case 0x3B:
- gameplay::Platform::keyEventInternal((flags & NSControlKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_CTRL);
- break;
- case 0x3E:
- gameplay::Platform::keyEventInternal((flags & NSControlKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_CTRL);
- break;
- case 0x37:
- gameplay::Platform::keyEventInternal((flags & NSCommandKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_HYPER);
- break;
- case 0x36:
- gameplay::Platform::keyEventInternal((flags & NSCommandKeyMask) ? Keyboard::KEY_PRESS : Keyboard::KEY_RELEASE, Keyboard::KEY_HYPER);
- break;
- }
- [__view->gameLock unlock];
- }
- - (void) keyDown: (NSEvent*) event
- {
- if ([event isARepeat] == NO)
- {
- int key = getKey([event keyCode], [event modifierFlags]);
- [__view->gameLock lock];
- gameplay::Platform::keyEventInternal(Keyboard::KEY_PRESS, key);
-
- int character = getUnicode(key);
- if (character)
- {
- gameplay::Platform::keyEventInternal(Keyboard::KEY_CHAR, character);
- }
- [__view->gameLock unlock];
- }
- }
- - (void) keyUp: (NSEvent*) event
- {
- [__view->gameLock lock];
- gameplay::Platform::keyEventInternal(Keyboard::KEY_RELEASE, getKey([event keyCode], [event modifierFlags]));
- [__view->gameLock unlock];
- }
- // Gesture support for Mac OS X Trackpads
- - (bool)isGestureRegistered: (Gesture::GestureEvent) evt
- {
- return ((_gestureEvents & evt) == evt);
- }
- - (void)registerGesture: (Gesture::GestureEvent) evt
- {
- _gestureEvents |= evt;
- }
- - (void)unregisterGesture: (Gesture::GestureEvent) evt
- {
- _gestureEvents &= (~evt);
- }
- - (void)magnifyWithEvent:(NSEvent *)event
- {
- if([self isGestureRegistered:Gesture::GESTURE_PINCH] == false) return;
-
- NSSet *touches = [event touchesMatchingPhase:NSTouchPhaseAny inView:nil];
- // Approximate the center by adding and averageing for now
- // Note this is centroid on the physical device be used for touching, not the display
- float xavg = 0.0f;
- float yavg = 0.0f;
- for(NSTouch *t in touches) {
- xavg += [t normalizedPosition].x;
- yavg += [t normalizedPosition].y;
- }
- xavg /= [touches count];
- yavg /= [touches count];
-
- [gameLock lock];
- gameplay::Platform::gesturePinchEventInternal((int)xavg, (int)yavg, [event magnification]);
- [gameLock unlock];
- }
- @end
- @interface FullscreenWindow : NSWindow
- {
- }
- - (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController;
- @end
- @implementation FullscreenWindow
- - (BOOL)canBecomeKeyWindow
- {
- return YES;
- }
- - (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController
- {
- GKDialogController *sdc = [GKDialogController sharedDialogController];
- [sdc dismiss: self];
- }
- @end
- namespace gameplay
- {
- extern void print(const char* format, ...)
- {
- GP_ASSERT(format);
- va_list argptr;
- va_start(argptr, format);
- vfprintf(stderr, format, argptr);
- va_end(argptr);
- }
- extern int strcmpnocase(const char* s1, const char* s2)
- {
- return strcasecmp(s1, s2);
- }
-
- Platform::Platform(Game* game)
- : _game(game)
- {
- __activeGamepads = [[NSMutableDictionary alloc] init];
- __gamepads = [[NSMutableArray alloc] init];
- __hidManagerRef = IOHIDManagerCreate(CFAllocatorGetDefault(), kIOHIDOptionsTypeNone);
- IOHIDManagerRegisterDeviceMatchingCallback(__hidManagerRef, hidDeviceDiscoveredCallback, NULL);
- IOHIDManagerRegisterDeviceRemovalCallback(__hidManagerRef, hidDeviceRemovalCallback, NULL);
-
- CFMutableArrayRef matching = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- if (matching)
- {
- CFDictionaryRef matchingJoystick = IOHIDCreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
- CFDictionaryRef matchingGamepad = IOHIDCreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
-
- if (matchingJoystick && matchingGamepad)
- {
- CFArrayAppendValue(matching, matchingJoystick);
- CFRelease(matchingJoystick);
- CFArrayAppendValue(matching, matchingGamepad);
- CFRelease(matchingGamepad);
- IOHIDManagerSetDeviceMatchingMultiple(__hidManagerRef, matching);
- }
- }
-
- IOHIDManagerScheduleWithRunLoop(__hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
- IOReturn kr = IOHIDManagerOpen(__hidManagerRef, kIOHIDOptionsTypeNone);
- assert(kr == 0);
- }
-
- Platform::~Platform()
- {
- IOHIDManagerUnscheduleFromRunLoop(__hidManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
- IOHIDManagerClose(__hidManagerRef, kIOHIDOptionsTypeNone);
-
- CFRelease(__hidManagerRef);
- __hidManagerRef = NULL;
- [__activeGamepads release];
- __activeGamepads = NULL;
- [__gamepads release];
- __gamepads = NULL;
- }
-
- Platform* Platform::create(Game* game)
- {
- Platform* platform = new Platform(game);
-
- return platform;
- }
- int Platform::enterMessagePump()
- {
- NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
- NSString* path = [bundlePath stringByAppendingString:@"/Contents/Resources/"];
- FileSystem::setResourcePath([path cStringUsingEncoding:NSASCIIStringEncoding]);
-
- // Read window settings from config.
- if (_game->getConfig())
- {
- Properties* config = _game->getConfig()->getNamespace("window", true);
- if (config)
- {
- // Read window title.
- __title = const_cast<char *>(config->getString("title"));
- // Read window size.
- int width = config->getInt("width");
- if (width != 0)
- __width = width;
- int height = config->getInt("height");
- if (height != 0)
- __height = height;
- // Read fullscreen state.
- __fullscreen = config->getBool("fullscreen");
- if (__fullscreen && width == 0 && height == 0)
- {
- CGRect mainMonitor = CGDisplayBounds(CGMainDisplayID());
- __width = CGRectGetWidth(mainMonitor);
- __height = CGRectGetHeight(mainMonitor);
- }
-
- // Read resizable state.
- __resizable = config->getBool("resizable");
- }
- }
- NSAutoreleasePool* pool = [NSAutoreleasePool new];
- NSApplication* app = [NSApplication sharedApplication];
- NSRect screenBounds = [[NSScreen mainScreen] frame];
- NSRect viewBounds = NSMakeRect(0, 0, __width, __height);
-
- __view = [[View alloc] initWithFrame:viewBounds];
- if (__view == NULL)
- {
- GP_ERROR("Failed to create view: exiting.");
- return EXIT_FAILURE;
- }
-
- NSRect centered = NSMakeRect(NSMidX(screenBounds) - NSMidX(viewBounds),
- NSMidY(screenBounds) - NSMidY(viewBounds),
- viewBounds.size.width,
- viewBounds.size.height);
-
- NSWindow* window = NULL;
- if (__fullscreen)
- {
- window = [[FullscreenWindow alloc]
- initWithContentRect:screenBounds
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:NO];
- }
- else
- {
- window = [[NSWindow alloc]
- initWithContentRect:centered
- styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
- backing:NSBackingStoreBuffered
- defer:NO];
- }
-
- [window setAcceptsMouseMovedEvents:YES];
- [window setContentView:__view];
- [window setDelegate:__view];
- [__view release];
-
- [app run];
-
- [pool release];
- return EXIT_SUCCESS;
- }
- void Platform::signalShutdown()
- {
- [__view haltDisplayRenderer];
- // Don't perform terminate right away, enqueue to give game object
- // a chance to cleanup
- NSApplication* app = [NSApplication sharedApplication];
- [app performSelectorOnMainThread:@selector(terminate:) withObject:nil waitUntilDone:NO];
- }
- bool Platform::canExit()
- {
- return true;
- }
-
- unsigned int Platform::getDisplayWidth()
- {
- return __width;
- }
- unsigned int Platform::getDisplayHeight()
- {
- return __height;
- }
- double Platform::getAbsoluteTime()
- {
- __timeAbsolute = getMachTimeInMilliseconds();
- return __timeAbsolute;
- }
- void Platform::setAbsoluteTime(double time)
- {
- __timeAbsolute = time;
- }
- bool Platform::isVsync()
- {
- return __vsync;
- }
- void Platform::setVsync(bool enable)
- {
- __vsync = enable;
- GLint swapInt = enable ? 1 : 0;
- [[__view openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
- }
- void Platform::swapBuffers()
- {
- if (__view)
- CGLFlushDrawable((CGLContextObj)[[__view openGLContext] CGLContextObj]);
- }
- void Platform::sleep(long ms)
- {
- usleep(ms * 1000);
- }
- void Platform::setMultiSampling(bool enabled)
- {
- if (enabled == __multiSampling)
- {
- return;
- }
- //todo
- __multiSampling = enabled;
- }
- bool Platform::isMultiSampling()
- {
- return __multiSampling;
- }
- void Platform::setMultiTouch(bool enabled)
- {
- }
-
- bool Platform::isMultiTouch()
- {
- return true;
- }
- bool Platform::hasAccelerometer()
- {
- return false;
- }
-
- void Platform::getAccelerometerValues(float* pitch, float* roll)
- {
- GP_ASSERT(pitch);
- GP_ASSERT(roll);
- *pitch = 0;
- *roll = 0;
- }
- void Platform::getSensorValues(float* accelX, float* accelY, float* accelZ, float* gyroX, float* gyroY, float* gyroZ)
- {
- if (accelX)
- {
- *accelX = 0;
- }
- if (accelY)
- {
- *accelY = 0;
- }
- if (accelZ)
- {
- *accelZ = 0;
- }
- if (gyroX)
- {
- *gyroX = 0;
- }
- if (gyroY)
- {
- *gyroY = 0;
- }
- if (gyroZ)
- {
- *gyroZ = 0;
- }
- }
- void Platform::getArguments(int* argc, char*** argv)
- {
- if (argc)
- *argc = __argc;
- if (argv)
- *argv = __argv;
- }
-
- bool Platform::hasMouse()
- {
- return true;
- }
- void Platform::setMouseCaptured(bool captured)
- {
- if (captured != __mouseCaptured)
- {
- if (captured)
- {
- [NSCursor hide];
- __mouseCapturedFirstPass = true;
- }
- else
- {
- [NSCursor unhide];
- }
- NSWindow* window = __view.window;
- NSRect rect = window.frame;
- CGPoint centerPoint;
- centerPoint.x = rect.origin.x + (rect.size.width / 2);
- centerPoint.y = rect.origin.y + (rect.size.height / 2);
- CGDisplayMoveCursorToPoint(CGDisplayPrimaryDisplay(NULL), centerPoint);
- __mouseCaptured = captured;
- }
- }
- bool Platform::isMouseCaptured()
- {
- return __mouseCaptured;
- }
- void Platform::setCursorVisible(bool visible)
- {
- if (visible != __cursorVisible)
- {
- if (visible)
- {
- [NSCursor unhide];
- }
- else
- {
- [NSCursor hide];
- }
- __cursorVisible = visible;
- }
- }
- bool Platform::isCursorVisible()
- {
- return __cursorVisible;
- }
- void Platform::displayKeyboard(bool display)
- {
- // Do nothing.
- }
- void Platform::shutdownInternal()
- {
- Game::getInstance()->shutdown();
- }
- bool Platform::isGestureSupported(Gesture::GestureEvent evt)
- {
- // Swipe unsupported as it is considered moving mouse cursor
- // Two fingers is scrolling
- // Three fingers is swipe, but is not always enabled on users system
- // Tap not supported as it is considered a mouse click/button click
- // on some systems making it difficult to differentiate
- switch(evt)
- {
- case Gesture::GESTURE_PINCH:
- return true;
- default:
- break;
- }
- return false;
- }
- void Platform::registerGesture(Gesture::GestureEvent evt)
- {
- [__view registerGesture:evt];
- }
- void Platform::unregisterGesture(Gesture::GestureEvent evt)
- {
- [__view unregisterGesture:evt];
- }
-
- bool Platform::isGestureRegistered(Gesture::GestureEvent evt)
- {
- return [__view isGestureRegistered:evt];
- }
- void Platform::pollGamepadState(Gamepad* gamepad)
- {
- HIDGamepad* gp = gamepadForGameHandle(gamepad->_handle);
- if (gp)
- {
- // Haven't figured out how to have the triggers not also show up in the buttons array.
- // So for now a value of -1 means "Don't map this button."
- static const int PS3Mapping[17] = {
- Gamepad::BUTTON_MENU1, // 0x0001
- Gamepad::BUTTON_L3, // 0x0002
- Gamepad::BUTTON_R3, // 0x0004
- Gamepad::BUTTON_MENU2, // 0x0008
- Gamepad::BUTTON_UP, // 0x0010
- Gamepad::BUTTON_RIGHT, // 0x0020
- Gamepad::BUTTON_DOWN, // 0x0040
- Gamepad::BUTTON_LEFT, // 0x0080
- -1, // Gamepad::BUTTON_L2, // 0x0100
- -1, // Gamepad::BUTTON_R2, // 0x0200
- Gamepad::BUTTON_L1, // 0x0400
- Gamepad::BUTTON_R1, // 0x0800
- Gamepad::BUTTON_Y, // 0x1000
- Gamepad::BUTTON_B, // 0x2000
- Gamepad::BUTTON_A, // 0x4000
- Gamepad::BUTTON_X, // 0x8000
- Gamepad::BUTTON_MENU3 // 0x10000
- };
-
- static const int XBox360Mapping[20] = {
- -1, -1, -1, -1, -1,
- Gamepad::BUTTON_UP,
- Gamepad::BUTTON_DOWN,
- Gamepad::BUTTON_LEFT,
- Gamepad::BUTTON_RIGHT,
- Gamepad::BUTTON_MENU2,
- Gamepad::BUTTON_MENU1,
- Gamepad::BUTTON_L3,
- Gamepad::BUTTON_R3,
- Gamepad::BUTTON_L1,
- Gamepad::BUTTON_R1,
- Gamepad::BUTTON_MENU3,
- Gamepad::BUTTON_A,
- Gamepad::BUTTON_B,
- Gamepad::BUTTON_X,
- Gamepad::BUTTON_Y
- };
-
- static const int SteelSeriesFreeMapping[13] = {
- Gamepad::BUTTON_A,
- Gamepad::BUTTON_B,
- -1,
- Gamepad::BUTTON_X,
- Gamepad::BUTTON_Y,
- -1,
- Gamepad::BUTTON_L1,
- Gamepad::BUTTON_R1,
- -1, -1, -1,
- Gamepad::BUTTON_MENU2,
- Gamepad::BUTTON_MENU1
- };
-
- static const int GametelMapping103[12] = {
- Gamepad::BUTTON_B,
- Gamepad::BUTTON_X,
- Gamepad::BUTTON_Y,
- Gamepad::BUTTON_A,
- Gamepad::BUTTON_L1,
- Gamepad::BUTTON_R1,
- Gamepad::BUTTON_MENU1,
- Gamepad::BUTTON_MENU2,
- Gamepad::BUTTON_RIGHT,
- Gamepad::BUTTON_LEFT,
- Gamepad::BUTTON_DOWN,
- Gamepad::BUTTON_UP
- };
-
- const int* mapping = NULL;
- float axisDeadZone = 0.0f;
- if (gamepad->_vendorId == SONY_USB_VENDOR_ID &&
- gamepad->_productId == SONY_USB_PS3_PRODUCT_ID)
- {
- mapping = PS3Mapping;
- axisDeadZone = 0.07f;
- }
- else if (gamepad->_vendorId == MICROSOFT_VENDOR_ID &&
- gamepad->_productId == MICROSOFT_XBOX360_PRODUCT_ID)
- {
- mapping = XBox360Mapping;
- axisDeadZone = 0.2f;
- }
- else if (gamepad->_vendorId == STEELSERIES_VENDOR_ID &&
- gamepad->_productId == STEELSERIES_FREE_PRODUCT_ID)
- {
- mapping = SteelSeriesFreeMapping;
- axisDeadZone = 0.005f;
- }
- else if (gamepad->_vendorId == FRUCTEL_VENDOR_ID &&
- gamepad->_productId == FRUCTEL_GAMETEL_PRODUCT_ID)
- {
- int ver = [gp versionNumber];
- int major = ver >> 8;
- int minor = ver & 0x00ff;
- if (major >= 1 && minor > 1)
- {
- mapping = GametelMapping103;
- }
- }
-
- unsigned int buttons = 0;
- for (int i = 0; i < [gp numberOfButtons]; ++i)
- {
- HIDGamepadButton* b = [gp buttonAtIndex: i];
- if ([b state])
- {
- // This button is down.
- if (mapping)
- {
- if (mapping[i] >= 0)
- buttons |= (1 << mapping[i]);
- }
- else
- {
- buttons |= (1 << i);
- }
- }
- }
-
- HIDGamepadAxis* hatSwitch = [gp getHatSwitch];
- if (hatSwitch != NULL)
- {
- CFIndex v = [hatSwitch value];
- switch (v)
- {
- case -1:
- break;
- case 0:
- buttons |= (1 << Gamepad::BUTTON_UP);
- break;
- case 1:
- buttons |= (1 << Gamepad::BUTTON_UP) | (1 << Gamepad::BUTTON_RIGHT);
- break;
- case 2:
- buttons |= (1 << Gamepad::BUTTON_RIGHT);
- break;
- case 3:
- buttons |= (1 << Gamepad::BUTTON_RIGHT) | (1 << Gamepad::BUTTON_DOWN);
- break;
- case 4:
- buttons |= (1 << Gamepad::BUTTON_DOWN);
- break;
- case 5:
- buttons |= (1 << Gamepad::BUTTON_DOWN) | (1 << Gamepad::BUTTON_LEFT);
- break;
- case 6:
- buttons |= (1 << Gamepad::BUTTON_LEFT);
- break;
- case 7:
- buttons |= (1 << Gamepad::BUTTON_LEFT) | (1 << Gamepad::BUTTON_UP);
- break;
- }
- }
-
- gamepad->setButtons(buttons);
-
- for (unsigned int i = 0; i < [gp numberOfSticks]; ++i)
- {
- float rawX = [[gp axisAtIndex: i*2] calibratedValue];
- float rawY = -[[gp axisAtIndex: i*2 + 1] calibratedValue];
- if (std::fabs(rawX) <= axisDeadZone)
- rawX = 0;
- if (std::fabs(rawY) <= axisDeadZone)
- rawY = 0;
-
- gamepad->setJoystickValue(i, rawX, rawY);
- }
-
- for (unsigned int i = 0; i < [gp numberOfTriggerButtons]; ++i)
- {
- gamepad->setTriggerValue(i, [[gp triggerButtonAtIndex: i] calibratedStateValue]);
- }
- }
- }
- }
- HIDGamepad* gamepadForLocationID(NSNumber* locationID)
- {
- HIDGamepad* fgamepad = NULL;
- for(HIDGamepad* gamepad in __gamepads)
- {
- if([[gamepad locationID] isEqual:locationID])
- {
- fgamepad = gamepad;
- break;
- }
- }
- return fgamepad;
- }
- HIDGamepad* gamepadForLocationIDValue(unsigned int locationIDValue)
- {
- return gamepadForLocationID([NSNumber numberWithUnsignedInt:locationIDValue]);
- }
- HIDGamepad* gamepadForGameHandle(int gameHandle)
- {
- HIDGamepad* gamepad = NULL;
- for(NSNumber* locationID in __activeGamepads)
- {
- NSNumber* handleID = [__activeGamepads objectForKey:locationID];
- if([handleID integerValue] == gameHandle)
- {
- gamepad = gamepadForLocationID(locationID);
- break;
- }
- }
- return gamepad;
- }
- CFMutableDictionaryRef IOHIDCreateDeviceMatchingDictionary(UInt32 inUsagePage, UInt32 inUsage)
- {
- // create a dictionary to add usage page/usages to
- CFMutableDictionaryRef result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (result) {
- if (inUsagePage)
- {
- // Add key for device type to refine the matching dictionary.
- CFNumberRef pageCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &inUsagePage);
- if (pageCFNumberRef)
- {
- CFDictionarySetValue(result, CFSTR( kIOHIDDeviceUsagePageKey ), pageCFNumberRef);
- CFRelease(pageCFNumberRef);
-
- // note: the usage is only valid if the usage page is also defined
- if (inUsage)
- {
- CFNumberRef usageCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &inUsage);
- if (usageCFNumberRef)
- {
- CFDictionarySetValue(result, CFSTR(kIOHIDDeviceUsageKey), usageCFNumberRef);
- CFRelease(usageCFNumberRef);
- }
- else
- {
- fprintf(stderr, "%s: CFNumberCreate( usage ) failed.", __PRETTY_FUNCTION__);
- }
- }
- }
- else
- {
- fprintf( stderr, "%s: CFNumberCreate( usage page ) failed.", __PRETTY_FUNCTION__);
- }
- }
- }
- else
- {
- fprintf( stderr, "%s: CFDictionaryCreateMutable failed.", __PRETTY_FUNCTION__);
- }
- return result;
- }
- CFStringRef IOHIDDeviceGetStringProperty(IOHIDDeviceRef deviceRef, CFStringRef key)
- {
- CFTypeRef typeRef = IOHIDDeviceGetProperty(deviceRef, key);
- if (typeRef == NULL || CFGetTypeID(typeRef) != CFNumberGetTypeID())
- {
- return NULL;
- }
- return (CFStringRef)typeRef;
- }
- int IOHIDDeviceGetIntProperty(IOHIDDeviceRef deviceRef, CFStringRef key)
- {
- CFTypeRef typeRef = IOHIDDeviceGetProperty(deviceRef, key);
- if (typeRef == NULL || CFGetTypeID(typeRef) != CFNumberGetTypeID())
- {
- return 0;
- }
-
- int value;
- CFNumberGetValue((CFNumberRef) typeRef, kCFNumberSInt32Type, &value);
- return value;
- }
- static void hidDeviceDiscoveredCallback(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device)
- {
- CFNumberRef locID = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey));
- if(locID)
- {
- HIDGamepad* gamepad = [[HIDGamepad alloc] initWithDevice: device];
- [__gamepads addObject:gamepad];
- }
- }
- static void hidDeviceRemovalCallback(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef device)
- {
- int removeIndex = -1;
- NSNumber *locID = (NSNumber*)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey));
- if(locID)
- {
- for(int i = 0; i < [__gamepads count]; i++)
- {
- HIDGamepad* gamepad = [__gamepads objectAtIndex:i];
- if([[gamepad locationID] isEqual:locID])
- {
- removeIndex = i;
- break;
- }
- }
- }
- if(removeIndex >= 0)
- {
- [__gamepads removeObjectAtIndex:removeIndex];
- }
- }
- static void hidDeviceValueAvailableCallback(void* inContext, IOReturn inResult, void* inSender)
- {
- HIDGamepad* d = (HIDGamepad*)inContext;
- do
- {
- IOHIDValueRef valueRef = IOHIDQueueCopyNextValueWithTimeout( ( IOHIDQueueRef ) inSender, 0. );
- if (!valueRef) break;
- [d hidValueAvailable:valueRef];
- CFRelease(valueRef); // Don't forget to release our HID value reference
- } while (1);
- }
- bool Platform::launchURL(const char *url)
- {
- if (url == NULL || *url == '\0')
- return false;
- CFURLRef urlRef = CFURLCreateWithBytes(
- NULL,
- (UInt8*)url,
- strlen(url),
- kCFStringEncodingASCII,
- NULL
- );
- const OSStatus err = LSOpenCFURLRef(urlRef, 0);
- CFRelease(urlRef);
- return (err == noErr);
- }
- NSString* getAbsolutePath(const char* path)
- {
- NSString* bundlePathStr = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Contents/Resources"];
- if (path == NULL )
- return bundlePathStr;
-
- NSString* absPath = [NSString stringWithUTF8String:path];
- if ([absPath length] == 0)
- return @"";
-
- if ([absPath hasPrefix:@"/"])
- {
- absPath = [NSString stringWithUTF8String:path];
- }
- else
- {
- absPath = bundlePathStr;
- absPath = [absPath stringByAppendingString:@"/"];
- absPath = [absPath stringByAppendingString:[NSString stringWithUTF8String:path]];
- }
- return absPath;
- }
- std::string Platform::displayFileDialog(size_t mode, const char* title, const char* filterDescription, const char* filterExtensions, const char* initialDirectory)
- {
- std::string filename = "";
-
- if (mode == FileSystem::OPEN)
- {
- NSOpenPanel* openPanel = [NSOpenPanel openPanel];
-
- [openPanel setCanChooseFiles:TRUE];
- [openPanel setCanChooseDirectories:FALSE];
- [openPanel setAllowsMultipleSelection:FALSE];
- // Title
- NSString* titleStr = [NSString stringWithUTF8String:title];
- [openPanel setTitle:titleStr];
-
- // Filter ext.
- NSString* ext = [NSString stringWithUTF8String:filterExtensions];
- NSArray* fileTypes = [NSArray arrayWithObjects: ext, nil];
- [openPanel setAllowedFileTypes:fileTypes];
-
- // Set the initial directory
- NSString* absPath = getAbsolutePath(initialDirectory);
- NSURL* url = [NSURL fileURLWithPath:absPath];
- [openPanel setDirectoryURL:url];
-
- // Show the open dialog
- if ([openPanel runModal] == NSOKButton)
- {
- NSURL* selectedFileName = [openPanel URL];
- NSString* urlStr = [selectedFileName absoluteString];
- filename = std::string([urlStr UTF8String]);
- const std::string fileProtocol = std::string("file://localhost");
- filename.replace(filename.find(fileProtocol), fileProtocol.size(), "");
- }
- }
- else
- {
- NSSavePanel* savePanel = [NSSavePanel savePanel];
- [savePanel setCanCreateDirectories:TRUE];
- [savePanel setCanSelectHiddenExtension:TRUE];
- // Title
- NSString* titleStr = [NSString stringWithUTF8String:title];
- [savePanel setTitle:titleStr];
-
- // Filter ext.
- NSString* ext = [NSString stringWithUTF8String:filterExtensions];
- NSArray* fileTypes = [NSArray arrayWithObjects: ext, nil];
- [savePanel setAllowedFileTypes:fileTypes];
-
- // Set the initial directory
- NSString* absPath = getAbsolutePath(initialDirectory);
- NSURL* url = [NSURL fileURLWithPath:absPath];
- [savePanel setDirectoryURL:url];
-
- // Show the save dialog
- if ([savePanel runModal] == NSOKButton)
- {
- NSURL* selectedFileName = [savePanel URL];
- NSString* urlStr = [selectedFileName absoluteString];
- filename = std::string([urlStr UTF8String]);
- const std::string fileProtocol = std::string("file://localhost");
- filename.replace(filename.find(fileProtocol), fileProtocol.size(), "");
- }
- }
-
- return filename;
- }
- #endif
|