mirror of
https://github.com/glfw/glfw.git
synced 2024-11-26 12:02:00 +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
|
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||||
receiving window maximization events (#778)
|
receiving window maximization events (#778)
|
||||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
- 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 `glfwInitHint` function for setting library initialization hints
|
||||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||||
- Added definition of `GLAPIENTRY` to public header
|
- Added definition of `GLAPIENTRY` to public header
|
||||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||||
(#749,#842)
|
(#749,#842)
|
||||||
|
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||||
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
||||||
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
|
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
|
||||||
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
|
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
|
||||||
|
@ -204,7 +204,8 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
|||||||
"x11=__X11:__" \
|
"x11=__X11:__" \
|
||||||
"wayland=__Wayland:__" \
|
"wayland=__Wayland:__" \
|
||||||
"win32=__Windows:__" \
|
"win32=__Windows:__" \
|
||||||
"macos=__macOS:__"
|
"macos=__macOS:__" \
|
||||||
|
"linux=__Linux:__"
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
# 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
|
# 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
|
The joystick functions expose connected joysticks and controllers, with both
|
||||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
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
|
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||||
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
|
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||||
|
present with @ref glfwJoystickPresent.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
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
|
the array. Once a joystick is detected, it keeps its assigned ID until it is
|
||||||
keeps its assigned index until it is disconnected, so as joysticks are connected
|
disconnected or the library is terminated, so as joysticks are connected and
|
||||||
and disconnected, they will become spread out.
|
disconnected, there may appear gaps in the IDs.
|
||||||
|
|
||||||
Joystick state is updated as needed when a joystick function is called and does
|
Joystick axis, button and hat state is updated when polled and does not require
|
||||||
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
|
a window to be created or events to be processed. However, if you want joystick
|
||||||
to be called.
|
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
|
To see all the properties of all connected joysticks in real-time, run the
|
||||||
`joysticks` test program.
|
`joysticks` test program.
|
||||||
@ -538,7 +541,7 @@ returned array.
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
int count;
|
int count;
|
||||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
|
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Each element in the returned array is a value between -1.0 and 1.0.
|
Each element in the returned array is a value between -1.0 and 1.0.
|
||||||
@ -552,11 +555,55 @@ returned array.
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
int count;
|
int count;
|
||||||
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
|
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
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
|
@subsection joystick_name Joystick name
|
||||||
|
|
||||||
@ -565,7 +612,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
|
|||||||
returned string.
|
returned string.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
|
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
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
|
will simply ignore them. Setting these hints requires no platform specific
|
||||||
headers or calls.
|
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
|
@subsubsection init_hints_osx macOS specific hints
|
||||||
|
|
||||||
@ -95,6 +100,7 @@ initialized.
|
|||||||
|
|
||||||
Init hint | Default value | Supported values
|
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_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
@ref GLFW_COCOA_MENUBAR | `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.
|
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
|
@subsection news_33_inithint Support for initialization hints
|
||||||
|
|
||||||
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
||||||
|
@ -297,7 +297,7 @@ extern "C" {
|
|||||||
#define GLFW_REPEAT 2
|
#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.
|
* See [joystick hat input](@ref joystick_hat) for how these are used.
|
||||||
*
|
*
|
||||||
@ -945,6 +945,8 @@ extern "C" {
|
|||||||
|
|
||||||
/*! @addtogroup init
|
/*! @addtogroup init
|
||||||
* @{ */
|
* @{ */
|
||||||
|
#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
|
||||||
|
|
||||||
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
|
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
|
||||||
#define GLFW_COCOA_MENUBAR 0x00051002
|
#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.
|
* 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.
|
* 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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* 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.
|
* This function returns the state of all buttons of the specified joystick.
|
||||||
* Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
* 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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* 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.
|
/*! @brief Returns the state of all hats of the specified joystick.
|
||||||
*
|
*
|
||||||
* This function 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
|
* Name | Value
|
||||||
* GLFW_HAT_UP
|
* --------------------- | --------------------------------
|
||||||
* GLFW_HAT_RIGHT
|
* `GLFW_HAT_CENTERED` | 0
|
||||||
* GLFW_HAT_DOWN
|
* `GLFW_HAT_UP` | 1
|
||||||
* GLFW_HAT_LEFT
|
* `GLFW_HAT_RIGHT` | 2
|
||||||
* GLFW_HAT_RIGHT_UP
|
* `GLFW_HAT_DOWN` | 4
|
||||||
* GLFW_HAT_RIGHT_DOWN
|
* `GLFW_HAT_LEFT` | 8
|
||||||
* GLFW_HAT_LEFT_UP
|
* `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
|
||||||
* GLFW_HAT_LEFT_DOWN
|
* `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
|
* The diagonal directions are bitwise combinations of the primary (up, right,
|
||||||
* directions:
|
* down and left) directions and you can test for these individually by ANDing
|
||||||
|
* it with the corresponding direction.
|
||||||
*
|
*
|
||||||
* GLFW_HAT_UP
|
* @code
|
||||||
* GLFW_HAT_RIGHT
|
* if (hats[2] & GLFW_HAT_RIGHT)
|
||||||
* GLFW_HAT_DOWN
|
* {
|
||||||
* GLFW_HAT_LEFT
|
* // 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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* 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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
* 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
|
* @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
|
* 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
|
* The returned string is allocated and freed by GLFW. You should not free it
|
||||||
* yourself.
|
* 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
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* check device presence.
|
||||||
*
|
*
|
||||||
|
@ -204,7 +204,8 @@ static void matchCallback(void* context,
|
|||||||
|
|
||||||
js = _glfwAllocJoystick(name,
|
js = _glfwAllocJoystick(name,
|
||||||
CFArrayGetCount(axes),
|
CFArrayGetCount(axes),
|
||||||
CFArrayGetCount(buttons) + CFArrayGetCount(hats) * 4);
|
CFArrayGetCount(buttons),
|
||||||
|
CFArrayGetCount(hats));
|
||||||
|
|
||||||
js->ns.device = device;
|
js->ns.device = device;
|
||||||
js->ns.axes = axes;
|
js->ns.axes = axes;
|
||||||
@ -358,33 +359,38 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
}
|
}
|
||||||
else if (mode == _GLFW_POLL_BUTTONS)
|
else if (mode == _GLFW_POLL_BUTTONS)
|
||||||
{
|
{
|
||||||
CFIndex i, bi = 0;
|
CFIndex i;
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||||
const char value = getElementValue(js, button) ? 1 : 0;
|
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++)
|
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*)
|
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->ns.hats, i);
|
CFArrayGetValueAtIndex(js->ns.hats, i);
|
||||||
|
long state = getElementValue(js, hat);
|
||||||
// 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);
|
|
||||||
if (state < 0 || state > 8)
|
if (state < 0 || state > 8)
|
||||||
state = 8;
|
state = 8;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
_glfwInputJoystickHat(jid, i, states[state]);
|
||||||
{
|
|
||||||
const char value = directions[state] & (1 << j) ? 1 : 0;
|
|
||||||
_glfwInputJoystickButton(jid, bi++, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ _GLFWlibrary _glfw = { GLFW_FALSE };
|
|||||||
static GLFWerrorfun _glfwErrorCallback;
|
static GLFWerrorfun _glfwErrorCallback;
|
||||||
static _GLFWinitconfig _glfwInitHints =
|
static _GLFWinitconfig _glfwInitHints =
|
||||||
{
|
{
|
||||||
|
GLFW_TRUE, // hat buttons
|
||||||
{
|
{
|
||||||
GLFW_TRUE, // menubar
|
GLFW_TRUE, // menubar
|
||||||
GLFW_TRUE // chdir
|
GLFW_TRUE // chdir
|
||||||
@ -188,6 +189,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
|
|||||||
{
|
{
|
||||||
switch (hint)
|
switch (hint)
|
||||||
{
|
{
|
||||||
|
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||||
|
_glfwInitHints.hatButtons = value;
|
||||||
|
return;
|
||||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||||
_glfwInitHints.ns.chdir = value;
|
_glfwInitHints.ns.chdir = value;
|
||||||
return;
|
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;
|
_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 //////
|
////// GLFW internal API //////
|
||||||
@ -152,7 +165,10 @@ GLFWbool _glfwIsPrintable(int key)
|
|||||||
key == GLFW_KEY_KP_EQUAL;
|
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;
|
int jid;
|
||||||
_GLFWjoystick* js;
|
_GLFWjoystick* js;
|
||||||
@ -170,9 +186,11 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCou
|
|||||||
js->present = GLFW_TRUE;
|
js->present = GLFW_TRUE;
|
||||||
js->name = strdup(name);
|
js->name = strdup(name);
|
||||||
js->axes = calloc(axisCount, sizeof(float));
|
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->axisCount = axisCount;
|
||||||
js->buttonCount = buttonCount;
|
js->buttonCount = buttonCount;
|
||||||
|
js->hatCount = hatCount;
|
||||||
|
|
||||||
return js;
|
return js;
|
||||||
}
|
}
|
||||||
@ -182,6 +200,7 @@ void _glfwFreeJoystick(_GLFWjoystick* js)
|
|||||||
free(js->name);
|
free(js->name);
|
||||||
free(js->axes);
|
free(js->axes);
|
||||||
free(js->buttons);
|
free(js->buttons);
|
||||||
|
free(js->hats);
|
||||||
memset(js, 0, sizeof(_GLFWjoystick));
|
memset(js, 0, sizeof(_GLFWjoystick));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,13 +682,23 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
|||||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||||
return NULL;
|
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;
|
return _glfw.joysticks[jid].buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||||
{
|
{
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
assert(count != NULL);
|
assert(count != NULL);
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
@ -680,7 +709,14 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
|||||||
return NULL;
|
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)
|
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||||
|
@ -266,6 +266,7 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
*/
|
*/
|
||||||
struct _GLFWinitconfig
|
struct _GLFWinitconfig
|
||||||
{
|
{
|
||||||
|
GLFWbool hatButtons;
|
||||||
struct {
|
struct {
|
||||||
GLFWbool menubar;
|
GLFWbool menubar;
|
||||||
GLFWbool chdir;
|
GLFWbool chdir;
|
||||||
@ -476,6 +477,8 @@ struct _GLFWjoystick
|
|||||||
int axisCount;
|
int axisCount;
|
||||||
unsigned char* buttons;
|
unsigned char* buttons;
|
||||||
int buttonCount;
|
int buttonCount;
|
||||||
|
unsigned char* hats;
|
||||||
|
int hatCount;
|
||||||
char* name;
|
char* name;
|
||||||
|
|
||||||
// This is defined in the joystick API's joystick.h
|
// 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);
|
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
|
// Utility functions
|
||||||
@ -912,7 +922,7 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
|||||||
/*! @brief Returns an available joystick object with arrays and name allocated.
|
/*! @brief Returns an available joystick object with arrays and name allocated.
|
||||||
* @ingroup utility
|
* @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.
|
/*! @brief Frees arrays and name and flags the joystick object as unused.
|
||||||
* @ingroup utility
|
* @ingroup utility
|
||||||
|
@ -77,7 +77,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||||
|
|
||||||
js = _glfwAllocJoystick(name, axisCount, buttonCount);
|
js = _glfwAllocJoystick(name, axisCount, buttonCount, 0);
|
||||||
if (!js)
|
if (!js)
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -427,7 +427,8 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
|
|
||||||
js = _glfwAllocJoystick(name,
|
js = _glfwAllocJoystick(name,
|
||||||
data.axisCount + data.sliderCount,
|
data.axisCount + data.sliderCount,
|
||||||
data.buttonCount + data.povCount * 4);
|
data.buttonCount,
|
||||||
|
data.povCount);
|
||||||
if (!js)
|
if (!js)
|
||||||
{
|
{
|
||||||
IDirectInputDevice8_Release(device);
|
IDirectInputDevice8_Release(device);
|
||||||
@ -512,7 +513,7 @@ void _glfwDetectJoystickConnectionWin32(void)
|
|||||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 14);
|
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 10, 1);
|
||||||
if (!js)
|
if (!js)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -561,7 +562,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
|
|
||||||
if (js->win32.device)
|
if (js->win32.device)
|
||||||
{
|
{
|
||||||
int i, j, ai = 0, bi = 0;
|
int i, ai = 0, bi = 0, pi = 0;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
DIJOYSTATE state;
|
DIJOYSTATE state;
|
||||||
|
|
||||||
@ -612,19 +613,26 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
|
|
||||||
case _GLFW_TYPE_POV:
|
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
|
// Screams of horror are appropriate at this point
|
||||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||||
if (state < 0 || state > 8)
|
if (state < 0 || state > 8)
|
||||||
state = 8;
|
state = 8;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
_glfwInputJoystickHat(jid, pi, states[state]);
|
||||||
{
|
pi++;
|
||||||
const char value = (directions[state] & (1 << j)) != 0;
|
|
||||||
_glfwInputJoystickButton(jid, bi, value);
|
|
||||||
bi++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,7 +640,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i, dpad = 0;
|
||||||
DWORD result;
|
DWORD result;
|
||||||
XINPUT_STATE xis;
|
XINPUT_STATE xis;
|
||||||
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
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_BACK,
|
||||||
XINPUT_GAMEPAD_START,
|
XINPUT_GAMEPAD_START,
|
||||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||||
XINPUT_GAMEPAD_RIGHT_THUMB,
|
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||||
XINPUT_GAMEPAD_DPAD_UP,
|
|
||||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
|
||||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
|
||||||
XINPUT_GAMEPAD_DPAD_LEFT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
result = XInputGetState(js->win32.index, &xis);
|
result = XInputGetState(js->win32.index, &xis);
|
||||||
@ -693,11 +697,22 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
_glfwInputJoystickAxis(jid, i, axes[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;
|
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
_glfwInputJoystickButton(jid, i, value);
|
_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;
|
return GLFW_TRUE;
|
||||||
|
@ -98,6 +98,7 @@ int main(void)
|
|||||||
memset(joysticks, 0, sizeof(joysticks));
|
memset(joysticks, 0, sizeof(joysticks));
|
||||||
|
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
|
||||||
|
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -142,6 +143,8 @@ int main(void)
|
|||||||
{
|
{
|
||||||
nk_layout_row_dynamic(nk, 30, 1);
|
nk_layout_row_dynamic(nk, 30, 1);
|
||||||
|
|
||||||
|
nk_label(nk, "Hat buttons disabled", NK_TEXT_LEFT);
|
||||||
|
|
||||||
if (joystick_count)
|
if (joystick_count)
|
||||||
{
|
{
|
||||||
for (i = 0; i < joystick_count; i++)
|
for (i = 0; i < joystick_count; i++)
|
||||||
@ -167,29 +170,77 @@ int main(void)
|
|||||||
NK_WINDOW_MINIMIZABLE |
|
NK_WINDOW_MINIMIZABLE |
|
||||||
NK_WINDOW_TITLE))
|
NK_WINDOW_TITLE))
|
||||||
{
|
{
|
||||||
int j, axis_count, button_count;
|
int j, axis_count, button_count, hat_count;
|
||||||
const float* axes;
|
const float* axes;
|
||||||
const unsigned char* buttons;
|
const unsigned char* buttons;
|
||||||
|
const unsigned char* hats;
|
||||||
|
|
||||||
nk_layout_row_dynamic(nk, 30, 1);
|
nk_layout_row_dynamic(nk, 30, 1);
|
||||||
|
|
||||||
axes = glfwGetJoystickAxes(joysticks[i], &axis_count);
|
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);
|
nk_layout_row_dynamic(nk, 30, 8);
|
||||||
|
|
||||||
buttons = glfwGetJoystickButtons(joysticks[i], &button_count);
|
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];
|
const float angles[] =
|
||||||
snprintf(name, sizeof(name), "%i", j + 1);
|
{
|
||||||
nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]);
|
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