mirror of
https://github.com/glfw/glfw.git
synced 2024-11-11 04:53:50 +00:00
Implement glfwGetJoystickHats
This moves the buttons-as-hats logic to shared code and adds the GLFW_JOYSTICK_HAT_BUTTONS input mode as a way to disable this legacy behavior. Fixes #889.
This commit is contained in:
parent
368dec7ac7
commit
798d7c6d68
@ -127,11 +127,14 @@ information on what to include when reporting a bug.
|
||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||
receiving window maximization events (#778)
|
||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
||||
- Added `glfwGetJoystickHats` function for querying joystick hats
|
||||
(#889,#906,#934)
|
||||
- Added `glfwInitHint` function for setting library initialization hints
|
||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||
- Added definition of `GLAPIENTRY` to public header
|
||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||
(#749,#842)
|
||||
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
||||
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
|
||||
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
|
||||
|
@ -204,7 +204,8 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
||||
"x11=__X11:__" \
|
||||
"wayland=__Wayland:__" \
|
||||
"win32=__Windows:__" \
|
||||
"macos=__macOS:__"
|
||||
"macos=__macOS:__" \
|
||||
"linux=__Linux:__"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding
|
||||
|
@ -510,21 +510,24 @@ A simple mouse wheel, being vertical, provides offsets along the Y-axis.
|
||||
|
||||
The joystick functions expose connected joysticks and controllers, with both
|
||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to `GLFW_JOYSTICK_LAST`. You can test
|
||||
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||
present with @ref glfwJoystickPresent.
|
||||
|
||||
@code
|
||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||
@endcode
|
||||
|
||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
||||
the array, starting with `GLFW_JOYSTICK_1`. Once a joystick is detected, it
|
||||
keeps its assigned index until it is disconnected, so as joysticks are connected
|
||||
and disconnected, they will become spread out.
|
||||
the array. Once a joystick is detected, it keeps its assigned ID until it is
|
||||
disconnected or the library is terminated, so as joysticks are connected and
|
||||
disconnected, there may appear gaps in the IDs.
|
||||
|
||||
Joystick state is updated as needed when a joystick function is called and does
|
||||
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
|
||||
to be called.
|
||||
Joystick axis, button and hat state is updated when polled and does not require
|
||||
a window to be created or events to be processed. However, if you want joystick
|
||||
connection and disconnection events reliably delivered to the
|
||||
[joystick callback](@ref joystick_event) then you must
|
||||
[process events](@ref events).
|
||||
|
||||
To see all the properties of all connected joysticks in real-time, run the
|
||||
`joysticks` test program.
|
||||
@ -538,7 +541,7 @@ returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is a value between -1.0 and 1.0.
|
||||
@ -552,11 +555,55 @@ returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
|
||||
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
For backward compatibility with earlier versions that did not have @ref
|
||||
glfwGetJoystickHats, the button array by default also includes all hats. See
|
||||
the reference documentation for @ref glfwGetJoystickButtons for details.
|
||||
|
||||
|
||||
@subsection joystick_hat Joystick hat states
|
||||
|
||||
The states of all hats are returned by @ref glfwGetJoystickHats. See the
|
||||
reference documentation for the lifetime of the returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is one of the following:
|
||||
|
||||
Name | Value
|
||||
--------------------- | --------------------------------
|
||||
`GLFW_HAT_CENTERED` | 0
|
||||
`GLFW_HAT_UP` | 1
|
||||
`GLFW_HAT_RIGHT` | 2
|
||||
`GLFW_HAT_DOWN` | 4
|
||||
`GLFW_HAT_LEFT` | 8
|
||||
`GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
|
||||
`GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
|
||||
`GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
|
||||
`GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
|
||||
|
||||
The diagonal directions are bitwise combinations of the primary (up, right, down
|
||||
and left) directions and you can test for these individually by ANDing it with
|
||||
the corresponding direction.
|
||||
|
||||
@code
|
||||
if (hats[2] & GLFW_HAT_RIGHT)
|
||||
{
|
||||
// State of hat 2 could be right-up, right or right-down
|
||||
}
|
||||
@endcode
|
||||
|
||||
For backward compatibility with earlier versions that did not have @ref
|
||||
glfwGetJoystickHats, all hats are by default also included in the button array.
|
||||
See the reference documentation for @ref glfwGetJoystickButtons for details.
|
||||
|
||||
|
||||
@subsection joystick_name Joystick name
|
||||
|
||||
@ -565,7 +612,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
|
||||
returned string.
|
||||
|
||||
@code
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||
@endcode
|
||||
|
||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
||||
|
@ -77,6 +77,11 @@ platform but they will only affect their specific platform. Other platforms
|
||||
will simply ignore them. Setting these hints requires no platform specific
|
||||
headers or calls.
|
||||
|
||||
@anchor GLFW_JOYSTICK_HAT_BUTTONS
|
||||
__GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as
|
||||
buttons, for compatibility with earlier versions of GLFW that did not have @ref
|
||||
glfwGetJoystickHats.
|
||||
|
||||
|
||||
@subsubsection init_hints_osx macOS specific hints
|
||||
|
||||
@ -95,6 +100,7 @@ initialized.
|
||||
|
||||
Init hint | Default value | Supported values
|
||||
------------------------------- | ------------- | ----------------
|
||||
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
|
||||
|
@ -25,6 +25,13 @@ GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
||||
windows with @ref glfwSetWindowAttrib.
|
||||
|
||||
|
||||
@subsection news_33_joyhats Support for joystick hats
|
||||
|
||||
GLFW now supports querying the hats of a joystick with @ref glfwGetJoystickHats
|
||||
and controlling whether hats are also exposed as buttons with the @ref
|
||||
GLFW_JOYSTICK_HAT_BUTTONS init hint.
|
||||
|
||||
|
||||
@subsection news_33_inithint Support for initialization hints
|
||||
|
||||
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
||||
|
@ -297,7 +297,7 @@ extern "C" {
|
||||
#define GLFW_REPEAT 2
|
||||
/*! @} */
|
||||
|
||||
/*! @defgroup hat_directions Joystick hat directions
|
||||
/*! @defgroup hat_state Joystick hat states
|
||||
*
|
||||
* See [joystick hat input](@ref joystick_hat) for how these are used.
|
||||
*
|
||||
@ -945,6 +945,8 @@ extern "C" {
|
||||
|
||||
/*! @addtogroup init
|
||||
* @{ */
|
||||
#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
|
||||
|
||||
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
|
||||
#define GLFW_COCOA_MENUBAR 0x00051002
|
||||
/*! @} */
|
||||
@ -4020,7 +4022,7 @@ GLFWAPI int glfwJoystickPresent(int jid);
|
||||
* This function returns the values of all axes of the specified joystick.
|
||||
* Each element in the array is a value between -1.0 and 1.0.
|
||||
*
|
||||
* Querying a joystick slot with no device present is not an error, but will
|
||||
* Querying a joystick ID with no device present is not an error, but will
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
@ -4053,7 +4055,14 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
|
||||
* This function returns the state of all buttons of the specified joystick.
|
||||
* Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
*
|
||||
* Querying a joystick slot with no device present is not an error, but will
|
||||
* For backward compatibility with earlier versions that did not have @ref
|
||||
* glfwGetJoystickHats, the button array also includes all hats, each
|
||||
* represented as four buttons. The hats are in the same order as returned by
|
||||
* __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and
|
||||
* _left_. To disable these extra buttons, set the @ref
|
||||
* GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
|
||||
*
|
||||
* Querying a joystick ID with no device present is not an error, but will
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
@ -4085,27 +4094,32 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
|
||||
/*! @brief Returns the state of all hats of the specified joystick.
|
||||
*
|
||||
* This function returns the state of all hats of the specified joystick.
|
||||
* Each element in the array is one of the following:
|
||||
* Each element in the array is one of the following values:
|
||||
*
|
||||
* GLFW_HAT_CENTERED
|
||||
* GLFW_HAT_UP
|
||||
* GLFW_HAT_RIGHT
|
||||
* GLFW_HAT_DOWN
|
||||
* GLFW_HAT_LEFT
|
||||
* GLFW_HAT_RIGHT_UP
|
||||
* GLFW_HAT_RIGHT_DOWN
|
||||
* GLFW_HAT_LEFT_UP
|
||||
* GLFW_HAT_LEFT_DOWN
|
||||
* Name | Value
|
||||
* --------------------- | --------------------------------
|
||||
* `GLFW_HAT_CENTERED` | 0
|
||||
* `GLFW_HAT_UP` | 1
|
||||
* `GLFW_HAT_RIGHT` | 2
|
||||
* `GLFW_HAT_DOWN` | 4
|
||||
* `GLFW_HAT_LEFT` | 8
|
||||
* `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
|
||||
* `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
|
||||
* `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
|
||||
* `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
|
||||
*
|
||||
* For masking purposes, the hat state may be ANDed with the following primary
|
||||
* directions:
|
||||
* The diagonal directions are bitwise combinations of the primary (up, right,
|
||||
* down and left) directions and you can test for these individually by ANDing
|
||||
* it with the corresponding direction.
|
||||
*
|
||||
* GLFW_HAT_UP
|
||||
* GLFW_HAT_RIGHT
|
||||
* GLFW_HAT_DOWN
|
||||
* GLFW_HAT_LEFT
|
||||
* @code
|
||||
* if (hats[2] & GLFW_HAT_RIGHT)
|
||||
* {
|
||||
* // State of hat 2 could be right-up, right or right-down
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Querying a joystick slot with no device present is not an error, but will
|
||||
* Querying a joystick ID with no device present is not an error, but will
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
@ -4119,7 +4133,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @linux Linux does not currently support hats.
|
||||
* @bug @linux Joystick hats are currently unimplemented.
|
||||
*
|
||||
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
||||
* should not free it yourself. It is valid until the specified joystick is
|
||||
@ -4142,7 +4156,7 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count);
|
||||
* The returned string is allocated and freed by GLFW. You should not free it
|
||||
* yourself.
|
||||
*
|
||||
* Querying a joystick slot with no device present is not an error, but will
|
||||
* Querying a joystick ID with no device present is not an error, but will
|
||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||
* check device presence.
|
||||
*
|
||||
|
@ -204,7 +204,8 @@ static void matchCallback(void* context,
|
||||
|
||||
js = _glfwAllocJoystick(name,
|
||||
CFArrayGetCount(axes),
|
||||
CFArrayGetCount(buttons) + CFArrayGetCount(hats) * 4);
|
||||
CFArrayGetCount(buttons),
|
||||
CFArrayGetCount(hats));
|
||||
|
||||
js->ns.device = device;
|
||||
js->ns.axes = axes;
|
||||
@ -358,33 +359,38 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
}
|
||||
else if (mode == _GLFW_POLL_BUTTONS)
|
||||
{
|
||||
CFIndex i, bi = 0;
|
||||
CFIndex i;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||
const char value = getElementValue(js, button) ? 1 : 0;
|
||||
_glfwInputJoystickButton(jid, bi++, value);
|
||||
_glfwInputJoystickButton(jid, i, value);
|
||||
}
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||
{
|
||||
const int states[9] =
|
||||
{
|
||||
GLFW_HAT_UP,
|
||||
GLFW_HAT_RIGHT_UP,
|
||||
GLFW_HAT_RIGHT,
|
||||
GLFW_HAT_RIGHT_DOWN,
|
||||
GLFW_HAT_DOWN,
|
||||
GLFW_HAT_LEFT_DOWN,
|
||||
GLFW_HAT_LEFT,
|
||||
GLFW_HAT_LEFT_UP,
|
||||
GLFW_HAT_CENTERED
|
||||
};
|
||||
|
||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.hats, 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, state = getElementValue(js, hat);
|
||||
long state = getElementValue(js, hat);
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
const char value = directions[state] & (1 << j) ? 1 : 0;
|
||||
_glfwInputJoystickButton(jid, bi++, value);
|
||||
}
|
||||
_glfwInputJoystickHat(jid, i, states[state]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ _GLFWlibrary _glfw = { GLFW_FALSE };
|
||||
static GLFWerrorfun _glfwErrorCallback;
|
||||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
GLFW_TRUE, // hat buttons
|
||||
{
|
||||
GLFW_TRUE, // menubar
|
||||
GLFW_TRUE // chdir
|
||||
@ -188,6 +189,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
|
||||
{
|
||||
switch (hint)
|
||||
{
|
||||
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||
_glfwInitHints.hatButtons = value;
|
||||
return;
|
||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||
_glfwInitHints.ns.chdir = value;
|
||||
return;
|
||||
|
44
src/input.c
44
src/input.c
@ -140,6 +140,19 @@ void _glfwInputJoystickButton(int jid, int button, char value)
|
||||
_glfw.joysticks[jid].buttons[button] = value;
|
||||
}
|
||||
|
||||
void _glfwInputJoystickHat(int jid, int hat, char value)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
const int base = js->buttonCount + hat * 4;
|
||||
|
||||
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
|
||||
js->hats[hat] = value;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@ -152,7 +165,10 @@ GLFWbool _glfwIsPrintable(int key)
|
||||
key == GLFW_KEY_KP_EQUAL;
|
||||
}
|
||||
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount)
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
int axisCount,
|
||||
int buttonCount,
|
||||
int hatCount)
|
||||
{
|
||||
int jid;
|
||||
_GLFWjoystick* js;
|
||||
@ -170,9 +186,11 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCou
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(name);
|
||||
js->axes = calloc(axisCount, sizeof(float));
|
||||
js->buttons = calloc(buttonCount, 1);
|
||||
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||
js->hats = calloc(hatCount, 1);
|
||||
js->axisCount = axisCount;
|
||||
js->buttonCount = buttonCount;
|
||||
js->hatCount = hatCount;
|
||||
|
||||
return js;
|
||||
}
|
||||
@ -182,6 +200,7 @@ void _glfwFreeJoystick(_GLFWjoystick* js)
|
||||
free(js->name);
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->hats);
|
||||
memset(js, 0, sizeof(_GLFWjoystick));
|
||||
}
|
||||
|
||||
@ -663,13 +682,23 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||
return NULL;
|
||||
|
||||
*count = _glfw.joysticks[jid].buttonCount;
|
||||
if (_glfw.hints.init.hatButtons)
|
||||
{
|
||||
*count = _glfw.joysticks[jid].buttonCount +
|
||||
_glfw.joysticks[jid].hatCount * 4;
|
||||
}
|
||||
else
|
||||
*count = _glfw.joysticks[jid].buttonCount;
|
||||
|
||||
return _glfw.joysticks[jid].buttons;
|
||||
}
|
||||
|
||||
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||
{
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
@ -680,7 +709,14 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||
return NULL;
|
||||
|
||||
*count = _glfw.joysticks[jid].hatCount;
|
||||
return _glfw.joysticks[jid].hats;
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||
|
@ -266,6 +266,7 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
*/
|
||||
struct _GLFWinitconfig
|
||||
{
|
||||
GLFWbool hatButtons;
|
||||
struct {
|
||||
GLFWbool menubar;
|
||||
GLFWbool chdir;
|
||||
@ -476,6 +477,8 @@ struct _GLFWjoystick
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
unsigned char* hats;
|
||||
int hatCount;
|
||||
char* name;
|
||||
|
||||
// This is defined in the joystick API's joystick.h
|
||||
@ -823,6 +826,13 @@ void _glfwInputJoystickAxis(int jid, int axis, float value);
|
||||
*/
|
||||
void _glfwInputJoystickButton(int jid, int button, char value);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick hat.
|
||||
* @param[in] jid The joystick whose hat to update.
|
||||
* @param[in] button The index of the hat to update.
|
||||
* @param[in] value The new value of the hat.
|
||||
*/
|
||||
void _glfwInputJoystickHat(int jid, int hat, char value);
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Utility functions
|
||||
@ -912,7 +922,7 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
||||
/*! @brief Returns an available joystick object with arrays and name allocated.
|
||||
* @ingroup utility
|
||||
*/
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount);
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount, int hatCount);
|
||||
|
||||
/*! @brief Frees arrays and name and flags the joystick object as unused.
|
||||
* @ingroup utility
|
||||
|
@ -77,7 +77,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||
|
||||
js = _glfwAllocJoystick(name, axisCount, buttonCount);
|
||||
js = _glfwAllocJoystick(name, axisCount, buttonCount, 0);
|
||||
if (!js)
|
||||
{
|
||||
close(fd);
|
||||
|
@ -427,7 +427,8 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
|
||||
js = _glfwAllocJoystick(name,
|
||||
data.axisCount + data.sliderCount,
|
||||
data.buttonCount + data.povCount * 4);
|
||||
data.buttonCount,
|
||||
data.povCount);
|
||||
if (!js)
|
||||
{
|
||||
IDirectInputDevice8_Release(device);
|
||||
@ -512,7 +513,7 @@ void _glfwDetectJoystickConnectionWin32(void)
|
||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||
continue;
|
||||
|
||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 14);
|
||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 10, 1);
|
||||
if (!js)
|
||||
continue;
|
||||
|
||||
@ -561,7 +562,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
|
||||
if (js->win32.device)
|
||||
{
|
||||
int i, j, ai = 0, bi = 0;
|
||||
int i, ai = 0, bi = 0, pi = 0;
|
||||
HRESULT result;
|
||||
DIJOYSTATE state;
|
||||
|
||||
@ -612,19 +613,26 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
|
||||
case _GLFW_TYPE_POV:
|
||||
{
|
||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||
const int states[9] =
|
||||
{
|
||||
GLFW_HAT_UP,
|
||||
GLFW_HAT_RIGHT_UP,
|
||||
GLFW_HAT_RIGHT,
|
||||
GLFW_HAT_RIGHT_DOWN,
|
||||
GLFW_HAT_DOWN,
|
||||
GLFW_HAT_LEFT_DOWN,
|
||||
GLFW_HAT_LEFT,
|
||||
GLFW_HAT_LEFT_UP,
|
||||
GLFW_HAT_CENTERED
|
||||
};
|
||||
|
||||
// Screams of horror are appropriate at this point
|
||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
const char value = (directions[state] & (1 << j)) != 0;
|
||||
_glfwInputJoystickButton(jid, bi, value);
|
||||
bi++;
|
||||
}
|
||||
|
||||
_glfwInputJoystickHat(jid, pi, states[state]);
|
||||
pi++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -632,7 +640,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int i, dpad = 0;
|
||||
DWORD result;
|
||||
XINPUT_STATE xis;
|
||||
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
||||
@ -647,11 +655,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
XINPUT_GAMEPAD_BACK,
|
||||
XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||
XINPUT_GAMEPAD_DPAD_UP,
|
||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
||||
XINPUT_GAMEPAD_DPAD_LEFT
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||
};
|
||||
|
||||
result = XInputGetState(js->win32.index, &xis);
|
||||
@ -693,11 +697,22 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
||||
for (i = 0; i < 6; i++)
|
||||
_glfwInputJoystickAxis(jid, i, axes[i]);
|
||||
|
||||
for (i = 0; i < 14; i++)
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||
_glfwInputJoystickButton(jid, i, value);
|
||||
}
|
||||
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
||||
dpad |= GLFW_HAT_UP;
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
||||
dpad |= GLFW_HAT_RIGHT;
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
||||
dpad |= GLFW_HAT_DOWN;
|
||||
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
||||
dpad |= GLFW_HAT_LEFT;
|
||||
|
||||
_glfwInputJoystickHat(jid, 0, dpad);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
|
@ -98,6 +98,7 @@ int main(void)
|
||||
memset(joysticks, 0, sizeof(joysticks));
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
@ -142,6 +143,8 @@ int main(void)
|
||||
{
|
||||
nk_layout_row_dynamic(nk, 30, 1);
|
||||
|
||||
nk_label(nk, "Hat buttons disabled", NK_TEXT_LEFT);
|
||||
|
||||
if (joystick_count)
|
||||
{
|
||||
for (i = 0; i < joystick_count; i++)
|
||||
@ -167,29 +170,77 @@ int main(void)
|
||||
NK_WINDOW_MINIMIZABLE |
|
||||
NK_WINDOW_TITLE))
|
||||
{
|
||||
int j, axis_count, button_count;
|
||||
int j, axis_count, button_count, hat_count;
|
||||
const float* axes;
|
||||
const unsigned char* buttons;
|
||||
const unsigned char* hats;
|
||||
|
||||
nk_layout_row_dynamic(nk, 30, 1);
|
||||
|
||||
axes = glfwGetJoystickAxes(joysticks[i], &axis_count);
|
||||
if (axis_count)
|
||||
{
|
||||
for (j = 0; j < axis_count; j++)
|
||||
nk_slide_float(nk, -1.f, axes[j], 1.f, 0.1f);
|
||||
}
|
||||
for (j = 0; j < axis_count; j++)
|
||||
nk_slide_float(nk, -1.f, axes[j], 1.f, 0.1f);
|
||||
|
||||
nk_layout_row_dynamic(nk, 30, 8);
|
||||
|
||||
buttons = glfwGetJoystickButtons(joysticks[i], &button_count);
|
||||
if (button_count)
|
||||
for (j = 0; j < button_count; j++)
|
||||
{
|
||||
for (j = 0; j < button_count; j++)
|
||||
char name[16];
|
||||
snprintf(name, sizeof(name), "%i", j + 1);
|
||||
nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]);
|
||||
}
|
||||
|
||||
nk_layout_row_dynamic(nk, 30, 8);
|
||||
|
||||
hats = glfwGetJoystickHats(joysticks[i], &hat_count);
|
||||
for (j = 0; j < hat_count; j++)
|
||||
{
|
||||
float radius;
|
||||
struct nk_rect area;
|
||||
struct nk_vec2 center;
|
||||
|
||||
if (nk_widget(&area, nk) != NK_WIDGET_VALID)
|
||||
continue;
|
||||
|
||||
center = nk_vec2(area.x + area.w / 2.f,
|
||||
area.y + area.h / 2.f);
|
||||
radius = NK_MIN(area.w, area.h) / 2.f;
|
||||
|
||||
nk_stroke_circle(nk_window_get_canvas(nk),
|
||||
nk_rect(center.x - radius,
|
||||
center.y - radius,
|
||||
radius * 2.f,
|
||||
radius * 2.f),
|
||||
1.f,
|
||||
nk_rgb(175, 175, 175));
|
||||
|
||||
if (hats[j])
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, sizeof(name), "%i", j + 1);
|
||||
nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]);
|
||||
const float angles[] =
|
||||
{
|
||||
0.f, 0.f,
|
||||
NK_PI * 1.5f, NK_PI * 1.75f,
|
||||
NK_PI, 0.f,
|
||||
NK_PI * 1.25f, 0.f,
|
||||
NK_PI * 0.5f, NK_PI * 0.25f,
|
||||
0.f, 0.f,
|
||||
NK_PI * 0.75f, 0.f,
|
||||
};
|
||||
const float cosa = nk_cos(angles[hats[j]]);
|
||||
const float sina = nk_sin(angles[hats[j]]);
|
||||
const struct nk_vec2 p0 = nk_vec2(0.f, -radius);
|
||||
const struct nk_vec2 p1 = nk_vec2( radius / 2.f, -radius / 3.f);
|
||||
const struct nk_vec2 p2 = nk_vec2(-radius / 2.f, -radius / 3.f);
|
||||
|
||||
nk_fill_triangle(nk_window_get_canvas(nk),
|
||||
center.x + cosa * p0.x + sina * p0.y,
|
||||
center.y + cosa * p0.y - sina * p0.x,
|
||||
center.x + cosa * p1.x + sina * p1.y,
|
||||
center.y + cosa * p1.y - sina * p1.x,
|
||||
center.x + cosa * p2.x + sina * p2.y,
|
||||
center.y + cosa * p2.y - sina * p2.x,
|
||||
nk_rgb(175, 175, 175));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user