mirror of
https://github.com/gwm17/glfw.git
synced 2024-11-23 02:38:52 -05:00
New joystick API.
This commit is contained in:
parent
c4d856bcb2
commit
7f2eb7b15b
|
@ -530,10 +530,6 @@ extern "C" {
|
||||||
#define GLFW_CURSOR_HIDDEN 0x00040002
|
#define GLFW_CURSOR_HIDDEN 0x00040002
|
||||||
#define GLFW_CURSOR_CAPTURED 0x00040003
|
#define GLFW_CURSOR_CAPTURED 0x00040003
|
||||||
|
|
||||||
#define GLFW_PRESENT 0x00050001
|
|
||||||
#define GLFW_AXES 0x00050002
|
|
||||||
#define GLFW_BUTTONS 0x00050003
|
|
||||||
|
|
||||||
#define GLFW_GAMMA_RAMP_SIZE 256
|
#define GLFW_GAMMA_RAMP_SIZE 256
|
||||||
|
|
||||||
#define GLFW_CONNECTED 0x00061000
|
#define GLFW_CONNECTED 0x00061000
|
||||||
|
@ -1930,37 +1926,31 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cb
|
||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI int glfwGetJoystickParam(int joy, int param);
|
GLFWAPI int glfwJoystickPresent(int joy);
|
||||||
|
|
||||||
/*! @brief Returns the values of axes of the specified joystick.
|
/*! @brief Returns the values of all axes of the specified joystick.
|
||||||
*
|
|
||||||
* This function returns the current positions of axes of the specified
|
|
||||||
* joystick.
|
|
||||||
*
|
|
||||||
* @param[in] joy The joystick to query.
|
* @param[in] joy The joystick to query.
|
||||||
* @param[out] axes The array to hold the values.
|
* @param[out] count The size of the returned array.
|
||||||
* @param[in] numaxes The size of the provided array.
|
* @return An array of axis values, or @c NULL if the joystick is not present.
|
||||||
* @return The number of values written to `axes`, or zero if an error
|
*
|
||||||
* occurred.
|
* @note The returned array is valid only until the next call to @ref
|
||||||
|
* glfwGetJoystickAxes for that joystick.
|
||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI int glfwGetJoystickAxes(int joy, float* axes, int numaxes);
|
GLFWAPI float* glfwGetJoystickAxes(int joy, int* count);
|
||||||
|
|
||||||
/*! @brief Returns the values of buttons of the specified joystick.
|
/*! @brief Returns the values of all buttons of the specified joystick.
|
||||||
*
|
|
||||||
* This function returns the current state of buttons of the specified
|
|
||||||
* joystick.
|
|
||||||
*
|
|
||||||
* @param[in] joy The joystick to query.
|
* @param[in] joy The joystick to query.
|
||||||
* @param[out] buttons The array to hold the values.
|
* @param[out] count The size of the returned array.
|
||||||
* @param[in] numbuttons The size of the provided array.
|
* @return An array of axis values, or @c NULL if the joystick is not present.
|
||||||
* @return The number of values written to `buttons`, or zero if an error
|
*
|
||||||
* occurred.
|
* @note The returned array is valid only until the next call to @ref
|
||||||
|
* glfwGetJoystickButtons for that joystick.
|
||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons);
|
GLFWAPI unsigned char* glfwGetJoystickButtons(int joy, int* count);
|
||||||
|
|
||||||
/*! @brief Returns the name of the specified joystick.
|
/*! @brief Returns the name of the specified joystick.
|
||||||
*
|
*
|
||||||
|
|
|
@ -47,8 +47,6 @@ typedef struct
|
||||||
{
|
{
|
||||||
IOHIDElementCookie cookie;
|
IOHIDElementCookie cookie;
|
||||||
|
|
||||||
long value;
|
|
||||||
|
|
||||||
long min;
|
long min;
|
||||||
long max;
|
long max;
|
||||||
|
|
||||||
|
@ -63,20 +61,17 @@ static void getElementsCFArrayHandler(const void* value, void* parameter);
|
||||||
|
|
||||||
// Adds an element to the specified joystick
|
// 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;
|
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;
|
CFMutableArrayRef elementsArray = NULL;
|
||||||
|
|
||||||
CFNumberGetValue(refElementType, kCFNumberLongType, &elementType);
|
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementTypeKey)),
|
||||||
CFNumberGetValue(refUsagePage, kCFNumberLongType, &usagePage);
|
kCFNumberLongType, &elementType);
|
||||||
CFNumberGetValue(refUsage, kCFNumberLongType, &usage);
|
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsagePageKey)),
|
||||||
|
kCFNumberLongType, &usagePage);
|
||||||
|
CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsageKey)),
|
||||||
|
kCFNumberLongType, &usage);
|
||||||
|
|
||||||
if ((elementType == kIOHIDElementTypeInput_Axis) ||
|
if ((elementType == kIOHIDElementTypeInput_Axis) ||
|
||||||
(elementType == kIOHIDElementTypeInput_Button) ||
|
(elementType == kIOHIDElementTypeInput_Button) ||
|
||||||
|
@ -97,12 +92,10 @@ static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement)
|
||||||
case kHIDUsage_GD_Slider:
|
case kHIDUsage_GD_Slider:
|
||||||
case kHIDUsage_GD_Dial:
|
case kHIDUsage_GD_Dial:
|
||||||
case kHIDUsage_GD_Wheel:
|
case kHIDUsage_GD_Wheel:
|
||||||
joystick->numAxes++;
|
elementsArray = joystick->axisElements;
|
||||||
elementsArray = joystick->axes;
|
|
||||||
break;
|
break;
|
||||||
case kHIDUsage_GD_Hatswitch:
|
case kHIDUsage_GD_Hatswitch:
|
||||||
joystick->numHats++;
|
elementsArray = joystick->hatElements;
|
||||||
elementsArray = joystick->hats;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +103,7 @@ static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
case kHIDPage_Button:
|
case kHIDPage_Button:
|
||||||
joystick->numButtons++;
|
elementsArray = joystick->buttonElements;
|
||||||
elementsArray = joystick->buttons;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -120,35 +112,33 @@ static void addJoystickElement(_GLFWjoy* joystick, CFTypeRef refElement)
|
||||||
if (elementsArray)
|
if (elementsArray)
|
||||||
{
|
{
|
||||||
long number;
|
long number;
|
||||||
CFTypeRef refType;
|
CFTypeRef numberRef;
|
||||||
|
|
||||||
_GLFWjoyelement* element = (_GLFWjoyelement*) malloc(sizeof(_GLFWjoyelement));
|
_GLFWjoyelement* element = (_GLFWjoyelement*) malloc(sizeof(_GLFWjoyelement));
|
||||||
|
|
||||||
CFArrayAppendValue(elementsArray, element);
|
CFArrayAppendValue(elementsArray, element);
|
||||||
|
|
||||||
refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementCookieKey));
|
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementCookieKey));
|
||||||
if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number))
|
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
|
||||||
element->cookie = (IOHIDElementCookie) number;
|
element->cookie = (IOHIDElementCookie) number;
|
||||||
|
|
||||||
refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMinKey));
|
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMinKey));
|
||||||
if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number))
|
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
|
||||||
element->minReport = element->min = number;
|
element->minReport = element->min = number;
|
||||||
|
|
||||||
refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMaxKey));
|
numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMaxKey));
|
||||||
if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number))
|
if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))
|
||||||
element->maxReport = element->max = number;
|
element->maxReport = element->max = number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CFTypeRef refElementTop = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementKey));
|
CFTypeRef array = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementKey));
|
||||||
if (refElementTop)
|
if (array)
|
||||||
{
|
{
|
||||||
CFTypeID type = CFGetTypeID (refElementTop);
|
if (CFGetTypeID(array) == CFArrayGetTypeID())
|
||||||
if (type == CFArrayGetTypeID())
|
|
||||||
{
|
{
|
||||||
CFRange range = {0, CFArrayGetCount (refElementTop)};
|
CFRange range = { 0, CFArrayGetCount(array) };
|
||||||
CFArrayApplyFunction(refElementTop, range, getElementsCFArrayHandler, joystick);
|
CFArrayApplyFunction(array, range, getElementsCFArrayHandler, joystick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,42 +185,28 @@ static void removeJoystick(_GLFWjoy* joystick)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (joystick->present)
|
if (!joystick->present)
|
||||||
{
|
return;
|
||||||
joystick->present = GL_FALSE;
|
|
||||||
|
|
||||||
for (i = 0; i < joystick->numAxes; i++)
|
for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)
|
||||||
{
|
free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i));
|
||||||
_GLFWjoyelement* axes =
|
CFArrayRemoveAllValues(joystick->axisElements);
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axes, i);
|
|
||||||
free(axes);
|
|
||||||
}
|
|
||||||
CFArrayRemoveAllValues(joystick->axes);
|
|
||||||
joystick->numAxes = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < joystick->numButtons; i++)
|
for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)
|
||||||
{
|
free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i));
|
||||||
_GLFWjoyelement* button =
|
CFArrayRemoveAllValues(joystick->buttonElements);
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttons, i);
|
|
||||||
free(button);
|
|
||||||
}
|
|
||||||
CFArrayRemoveAllValues(joystick->buttons);
|
|
||||||
joystick->numButtons = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < joystick->numHats; i++)
|
for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)
|
||||||
{
|
free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i));
|
||||||
_GLFWjoyelement* hat =
|
CFArrayRemoveAllValues(joystick->hatElements);
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hats, i);
|
|
||||||
free(hat);
|
|
||||||
}
|
|
||||||
CFArrayRemoveAllValues(joystick->hats);
|
|
||||||
joystick->hats = 0;
|
|
||||||
|
|
||||||
(*(joystick->interface))->close(joystick->interface);
|
free(joystick->axes);
|
||||||
(*(joystick->interface))->Release(joystick->interface);
|
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
|
// 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)
|
static void pollJoystickEvents(void)
|
||||||
{
|
{
|
||||||
int i;
|
int joy;
|
||||||
CFIndex j;
|
|
||||||
|
|
||||||
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->buttonElements, i);
|
||||||
_GLFWjoyelement* button =
|
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttons, j);
|
|
||||||
button->value = getElementValue(joystick, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < joystick->numAxes; j++)
|
if (getElementValue(joystick, button))
|
||||||
{
|
joystick->buttons[buttonIndex++] = GLFW_PRESS;
|
||||||
_GLFWjoyelement* axes =
|
else
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axes, j);
|
joystick->buttons[buttonIndex++] = GLFW_RELEASE;
|
||||||
axes->value = getElementValue(joystick, axes);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < joystick->numHats; j++)
|
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 < 4; j++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelement* hat =
|
if (directions[value] & (1 << j))
|
||||||
(_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hats, j);
|
joystick->buttons[buttonIndex++] = GLFW_PRESS;
|
||||||
hat->value = getElementValue(joystick, hat);
|
else
|
||||||
|
joystick->buttons[buttonIndex++] = GLFW_RELEASE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,7 +291,7 @@ static void pollJoystickEvents(void)
|
||||||
//
|
//
|
||||||
void _glfwInitJoysticks(void)
|
void _glfwInitJoysticks(void)
|
||||||
{
|
{
|
||||||
int deviceCounter = 0;
|
int joy = 0;
|
||||||
IOReturn result = kIOReturnSuccess;
|
IOReturn result = kIOReturnSuccess;
|
||||||
mach_port_t masterPort = 0;
|
mach_port_t masterPort = 0;
|
||||||
io_iterator_t objectIterator = 0;
|
io_iterator_t objectIterator = 0;
|
||||||
|
@ -318,7 +323,7 @@ void _glfwInitJoysticks(void)
|
||||||
while ((ioHIDDeviceObject = IOIteratorNext(objectIterator)))
|
while ((ioHIDDeviceObject = IOIteratorNext(objectIterator)))
|
||||||
{
|
{
|
||||||
kern_return_t result;
|
kern_return_t result;
|
||||||
CFTypeRef refCF = 0;
|
CFTypeRef valueRef = 0;
|
||||||
|
|
||||||
IOCFPlugInInterface** ppPlugInInterface = NULL;
|
IOCFPlugInInterface** ppPlugInInterface = NULL;
|
||||||
HRESULT plugInResult = S_OK;
|
HRESULT plugInResult = S_OK;
|
||||||
|
@ -327,27 +332,29 @@ void _glfwInitJoysticks(void)
|
||||||
long usagePage, usage;
|
long usagePage, usage;
|
||||||
|
|
||||||
// Check device type
|
// Check device type
|
||||||
refCF = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
||||||
CFSTR(kIOHIDPrimaryUsagePageKey),
|
CFSTR(kIOHIDPrimaryUsagePageKey),
|
||||||
kCFAllocatorDefault,
|
kCFAllocatorDefault,
|
||||||
kNilOptions);
|
kNilOptions);
|
||||||
if (refCF)
|
if (valueRef)
|
||||||
{
|
{
|
||||||
CFNumberGetValue(refCF, kCFNumberLongType, &usagePage);
|
CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage);
|
||||||
if (usagePage != kHIDPage_GenericDesktop)
|
if (usagePage != kHIDPage_GenericDesktop)
|
||||||
{
|
{
|
||||||
// This device is not relevant to GLFW
|
// This device is not relevant to GLFW
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFRelease(valueRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
refCF = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
||||||
CFSTR(kIOHIDPrimaryUsageKey),
|
CFSTR(kIOHIDPrimaryUsageKey),
|
||||||
kCFAllocatorDefault,
|
kCFAllocatorDefault,
|
||||||
kNilOptions);
|
kNilOptions);
|
||||||
if (refCF)
|
if (valueRef)
|
||||||
{
|
{
|
||||||
CFNumberGetValue(refCF, kCFNumberLongType, &usage);
|
CFNumberGetValue(valueRef, kCFNumberLongType, &usage);
|
||||||
|
|
||||||
if ((usage != kHIDUsage_GD_Joystick &&
|
if ((usage != kHIDUsage_GD_Joystick &&
|
||||||
usage != kHIDUsage_GD_GamePad &&
|
usage != kHIDUsage_GD_GamePad &&
|
||||||
|
@ -356,10 +363,11 @@ void _glfwInitJoysticks(void)
|
||||||
// This device is not relevant to GLFW
|
// This device is not relevant to GLFW
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFRelease(valueRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLFWjoy* joystick = &_glfw.ns.joysticks[deviceCounter];
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy;
|
||||||
|
|
||||||
joystick->present = GL_TRUE;
|
joystick->present = GL_TRUE;
|
||||||
|
|
||||||
result = IOCreatePlugInInterfaceForService(ioHIDDeviceObject,
|
result = IOCreatePlugInInterfaceForService(ioHIDDeviceObject,
|
||||||
|
@ -388,42 +396,45 @@ void _glfwInitJoysticks(void)
|
||||||
joystick);
|
joystick);
|
||||||
|
|
||||||
// Get product string
|
// Get product string
|
||||||
refCF = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
||||||
CFSTR(kIOHIDProductKey),
|
CFSTR(kIOHIDProductKey),
|
||||||
kCFAllocatorDefault,
|
kCFAllocatorDefault,
|
||||||
kNilOptions);
|
kNilOptions);
|
||||||
if (refCF)
|
if (valueRef)
|
||||||
{
|
{
|
||||||
CFStringGetCString(refCF,
|
CFStringGetCString(valueRef,
|
||||||
joystick->name,
|
joystick->name,
|
||||||
sizeof(joystick->name),
|
sizeof(joystick->name),
|
||||||
kCFStringEncodingUTF8);
|
kCFStringEncodingUTF8);
|
||||||
|
CFRelease(valueRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
joystick->numAxes = 0;
|
joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
joystick->numButtons = 0;
|
joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
joystick->numHats = 0;
|
joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||||
joystick->axes = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
joystick->buttons = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
joystick->hats = CFArrayCreateMutable(NULL, 0, NULL);
|
|
||||||
|
|
||||||
CFTypeRef refTopElement;
|
valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
||||||
|
CFSTR(kIOHIDElementKey),
|
||||||
refTopElement = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,
|
kCFAllocatorDefault,
|
||||||
CFSTR(kIOHIDElementKey),
|
kNilOptions);
|
||||||
kCFAllocatorDefault,
|
if (CFGetTypeID(valueRef) == CFArrayGetTypeID())
|
||||||
kNilOptions);
|
|
||||||
CFTypeID type = CFGetTypeID(refTopElement);
|
|
||||||
if (type == CFArrayGetTypeID())
|
|
||||||
{
|
{
|
||||||
CFRange range = { 0, CFArrayGetCount(refTopElement) };
|
CFRange range = { 0, CFArrayGetCount(valueRef) };
|
||||||
CFArrayApplyFunction(refTopElement,
|
CFArrayApplyFunction(valueRef,
|
||||||
range,
|
range,
|
||||||
getElementsCFArrayHandler,
|
getElementsCFArrayHandler,
|
||||||
(void*) joystick);
|
(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 //////
|
////// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
_GLFWjoy joystick = _glfw.ns.joysticks[joy];
|
|
||||||
|
|
||||||
if (!joystick.present)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
numaxes = numaxes < joystick.numAxes ? numaxes : joystick.numAxes;
|
|
||||||
|
|
||||||
// Update joystick state
|
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
for (i = 0; i < numaxes; i++)
|
return _glfw.ns.joysticks[joy].present;
|
||||||
{
|
|
||||||
_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 (i & 1)
|
|
||||||
axes[i] = -axes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return numaxes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons,
|
float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
int numbuttons)
|
|
||||||
{
|
{
|
||||||
int i, j, button;
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy;
|
||||||
|
|
||||||
if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
_GLFWjoy joystick = _glfw.ns.joysticks[joy];
|
|
||||||
|
|
||||||
if (!joystick.present)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Update joystick state
|
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
for (button = 0; button < numbuttons && button < joystick.numButtons; button++)
|
if (!joystick->present)
|
||||||
{
|
return NULL;
|
||||||
_GLFWjoyelement* element = (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick.buttons, button);
|
|
||||||
buttons[button] = element->value ? GLFW_PRESS : GLFW_RELEASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Virtual buttons - Inject data from hats
|
*count = (int) CFArrayGetCount(joystick->axisElements);
|
||||||
// Each hat is exposed as 4 buttons which exposes 8 directions with concurrent button presses
|
return joystick->axes;
|
||||||
|
}
|
||||||
|
|
||||||
// Bit fields of button presses for each direction, including nil
|
unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
{
|
||||||
|
_GLFWjoy* joystick = _glfw.ns.joysticks + joy;
|
||||||
|
|
||||||
for (i = 0; i < joystick.numHats; i++)
|
pollJoystickEvents();
|
||||||
{
|
|
||||||
_GLFWjoyelement* hat = (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick.hats, i);
|
|
||||||
|
|
||||||
int value = hat->value;
|
if (!joystick->present)
|
||||||
if (value < 0 || value > 8)
|
return NULL;
|
||||||
value = 8;
|
|
||||||
|
|
||||||
for (j = 0; j < 4 && button < numbuttons; j++)
|
*count = (int) CFArrayGetCount(joystick->buttonElements) +
|
||||||
{
|
(int) CFArrayGetCount(joystick->hatElements) * 4;
|
||||||
if (directions[value] & (1 << j))
|
return joystick->buttons;
|
||||||
buttons[button] = GLFW_PRESS;
|
|
||||||
else
|
|
||||||
buttons[button] = GLFW_RELEASE;
|
|
||||||
|
|
||||||
button++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int joy)
|
const char* _glfwPlatformGetJoystickName(int joy)
|
||||||
{
|
{
|
||||||
|
pollJoystickEvents();
|
||||||
|
|
||||||
return _glfw.ns.joysticks[joy].name;
|
return _glfw.ns.joysticks[joy].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,18 +78,17 @@ typedef struct _GLFWwindowNS
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int present;
|
int present;
|
||||||
char name[256];
|
char name[256];
|
||||||
|
|
||||||
IOHIDDeviceInterface** interface;
|
IOHIDDeviceInterface** interface;
|
||||||
|
|
||||||
int numAxes;
|
CFMutableArrayRef axisElements;
|
||||||
int numButtons;
|
CFMutableArrayRef buttonElements;
|
||||||
int numHats;
|
CFMutableArrayRef hatElements;
|
||||||
|
|
||||||
CFMutableArrayRef axes;
|
float* axes;
|
||||||
CFMutableArrayRef buttons;
|
unsigned char* buttons;
|
||||||
CFMutableArrayRef hats;
|
|
||||||
|
|
||||||
} _GLFWjoy;
|
} _GLFWjoy;
|
||||||
|
|
||||||
|
|
|
@ -407,20 +407,20 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string);
|
||||||
*/
|
*/
|
||||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickParam
|
/*! @copydoc glfwJoystickPresent
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
int _glfwPlatformGetJoystickParam(int joy, int param);
|
int _glfwPlatformJoystickPresent(int joy);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickAxes
|
/*! @copydoc glfwGetJoystickAxes
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes);
|
float* _glfwPlatformGetJoystickAxes(int joy, int* count);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickButtons
|
/*! @copydoc glfwGetJoystickButtons
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
*/
|
*/
|
||||||
int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons);
|
unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
|
||||||
|
|
||||||
/*! @copydoc glfwGetJoystickName
|
/*! @copydoc glfwGetJoystickName
|
||||||
* @ingroup platform
|
* @ingroup platform
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWAPI int glfwGetJoystickParam(int joy, int param)
|
GLFWAPI int glfwJoystickPresent(int joy)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
|
|
||||||
|
@ -45,59 +45,37 @@ GLFWAPI int glfwGetJoystickParam(int joy, int param)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickParam(joy, param);
|
return _glfwPlatformJoystickPresent(joy);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetJoystickAxes(int joy, float* axes, int numaxes)
|
GLFWAPI float* glfwGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
int i;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (axes == NULL || numaxes < 0)
|
return _glfwPlatformGetJoystickAxes(joy, count);
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear positions
|
|
||||||
for (i = 0; i < numaxes; i++)
|
|
||||||
axes[i] = 0.0f;
|
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickAxes(joy, axes, numaxes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetJoystickButtons(int joy,
|
GLFWAPI unsigned char* glfwGetJoystickButtons(int joy, int* count)
|
||||||
unsigned char* buttons,
|
|
||||||
int numbuttons)
|
|
||||||
{
|
{
|
||||||
int i;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buttons == NULL || numbuttons < 0)
|
return _glfwPlatformGetJoystickButtons(joy, count);
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear button states
|
|
||||||
for (i = 0; i < numbuttons; i++)
|
|
||||||
buttons[i] = GLFW_RELEASE;
|
|
||||||
|
|
||||||
return _glfwPlatformGetJoystickButtons(joy, buttons, numbuttons);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetJoystickName(int joy)
|
GLFWAPI const char* glfwGetJoystickName(int joy)
|
||||||
|
|
|
@ -37,23 +37,6 @@
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Return GL_TRUE if joystick is present, otherwise GL_FALSE
|
|
||||||
//
|
|
||||||
static GLboolean isJoystickPresent(int joy)
|
|
||||||
{
|
|
||||||
JOYINFO ji;
|
|
||||||
|
|
||||||
// Is it a valid stick ID (Windows don't support more than 16 sticks)?
|
|
||||||
if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_16)
|
|
||||||
return GL_FALSE;
|
|
||||||
|
|
||||||
// Is the joystick present?
|
|
||||||
if (_glfw_joyGetPos(joy - GLFW_JOYSTICK_1, &ji) != JOYERR_NOERROR)
|
|
||||||
return GL_FALSE;
|
|
||||||
|
|
||||||
return GL_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate normalized joystick position
|
// Calculate normalized joystick position
|
||||||
//
|
//
|
||||||
static float calcJoystickPos(DWORD pos, DWORD min, DWORD max)
|
static float calcJoystickPos(DWORD pos, DWORD min, DWORD max)
|
||||||
|
@ -91,107 +74,68 @@ void _glfwTerminateJoysticks(void)
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickParam(int joy, int param)
|
int _glfwPlatformJoystickPresent(int joy)
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
JOYINFO ji;
|
||||||
int hats;
|
|
||||||
|
|
||||||
if (!isJoystickPresent(joy))
|
if (_glfw_joyGetPos(joy, &ji) != JOYERR_NOERROR)
|
||||||
return 0;
|
return GL_FALSE;
|
||||||
|
|
||||||
// We got this far, the joystick is present
|
return GL_TRUE;
|
||||||
if (param == GLFW_PRESENT)
|
|
||||||
return GL_TRUE;
|
|
||||||
|
|
||||||
// Get joystick capabilities
|
|
||||||
_glfw_joyGetDevCaps(joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS));
|
|
||||||
|
|
||||||
hats = (jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR) ? 1 : 0;
|
|
||||||
|
|
||||||
switch (param)
|
|
||||||
{
|
|
||||||
case GLFW_AXES:
|
|
||||||
// Return number of joystick axes
|
|
||||||
return jc.wNumAxes;
|
|
||||||
|
|
||||||
case GLFW_BUTTONS:
|
|
||||||
// Return number of joystick buttons
|
|
||||||
return jc.wNumButtons + hats * 4;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes)
|
float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
JOYCAPS jc;
|
||||||
JOYINFOEX ji;
|
JOYINFOEX ji;
|
||||||
int axis;
|
float* axes = _glfw.win32.joystick[joy].axes;
|
||||||
|
|
||||||
if (!isJoystickPresent(joy))
|
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
// Get joystick capabilities
|
|
||||||
_glfw_joyGetDevCaps(joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS));
|
|
||||||
|
|
||||||
// Get joystick state
|
|
||||||
ji.dwSize = sizeof(JOYINFOEX);
|
ji.dwSize = sizeof(JOYINFOEX);
|
||||||
ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |
|
ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |
|
||||||
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;
|
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;
|
||||||
_glfw_joyGetPosEx(joy - GLFW_JOYSTICK_1, &ji);
|
if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Get position values for all axes
|
axes[(*count)++] = calcJoystickPos(ji.dwXpos, jc.wXmin, jc.wXmax);
|
||||||
axis = 0;
|
axes[(*count)++] = -calcJoystickPos(ji.dwYpos, jc.wYmin, jc.wYmax);
|
||||||
if (axis < numaxes)
|
|
||||||
axes[axis++] = calcJoystickPos(ji.dwXpos, jc.wXmin, jc.wXmax);
|
|
||||||
|
|
||||||
if (axis < numaxes)
|
if (jc.wCaps & JOYCAPS_HASZ)
|
||||||
axes[axis++] = -calcJoystickPos(ji.dwYpos, jc.wYmin, jc.wYmax);
|
axes[(*count)++] = calcJoystickPos(ji.dwZpos, jc.wZmin, jc.wZmax);
|
||||||
|
|
||||||
if (axis < numaxes && jc.wCaps & JOYCAPS_HASZ)
|
if (jc.wCaps & JOYCAPS_HASR)
|
||||||
axes[axis++] = calcJoystickPos(ji.dwZpos, jc.wZmin, jc.wZmax);
|
axes[(*count)++] = calcJoystickPos(ji.dwRpos, jc.wRmin, jc.wRmax);
|
||||||
|
|
||||||
if (axis < numaxes && jc.wCaps & JOYCAPS_HASR)
|
if (jc.wCaps & JOYCAPS_HASU)
|
||||||
axes[axis++] = calcJoystickPos(ji.dwRpos, jc.wRmin, jc.wRmax);
|
axes[(*count)++] = calcJoystickPos(ji.dwUpos, jc.wUmin, jc.wUmax);
|
||||||
|
|
||||||
if (axis < numaxes && jc.wCaps & JOYCAPS_HASU)
|
if (jc.wCaps & JOYCAPS_HASV)
|
||||||
axes[axis++] = calcJoystickPos(ji.dwUpos, jc.wUmin, jc.wUmax);
|
axes[(*count)++] = -calcJoystickPos(ji.dwVpos, jc.wVmin, jc.wVmax);
|
||||||
|
|
||||||
if (axis < numaxes && jc.wCaps & JOYCAPS_HASV)
|
return axes;
|
||||||
axes[axis++] = -calcJoystickPos(ji.dwVpos, jc.wVmin, jc.wVmax);
|
|
||||||
|
|
||||||
return axis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons,
|
unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
int numbuttons)
|
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
JOYCAPS jc;
|
||||||
JOYINFOEX ji;
|
JOYINFOEX ji;
|
||||||
int button, hats;
|
unsigned char* buttons = _glfw.win32.joystick[joy].buttons;
|
||||||
|
|
||||||
// Bit fields of button presses for each direction, including nil
|
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
return NULL;
|
||||||
|
|
||||||
if (!isJoystickPresent(joy))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Get joystick capabilities
|
|
||||||
_glfw_joyGetDevCaps(joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS));
|
|
||||||
|
|
||||||
// Get joystick state
|
|
||||||
ji.dwSize = sizeof(JOYINFOEX);
|
ji.dwSize = sizeof(JOYINFOEX);
|
||||||
ji.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;
|
ji.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;
|
||||||
_glfw_joyGetPosEx(joy - GLFW_JOYSTICK_1, &ji);
|
if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// Get states of all requested buttons
|
while (*count < jc.wNumButtons)
|
||||||
for (button = 0; button < numbuttons && button < (int) jc.wNumButtons; button++)
|
|
||||||
{
|
{
|
||||||
buttons[button] = (unsigned char)
|
buttons[*count] = (unsigned char)
|
||||||
(ji.dwButtons & (1UL << button) ? GLFW_PRESS : GLFW_RELEASE);
|
(ji.dwButtons & (1UL << *count) ? GLFW_PRESS : GLFW_RELEASE);
|
||||||
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Virtual buttons - Inject data from hats
|
// Virtual buttons - Inject data from hats
|
||||||
|
@ -199,42 +143,38 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons,
|
||||||
// concurrent button presses
|
// concurrent button presses
|
||||||
// NOTE: this API exposes only one hat
|
// NOTE: this API exposes only one hat
|
||||||
|
|
||||||
hats = (jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR) ? 1 : 0;
|
if ((jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR))
|
||||||
|
|
||||||
if (hats > 0)
|
|
||||||
{
|
{
|
||||||
int j, value = ji.dwPOV / 100 / 45;
|
int i, value = ji.dwPOV / 100 / 45;
|
||||||
|
|
||||||
|
// Bit fields of button presses for each direction, including nil
|
||||||
|
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||||
|
|
||||||
if (value < 0 || value > 8)
|
if (value < 0 || value > 8)
|
||||||
value = 8;
|
value = 8;
|
||||||
|
|
||||||
for (j = 0; j < 4 && button < numbuttons; j++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (directions[value] & (1 << j))
|
if (directions[value] & (1 << i))
|
||||||
buttons[button] = GLFW_PRESS;
|
buttons[(*count)++] = GLFW_PRESS;
|
||||||
else
|
else
|
||||||
buttons[button] = GLFW_RELEASE;
|
buttons[(*count)++] = GLFW_RELEASE;
|
||||||
|
|
||||||
button++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return button;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int joy)
|
const char* _glfwPlatformGetJoystickName(int joy)
|
||||||
{
|
{
|
||||||
JOYCAPS jc;
|
JOYCAPS jc;
|
||||||
const int i = joy - GLFW_JOYSTICK_1;
|
|
||||||
|
|
||||||
if (!isJoystickPresent(joy))
|
if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
_glfw_joyGetDevCaps(i, &jc, sizeof(JOYCAPS));
|
free(_glfw.win32.joystick[joy].name);
|
||||||
|
_glfw.win32.joystick[joy].name = _glfwCreateUTF8FromWideString(jc.szPname);
|
||||||
|
|
||||||
free(_glfw.win32.joystick[i].name);
|
return _glfw.win32.joystick[joy].name;
|
||||||
_glfw.win32.joystick[i].name = _glfwCreateUTF8FromWideString(jc.szPname);
|
|
||||||
|
|
||||||
return _glfw.win32.joystick[i].name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,8 @@ typedef struct _GLFWlibraryWin32
|
||||||
} dwmapi;
|
} dwmapi;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
float axes[6];
|
||||||
|
unsigned char buttons[36]; // 32 buttons plus one hat
|
||||||
char* name;
|
char* name;
|
||||||
} joystick[GLFW_JOYSTICK_LAST + 1];
|
} joystick[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
static int openJoystickDevice(int joy, const char* path)
|
static int openJoystickDevice(int joy, const char* path)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
char numAxes, numButtons;
|
char axisCount, buttonCount;
|
||||||
char name[256];
|
char name[256];
|
||||||
int fd, version;
|
int fd, version;
|
||||||
|
|
||||||
|
@ -74,14 +74,14 @@ static int openJoystickDevice(int joy, const char* path)
|
||||||
|
|
||||||
_glfw.x11.joystick[joy].name = strdup(name);
|
_glfw.x11.joystick[joy].name = strdup(name);
|
||||||
|
|
||||||
ioctl(fd, JSIOCGAXES, &numAxes);
|
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||||
_glfw.x11.joystick[joy].numAxes = (int) numAxes;
|
_glfw.x11.joystick[joy].axisCount = (int) axisCount;
|
||||||
|
|
||||||
ioctl(fd, JSIOCGBUTTONS, &numButtons);
|
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||||
_glfw.x11.joystick[joy].numButtons = (int) numButtons;
|
_glfw.x11.joystick[joy].buttonCount = (int) buttonCount;
|
||||||
|
|
||||||
_glfw.x11.joystick[joy].axis = (float*) calloc(numAxes, sizeof(float));
|
_glfw.x11.joystick[joy].axes = (float*) calloc(axisCount, sizeof(float));
|
||||||
_glfw.x11.joystick[joy].button = (unsigned char*) calloc(numButtons, 1);
|
_glfw.x11.joystick[joy].buttons = (unsigned char*) calloc(buttonCount, 1);
|
||||||
|
|
||||||
_glfw.x11.joystick[joy].present = GL_TRUE;
|
_glfw.x11.joystick[joy].present = GL_TRUE;
|
||||||
#endif // __linux__
|
#endif // __linux__
|
||||||
|
@ -110,7 +110,12 @@ static void pollJoystickEvents(void)
|
||||||
result = read(_glfw.x11.joystick[i].fd, &e, sizeof(e));
|
result = read(_glfw.x11.joystick[i].fd, &e, sizeof(e));
|
||||||
|
|
||||||
if (errno == ENODEV)
|
if (errno == ENODEV)
|
||||||
|
{
|
||||||
|
free(_glfw.x11.joystick[i].axes);
|
||||||
|
free(_glfw.x11.joystick[i].buttons);
|
||||||
|
free(_glfw.x11.joystick[i].name);
|
||||||
_glfw.x11.joystick[i].present = GL_FALSE;
|
_glfw.x11.joystick[i].present = GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -121,21 +126,21 @@ static void pollJoystickEvents(void)
|
||||||
switch (e.type)
|
switch (e.type)
|
||||||
{
|
{
|
||||||
case JS_EVENT_AXIS:
|
case JS_EVENT_AXIS:
|
||||||
_glfw.x11.joystick[i].axis[e.number] =
|
_glfw.x11.joystick[i].axes[e.number] =
|
||||||
(float) e.value / 32767.0f;
|
(float) e.value / 32767.0f;
|
||||||
|
|
||||||
// We need to change the sign for the Y axes, so that
|
// We need to change the sign for the Y axes, so that
|
||||||
// positive = up/forward, according to the GLFW spec.
|
// positive = up/forward, according to the GLFW spec.
|
||||||
if (e.number & 1)
|
if (e.number & 1)
|
||||||
{
|
{
|
||||||
_glfw.x11.joystick[i].axis[e.number] =
|
_glfw.x11.joystick[i].axes[e.number] =
|
||||||
-_glfw.x11.joystick[i].axis[e.number];
|
-_glfw.x11.joystick[i].axes[e.number];
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JS_EVENT_BUTTON:
|
case JS_EVENT_BUTTON:
|
||||||
_glfw.x11.joystick[i].button[e.number] =
|
_glfw.x11.joystick[i].buttons[e.number] =
|
||||||
e.value ? GLFW_PRESS : GLFW_RELEASE;
|
e.value ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -214,8 +219,8 @@ void _glfwTerminateJoysticks(void)
|
||||||
if (_glfw.x11.joystick[i].present)
|
if (_glfw.x11.joystick[i].present)
|
||||||
{
|
{
|
||||||
close(_glfw.x11.joystick[i].fd);
|
close(_glfw.x11.joystick[i].fd);
|
||||||
free(_glfw.x11.joystick[i].axis);
|
free(_glfw.x11.joystick[i].axes);
|
||||||
free(_glfw.x11.joystick[i].button);
|
free(_glfw.x11.joystick[i].buttons);
|
||||||
free(_glfw.x11.joystick[i].name);
|
free(_glfw.x11.joystick[i].name);
|
||||||
|
|
||||||
_glfw.x11.joystick[i].present = GL_FALSE;
|
_glfw.x11.joystick[i].present = GL_FALSE;
|
||||||
|
@ -229,72 +234,38 @@ void _glfwTerminateJoysticks(void)
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickParam(int joy, int param)
|
int _glfwPlatformJoystickPresent(int joy)
|
||||||
{
|
{
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
if (!_glfw.x11.joystick[joy].present)
|
return _glfw.x11.joystick[joy].present;
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (param)
|
|
||||||
{
|
|
||||||
case GLFW_PRESENT:
|
|
||||||
return GL_TRUE;
|
|
||||||
|
|
||||||
case GLFW_AXES:
|
|
||||||
return _glfw.x11.joystick[joy].numAxes;
|
|
||||||
|
|
||||||
case GLFW_BUTTONS:
|
|
||||||
return _glfw.x11.joystick[joy].numButtons;
|
|
||||||
|
|
||||||
default:
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numAxes)
|
float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
if (!_glfw.x11.joystick[joy].present)
|
if (!_glfw.x11.joystick[joy].present)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
if (_glfw.x11.joystick[joy].numAxes < numAxes)
|
*count = _glfw.x11.joystick[joy].axisCount;
|
||||||
numAxes = _glfw.x11.joystick[joy].numAxes;
|
return _glfw.x11.joystick[joy].axes;
|
||||||
|
|
||||||
for (i = 0; i < numAxes; i++)
|
|
||||||
axes[i] = _glfw.x11.joystick[joy].axis[i];
|
|
||||||
|
|
||||||
return numAxes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons,
|
unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
int numButtons)
|
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
pollJoystickEvents();
|
pollJoystickEvents();
|
||||||
|
|
||||||
if (!_glfw.x11.joystick[joy].present)
|
if (!_glfw.x11.joystick[joy].present)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
if (_glfw.x11.joystick[joy].numButtons < numButtons)
|
*count = _glfw.x11.joystick[joy].buttonCount;
|
||||||
numButtons = _glfw.x11.joystick[joy].numButtons;
|
return _glfw.x11.joystick[joy].buttons;
|
||||||
|
|
||||||
for (i = 0; i < numButtons; i++)
|
|
||||||
buttons[i] = _glfw.x11.joystick[joy].button[i];
|
|
||||||
|
|
||||||
return numButtons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetJoystickName(int joy)
|
const char* _glfwPlatformGetJoystickName(int joy)
|
||||||
{
|
{
|
||||||
if (!_glfw.x11.joystick[joy].present)
|
pollJoystickEvents();
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return _glfw.x11.joystick[joy].name;
|
return _glfw.x11.joystick[joy].name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,10 +189,10 @@ typedef struct _GLFWlibraryX11
|
||||||
struct {
|
struct {
|
||||||
int present;
|
int present;
|
||||||
int fd;
|
int fd;
|
||||||
int numAxes;
|
float* axes;
|
||||||
int numButtons;
|
int axisCount;
|
||||||
float* axis;
|
unsigned char* buttons;
|
||||||
unsigned char* button;
|
int buttonCount;
|
||||||
char* name;
|
char* name;
|
||||||
} joystick[GLFW_JOYSTICK_LAST + 1];
|
} joystick[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
|
||||||
|
|
|
@ -136,30 +136,32 @@ static void refresh_joysticks(void)
|
||||||
{
|
{
|
||||||
Joystick* j = joysticks + i;
|
Joystick* j = joysticks + i;
|
||||||
|
|
||||||
if (glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_PRESENT))
|
if (glfwJoystickPresent(GLFW_JOYSTICK_1 + i))
|
||||||
{
|
{
|
||||||
|
float* axes;
|
||||||
|
unsigned char* buttons;
|
||||||
int axis_count, button_count;
|
int axis_count, button_count;
|
||||||
|
|
||||||
free(j->name);
|
free(j->name);
|
||||||
j->name = strdup(glfwGetJoystickName(GLFW_JOYSTICK_1 + i));
|
j->name = strdup(glfwGetJoystickName(GLFW_JOYSTICK_1 + i));
|
||||||
|
|
||||||
axis_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_AXES);
|
axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &axis_count);
|
||||||
if (axis_count != j->axis_count)
|
if (axis_count != j->axis_count)
|
||||||
{
|
{
|
||||||
j->axis_count = axis_count;
|
j->axis_count = axis_count;
|
||||||
j->axes = realloc(j->axes, j->axis_count * sizeof(float));
|
j->axes = realloc(j->axes, j->axis_count * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, j->axes, j->axis_count);
|
memcpy(j->axes, axes, axis_count * sizeof(float));
|
||||||
|
|
||||||
button_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_BUTTONS);
|
buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &button_count);
|
||||||
if (button_count != j->button_count)
|
if (button_count != j->button_count)
|
||||||
{
|
{
|
||||||
j->button_count = button_count;
|
j->button_count = button_count;
|
||||||
j->buttons = realloc(j->buttons, j->button_count);
|
j->buttons = realloc(j->buttons, j->button_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, j->buttons, j->button_count);
|
memcpy(j->buttons, buttons, button_count * sizeof(unsigned char));
|
||||||
|
|
||||||
if (!j->present)
|
if (!j->present)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user