Просмотр исходного кода

Added basic example of supporting trigger buttons PS3

NOTE: Untested on trigger buttons due to multiple unanswered questions
and what appears to be an incomplete API so trigger support might not be
there. For now trigger buttons appear as regular buttons
Brandon Slack 13 лет назад
Родитель
Сommit
060ae87dfc
1 измененных файлов с 149 добавлено и 23 удалено
  1. 149 23
      gameplay/src/PlatformMacOSX.mm

+ 149 - 23
gameplay/src/PlatformMacOSX.mm

@@ -14,6 +14,11 @@
 #import <mach/mach_time.h>
 #import <Foundation/Foundation.h>
 
+// These should probably be moved to a platform common file
+#define SONY_USB_VENDOR_ID          0x54c
+#define SONY_USB_PS3_PRODUCT_ID     0x268
+
+
 using namespace std;
 using namespace gameplay;
 
@@ -129,6 +134,9 @@ double getMachTimeInMilliseconds()
 {
     return IOHIDElementGetCookie(e);
 }
+- (bool)isHatSwitch {
+    return (IOHIDElementGetUsage(e) == kHIDUsage_GD_Hatswitch);
+}
 - (uint32_t)usage
 {
     return IOHIDElementGetUsage(e);
@@ -164,15 +172,24 @@ double getMachTimeInMilliseconds()
 @interface OSXGamepadButton : 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;
-- (float)stateValue;
+- (int)stateValue;
+- (float)calibratedStateValue;
+- (void)setStateValue:(int)value;
 - (bool)state;
 - (void)setState:(bool)state;
 @end
@@ -186,6 +203,7 @@ double getMachTimeInMilliseconds()
     if((self = [super init]))
     {
         e = (IOHIDElementRef)CFRetain(element);
+        te = NULL;
         state = false;
     }
     return self;
@@ -193,8 +211,20 @@ double getMachTimeInMilliseconds()
 - (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;
@@ -203,6 +233,18 @@ double getMachTimeInMilliseconds()
 {
     return IOHIDElementGetCookie(e);
 }
+- (IOHIDElementRef)triggerElement
+{
+    return te;
+}
+- (IOHIDElementCookie)triggerCookie
+{
+    return IOHIDElementGetCookie(te);
+}
+- (bool)isTriggerButton
+{
+    return (te != NULL);
+}
 - (uint32_t)usage
 {
     return IOHIDElementGetUsage(e);
@@ -211,9 +253,16 @@ double getMachTimeInMilliseconds()
 {
     return IOHIDElementGetUsagePage(e);
 }
-- (float)stateValue
+- (void)setStateValue:(int)value {
+    triggerValue = value;
+}
+- (int)stateValue
+{
+    return triggerValue;
+}
+- (float)calibratedStateValue
 {
-    return 0.0f; // TODO
+    return (float)triggerValue; // TODO: Need to figure out expected range
 }
 - (bool)state
 {
@@ -230,11 +279,13 @@ double getMachTimeInMilliseconds()
     IOHIDDeviceRef hidDeviceRef;
     IOHIDQueueRef queueRef;
     NSMutableArray *buttons;
+    NSMutableArray *triggerButtons;
     NSMutableArray *axes;
 }
 @property (assign) IOHIDDeviceRef hidDeviceRef;
 @property (assign) IOHIDQueueRef queueRef;
 @property (retain) NSMutableArray *buttons;
+@property (retain) NSMutableArray *triggerButtons;
 @property (retain) NSMutableArray *axes;
 
 - initWithDevice:(IOHIDDeviceRef)rawDevice;
@@ -242,6 +293,8 @@ double getMachTimeInMilliseconds()
 - (NSNumber*)locationID;
 
 - (void)initializeGamepadElements;
+- (OSXGamepadButton*)buttonWithCookie:(IOHIDElementCookie)cookie;
+
 - (bool)startListening;
 - (void)stopListening;
 
@@ -266,6 +319,7 @@ double getMachTimeInMilliseconds()
 @synthesize hidDeviceRef;
 @synthesize queueRef;
 @synthesize buttons;
+@synthesize triggerButtons;
 @synthesize axes;
 
 - initWithDevice:(IOHIDDeviceRef)rawDevice
@@ -273,9 +327,10 @@ double getMachTimeInMilliseconds()
     if((self = [super init]))
     {
         [self setButtons:[NSMutableArray array]];
+        [self setTriggerButtons:[NSMutableArray array]];
         [self setAxes:[NSMutableArray array]];
 
-        //CFRetain(rawDevice);
+        CFRetain(rawDevice);
         IOHIDQueueRef queue = IOHIDQueueCreate(CFAllocatorGetDefault(), rawDevice, 10, kIOHIDOptionsTypeNone);
         [self setHidDeviceRef:rawDevice];
         [self setQueueRef:queue];
@@ -289,12 +344,13 @@ double getMachTimeInMilliseconds()
 {
     [self stopListening];
     
-    //CFRelease([self rawDevice]);
+    CFRelease([self rawDevice]);
     CFRelease([self queueRef]);
     [self setQueueRef:NULL];
     [self setHidDeviceRef:NULL];
     
     [self setButtons:NULL];
+    [self setTriggerButtons:NULL];
     [self setAxes:NULL];
     [super dealloc];
 }
@@ -318,6 +374,7 @@ double getMachTimeInMilliseconds()
         if (type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis)
         {
             uint32_t pageUsage = IOHIDElementGetUsage(hidElement);
+            IOHIDElementCookie cookie = IOHIDElementGetCookie(hidElement);
 
             switch(pageUsage)
             {
@@ -334,17 +391,61 @@ double getMachTimeInMilliseconds()
                     break;
                 default:
                     // Ignore the pointers
-                    // Not: Some of the pointers are for the 6-axis accelerometer in a PS3 controller
+                    // 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)
         {
             OSXGamepadButton *button = [OSXGamepadButton gamepadButtonWithButtonElement:hidElement];
             [[self buttons] addObject:button];
         }
-
     }
+    // Go back and get proprietary information (e.g. triggers) and asscoaite with appropriate values
+    // Example for other trigger buttons
+    uint32_t vendorID = [self vendorID];
+    uint32_t productID = [self productID];
+    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
+        // Not sure if there is a better way to associate buttons and misc hid elements :/
+        if(vendorID == SONY_USB_VENDOR_ID && productID == SONY_USB_PS3_PRODUCT_ID)
+        {
+            if((unsigned long)cookie == 39)
+            {
+                OSXGamepadButton *leftTrigger = [self buttonWithCookie:(IOHIDElementCookie)9];
+                if(leftTrigger)
+                {
+                    [leftTrigger setTriggerElement:hidElement];
+                    [[self triggerButtons] addObject:leftTrigger];
+                    //[[self buttons] removeObject:leftTrigger]; Defer to gamepad team on this line..  not sure how they intend to tackle
+                }
+            }
+            if((unsigned long)cookie == 40)
+            {
+                OSXGamepadButton *rightTrigger = [self buttonWithCookie:(IOHIDElementCookie)10];
+                if(rightTrigger)
+                {
+                    [rightTrigger setTriggerElement:hidElement];
+                    [[self triggerButtons] addObject:rightTrigger];
+                    //[[self buttons] removeObject:rightTrigger];
+                }
+            }
+        }
+    }
+    
+}
+- (OSXGamepadButton*)buttonWithCookie:(IOHIDElementCookie)cookie {
+    for(OSXGamepadButton *b in [self buttons]) {
+        if([b cookie] == cookie) return b;
+    }
+    return NULL;
 }
 
 - (bool)startListening
@@ -387,19 +488,29 @@ double getMachTimeInMilliseconds()
     return idName;
 }
 
-- (NSString *)productName
-{
-    return (NSString*)IOHIDDeviceGetStringProperty([self rawDevice], CFSTR(kIOHIDProductKey));
+- (NSString *)productName {
+    CFStringRef productName = (CFStringRef)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDProductKey));
+    if(productName == NULL || CFGetTypeID(productName) != CFStringGetTypeID()) {
+        return NULL;
+    }
+    return (NSString*)productName;
 }
-- (NSString *)manufacturerName
-{
-    return (NSString*)IOHIDDeviceGetStringProperty([self rawDevice], CFSTR(kIOHIDManufacturerKey));
+- (NSString *)manufacturerName {
+    CFStringRef manufacturerName = (CFStringRef)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDManufacturerKey));
+    if(manufacturerName == NULL || CFGetTypeID(manufacturerName) != CFStringGetTypeID()) {
+        return NULL;
+    }
+    return (NSString*)manufacturerName;
 }
