|
|
|
@ -47,8 +47,6 @@ typedef struct |
|
|
|
|
{ |
|
|
|
|
IOHIDElementCookie cookie; |
|
|
|
|
|
|
|
|
|
long value; |
|
|
|
|
|
|
|
|
|
long min; |
|
|
|
|
long max; |
|
|
|
|
|
|
|
|
@ -63,20 +61,17 @@ static void getElementsCFArrayHandler(const void* value, void* parameter); |
|
|
|
|
|
|
|
|
|
// Adds an element to the specified joystick |
|
|
|
|
// |
|
|
|
|
static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement) |
|
|
|
|
static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef elementRef) |
|
|
|
|
{ |
|
|
|
|
long elementType, usagePage, usage; |
|
|
|
|
CFTypeRef refElementType, refUsagePage, refUsage; |
|
|
|
|
|
|
|
|
|
refElementType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementTypeKey)); |
|
|
|
|
refUsagePage = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementUsagePageKey)); |
|
|
|
|
refUsage = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementUsageKey)); |
|
|
|
|
|
|
|
|
|
CFMutableArrayRef elementsArray = NULL; |
|
|
|
|
|
|
|
|
|
CFNumberGetValue(refElementType, kCFNumberLongType, &elementType); |
|
|
|
|
CFNumberGetValue(refUsagePage, kCFNumberLongType, &usagePage); |
|
|
|
|
CFNumberGetValue(refUsage, kCFNumberLongType, &usage); |
|
|
|
|
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementTypeKey)), |
|
|
|
|
kCFNumberLongType, &elementType); |
|
|
|
|
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsagePageKey)), |
|
|
|
|
kCFNumberLongType, &usagePage); |
|
|
|
|
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsageKey)), |
|
|
|
|
kCFNumberLongType, &usage); |
|
|
|
|
|
|
|
|
|
if ((elementType == kIOHIDElementTypeInput_Axis) || |
|
|
|
|
(elementType == kIOHIDElementTypeInput_Button) || |
|
|
|
@ -97,12 +92,10 @@ static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement) |
|
|
|
|
case kHIDUsage_GD_Slider: |
|
|
|
|
case kHIDUsage_GD_Dial: |
|
|
|
|
case kHIDUsage_GD_Wheel: |
|
|
|
|
joystick->numAxes++; |
|
|
|
|
elementsArray = joystick->axes; |
|
|
|
|
elementsArray = joystick->axisElements; |
|
|
|
|
break; |
|
|
|
|
case kHIDUsage_GD_Hatswitch: |
|
|
|
|
joystick->numHats++; |
|
|
|
|
elementsArray = joystick->hats; |
|
|
|
|
elementsArray = joystick->hatElements; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -110,8 +103,7 @@ static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case kHIDPage_Button: |
|
|
|
|
joystick->numButtons++; |
|
|
|
|
elementsArray = joystick->buttons; |
|
|
|
|
elementsArray = joystick->buttonElements; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
@ -120,35 +112,33 @@ static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement) |
|
|
|
|
if (elementsArray) |
|
|
|
|
{ |
|
|
|
|
long number; |
|
|
|
|
CFTypeRef refType; |
|
|
|
|
|
|
|
|
|
CFTypeRef numberRef; |
|
|
|
|
_GLFWjoyelement* element = (_GLFWjoyelement*) malloc(sizeof(_GLFWjoyelement)); |
|
|
|
|
|
|
|
|
|
CFArrayAppendValue(elementsArray, element); |
|
|
|
|
|
|
|
|
|
refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementCookieKey)); |
|
|
|
|
if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) |
|
|
|
|
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementCookieKey)); |
|
|
|
|
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number)) |
|
|
|
|
element->cookie = (IOHIDElementCookie) number; |
|
|
|
|
|
|
|
|
|
refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMinKey)); |
|
|
|
|
if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) |
|
|
|
|
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMinKey)); |
|
|
|
|
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number)) |
|
|
|
|
element->minReport = element->min = number; |
|
|
|
|
|
|
|
|
|
refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMaxKey)); |
|
|
|
|
if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) |
|
|
|
|
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMaxKey)); |
|
|
|
|
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number)) |
|
|
|
|
element->maxReport = element->max = number; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
CFTypeRef refElementTop = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementKey)); |
|
|
|
|
if (refElementTop) |
|
|
|
|
CFTypeRef array = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementKey)); |
|
|
|
|
if (array) |
|
|
|
|
{ |
|
|
|
|
CFTypeID type = CFGetTypeID (refElementTop); |
|
|
|
|
if (type == CFArrayGetTypeID()) |
|
|
|
|
if (CFGetTypeID(array) == CFArrayGetTypeID()) |
|
|
|
|
{ |
|
|
|
|
CFRange range = {0, CFArrayGetCount (refElementTop)}; |
|
|
|
|
CFArrayApplyFunction(refElementTop, range, getElementsCFArrayHandler, joystick); |
|
|
|
|
CFRange range = { 0, CFArrayGetCount(array) }; |
|
|
|
|
CFArrayApplyFunction(array, range, getElementsCFArrayHandler, joystick); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -195,42 +185,28 @@ static void removeJoystick(_GLFWjoy* joystick) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (joystick->present) |
|
|
|
|
{ |
|
|
|
|
joystick->present = GL_FALSE; |
|
|
|
|
if (!joystick->present) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < joystick->numAxes; i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* axes = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axes, i); |
|
|
|
|
free(axes); |
|
|
|
|
} |
|
|
|
|
CFArrayRemoveAllValues(joystick->axes); |
|
|
|
|
joystick->numAxes = 0; |
|
|
|
|
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++) |
|
|
|
|
free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i)); |
|
|
|
|
CFArrayRemoveAllValues(joystick->axisElements); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < joystick->numButtons; i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* button = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttons, i); |
|
|
|
|
free(button); |
|
|
|
|
} |
|
|
|
|
CFArrayRemoveAllValues(joystick->buttons); |
|
|
|
|
joystick->numButtons = 0; |
|
|
|
|
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++) |
|
|
|
|
free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i)); |
|
|
|
|
CFArrayRemoveAllValues(joystick->buttonElements); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < joystick->numHats; i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* hat = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hats, i); |
|
|
|
|
free(hat); |
|
|
|
|
} |
|
|
|
|
CFArrayRemoveAllValues(joystick->hats); |
|
|
|
|
joystick->hats = 0; |
|
|
|
|
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++) |
|
|
|
|
free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i)); |
|
|
|
|
CFArrayRemoveAllValues(joystick->hatElements); |
|
|
|
|
|
|
|
|
|
(*(joystick->interface))->close(joystick->interface); |
|
|
|
|
(*(joystick->interface))->Release(joystick->interface); |
|
|
|
|
free(joystick->axes); |
|
|
|
|
free(joystick->buttons); |
|
|
|
|
|
|
|
|
|
joystick->interface = NULL; |
|
|
|
|
} |
|
|
|
|
(*(joystick->interface))->close(joystick->interface); |
|
|
|
|
(*(joystick->interface))->Release(joystick->interface); |
|
|
|
|
|
|
|
|
|
memset(joystick, 0, sizeof(_GLFWjoy)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Callback for user-initiated joystick removal |
|
|
|
@ -244,34 +220,63 @@ static void removalCallback(void* target, IOReturn result, void* refcon, void* s |
|
|
|
|
// |
|
|
|
|
static void pollJoystickEvents(void) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
CFIndex j; |
|
|
|
|
int joy; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < GLFW_JOYSTICK_LAST + 1; i++) |
|
|
|
|
for (joy = 0; joy <= GLFW_JOYSTICK_LAST; joy++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoy* joystick = &_glfw.ns.joysticks[i]; |
|
|
|
|
CFIndex i; |
|
|
|
|
int buttonIndex = 0; |
|
|
|
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy; |
|
|
|
|
|
|
|
|
|
if (joystick->present) |
|
|
|
|
if (!joystick->present) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++) |
|
|
|
|
{ |
|
|
|
|
for (j = 0; j < joystick->numButtons; j++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* button = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttons, j); |
|
|
|
|
button->value = getElementValue(joystick, button); |
|
|
|
|
} |
|
|
|
|
_GLFWjoyelement* button = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttonElements, i); |
|
|
|
|
|
|
|
|
|
for (j = 0; j < joystick->numAxes; j++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* axes = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axes, j); |
|
|
|
|
axes->value = getElementValue(joystick, axes); |
|
|
|
|
} |
|
|
|
|
if (getElementValue(joystick, button)) |
|
|
|
|
joystick->buttons[buttonIndex++] = GLFW_PRESS; |
|
|
|
|
else |
|
|
|
|
joystick->buttons[buttonIndex++] = GLFW_RELEASE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* axis = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axisElements, i); |
|
|
|
|
|
|
|
|
|
long value = getElementValue(joystick, axis); |
|
|
|
|
long readScale = axis->maxReport - axis->minReport; |
|
|
|
|
|
|
|
|
|
if (readScale == 0) |
|
|
|
|
joystick->axes[i] = value; |
|
|
|
|
else |
|
|
|
|
joystick->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f; |
|
|
|
|
|
|
|
|
|
if (i & 1) |
|
|
|
|
joystick->axes[i] = -joystick->axes[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* hat = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hatElements, i); |
|
|
|
|
|
|
|
|
|
// Bit fields of button presses for each direction, including nil |
|
|
|
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; |
|
|
|
|
|
|
|
|
|
long j, value = getElementValue(joystick, hat); |
|
|
|
|
if (value < 0 || value > 8) |
|
|
|
|
value = 8; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < joystick->numHats; j++) |
|
|
|
|
for (j = 0; j < 4; j++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* hat = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hats, j); |
|
|
|
|
hat->value = getElementValue(joystick, hat); |
|
|
|
|
if (directions[value] & (1 << j)) |
|
|
|
|
joystick->buttons[buttonIndex++] = GLFW_PRESS; |
|
|
|
|
else |
|
|
|
|
joystick->buttons[buttonIndex++] = GLFW_RELEASE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -286,7 +291,7 @@ static void pollJoystickEvents(void) |
|
|
|
|
// |
|
|
|
|
void _glfwInitJoysticks(void) |
|
|
|
|
{ |
|
|
|
|
int deviceCounter = 0; |
|
|
|
|
int joy = 0; |
|
|
|
|
IOReturn result = kIOReturnSuccess; |
|
|
|
|
mach_port_t masterPort = 0; |
|
|
|
|
io_iterator_t objectIterator = 0; |
|
|
|
@ -318,7 +323,7 @@ void _glfwInitJoysticks(void) |
|
|
|
|
while ((ioHIDDeviceObject = IOIteratorNext(objectIterator))) |
|
|
|
|
{ |
|
|
|
|
kern_return_t result; |
|
|
|
|
CFTypeRef refCF = 0; |
|
|
|
|
CFTypeRef valueRef = 0; |
|
|
|
|
|
|
|
|
|
IOCFPlugInInterface** ppPlugInInterface = NULL; |
|
|
|
|
HRESULT plugInResult = S_OK; |
|
|
|
@ -327,27 +332,29 @@ void _glfwInitJoysticks(void) |
|
|
|
|
long usagePage, usage; |
|
|
|
|
|
|
|
|
|
// Check device type |
|
|
|
|
refCF = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDPrimaryUsagePageKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (refCF) |
|
|
|
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDPrimaryUsagePageKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (valueRef) |
|
|
|
|
{ |
|
|
|
|
CFNumberGetValue(refCF, kCFNumberLongType, &usagePage); |
|
|
|
|
CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage); |
|
|
|
|
if (usagePage != kHIDPage_GenericDesktop) |
|
|
|
|
{ |
|
|
|
|
// This device is not relevant to GLFW |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CFRelease(valueRef); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
refCF = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDPrimaryUsageKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (refCF) |
|
|
|
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDPrimaryUsageKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (valueRef) |
|
|
|
|
{ |
|
|
|
|
CFNumberGetValue(refCF, kCFNumberLongType, &usage); |
|
|
|
|
CFNumberGetValue(valueRef, kCFNumberLongType, &usage); |
|
|
|
|
|
|
|
|
|
if ((usage != kHIDUsage_GD_Joystick && |
|
|
|
|
usage != kHIDUsage_GD_GamePad && |
|
|
|
@ -356,10 +363,11 @@ void _glfwInitJoysticks(void) |
|
|
|
|
// This device is not relevant to GLFW |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_GLFWjoy* joystick = &_glfw.ns.joysticks[deviceCounter]; |
|
|
|
|
CFRelease(valueRef); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy; |
|
|
|
|
joystick->present = GL_TRUE; |
|
|
|
|
|
|
|
|
|
result = IOCreatePlugInInterfaceForService(ioHIDDeviceObject, |
|
|
|
@ -388,42 +396,45 @@ void _glfwInitJoysticks(void) |
|
|
|
|
joystick); |
|
|
|
|
|
|
|
|
|
// Get product string |
|
|
|
|
refCF = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDProductKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (refCF) |
|
|
|
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDProductKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (valueRef) |
|
|
|
|
{ |
|
|
|
|
CFStringGetCString(refCF, |
|
|
|
|
CFStringGetCString(valueRef, |
|
|
|
|
joystick->name, |
|
|
|
|
sizeof(joystick->name), |
|
|
|
|
kCFStringEncodingUTF8); |
|
|
|
|
CFRelease(valueRef); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
joystick->numAxes = 0; |
|
|
|
|
joystick->numButtons = 0; |
|
|
|
|
joystick->numHats = 0; |
|
|
|
|
joystick->axes = CFArrayCreateMutable(NULL, 0, NULL); |
|
|
|
|
joystick->buttons = CFArrayCreateMutable(NULL, 0, NULL); |
|
|
|
|
joystick->hats = CFArrayCreateMutable(NULL, 0, NULL); |
|
|
|
|
|
|
|
|
|
CFTypeRef refTopElement; |
|
|
|
|
|
|
|
|
|
refTopElement = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDElementKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
CFTypeID type = CFGetTypeID(refTopElement); |
|
|
|
|
if (type == CFArrayGetTypeID()) |
|
|
|
|
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL); |
|
|
|
|
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL); |
|
|
|
|
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL); |
|
|
|
|
|
|
|
|
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, |
|
|
|
|
CFSTR(kIOHIDElementKey), |
|
|
|
|
kCFAllocatorDefault, |
|
|
|
|
kNilOptions); |
|
|
|
|
if (CFGetTypeID(valueRef) == CFArrayGetTypeID()) |
|
|
|
|
{ |
|
|
|
|
CFRange range = { 0, CFArrayGetCount(refTopElement) }; |
|
|
|
|
CFArrayApplyFunction(refTopElement, |
|
|
|
|
CFRange range = { 0, CFArrayGetCount(valueRef) }; |
|
|
|
|
CFArrayApplyFunction(valueRef, |
|
|
|
|
range, |
|
|
|
|
getElementsCFArrayHandler, |
|
|
|
|
(void*) joystick); |
|
|
|
|
CFRelease(valueRef); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
deviceCounter++; |
|
|
|
|
joystick->axes = (float*) calloc(CFArrayGetCount(joystick->axisElements), |
|
|
|
|
sizeof(float)); |
|
|
|
|
joystick->buttons = (unsigned char*) calloc(CFArrayGetCount(joystick->buttonElements) + |
|
|
|
|
CFArrayGetCount(joystick->hatElements) * 4, 1); |
|
|
|
|
|
|
|
|
|
joy++; |
|
|
|
|
if (joy > GLFW_JOYSTICK_LAST) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -445,118 +456,44 @@ void _glfwTerminateJoysticks(void) |
|
|
|
|
////// GLFW platform API ////// |
|
|
|
|
////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
|
|
int _glfwPlatformGetJoystickParam(int joy, int param) |
|
|
|
|
int _glfwPlatformJoystickPresent(int joy) |
|
|
|
|
{ |
|
|
|
|
if (!_glfw.ns.joysticks[joy].present) |
|
|
|
|
return GL_FALSE; |
|
|
|
|
|
|
|
|
|
switch (param) |
|
|
|
|
{ |
|
|
|
|
case GLFW_PRESENT: |
|
|
|
|
return GL_TRUE; |
|
|
|
|
|
|
|
|
|
case GLFW_AXES: |
|
|
|
|
return (int) CFArrayGetCount(_glfw.ns.joysticks[joy].axes); |
|
|
|
|
|
|
|
|
|
case GLFW_BUTTONS: |
|
|
|
|
return (int) CFArrayGetCount(_glfw.ns.joysticks[joy].buttons) + |
|
|
|
|
(int) CFArrayGetCount(_glfw.ns.joysticks[joy].hats) * 4; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
pollJoystickEvents(); |
|
|
|
|
|
|
|
|
|
return GL_FALSE; |
|
|
|
|
return _glfw.ns.joysticks[joy].present; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes) |
|
|
|
|
float* _glfwPlatformGetJoystickAxes(int joy, int* count) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
_GLFWjoy joystick = _glfw.ns.joysticks[joy]; |
|
|
|
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy; |
|
|
|
|
|
|
|
|
|
if (!joystick.present) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
numaxes = numaxes < joystick.numAxes ? numaxes : joystick.numAxes; |
|
|
|
|
|
|
|
|
|
// Update joystick state |
|
|
|
|
pollJoystickEvents(); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < numaxes; i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* elements = |
|
|
|
|
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick.axes, i); |
|
|
|
|
|
|
|
|
|
long readScale = elements->maxReport - elements->minReport; |
|
|
|
|
|
|
|
|
|
if (readScale == 0) |
|
|
|
|
axes[i] = elements->value; |
|
|
|
|
else |
|
|
|
|
axes[i] = (2.0f * (elements->value - elements->minReport) / readScale) - 1.0f; |
|
|
|
|
if (!joystick->present) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
if (i & 1) |
|
|
|
|
axes[i] = -axes[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return numaxes; |
|
|
|
|
*count = (int) CFArrayGetCount(joystick->axisElements); |
|
|
|
|
return joystick->axes; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, |
|
|
|
|
int numbuttons) |
|
|
|
|
unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count) |
|
|
|
|
{ |
|
|
|
|
int i, j, button; |
|
|
|
|
|
|
|
|
|
if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
_GLFWjoy joystick = _glfw.ns.joysticks[joy]; |
|
|
|
|
|
|
|
|
|
if (!joystick.present) |
|
|
|
|
return 0; |
|
|
|
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy; |
|
|
|
|
|
|
|
|
|
// Update joystick state |
|
|
|
|
pollJoystickEvents(); |
|
|
|
|
|
|
|
|
|
for (button = 0; button < numbuttons && button < joystick.numButtons; button++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* element = (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick.buttons, button); |
|
|
|
|
buttons[button] = element->value ? GLFW_PRESS : GLFW_RELEASE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Virtual buttons - Inject data from hats |
|
|
|
|
// Each hat is exposed as 4 buttons which exposes 8 directions with concurrent button presses |
|
|
|
|
|
|
|
|
|
// Bit fields of button presses for each direction, including nil |
|
|
|
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < joystick.numHats; i++) |
|
|
|
|
{ |
|
|
|
|
_GLFWjoyelement* hat = (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick.hats, i); |
|
|
|
|
|
|
|
|
|
int value = hat->value; |
|
|
|
|
if (value < 0 || value > 8) |
|
|
|
|
value = 8; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < 4 && button < numbuttons; j++) |
|
|
|
|
{ |
|
|
|
|
if (directions[value] & (1 << j)) |
|
|
|
|
buttons[button] = GLFW_PRESS; |
|
|
|
|
else |
|
|
|
|
buttons[button] = GLFW_RELEASE; |
|
|
|
|
if (!joystick->present) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
button++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return button; |
|
|
|
|
*count = (int) CFArrayGetCount(joystick->buttonElements) + |
|
|
|
|
(int) CFArrayGetCount(joystick->hatElements) * 4; |
|
|
|
|
return joystick->buttons; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const char* _glfwPlatformGetJoystickName(int joy) |
|
|
|
|
{ |
|
|
|
|
pollJoystickEvents(); |
|
|
|
|
|
|
|
|
|
return _glfw.ns.joysticks[joy].name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|