This commit is contained in:
IntellectualKitty 2016-10-14 09:05:54 +00:00 committed by GitHub
commit cf2dab9b27
5 changed files with 212 additions and 49 deletions

View File

@ -1140,6 +1140,42 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
*/
typedef void (* GLFWjoystickfun)(int,int);
/*! @brief The function signature for joystick button callbacks.
*
* This is the function signature for joystick button callback
* functions.
*
* @param[in] joy The joystick that had a button pressed or released.
* @param[in] button The button that was pressed or released.
* @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.
*
* @sa @ref joystick_event
* @sa glfwSetJoystickButtonCallback
*
* @since Added in version 3.2.
*
* @ingroup input
*/
typedef void (* GLFWjoystickbuttonfun)(int,int,int);
/*! @brief The function signature for joystick axis callbacks.
*
* This is the function signature for joystick axis callback
* functions.
*
* @param[in] joy The joystick that had an axis moved.
* @param[in] axis The axis that was moved.
* @param[in] value The axis value.
*
* @sa @ref joystick_event
* @sa glfwSetJoystickAxisCallback
*
* @since Added in version 3.2.
*
* @ingroup input
*/
typedef void (* GLFWjoystickaxisfun)(int,int,float);
/*! @brief Video mode type.
*
* This describes a single video mode.
@ -3724,6 +3760,50 @@ GLFWAPI const char* glfwGetJoystickName(int joy);
*/
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
/*! @brief Sets the joystick button callback.
*
* This function sets the joystick button callback, or removes the currently
* set callback. This is called when a joystick button is pressed or released.
*
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref joystick_event
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI GLFWjoystickbuttonfun glfwSetJoystickButtonCallback(GLFWjoystickbuttonfun cbfun);
/*! @brief Sets the joystick axis callback.
*
* This function sets the joystick axis callback, or removes the currently
* set callback. This is called when a joystick axis is moved.
*
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref joystick_event
*
* @since Added in version 3.2.
*
* @ingroup input
*/
GLFWAPI GLFWjoystickaxisfun glfwSetJoystickAxisCallback(GLFWjoystickaxisfun cbfun);
/*! @brief Sets the clipboard to the specified string.
*
* This function sets the system clipboard to the specified, UTF-8 encoded

View File

@ -37,7 +37,6 @@
#include <CoreFoundation/CoreFoundation.h>
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
// Joystick element information
//
typedef struct _GLFWjoyelementNS
@ -193,75 +192,96 @@ static void removeJoystick(_GLFWjoystickNS* js)
_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;
int buttonIndex = 0;
if (kIOReturnSuccess != valueResult)
return;
js = (_GLFWjoystickNS*)context;
if (!js)
return;
if (!js->present)
return GLFW_FALSE;
return;
IOHIDElementRef elementRef = IOHIDValueGetElement(valueRef);
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
{
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->axisElements, i);
long value = getElementValue(js, axis);
long readScale = axis->maxReport - axis->minReport;
if (elementRef == axis->elementRef)
{
long value = getElementValue(js, axis);
long readScale = axis->maxReport - axis->minReport;
if (readScale == 0)
js->axes[i] = value;
else
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
if (readScale == 0)
js->axes[i] = value;
else
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
_glfwInputJoystickAxisMoved(js-_glfw.ns_js,i,js->axes[i]);
return;
}
}
return GLFW_TRUE;
}
// 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++)
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++, buttonIndex++)
{
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
CFArrayGetValueAtIndex(js->buttonElements, i);
if (getElementValue(js, button))
js->buttons[buttonIndex++] = GLFW_PRESS;
else
js->buttons[buttonIndex++] = GLFW_RELEASE;
if (elementRef == button->elementRef)
{
if (getElementValue(js, button))
js->buttons[buttonIndex] = GLFW_PRESS;
else
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*)
CFArrayGetValueAtIndex(js->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(js, hat);
if (value < 0 || value > 8)
value = 8;
for (j = 0; j < 4; j++)
if (elementRef == hat->elementRef)
{
if (directions[value] & (1 << j))
js->buttons[buttonIndex++] = GLFW_PRESS;
else
js->buttons[buttonIndex++] = GLFW_RELEASE;
}
}
// Bit fields of button presses for each direction, including nil
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
return GLFW_TRUE;
long j, value = getElementValue(js, hat);
if (value < 0 || value > 8)
value = 8;
for (j = 0; j < 4; j++)
{
const unsigned char oldValue = js->buttons[buttonIndex+j];
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
@ -324,6 +344,10 @@ static void matchCallback(void* context,
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
CFArrayGetCount(js->hatElements) * 4, 1);
IOHIDDeviceRegisterInputValueCallback(deviceRef,
inputValueCallback,
(void*)js);
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
}
@ -399,7 +423,6 @@ void _glfwInitJoysticksNS(void)
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeArrayCallBacks);
@ -482,7 +505,8 @@ int _glfwPlatformJoystickPresent(int joy)
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
{
_GLFWjoystickNS* js = _glfw.ns_js + joy;
if (!pollJoystickAxisEvents(js))
if (!js->present)
return NULL;
*count = (int) CFArrayGetCount(js->axisElements);
@ -492,7 +516,8 @@ const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
_GLFWjoystickNS* js = _glfw.ns_js + joy;
if (!pollJoystickButtonEvents(js))
if (!js->present)
return NULL;
*count = (int) CFArrayGetCount(js->buttonElements) +

View File

@ -130,6 +130,18 @@ void _glfwInputJoystickChange(int joy, int event)
_glfw.callbacks.joystick(joy, event);
}
void _glfwInputJoystickButtonState(int joy, int button, int action)
{
if (_glfw.callbacks.joystick_button)
_glfw.callbacks.joystick_button(joy, button, action);
}
void _glfwInputJoystickAxisMoved(int joy, int axis, float value)
{
if (_glfw.callbacks.joystick_axis)
_glfw.callbacks.joystick_axis(joy, axis, value);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@ -618,6 +630,20 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
return cbfun;
}
GLFWAPI GLFWjoystickbuttonfun glfwSetJoystickButtonCallback(GLFWjoystickbuttonfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick_button, cbfun);
return cbfun;
}
GLFWAPI GLFWjoystickaxisfun glfwSetJoystickAxisCallback(GLFWjoystickaxisfun cbfun)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(_glfw.callbacks.joystick_axis, cbfun);
return cbfun;
}
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
{
_GLFWwindow* window = (_GLFWwindow*) handle;

View File

@ -469,8 +469,10 @@ struct _GLFWlibrary
} vk;
struct {
GLFWmonitorfun monitor;
GLFWjoystickfun joystick;
GLFWmonitorfun monitor;
GLFWjoystickfun joystick;
GLFWjoystickbuttonfun joystick_button;
GLFWjoystickaxisfun joystick_axis;
} callbacks;
// This is defined in the window API's platform.h
@ -967,6 +969,22 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
*/
void _glfwInputJoystickChange(int joy, int event);
/*! @brief Notifies shared code of a joystick button pressed/release action.
* @param[in] joy The joystick that had a button pressed or released.
* @param[in] button The button that was pressed or released.
* @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.
* @ingroup event
*/
void _glfwInputJoystickButtonState(int joy, int button, int action);
/*! @brief Notifies shared code of joystick axis motion.
* @param[in] joy The joystick that had an axis moved.
* @param[in] axis The axis that was moved.
* @param[in] value The current position of the axis.
* @ingroup event
*/
void _glfwInputJoystickAxisMoved(int joy, int axis, float value);
//========================================================================
// Utility functions

View File

@ -482,6 +482,18 @@ static void joystick_callback(int joy, int event)
}
}
static void joystick_button_callback(int joy, int button, int action)
{
printf("%08x at %0.3f: Joystick %i button %i was %s\n",
counter++, glfwGetTime(), joy, button, get_action_name(action));
}
static void joystick_axis_callback(int joy, int axis, float value)
{
printf("%08x at %0.3f: Joystick %i axis %i was moved to %f\n",
counter++, glfwGetTime(), joy, axis, value);
}
int main(int argc, char** argv)
{
Slot* slots;
@ -499,6 +511,8 @@ int main(int argc, char** argv)
glfwSetMonitorCallback(monitor_callback);
glfwSetJoystickCallback(joystick_callback);
glfwSetJoystickButtonCallback(joystick_button_callback);
glfwSetJoystickAxisCallback(joystick_axis_callback);
while ((ch = getopt(argc, argv, "hfn:")) != -1)
{