-- (NSString *)serialNumber
-{
-    return (NSString*)IOHIDDeviceGetStringProperty([self rawDevice], CFSTR(kIOHIDSerialNumberKey));
+- (NSString *)serialNumber {
+    CFStringRef serialNumber = (CFStringRef)IOHIDDeviceGetProperty([self rawDevice], CFSTR(kIOHIDSerialNumberKey));
+    if(serialNumber == NULL || CFGetTypeID(serialNumber) != CFStringGetTypeID()) {
+        return NULL;
+    }
+    return (NSString*)serialNumber;
 }
 
+
 - (int)vendorID
 {
     return IOHIDDeviceGetIntProperty([self rawDevice], CFSTR(kIOHIDVendorIDKey));
@@ -424,11 +535,17 @@ double getMachTimeInMilliseconds()
 }
 - (NSUInteger)numberOfTriggerButtons
 {
-    return 0; // triggers not identified by api - need to manually configure?
+    return [[self triggerButtons] count];
 }
+
 - (OSXGamepadButton*)triggerButtonAtIndex:(NSUInteger)index
 {
-    return NULL; // todo
+    OSXGamepadButton *b = NULL;
+    if(index < [[self triggerButtons] count])
+    {
+        b = [[self triggerButtons] objectAtIndex:index];
+    }
+    return b;
 }
 
 - (OSXGamepadAxis*)axisAtIndex:(NSUInteger)index
@@ -467,12 +584,13 @@ double getMachTimeInMilliseconds()
     IOHIDElementRef element = IOHIDValueGetElement(value);
 	IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
     
+    if(IOHIDValueGetLength(value) > 4) return; // saftey precaution for PS3 cotroller
+    CFIndex integerValue = IOHIDValueGetIntegerValue(value);
     
     for(OSXGamepadAxis *a in [self axes])
     {
         if([a cookie] == cookie)
         {
-            CFIndex integerValue = IOHIDValueGetIntegerValue(value);
             [a setValue:integerValue];
         }
     }
@@ -481,8 +599,16 @@ double getMachTimeInMilliseconds()
     {
         if([b cookie] == cookie)
         {
-            bool pressed = IOHIDValueGetIntegerValue(value);
-            [b setState:pressed];
+            [b setState:(bool)integerValue];
+            break;
+        }
+    }
+    
+    for(OSXGamepadButton *b in [self triggerButtons])
+    {
+        if([b triggerCookie] == cookie)
+        {
+            [b setStateValue:integerValue];
             break;
         }
     }
@@ -921,8 +1047,8 @@ int getKey(unsigned short keyCode, unsigned int modifierFlags)
             return Keyboard::KEY_F10;
         
         // MACOS reserved:
-        //return Keyboard::KEY_F11;
-        //return Keyboard::KEY_F12;
+        // return Keyboard::KEY_F11;
+        // return Keyboard::KEY_F12;
         // return Keyboard::KEY_PAUSE;
         // return Keyboard::KEY_SCROLL_LOCK;