mirror of
https://github.com/glfw/glfw.git
synced 2025-10-04 13:46:37 +00:00
Added support for joystick button and axis callbacks
The major change is the addition of the inputValueCallback function. This callback function is registered with the HID Manager using the HIDDeviceRef when a joystick is connected. Whenever an axis, button, or hat switch value is changed for that HID device, the inputValueCallback function is called: the appropriate value will be updated (which alleviates the need for polling, hence the removal of the polling functions) and, if a user callback has been registered, event notification will be provided. (Note that in the case of hat switches, which are treated as quad sets of buttons, one for each direction, user notification is provided only if the value for that direction has actually changed).
This commit is contained in:
parent
ed211f35b5
commit
d3eaf9a9fa
@ -37,7 +37,6 @@
|
|||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
|
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
|
||||||
|
|
||||||
|
|
||||||
// Joystick element information
|
// Joystick element information
|
||||||
//
|
//
|
||||||
typedef struct _GLFWjoyelementNS
|
typedef struct _GLFWjoyelementNS
|
||||||
@ -193,20 +192,35 @@ static void removeJoystick(_GLFWjoystickNS* js)
|
|||||||
_glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);
|
_glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polls for joystick axis events and updates GLFW state
|
// Input value callback
|
||||||
//
|
//
|
||||||
static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)
|
static void inputValueCallback (void* context,
|
||||||
|
IOReturn valueResult,
|
||||||
|
void* deviceRef,
|
||||||
|
IOHIDValueRef valueRef)
|
||||||
{
|
{
|
||||||
|
_GLFWjoystickNS* js;
|
||||||
CFIndex i;
|
CFIndex i;
|
||||||
|
int buttonIndex = 0;
|
||||||
|
|
||||||
|
if (kIOReturnSuccess != valueResult)
|
||||||
|
return;
|
||||||
|
|
||||||
|
js = (_GLFWjoystickNS*)context;
|
||||||
|
if (!js)
|
||||||
|
return;
|
||||||
if (!js->present)
|
if (!js->present)
|
||||||
return GLFW_FALSE;
|
return;
|
||||||
|
|
||||||
|
IOHIDElementRef elementRef = IOHIDValueGetElement(valueRef);
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->axisElements, i);
|
CFArrayGetValueAtIndex(js->axisElements, i);
|
||||||
|
|
||||||
|
if (elementRef == axis->elementRef)
|
||||||
|
{
|
||||||
long value = getElementValue(js, axis);
|
long value = getElementValue(js, axis);
|
||||||
long readScale = axis->maxReport - axis->minReport;
|
long readScale = axis->maxReport - axis->minReport;
|
||||||
|
|
||||||
@ -214,37 +228,36 @@ static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)
|
|||||||
js->axes[i] = value;
|
js->axes[i] = value;
|
||||||
else
|
else
|
||||||
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
|
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
|
||||||
|
|
||||||
|
_glfwInputJoystickAxisMoved(js-_glfw.ns_js,i,js->axes[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++, buttonIndex++)
|
||||||
}
|
|
||||||
|
|
||||||
// Polls for joystick button events and updates GLFW state
|
|
||||||
//
|
|
||||||
static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)
|
|
||||||
{
|
|
||||||
CFIndex i;
|
|
||||||
int buttonIndex = 0;
|
|
||||||
|
|
||||||
if (!js->present)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->buttonElements, i);
|
CFArrayGetValueAtIndex(js->buttonElements, i);
|
||||||
|
|
||||||
|
if (elementRef == button->elementRef)
|
||||||
|
{
|
||||||
if (getElementValue(js, button))
|
if (getElementValue(js, button))
|
||||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
js->buttons[buttonIndex] = GLFW_PRESS;
|
||||||
else
|
else
|
||||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
js->buttons[buttonIndex] = GLFW_RELEASE;
|
||||||
|
|
||||||
|
_glfwInputJoystickButtonState(js-_glfw.ns_js,buttonIndex,js->buttons[buttonIndex]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
for (i = 0; i < CFArrayGetCount(js->hatElements); i++, buttonIndex += 4)
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->hatElements, i);
|
CFArrayGetValueAtIndex(js->hatElements, i);
|
||||||
|
|
||||||
|
if (elementRef == hat->elementRef)
|
||||||
|
{
|
||||||
// Bit fields of button presses for each direction, including nil
|
// Bit fields of button presses for each direction, including nil
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||||
|
|
||||||
@ -254,14 +267,21 @@ static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)
|
|||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
if (directions[value] & (1 << j))
|
const unsigned char oldValue = js->buttons[buttonIndex+j];
|
||||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
if (directions[value] & (1 << j))
|
||||||
|
js->buttons[buttonIndex+j] = GLFW_PRESS;
|
||||||
|
else
|
||||||
|
js->buttons[buttonIndex+j] = GLFW_RELEASE;
|
||||||
|
|
||||||
|
// Since we're treating hat switches as buttons, only send events for
|
||||||
|
// the values that have actually changed.
|
||||||
|
if (oldValue != js->buttons[buttonIndex+j])
|
||||||
|
_glfwInputJoystickButtonState(js-_glfw.ns_js,buttonIndex+j,js->buttons[buttonIndex+j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for user-initiated joystick addition
|
// Callback for user-initiated joystick addition
|
||||||
@ -324,6 +344,10 @@ static void matchCallback(void* context,
|
|||||||
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
||||||
CFArrayGetCount(js->hatElements) * 4, 1);
|
CFArrayGetCount(js->hatElements) * 4, 1);
|
||||||
|
|
||||||
|
IOHIDDeviceRegisterInputValueCallback(deviceRef,
|
||||||
|
inputValueCallback,
|
||||||
|
(void*)js);
|
||||||
|
|
||||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +423,6 @@ void _glfwInitJoysticksNS(void)
|
|||||||
|
|
||||||
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||||
kIOHIDOptionsTypeNone);
|
kIOHIDOptionsTypeNone);
|
||||||
|
|
||||||
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
|
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||||
0,
|
0,
|
||||||
&kCFTypeArrayCallBacks);
|
&kCFTypeArrayCallBacks);
|
||||||
@ -482,7 +505,8 @@ int _glfwPlatformJoystickPresent(int joy)
|
|||||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||||
if (!pollJoystickAxisEvents(js))
|
|
||||||
|
if (!js->present)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*count = (int) CFArrayGetCount(js->axisElements);
|
*count = (int) CFArrayGetCount(js->axisElements);
|
||||||
@ -492,7 +516,8 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
|||||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
{
|
{
|
||||||
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
_GLFWjoystickNS* js = _glfw.ns_js + joy;
|
||||||
if (!pollJoystickButtonEvents(js))
|
|
||||||
|
if (!js->present)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*count = (int) CFArrayGetCount(js->buttonElements) +
|
*count = (int) CFArrayGetCount(js->buttonElements) +
|
||||||
|
Loading…
Reference in New Issue
Block a user