2
0
Эх сурвалжийг харах

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 жил өмнө
parent
commit
060ae87dfc

+ 149 - 23
gameplay/src/PlatformMacOSX.mm

@@ -14,6 +14,11 @@
 #import <mach/mach_time.h>
 #import <mach/mach_time.h>
 #import <Foundation/Foundation.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 std;
 using namespace gameplay;
 using namespace gameplay;
 
 
@@ -129,6 +134,9 @@ double getMachTimeInMilliseconds()
 {
 {
     return IOHIDElementGetCookie(e);
     return IOHIDElementGetCookie(e);
 }
 }
+- (bool)isHatSwitch {
+    return (IOHIDElementGetUsage(e) == kHIDUsage_GD_Hatswitch);
+}
 - (uint32_t)usage
 - (uint32_t)usage
 {
 {
     return IOHIDElementGetUsage(e);
     return IOHIDElementGetUsage(e);
@@ -164,15 +172,24 @@ double getMachTimeInMilliseconds()
 @interface OSXGamepadButton : NSObject
 @interface OSXGamepadButton : NSObject
 {
 {
     IOHIDElementRef e;
     IOHIDElementRef e;
+    IOHIDElementRef te;
     bool state;
     bool state;
+    int triggerValue;
 }
 }
 + gamepadButtonWithButtonElement:(IOHIDElementRef)element;
 + gamepadButtonWithButtonElement:(IOHIDElementRef)element;
 - initWithButtonElement:(IOHIDElementRef)element;
 - initWithButtonElement:(IOHIDElementRef)element;
+- (void)setTriggerElement:(IOHIDElementRef)element;
 - (IOHIDElementRef)element;
 - (IOHIDElementRef)element;
 - (IOHIDElementCookie)cookie;
 - (IOHIDElementCookie)cookie;
+- (IOHIDElementRef)triggerElement;
+- (IOHIDElementCookie)triggerCookie;
+
+- (bool)isTriggerButton;
 - (uint32_t)usage;
 - (uint32_t)usage;
 - (uint32_t)usagePage;
 - (uint32_t)usagePage;
-- (float)stateValue;
+- (int)stateValue;
+- (float)calibratedStateValue;
+- (void)setStateValue:(int)value;
 - (bool)state;
 - (bool)state;
 - (void)setState:(bool)state;
 - (void)setState:(bool)state;
 @end
 @end
@@ -186,6 +203,7 @@ double getMachTimeInMilliseconds()
     if((self = [super init]))
     if((self = [super init]))
     {
     {
         e = (IOHIDElementRef)CFRetain(element);
         e = (IOHIDElementRef)CFRetain(element);
+        te = NULL;
         state = false;
         state = false;
     }
     }
     return self;
     return self;
@@ -193,8 +211,20 @@ double getMachTimeInMilliseconds()
 - (void)dealloc
 - (void)dealloc
 {
 {
     CFRelease(e);
     CFRelease(e);
+    if(te != NULL) CFRelease(te);
     [super dealloc];
     [super dealloc];
 }
 }
+- (void)setTriggerElement:(IOHIDElementRef)element {
+    if(te)
+    {
+        CFRelease(te);
+        te = NULL;
+    }
+    if(element)
+    {
+        te = (IOHIDElementRef)CFRetain(element);
+    }
+}
 - (IOHIDElementRef)element
 - (IOHIDElementRef)element
 {
 {
     return e;
     return e;
@@ -203,6 +233,18 @@ double getMachTimeInMilliseconds()
 {
 {
     return IOHIDElementGetCookie(e);
     return IOHIDElementGetCookie(e);
 }
 }
+- (IOHIDElementRef)triggerElement
+{
+    return te;
+}
+- (IOHIDElementCookie)triggerCookie
+{
+    return IOHIDElementGetCookie(te);
+}
+- (bool)isTriggerButton
+{
+    return (te != NULL);
+}
 - (uint32_t)usage
 - (uint32_t)usage
 {
 {
     return IOHIDElementGetUsage(e);
     return IOHIDElementGetUsage(e);
@@ -211,9 +253,16 @@ double getMachTimeInMilliseconds()
 {
 {
     return IOHIDElementGetUsagePage(e);
     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
 - (bool)state
 {
 {
@@ -230,11 +279,13 @@ double getMachTimeInMilliseconds()
     IOHIDDeviceRef hidDeviceRef;
     IOHIDDeviceRef hidDeviceRef;
     IOHIDQueueRef queueRef;
     IOHIDQueueRef queueRef;
     NSMutableArray *buttons;
     NSMutableArray *buttons;
+    NSMutableArray *triggerButtons;
     NSMutableArray *axes;
     NSMutableArray *axes;
 }
 }
 @property (assign) IOHIDDeviceRef hidDeviceRef;
 @property (assign) IOHIDDeviceRef hidDeviceRef;
 @property (assign) IOHIDQueueRef queueRef;
 @property (assign) IOHIDQueueRef queueRef;
 @property (retain) NSMutableArray *buttons;
 @property (retain) NSMutableArray *buttons;
+@property (retain) NSMutableArray *triggerButtons;
 @property (retain) NSMutableArray *axes;
 @property (retain) NSMutableArray *axes;
 
 
 - initWithDevice:(IOHIDDeviceRef)rawDevice;
 - initWithDevice:(IOHIDDeviceRef)rawDevice;
@@ -242,6 +293,8 @@ double getMachTimeInMilliseconds()
 - (NSNumber*)locationID;
 - (NSNumber*)locationID;
 
 
 - (void)initializeGamepadElements;
 - (void)initializeGamepadElements;
+- (OSXGamepadButton*)buttonWithCookie:(IOHIDElementCookie)cookie;
+
 - (bool)startListening;
 - (bool)startListening;
 - (void)stopListening;
 - (void)stopListening;
 
 
@@ -266,6 +319,7 @@ double getMachTimeInMilliseconds()
 @synthesize hidDeviceRef;
 @synthesize hidDeviceRef;
 @synthesize queueRef;
 @synthesize queueRef;
 @synthesize buttons;
 @synthesize buttons;
+@synthesize triggerButtons;
 @synthesize axes;
 @synthesize axes;
 
 
 - initWithDevice:(IOHIDDeviceRef)rawDevice
 - initWithDevice:(IOHIDDeviceRef)rawDevice
@@ -273,9 +327,10 @@ double getMachTimeInMilliseconds()
     if((self = [super init]))
     if((self = [super init]))
     {
     {
         [self setButtons:[NSMutableArray array]];
         [self setButtons:[NSMutableArray array]];
+        [self setTriggerButtons:[NSMutableArray array]];
         [self setAxes:[NSMutableArray array]];
         [self setAxes:[NSMutableArray array]];
 
 
-        //CFRetain(rawDevice);
+        CFRetain(rawDevice);
         IOHIDQueueRef queue = IOHIDQueueCreate(CFAllocatorGetDefault(), rawDevice, 10, kIOHIDOptionsTypeNone);
         IOHIDQueueRef queue = IOHIDQueueCreate(CFAllocatorGetDefault(), rawDevice, 10, kIOHIDOptionsTypeNone);
         [self setHidDeviceRef:rawDevice];
         [self setHidDeviceRef:rawDevice];
         [self setQueueRef:queue];
         [self setQueueRef:queue];
@@ -289,12 +344,13 @@ double getMachTimeInMilliseconds()
 {
 {
     [self stopListening];
     [self stopListening];
     
     
-    //CFRelease([self rawDevice]);
+    CFRelease([self rawDevice]);
     CFRelease([self queueRef]);
     CFRelease([self queueRef]);
     [self setQueueRef:NULL];
     [self setQueueRef:NULL];
     [self setHidDeviceRef:NULL];
     [self setHidDeviceRef:NULL];
     
     
     [self setButtons:NULL];
     [self setButtons:NULL];
+    [self setTriggerButtons:NULL];
     [self setAxes:NULL];
     [self setAxes:NULL];
     [super dealloc];
     [super dealloc];
 }
 }
@@ -318,6 +374,7 @@ double getMachTimeInMilliseconds()
         if (type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis)
         if (type == kIOHIDElementTypeInput_Misc || type == kIOHIDElementTypeInput_Axis)
         {
         {
             uint32_t pageUsage = IOHIDElementGetUsage(hidElement);
             uint32_t pageUsage = IOHIDElementGetUsage(hidElement);
+            IOHIDElementCookie cookie = IOHIDElementGetCookie(hidElement);
 
 
             switch(pageUsage)
             switch(pageUsage)
             {
             {
@@ -334,17 +391,61 @@ double getMachTimeInMilliseconds()
                     break;
                     break;
                 default:
                 default:
                     // Ignore the pointers
                     // 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;
                     break;
             }
             }
+
         }
         }
         if(type == kIOHIDElementTypeInput_Button)
         if(type == kIOHIDElementTypeInput_Button)
         {
         {
             OSXGamepadButton *button = [OSXGamepadButton gamepadButtonWithButtonElement:hidElement];
             OSXGamepadButton *button = [OSXGamepadButton gamepadButtonWithButtonElement:hidElement];
             [[self buttons] addObject:button];
             [[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
 - (bool)startListening
@@ -387,19 +488,29 @@ double getMachTimeInMilliseconds()
     return idName;
     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
 - (int)vendorID
 {
 {
     return IOHIDDeviceGetIntProperty([self rawDevice], CFSTR(kIOHIDVendorIDKey));
     return IOHIDDeviceGetIntProperty([self rawDevice], CFSTR(kIOHIDVendorIDKey));
@@ -424,11 +535,17 @@ double getMachTimeInMilliseconds()
 }
 }
 - (NSUInteger)numberOfTriggerButtons
 - (NSUInteger)numberOfTriggerButtons
 {
 {
-    return 0; // triggers not identified by api - need to manually configure?
+    return [[self triggerButtons] count];
 }
 }
+
 - (OSXGamepadButton*)triggerButtonAtIndex:(NSUInteger)index
 - (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
 - (OSXGamepadAxis*)axisAtIndex:(NSUInteger)index
@@ -467,12 +584,13 @@ double getMachTimeInMilliseconds()
     IOHIDElementRef element = IOHIDValueGetElement(value);
     IOHIDElementRef element = IOHIDValueGetElement(value);
 	IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
 	IOHIDElementCookie cookie = IOHIDElementGetCookie(element);
     
     
+    if(IOHIDValueGetLength(value) > 4) return; // saftey precaution for PS3 cotroller
+    CFIndex integerValue = IOHIDValueGetIntegerValue(value);
     
     
     for(OSXGamepadAxis *a in [self axes])
     for(OSXGamepadAxis *a in [self axes])
     {
     {
         if([a cookie] == cookie)
         if([a cookie] == cookie)
         {
         {
-            CFIndex integerValue = IOHIDValueGetIntegerValue(value);
             [a setValue:integerValue];
             [a setValue:integerValue];
         }
         }
     }
     }
@@ -481,8 +599,16 @@ double getMachTimeInMilliseconds()
     {
     {
         if([b cookie] == cookie)
         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;
             break;
         }
         }
     }
     }
@@ -921,8 +1047,8 @@ int getKey(unsigned short keyCode, unsigned int modifierFlags)
             return Keyboard::KEY_F10;
             return Keyboard::KEY_F10;
         
         
         // MACOS reserved:
         // 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_PAUSE;
         // return Keyboard::KEY_SCROLL_LOCK;
         // return Keyboard::KEY_SCROLL_LOCK;