From 609628d61854b94e9f6f5ee5543d0d233852614b Mon Sep 17 00:00:00 2001 From: Mhat <127427093+Mhatxotic@users.noreply.github.com> Date: Sun, 26 Jan 2025 00:31:30 +0000 Subject: [PATCH] 25.1.26 [Engine] * Move all joystick related code to a new 'joystick.hpp' module and tidy up names and clean out redundant code. * Increase supported buttons from GLFW_BUTTON_LAST+1 to 128 and protect from potential overflow. * Increase supported axes from GLFW_AXIS_LAST+1 to 8 and protect from overflow. * Show more information with 'input' console command. * Fix 'Input.GetJoyButton()' returning raw button data and not translated data. [Assets] * Update API documentation. --- docs/index.html | 22 +- src/conlib.hpp | 88 +++---- src/core.hpp | 2 +- src/engine.cpp | 1 + src/engine.hpp | 10 +- src/glfwutil.hpp | 12 + src/input.hpp | 502 ++-------------------------------------- src/joystick.hpp | 582 +++++++++++++++++++++++++++++++++++++++++++++++ src/json.hpp | 4 +- src/llcommon.hpp | 1 + src/llinput.hpp | 39 ++-- 11 files changed, 705 insertions(+), 558 deletions(-) create mode 100644 src/joystick.hpp diff --git a/docs/index.html b/docs/index.html index 03a6655..2325eaa 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,7 +1,7 @@ - - - + + + @@ -11,18 +11,18 @@ - + - + - + - + - Mhatxotic Engine 25.1.22.118 API reference + Mhatxotic Engine 25.1.26.24 API reference -

Mhatxotic Engine 25.1.22.118 API reference

+

Mhatxotic Engine 25.1.26.24 API reference

@@ -5736,7 +5736,7 @@

Function Parameters:-

Return Parameters:-

Result (integer) = Number of ticks the button has been held down.

Synopsis:-

-
Returns the state of the specified joystick button.

Result can be: =0: The button is not held down.
>0: The button was held down for this many game ticks.
+
Returns the state of the specified joystick button.

Result can be: =0: The button is not held down.
=1: The button was pressed.
>1: The button is being held.

▲ Return to table of contents

Copyright © 2025 Mhatxotic Design, All Rights Reserved.
- This document was generated at Thu Jan 23 01:39:36 2025 +0000
+ This document was generated at Sun Jan 26 00:32:39 2025 +0000 diff --git a/src/conlib.hpp b/src/conlib.hpp index eee654a..d59ebc5 100644 --- a/src/conlib.hpp +++ b/src/conlib.hpp @@ -889,71 +889,77 @@ cConsole->AddLineA(sTable.Finish(), /* ========================================================================= */ { "input", 1, 2, CFL_VIDEO, [](const Args &aArgs){ /* ------------------------------------------------------------------------- */ -// Get joysticks data -const JoyList &jlList = cInput->GetConstJoyList(); +// Required joystick namespace +using namespace IJoystick::P; // If argument specified if(aArgs.size() > 1) { // Convert parmeter to number const size_t stArg = StrToNum(aArgs[1]); - if(stArg >= jlList.size()) + if(stArg >= cInput->JoyGetCount()) return cConsole->AddLine("Joystick index argument invalid!"); // Get joystick information and return if not connected - const JoyInfo &jiRef = jlList[stArg]; - if(jiRef.IsDisconnected()) + const JoyInfo &jiRef = cInput->JoyGetConst(stArg); + if(jiRef.JoyIsDisconnected()) return cConsole->AddLine("Joystick is not being polled right now!"); // Build axis state data Statistic sAxes; - sAxes.Header(); - for(size_t stIndex = 0; stIndex < jiRef.GetAxisCount(); ++stIndex) - sAxes.Header(StrFormat("A$$$$", setw(2), right, setfill('0'), stIndex)); - // Buffered - sAxes.Data("BUF"); - for(size_t stIndex = 0; stIndex < jiRef.GetAxisCount(); ++stIndex) - sAxes.DataN(jiRef.GetAxisState(stIndex)); - // Unbuffered - sAxes.Data("RAW"); - for(size_t stIndex = 0; stIndex < jiRef.GetAxisCount(); ++stIndex) - sAxes.DataN(jiRef.GetUnbufferedAxisState(stIndex), 1); + // Buffered headers + StdForEach(seq, jiRef.JoyAxisListBegin(), jiRef.JoyAxisListEnd(), + [&sAxes](const JoyAxisInfo &jaiRef) { sAxes.Header(StrFormat("BA$$$$", + setw(2), right, setfill('0'), jaiRef.AxisGetId()), true); }); + // Unbuffered headers + StdForEach(seq, jiRef.JoyAxisListBegin(), jiRef.JoyAxisListEnd(), + [&sAxes](const JoyAxisInfo &jaiRef) { sAxes.Header(StrFormat("UA$$$$", + setw(2), right, setfill('0'), jaiRef.AxisGetId()), true); }); + // Reserve memory for data entries + sAxes.Reserve(jiRef.JoyAxisListCount() * 2); + // Buffered state + StdForEach(seq, jiRef.JoyAxisListBegin(), jiRef.JoyAxisListEnd(), + [&sAxes](const JoyAxisInfo &jaiRef) + { sAxes.DataN(jaiRef.AxisGetBufferedState()); }); + // Unbuffered state + StdForEach(seq, jiRef.JoyAxisListBegin(), jiRef.JoyAxisListEnd(), + [&sAxes](const JoyAxisInfo &jaiRef) + { sAxes.DataN(jaiRef.AxisGetUnbufferedState(), 1); }); // Build button state data Statistic sButtons; - sButtons.Header(); - for(size_t stIndex = 0; stIndex < jiRef.GetButtonCount(); ++stIndex) - sButtons.Header(StrFormat("B$$$$", setw(2), right, setfill('0'), stIndex)); - // Buffered - sButtons.Data("BUF"); - for(size_t stIndex = 0; stIndex < jiRef.GetButtonCount(); ++stIndex) - sButtons.DataN(jiRef.GetButtonState(stIndex)); - // Unbuffered - sButtons.Data("RAW"); - for(size_t stIndex = 0; stIndex < jiRef.GetButtonCount(); ++stIndex) - sButtons.DataN(jiRef.GetUnbufferedButtonState(stIndex)); + // Buffered headers + StdForEach(seq, jiRef.JoyButtonListBegin(), jiRef.JoyButtonListEnd(), + [&sButtons](const JoyButtonInfo &jbiRef) + { sButtons.Header(StrFormat("B$$$$", + setw(2), right, setfill('0'), jbiRef.ButtonGetId()), true); }); + // Reserve memory for data entries + sButtons.Reserve(jiRef.JoyButtonListCount()); + // Buffered state + StdForEach(seq, jiRef.JoyButtonListBegin(), jiRef.JoyButtonListEnd(), + [&sButtons](const JoyButtonInfo &jbiRef) + { sButtons.DataN(jbiRef.ButtonGetState()); }); // Dump to console output and return return cConsole->AddLineF("$$Data for $ '$' at index $.", sAxes.Finish(), - sButtons.Finish(), jiRef.GetGamepadOrJoystickString(), jiRef.IdentGet(), + sButtons.Finish(), jiRef.JoyGetGamepadOrJoystickString(), jiRef.IdentGet(), stArg); -} // Joysticks connected -size_t stConnected = 0; -// Make a table to automatically format our data neatly +} // Make a table to automatically format our data neatly Statistic sTable; sTable.Header("ID").Header("FL").Header("AX").Header("BT") - .Header("NAME", false).Reserve(jlList.size()); + .Header("GUID", false).Header("NAME", false) + .Header("IDENT", false).Reserve(cInput->JoyGetCount()); // For each joystick +const JoyList &jlList = cInput->JoyListGetConst(); for(const JoyInfo &jiRef : jlList) { // If joystick is connected - if(jiRef.IsDisconnected()) + if(jiRef.JoyIsDisconnected()) { // If joystick name was empty then ignore it. Still show disconnected ones if(jiRef.IdentGet().empty()) continue; - } // Connected - else ++stConnected; - // Store data - sTable.DataN(jiRef.GetId()).Data(StrFromEvalTokens({ - { jiRef.FlagIsSet(JF_GAMEPAD), 'G' }, - { jiRef.FlagIsSet(JF_CONNECTED), 'C' } - })).DataN(jiRef.GetAxisCount()).DataN(jiRef.GetButtonCount()) + } // Store data + sTable.DataN(jiRef.JoyGetId()).Data(StrFromEvalTokens({ + { jiRef.JoyIsGamepad(), 'G' }, { jiRef.JoyIsConnected(), 'C' } + })).DataN(jiRef.JoyAxisListCount()).DataN(jiRef.JoyButtonListCount()) + .Data(jiRef.JoyGUID()).Data(jiRef.JoyGamePadName()) .Data(jiRef.IdentGet()); } // Print totals cConsole->AddLineF("$$ connected ($ supported).", sTable.Finish(), - StrCPluraliseNum(stConnected, "input", "inputs"), jlList.size()); + StrCPluraliseNum(cInput->JoyGetConnected(), "input", "inputs"), + jlList.size()); /* ------------------------------------------------------------------------- */ } }, // End of 'input' function /* ========================================================================= */ diff --git a/src/core.hpp b/src/core.hpp index aec0434..d22a3f7 100644 --- a/src/core.hpp +++ b/src/core.hpp @@ -139,7 +139,7 @@ class Core final : // Members initially private { // Set main fbo by default on each frame cFboCore->ActivateMain(); // Poll joysticks - cInput->PollJoysticks(); + cInput->JoyPoll(); // Execute a tick for each frame missed cLua->ExecuteMain(); // Break if we've caught up diff --git a/src/engine.cpp b/src/engine.cpp index 77df6f6..f47b70a 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -103,6 +103,7 @@ namespace E { // Start of engine namespace #include "file.hpp" // FStream+FileMap class header #include "clip.hpp" // Clipboard class header #include "congraph.hpp" // Console rendering class header +#include "joystick.hpp" // Joystick structure class header #include "input.hpp" // Input handling class header #include "display.hpp" // Window handling class header #include "mask.hpp" // BitMask system header diff --git a/src/engine.hpp b/src/engine.hpp index 6c05671..be1c49e 100644 --- a/src/engine.hpp +++ b/src/engine.hpp @@ -12,9 +12,9 @@ #define VER_AUTHOR "Mhatxotic Design" // Author of engine #define VER_MAJOR 25 // Version major (year) #define VER_MINOR 1 // Version minor (month) -#define VER_BUILD 25 // Version build (day) -#define VER_REV 1 // Version rev (build#) -#define VER_STR_NQ 25,1,25,1 // Version as literal -#define VER_STR "25.1.25.1" // Version as string -#define VER_DATE "Sat Jan 25 00:32:33 2025 +0000" // Compilation date +#define VER_BUILD 26 // Version build (day) +#define VER_REV 27 // Version rev (build#) +#define VER_STR_NQ 25,1,26,27 // Version as literal +#define VER_STR "25.1.26.27" // Version as string +#define VER_DATE "Sun Jan 26 01:08:13 2025 +0000" // Compilation date /* == EoF =========================================================== EoF == */ diff --git a/src/glfwutil.hpp b/src/glfwutil.hpp index 35c0f7c..c571c52 100644 --- a/src/glfwutil.hpp +++ b/src/glfwutil.hpp @@ -180,6 +180,18 @@ static const unsigned char *GlFWGetJoystickButtons(int iJ, int &iJAB) /* -- Joystick other ------------------------------------------------------- */ static const char *GlFWGetJoystickName(const int iJ) { return glfwGetJoystickName(iJ); } +/* -- Joystick is actually a game controller ------------------------------- */ +static bool GlFWJoystickIsGamepad(const int iJ) + { return glfwJoystickIsGamepad(iJ); } +/* -- Get gamepad name ----------------------------------------------------- */ +static const char *GlFWGetGamepadName(const int iJ) + { return glfwGetGamepadName(iJ); } +/* -- Get joystick unique identification number ---------------------------- */ +static const char *GlFWGetJoystickGUID(const int iJ) + { return glfwGetJoystickGUID(iJ); } +/* -- Return if joystick is present ---------------------------------------- */ +static bool GlFWJoystickPresent(const int iJ) + { return glfwJoystickPresent(iJ); } /* -- Set swap interval ---------------------------------------------------- */ static void GlFWSetVSync(const int iI) { glfwSwapInterval(iI); } /* -- Wait for window event ------------------------------------------------ */ diff --git a/src/input.hpp b/src/input.hpp index 649e58c..f8bdf06 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -14,11 +14,11 @@ using namespace ICVar::P; using namespace ICVarDef::P; using namespace ICVarLib::P; using namespace IEvtMain::P; using namespace IEvtWin::P; using namespace IFboCore::P; using namespace IFlags; using namespace IGlFW::P; -using namespace IGlFWUtil::P; using namespace IIdent::P; +using namespace IGlFWUtil::P; using namespace IJoystick::P; using namespace ILog::P; using namespace ILuaFunc::P; using namespace IStd::P; using namespace IString::P; -using namespace ISysUtil::P; using namespace IUtf; -using namespace IUtil::P; using namespace Lib::OS::GlFW; +using namespace ISysUtil::P; using namespace IUtil::P; +using namespace Lib::OS::GlFW; /* ------------------------------------------------------------------------- */ namespace P { // Start of public module namespace /* == Input flags ========================================================== */ @@ -30,321 +30,14 @@ BUILD_FLAGS(Input, IF_FSTOGGLER {Flag[2]}, IF_MOUSEFOCUS {Flag[3]}, // Send events at startup Do joystick polling? IF_INITEVENTS {Flag[4]}, IF_POLLJOYSTICKS {Flag[5]} -);/* -- Axis class --------------------------------------------------------- */ -class JoyAxisInfo -{ /* -------------------------------------------------------------- */ private: - const int iId; // Axis unique identifier - float fDeadZoneR; // Reverse deadzone threshold - float fDeadZoneF; // Forward deadzone threshold - float fUnbuffered; // Current unbuffered axis press state - int iBuffered; // Current buffered axis press state - /* -- Get axis identifier ---------------------------------------- */ public: - int AxisGetId(void) const { return iId; } - /* -- Get reverse deadzone value ----------------------------------------- */ - float AxisGetReverseDeadZone(void) const { return fDeadZoneR; } - /* -- Get forward deadzone value ----------------------------------------- */ - float AxisGetForwardDeadZone(void) const { return fDeadZoneF; } - /* -- Set reverse deadzone value ----------------------------------------- */ - void AxisSetReverseDeadZone(const float fDZ) { fDeadZoneR = -fDZ; } - /* -- Set forward deadzone value ----------------------------------------- */ - void AxisSetForwardDeadZone(const float fDZ) { fDeadZoneF = fDZ; } - /* -- Get unbuffered state ----------------------------------------------- */ - float AxisGetUnbufferedState(void) const { return fUnbuffered; } - /* -- Get buffered state ------------------------------------------------- */ - int AxisGetBufferedState(void) const { return iBuffered; } - /* -- Clear button state ------------------------------------------------- */ - void AxisClearState(void) { fUnbuffered = 0.0f; iBuffered = GLFW_RELEASE; } - /* -- Set axis state ----------------------------------------------------- */ - void AxisSetState(const float*const fpData) - { // Get the axis reading and if it's moving negatively? - fUnbuffered = fpData[AxisGetId()]; - if(fUnbuffered < fDeadZoneR) - { // Released or already in reverse position? - if(iBuffered <= GLFW_RELEASE) - { // Set to -GLFW_REPEAT if currently -GLFW_PRESSED or - // -GLFW_PRESSED if currently GLFW_RELEASE - if(iBuffered > -GLFW_REPEAT) --iBuffered; - // State changed - return; - } - } // Moving positively? - else if(fUnbuffered > fDeadZoneF) - { // Released or already in forward position? - if(iBuffered >= GLFW_RELEASE) - { // Set to GLFW_REPEAT if currentl GLFW_PRESSED or - // GLFW_PRESSED if currently GLFW_RELEASE - if(iBuffered < GLFW_REPEAT) ++iBuffered; - // State changed - return; - } - } // Nothing pressed so reset buffered counter - iBuffered = GLFW_RELEASE; - } - /* -- Constructor with unique id ----------------------------------------- */ - explicit JoyAxisInfo(const int iNId) : - /* -- Initialisers ----------------------------------------------------- */ - iId(iNId), // Set unique id - fDeadZoneR(-0.25f), // Set default reverse deadzone - fDeadZoneF(0.25f), // Set default forward deadzone - fUnbuffered(0.0f), // Set default unbuffered state - iBuffered(GLFW_RELEASE) // Set default state - /* -- No code ---------------------------------------------------------- */ - { } -};/* -- Axis data list type ------------------------------------------------ */ -typedef array JoyAxisList; -/* -- Button class --------------------------------------------------------- */ -class JoyButtonInfo -{ /* -- Private variables ----------------------------------------- */ private: - const int iId; // Button unique identifier - unsigned int uiUnbuffered, // Current unbuffered butn press state - uiBuffered; // Current buffered butn press state - /* -- Get button id ---------------------------------------------- */ public: - int ButtonGetId(void) const { return iId; } - /* -- Get unbuffered state (GLFW_RELEASE or GLFW_PRESS) ------------------ */ - unsigned int ButtonGetUnbufferedState(void) const { return uiUnbuffered; } - /* -- Get buffered state (GLFW_RELEASE, GLFW_PRESS or GLFW_REPEAT) ------- */ - unsigned int ButtonGetBufferedState(void) const { return uiBuffered; } - /* -- Clear button state ------------------------------------------------- */ - void ButtonClearState(void) { uiUnbuffered = uiBuffered = GLFW_RELEASE; } - /* -- Set button state --------------------------------------------------- */ - void ButtonSetState(const unsigned char*const ucpState) - { // Save unbuffered state and compare it - uiUnbuffered = static_cast(ucpState[ButtonGetId()]); - switch(uiUnbuffered) - { // Button is released? - case GLFW_RELEASE: - // Reset button state if not released (0 = released) - if(uiBuffered > GLFW_RELEASE) uiBuffered = GLFW_RELEASE; - // Done - return; - // Button is pressed? Increase button state (1=pressed and 2=held) - case GLFW_PRESS: - // Set GLFW_PRESSED if GLFW_RELEASED or - // GLFW_REPEAT if GLFW_PRESSED. - if(uiBuffered < GLFW_REPEAT) ++uiBuffered; - // Done - return; - // Shouldn't get here - default: break; - } // Reset to released - uiBuffered = GLFW_RELEASE; - } - /* -- Constructor with unique id ----------------------------------------- */ - explicit JoyButtonInfo(const int iNId) : - /* -- Initialisers ----------------------------------------------------- */ - iId(iNId), // Set unique id - uiUnbuffered(GLFW_RELEASE), // Set default unbuffered state - uiBuffered(GLFW_RELEASE) // Set default buffered state - /* -- No code ---------------------------------------------------------- */ - { } -};/* -- Button data list --------------------------------------------------- */ -typedef array JoyButtonList; -/* -- Joystick type typedef ------------------------------------------------ */ -BUILD_FLAGS(Joy, - /* ----------------------------------------------------------------------- */ - // No flags Joystick is connnected? - JF_NONE {Flag[0]}, JF_CONNECTED {Flag[1]}, - // Joystick is actually a gamepad - JF_GAMEPAD {Flag[2]} -);/* -- Joystick class ----------------------------------------------------- */ -class JoyInfo : - /* -- Derived classes ---------------------------------------------------- */ - public JoyFlags, // Joystick flags - public Ident // Joystick identifier -{ /* -------------------------------------------------------------- */ private: - const int iId; // Unique identifier of this - /* -- Unbuffered and buffered axis data struct --------------------------- */ - JoyAxisList jalData; // Joystick axes data - JoyButtonList jblData; // Joystick buttons data - size_t stAxes; // Axes count - size_t stButtons; // Button count - /* -- Return joystick id ----------------------------------------- */ public: - int GetId(void) const { return iId; } - /* -- Clear button state ------------------------------------------------- */ - void ClearButtonState(void) - { StdForEach(par_unseq, jblData.begin(), jblData.end(), - [](JoyButtonInfo& jbiItem) { jbiItem.ButtonClearState(); }); } - /* -- Get button count --------------------------------------------------- */ - size_t GetButtonCount(void) const { return stButtons; } - /* -- Refresh button data ------------------------------------------------ */ - void RefreshButtons(void) - { // Get joystick buttons and if found? - int iButtons; - if(const unsigned char*const cpData = - GlFWGetJoystickButtons(GetId(), iButtons)) - { // Convert integer to sizet and return if there are no buttons - stButtons = UtilMinimum(static_cast(iButtons), jblData.size()); - if(!stButtons) return; - // Enumerate state for each joy button - for(size_t stBId = 0; stBId < stButtons; ++stBId) - jblData[stBId].ButtonSetState(cpData); - } - } - /* -- Clear axis state --------------------------------------------------- */ - void ClearAxisState(void) - { StdForEach(par_unseq, jalData.begin(), jalData.end(), - [](JoyAxisInfo &jaiItem) { jaiItem.AxisClearState(); }); } - /* -- Get axis count ----------------------------------------------------- */ - size_t GetAxisCount(void) const { return stAxes; } - /* -- Refresh axis data for this ----------------------------------------- */ - void RefreshAxes(void) - { // Get axis data and if succeeded? - int iAxes; - if(const float*const fpData = GlFWGetJoystickAxes(GetId(), iAxes)) - { // Clamp count to number we support on the stack and return if no axes - stAxes = UtilMinimum(static_cast(iAxes), jalData.size()); - if(!stAxes) return; - // Enumerate state for each joystick axis - for(size_t stAId = 0; stAId < stAxes; ++stAId) - jalData[stAId].AxisSetState(fpData); - } - } - /* -- Refresh data ------------------------------------------------------- */ - void RefreshData(void) { RefreshAxes(); RefreshButtons(); } - /* -- Return type of joystick -------------------------------------------- */ - const string_view &GetGamepadOrJoystickString(void) const - { // Return if it is a gamepad or a joystick - static const string_view svGamepad{ "gamepad" }, - svJoystick{ "joystick" }; - return FlagIsSet(JF_GAMEPAD) ? svGamepad : svJoystick; - } - /* -- Joystick is connected/disconnected? ------------------------ */ public: - bool IsConnected(void) const { return FlagIsSet(JF_CONNECTED); } - bool IsDisconnected(void) const { return !IsConnected(); } - /* -- Get joystick button list data -------------------------------------- */ - const JoyButtonList &GetConstButtonList(void) const { return jblData; } - /* -- Get joystick axis list data ---------------------------------------- */ - const JoyAxisList &GetConstAxisList(void) const { return jalData; } - /* -- Clear button state if connected ------------------------------------ */ - void ClearButtonStateIfConnected(void) - { if(IsConnected()) ClearButtonState(); } - /* -- Clear buttons and axis state --------------------------------------- */ - void ClearState(void) { ClearAxisState(); ClearButtonState(); } - /* -- Refresh data if connected ------------------------------------------ */ - void RefreshDataIfConnected() { if(IsConnected()) RefreshData(); } - /* -- Get buffered button state ------------------------------------------ */ - unsigned int GetButtonState(const size_t stButtonId) const - { return jblData[stButtonId].ButtonGetBufferedState(); } - /* -- Get unbuffered button state ---------------------------------------- */ - unsigned int GetUnbufferedButtonState(const size_t stButtonId) const - { return jblData[stButtonId].ButtonGetUnbufferedState(); } - /* -- Get axis state ----------------------------------------------------- */ - int GetAxisState(const size_t stAxisId) const - { return jalData[stAxisId].AxisGetBufferedState(); } - /* -- Get unbuffered axis state ------------------------------------------ */ - float GetUnbufferedAxisState(const size_t stAxisId) const - { return jalData[stAxisId].AxisGetUnbufferedState(); } - /* -- Get axis state ----------------------------------------------------- */ - void SetAxisForwardDeadZone(const size_t stAxisId, const float fDZ) - { jalData[stAxisId].AxisSetForwardDeadZone(fDZ); } - void SetAxisReverseDeadZone(const size_t stAxisId, const float fDZ) - { jalData[stAxisId].AxisSetReverseDeadZone(fDZ); } - void SetAxisDeadZones(const size_t stAxisId, - const float fFDZ, const float fRDZ) - { // Get axis data and set the new values - JoyAxisInfo &jaiItem = jalData[stAxisId]; - jaiItem.AxisSetForwardDeadZone(fFDZ); - jaiItem.AxisSetReverseDeadZone(fRDZ); - } - /* -- Set default positive deadzone -------------------------------------- */ - void SetReverseDeadZone(const float fDZ) - { StdForEach(par_unseq, jalData.begin(), jalData.end(), - [fDZ](JoyAxisInfo &jaiItem) - { jaiItem.AxisSetReverseDeadZone(fDZ); }); } - /* -- Set default positive deadzone -------------------------------------- */ - void SetForwardDeadZone(const float fDZ) - { StdForEach(par_unseq, jalData.begin(), jalData.end(), - [fDZ](JoyAxisInfo &jaiItem) - { jaiItem.AxisSetForwardDeadZone(fDZ); }); } - /* -- Get/Set gamepad status ------------------------------------------- */ - void Connect(void) - { // Now connected - FlagSet(JF_CONNECTED); - // Set gamepad status - FlagSetOrClear(JF_GAMEPAD, glfwJoystickIsGamepad(GetId())); - // Get joystick name and if it's not null? - if(const char*const cpName = GlFWGetJoystickName(GetId())) - { // If monitor name is blank return blank name - if(*cpName) IdentSet(cpName); - // Return blank name - else IdentSet(cCommon->Unspec()); - } // Return null name - else IdentSet(cCommon->Null()); - // Refresh joystick data - RefreshData(); - // We gained this joystick - cLog->LogInfoExSafe("Input detected $ '$' (I:$;B:$;A:$).", - GetGamepadOrJoystickString(), IdentGet(), GetId(), GetButtonCount(), - GetAxisCount()); - // Return if it's not a gamepad - if(FlagIsClear(JF_GAMEPAD)) return; - // Report name and identifier - if(const char*const cpName = glfwGetGamepadName(GetId())) - cLog->LogDebugExSafe("- Gamepad Name: $.", cpName); - if(const char*const cpIdent = glfwGetJoystickGUID(GetId())) - cLog->LogDebugExSafe("- Gamepad Identifier: $.", cpIdent); - } - /* -- Remove connected flag ---------------------------------------------- */ - void DoDisconnect(void) { FlagClear(JF_CONNECTED); } - /* -- Reset data --------------------------------------------------------- */ - void Disconnect(void) - { // Ignore if already disconnected - if(IsDisconnected()) return; - // No longer connected - DoDisconnect(); - // We lost the specified joystick - cLog->LogInfoExSafe("Input disconnected $ '$' (I:$).", - GetGamepadOrJoystickString(), IdentGet(), GetId()); - } - /* -- Detect joystick ---------------------------------------------------- */ - bool IsPresent(void) { return glfwJoystickPresent(GetId()); } - /* -- Constructor -------------------------------------------------------- */ - explicit JoyInfo(const int iNId) : - /* -- Initialisers ----------------------------------------------------- */ - JoyFlags{ JF_NONE }, // Set no flags - /* -- Other initialisers ----------------------------------------------- */ - iId(iNId), // Set unique joystick id - /* -- Initialise joystick axes ----------------------------------------- */ -#define JAI(x) JoyAxisInfo{ GLFW_GAMEPAD_AXIS_ ## x } - /* --------------------------------------------------------------------- */ - jalData{ { // Initialise joystick axes ids - /* ------------------------------------------------------------------- */ - JAI(LEFT_X), JAI(LEFT_Y), JAI(RIGHT_X), - JAI(RIGHT_Y), JAI(LEFT_TRIGGER), JAI(RIGHT_TRIGGER) - /* ------------------------------------------------------------------- */ - } }, // End of joystic axes ids init - /* --------------------------------------------------------------------- */ -#undef JAI // Done with this macro - /* -- Initialise joystick buttons -------------------------------------- */ -#define JBL(x) JoyButtonInfo{ GLFW_GAMEPAD_BUTTON_ ## x } - /* --------------------------------------------------------------------- */ - jblData{ { // Initialise joystick buttons ids - /* ------------------------------------------------------------------- */ - JBL(A), JBL(B), JBL(X), JBL(Y), - JBL(LEFT_BUMPER), JBL(RIGHT_BUMPER), JBL(BACK), JBL(START), - JBL(GUIDE), JBL(LEFT_THUMB), JBL(RIGHT_THUMB), JBL(DPAD_UP), - JBL(DPAD_RIGHT), JBL(DPAD_DOWN), JBL(DPAD_LEFT) - /* ------------------------------------------------------------------- */ - } }, // End of joystick button ids init - /* --------------------------------------------------------------------- */ -#undef JBL // Done with this macro - /* --------------------------------------------------------------------- */ - stAxes(0), // Set no axies - stButtons(0) // Set no buttons - /* -- No code ---------------------------------------------------------- */ - { } -};/* -- Joystick state typedefs -------------------------------------------- */ -typedef array JoyList; // Actual joystick data -typedef JoyList::const_iterator JoyListIt; // Iterator for vector of joys -/* == Input class ========================================================== */ +);/* == Input class ========================================================== */ static class Input final : // Handles keyboard, mouse & controllers /* -- Base classes ------------------------------------------------------- */ private IHelper, // Initialsation helper public InputFlags, // Input configuration settings - private EvtMain::RegVec // Events list to register -{ /* -- Controller --------------------------------------------------------- */ - JoyList jlData; // Joystick data - /* -- Console ------------------------------------------------------------ */ + private EvtMain::RegVec, // Events list to register + public Joystick // Joystick class +{ /* -- Console ------------------------------------------------------------ */ int iConsoleKey1, // First console key iConsoleKey2; // Second console key /* -- Events ----------------------------------------------------- */ public: @@ -354,10 +47,7 @@ static class Input final : // Handles keyboard, mouse & controllers lfOnMouseFocus, // Mouse focus changed from window lfOnKey, // Unfiltered key pressed lfOnChar, // Filtered key pressed - lfOnDragDrop, // Drag and dropped files - lfOnJoyState; // Joystick connection event - /* -------------------------------------------------------------- */ private: - size_t stConnected; // Joysticks connected + lfOnDragDrop; // Drag and dropped files /* ----------------------------------------------------------------------- */ int iWinWidth, // Actual window width iWinHeight; // Actual window height @@ -490,49 +180,14 @@ static class Input final : // Handles keyboard, mouse & controllers vFiles.clear(); vFiles.shrink_to_fit(); } - /* -- Enable or disable joystick polling --------------------------------- */ - void EnablePolling(void) { FlagSet(IF_POLLJOYSTICKS); } - void DisablePolling(void) { FlagClear(IF_POLLJOYSTICKS); } - /* -- Joystick state changed --------------------------------------------- */ - void OnJoyState(const EvtMainEvent &emeEvent) - { // Get reference to actual arguments vector - const EvtMainArgs &emaArgs = emeEvent.aArgs; - // Get joystick id as int - const int iId = emaArgs[0].i; - // What happened to the joystick? - switch(const int iState = emaArgs[1].i) - { // Connected? - case GLFW_CONNECTED: - // Increase connected count and enable polling if the first - if(++stConnected == 1) EnablePolling(); - // Setup the joystick state and return - return SetupJoystickAndDispatch(static_cast(iId)); - // Disconnected? - case GLFW_DISCONNECTED: - // Decrease connected count and disable polling if the last - if(!--stConnected) DisablePolling(); - // Clear the joystick state and return - return ClearJoystickAndDispatch(static_cast(iId)); - // Invalid code? - default: - // Log the bad joystick state and return - cLog->LogWarningExSafe("Input ignored bad joystick state ($ = $$)!", - iId, hex, iState); - // No need to dispatch any events - return; - } - } /* -- Window past event--------------------------------------------------- */ void OnWindowPaste(const EvtMainEvent&) { // Get text in clipboard - UtfDecoder utfString{ cGlFW->WinGetClipboard() }; + IUtf::UtfDecoder utfString{ cGlFW->WinGetClipboard() }; // For each character, ddd the character to queue if valid while(const unsigned int uiChar = utfString.Next()) if(uiChar >= 32) cConsole->OnCharPress(uiChar); } - /* -- Event handler for 'glfwSetJoystickCallback' ------------------------ */ - static void OnGamePad(int iJId, int iEvent) - { cEvtMain->Add(EMC_INP_JOY_STATE, iJId, iEvent); } /* -- Commit cursor visibility now ------------------------------- */ public: void CommitCursorNow(void) { cGlFW->WinSetCursor(FlagIsSet(IF_CURSOR)); } /* -- Commit cursor visibility ------------------------------------------- */ @@ -550,20 +205,9 @@ static class Input final : // Handles keyboard, mouse & controllers void ResetEnvironment(void) { // Reset cursor visibility SetCursor(true); - // For each joystick - for(JoyInfo &jsData : GetJoyList()) - { // Clear the connected flag - jsData.DoDisconnect(); - // Clear the state - jsData.ClearState(); - } // No devices connected until the joystick event is set again. - stConnected = 0; - // Disable polling - DisablePolling(); + // Reset joystick environment + JoyReset(); } - /* -- Get joystick list data --------------------------------------------- */ - JoyList &GetJoyList(void) { return jlData; } - const JoyList &GetConstJoyList(void) const { return jlData; } /* -- Get window size ---------------------------------------------------- */ int GetWindowWidth(void) const { return iWinWidth; } int GetWindowHeight(void) const { return iWinHeight; } @@ -597,79 +241,9 @@ static class Input final : // Handles keyboard, mouse & controllers void SetCursorCentre(void) { SetCursorPos(cFboCore->GetMatrixWidth() / 2.0f, cFboCore->GetMatrixHeight() / 2.0f); } - /* -- Joystick main tick ------------------------------------------------- */ - void DoPollJoysticks(void) - { for(JoyInfo &jsData : GetJoyList()) - jsData.RefreshDataIfConnected(); } - void PollJoysticks(void) - { if(FlagIsSet(IF_POLLJOYSTICKS)) DoPollJoysticks(); } - bool JoystickExists(const size_t stId) - { return GetJoyData(stId).IsConnected(); } - /* -- Dispatch connected event to lua ------------------------------------ */ - void DispatchLuaEvent(const size_t stJoystickId, const bool bConnected) - { lfOnJoyState.LuaFuncDispatch(static_cast(stJoystickId), - bConnected); } - /* -- DeInitialise a joystick -------------------------------------------- */ - void ClearJoystickAndDispatch(const size_t stJoystickId) - { // Get joystick data and ign ore if joystick wasn't originally connected - JoyInfo &jsData = GetJoyData(stJoystickId); - if(jsData.IsDisconnected()) return; - // Send lua event to let guest know joystick was disconnected - DispatchLuaEvent(stJoystickId, false); - // Clear joystick, axis and button data - jsData.Disconnect(); - jsData.ClearState(); - } - /* -- Initialise a new joystick ------------------------------------------ */ - void SetupJoystickAndDispatch(const size_t stJoystickId) - { // Get joystick data and ign ore if joystick wasn't originally connected - JoyInfo &jsData = GetJoyData(stJoystickId); - if(jsData.IsConnected()) return; - // Begin detection and refresh data - jsData.Connect(); - jsData.RefreshData(); - // Send lua event to let guest know joystick was connected and return - DispatchLuaEvent(stJoystickId, true); - } - /* -- Return a joystick is present? -------------------------------------- */ - void AutoDetectJoystick(void) - { // Reset connected count - stConnected = 0; - // Enumerate joysticks and if joystick is present? - for(JoyInfo &jsData : GetJoyList()) - // If joystick is present? - if(jsData.IsPresent()) - { // Send event that the joystick was connected - SetupJoystickAndDispatch(static_cast(jsData.GetId())); - // Increase connected count - ++stConnected; - } // Send event that the joystick was disconnected - else ClearJoystickAndDispatch(static_cast(jsData.GetId())); - // If we did not find joysticks? - if(!stConnected) - { // Disable polling to not waste CPU cycles - DisablePolling(); - // Log no controllers - return cLog->LogDebugSafe("Input detected no controller devices."); - } // Enable polling - EnablePolling(); - // Log result - cLog->LogDebugExSafe( - "Input enabling joystick polling as $ devices are detected.", - stConnected); - } - /* -- Clear joystick state ----------------------------------------------- */ - void ClearJoystickButtons(void) - { StdForEach(par_unseq, GetJoyList().begin(), GetJoyList().end(), - [](JoyInfo &jsData) { jsData.ClearButtonStateIfConnected(); }); } - /* -- Clear keyboard, mouse and joystick states -------------------------- */ - void ClearJoyStates(void) { ClearJoystickButtons(); } - /* -- Return joystick data ----------------------------------------------- */ - JoyInfo &GetJoyData(const size_t stId) { return GetJoyList()[stId]; } - /* -- Return joysticks count --------------------------------------------- */ - size_t GetJoyCount(void) const { return GetConstJoyList().size(); } - /* -- Disable/Enable input events ---------------------------------------- */ + /* -- Disable input events ----------------------------------------------- */ void DisableInputEvents(void) { cEvtMain->UnregisterEx(*this); } + /* -- Enable input events ------------------------------------------------ */ void EnableInputEvents(void) { cEvtMain->RegisterEx(*this); } /* -- Init --------------------------------------------------------------- */ void Init(void) @@ -684,19 +258,19 @@ static class Input final : // Handles keyboard, mouse & controllers IHInitialise(); // Log progress cLog->LogDebugSafe("Input interface is initialising..."); - // Init input engine events - EnableInputEvents(); // Init input settings SetRawMouseEnabled(cCVars->GetInternal(INP_RAWMOUSE)); SetStickyKeyEnabled(cCVars->GetInternal(INP_STICKYKEY)); SetStickyMouseEnabled(cCVars->GetInternal(INP_STICKYMOUSE)); // Set/Restore cursor state SetCursor(FlagIsSet(IF_CURSOR)); - // Register joystick callback - glfwSetJoystickCallback(OnGamePad); + // Init joystick system + JoyInit(); + // Init input engine events + EnableInputEvents(); // Log progress cLog->LogDebugExSafe("Input interface initialised (R:$;J:$).", - StrFromBoolTF(GlFWIsRawMouseMotionSupported()), GetJoyCount()); + StrFromBoolTF(GlFWIsRawMouseMotionSupported()), JoyGetCount()); } /* -- DeInit ------------------------------------------------------------- */ void DeInit(void) @@ -704,18 +278,18 @@ static class Input final : // Handles keyboard, mouse & controllers if(IHNotDeInitialise()) return; // Log progress cLog->LogDebugSafe("Input interface deinitialising..."); - // Unregister joystick callback - glfwSetJoystickCallback(nullptr); // Deinit engine events in the order they were registered DisableInputEvents(); + // De-init joystick system + JoyDeInit(); // Log progress cLog->LogDebugSafe("Input interface deinitialised."); } /* -- Constructor -------------------------------------------------------- */ Input(void) : /* -- Initialisers ----------------------------------------------------- */ - IHelper(__FUNCTION__), // Init initialisation helper class - InputFlags(IF_NONE), // No flags set initially + IHelper{ __FUNCTION__ }, // Init initialisation helper class + InputFlags{ IF_NONE }, // No flags set initially /* -- Init events for event manager ------------------------------------ */ EvtMain::RegVec{ // Events list to register { EMC_INP_CHAR, bind(&Input::OnFilteredKey, this, _1) }, @@ -726,17 +300,8 @@ static class Input final : // Handles keyboard, mouse & controllers { EMC_INP_MOUSE_SCROLL, bind(&Input::OnMouseWheel, this, _1) }, { EMC_INP_KEYPRESS, bind(&Input::OnKeyPress, this, _1) }, { EMC_INP_DRAG_DROP, bind(&Input::OnDragDrop, this, _1) }, - { EMC_INP_JOY_STATE, bind(&Input::OnJoyState, this, _1) }, + { EMC_INP_JOY_STATE, bind(&Joystick::OnJoyState, this, _1) }, }, - /* -- Init joysticks --------------------------------------------------- */ - jlData{ { JoyInfo{ GLFW_JOYSTICK_1 }, JoyInfo{ GLFW_JOYSTICK_2 }, - JoyInfo{ GLFW_JOYSTICK_3 }, JoyInfo{ GLFW_JOYSTICK_4 }, - JoyInfo{ GLFW_JOYSTICK_5 }, JoyInfo{ GLFW_JOYSTICK_6 }, - JoyInfo{ GLFW_JOYSTICK_7 }, JoyInfo{ GLFW_JOYSTICK_8 }, - JoyInfo{ GLFW_JOYSTICK_9 }, JoyInfo{ GLFW_JOYSTICK_10 }, - JoyInfo{ GLFW_JOYSTICK_11 }, JoyInfo{ GLFW_JOYSTICK_12 }, - JoyInfo{ GLFW_JOYSTICK_13 }, JoyInfo{ GLFW_JOYSTICK_14 }, - JoyInfo{ GLFW_JOYSTICK_15 }, JoyInfo{ GLFW_JOYSTICK_16 } } }, /* -- More initialisers ------------------------------------------------ */ iConsoleKey1(GLFW_KEY_UNKNOWN), // Init primary console key iConsoleKey2(GLFW_KEY_UNKNOWN), // Init secondary console key @@ -747,8 +312,6 @@ static class Input final : // Handles keyboard, mouse & controllers lfOnKey{ "OnUnfilteredKey" }, // Init unfiltered keypress lua event lfOnChar{ "OnFilteredKey" }, // Init filtered keypress lua event lfOnDragDrop{ "OnDragDrop" }, // Init drag & drop lua event - lfOnJoyState{ "OnJoyState" }, // Init joy state lua event - stConnected(0), // Init joystick count to zero iWinWidth(0), // Window width init by display iWinHeight(0) // Window height init by display /* -- No code ---------------------------------------------------------- */ @@ -778,25 +341,6 @@ static class Input final : // Handles keyboard, mouse & controllers // CVar allowed to be set return ACCEPT; } - /* -- Handle a deadzone change ------------------------------------------- */ - CVarReturn SetDefaultJoyDZ(const float fDZ, - const function &fcbCallBack) - { // Bail if invalid deadzone - if(fDZ > 1) return DENY; - // Set it - StdForEach(par_unseq, GetJoyList().begin(), - GetJoyList().end(), fcbCallBack); - // Success - return ACCEPT; - } - /* -- Set default negative deadzone -------------------------------------- */ - CVarReturn SetDefaultJoyRevDZ(const float fNewDeadZone) - { return SetDefaultJoyDZ(fNewDeadZone, [fNewDeadZone](JoyInfo &jiItem) - { jiItem.SetReverseDeadZone(fNewDeadZone); }); } - /* -- Set default positive deadzone -------------------------------------- */ - CVarReturn SetDefaultJoyFwdDZ(const float fNewDeadZone) - { return SetDefaultJoyDZ(fNewDeadZone, [fNewDeadZone](JoyInfo &jiItem) - { jiItem.SetForwardDeadZone(fNewDeadZone); }); } /* -- Set first console key ---------------------------------------------- */ CVarReturn SetConsoleKey1(const int iK) { return CVarSimpleSetIntNG(iConsoleKey1, iK, GLFW_KEY_LAST); } diff --git a/src/joystick.hpp b/src/joystick.hpp new file mode 100644 index 0000000..89ef4e6 --- /dev/null +++ b/src/joystick.hpp @@ -0,0 +1,582 @@ +/* == JOYSTICK.HPP ========================================================= ** +** ######################################################################### ** +** ## Mhatxotic Engine (c) Mhatxotic Design, All Rights Reserved ## ** +** ######################################################################### ** +** ## This module defines classes for setting and accessing joystick data ## ** +** ######################################################################### ** +** ========================================================================= */ +#pragma once // Only one incursion allowed +/* ------------------------------------------------------------------------- */ +namespace IJoystick { // Start of private module namespace +/* -- Dependencies --------------------------------------------------------- */ +using namespace ICVarDef::P; using namespace IEvtMain::P; +using namespace IEvtWin::P; using namespace IFlags; +using namespace IGlFWUtil::P; using namespace IIdent::P; +using namespace ILog::P; using namespace ILuaFunc::P; +using namespace IStd::P; using namespace IString::P; +using namespace Lib::OS::GlFW; +/* ------------------------------------------------------------------------- */ +namespace P { // Start of public module namespace +/* == Input flags ========================================================== */ +BUILD_FLAGS(Input, + /* ----------------------------------------------------------------------- */ + // No flags Mouse cursor is enabled? + IF_NONE {Flag[0]}, IF_CURSOR {Flag[1]}, + // Full-screen toggler enabled? Mouse cursor has focus? + IF_FSTOGGLER {Flag[2]}, IF_MOUSEFOCUS {Flag[3]}, + // Send events at startup Do joystick polling? + IF_INITEVENTS {Flag[4]}, IF_POLLJOYSTICKS {Flag[5]} +);/* -- Axis class --------------------------------------------------------- */ +class JoyAxisInfo +{ /* -------------------------------------------------------------- */ private: + const int iId; // Axis unique identifier + float fDeadZoneR; // Reverse deadzone threshold + float fDeadZoneF; // Forward deadzone threshold + float fUnbuffered; // Current unbuffered axis press state + int iBuffered; // Current buffered axis press state + /* -- Get axis identifier ---------------------------------------- */ public: + int AxisGetId(void) const { return iId; } + /* -- Get reverse deadzone value ----------------------------------------- */ + float AxisGetReverseDeadZone(void) const { return fDeadZoneR; } + /* -- Get forward deadzone value ----------------------------------------- */ + float AxisGetForwardDeadZone(void) const { return fDeadZoneF; } + /* -- Set reverse deadzone value ----------------------------------------- */ + void AxisSetReverseDeadZone(const float fDZ) { fDeadZoneR = -fDZ; } + /* -- Set forward deadzone value ----------------------------------------- */ + void AxisSetForwardDeadZone(const float fDZ) { fDeadZoneF = fDZ; } + /* -- Get unbuffered state ----------------------------------------------- */ + float AxisGetUnbufferedState(void) const { return fUnbuffered; } + /* -- Get buffered state ------------------------------------------------- */ + int AxisGetBufferedState(void) const { return iBuffered; } + /* -- Clear button state ------------------------------------------------- */ + void AxisClearState(void) { fUnbuffered = 0.0f; iBuffered = GLFW_RELEASE; } + /* -- Set axis state ----------------------------------------------------- */ + void AxisSetState(const float*const fpData) + { // Get the axis reading and if it's moving negatively? + fUnbuffered = fpData[AxisGetId()]; + if(fUnbuffered < fDeadZoneR) + { // Released or already in reverse position? + if(iBuffered <= GLFW_RELEASE) + { // Set to -GLFW_REPEAT if currently -GLFW_PRESSED or + // -GLFW_PRESSED if currently GLFW_RELEASE + if(iBuffered > -GLFW_REPEAT) --iBuffered; + // State changed + return; + } + } // Moving positively? + else if(fUnbuffered > fDeadZoneF) + { // Released or already in forward position? + if(iBuffered >= GLFW_RELEASE) + { // Set to GLFW_REPEAT if currentl GLFW_PRESSED or + // GLFW_PRESSED if currently GLFW_RELEASE + if(iBuffered < GLFW_REPEAT) ++iBuffered; + // State changed + return; + } + } // Nothing pressed so reset buffered counter + iBuffered = GLFW_RELEASE; + } + /* -- Constructor with unique id ----------------------------------------- */ + explicit JoyAxisInfo(const int iNId) : + /* -- Initialisers ----------------------------------------------------- */ + iId(iNId), // Set unique id + fDeadZoneR(-0.25f), // Set default reverse deadzone + fDeadZoneF(0.25f), // Set default forward deadzone + fUnbuffered(0.0f), // Set default unbuffered state + iBuffered(GLFW_RELEASE) // Set default state + /* -- No code ---------------------------------------------------------- */ + { } +};/* -- Axis data list type ------------------------------------------------ */ +template, + class Iterator = typename Container::const_iterator> + class JoyAxisList : private Container +{ /* -------------------------------------------------------------- */ private: + int iAxes; // Button count as int + /* -- Return axes count clamped ------------------------------------------ */ + int JoyAxisListSizeCountClamped(void) const { return iAxes & 0x7f; } + /* -- Return button class ------------------------------------------------ */ + JoyAxisInfo &JoyAxisListGetMod(const size_t stId) { return (*this)[stId]; } + /* -- Return axes array size ------------------------------------- */ public: + size_t JoyAxisListSize(void) const { return this->size(); } + /* -- Return axes count -------------------------------------------------- */ + size_t JoyAxisListCount(void) const { return static_cast(iAxes); } + /* -- Return button class ------------------------------------------------ */ + const JoyAxisInfo &JoyAxisListGet(const size_t stId) const + { return (*this)[stId]; } + /* -- Clear button data -------------------------------------------------- */ + void JoyAxisListClear(void) + { StdForEach(par_unseq, this->begin(), + this->begin() + JoyAxisListSizeCountClamped(), + [](JoyAxisInfo& jaiRef) { jaiRef.AxisClearState(); }); } + /* -- Refresh button data ------------------------------------------------ */ + void JoyAxisListRefresh(const int iJId) + { // Get joystick axes and if found? Refresh axes data for each one + if(const float *fpData = GlFWGetJoystickAxes(iJId, iAxes)) + StdForEach(seq, this->begin(), + this->begin() + JoyAxisListSizeCountClamped(), + [fpData](JoyAxisInfo &jaiData){ jaiData.AxisSetState(fpData); }); + else iAxes = 0; + } + /* -- Get axis state ----------------------------------------------------- */ + void JoyAxisListSetForwardDeadZone(const size_t stAxisId, const float fDZ) + { JoyAxisListGetMod(stAxisId).AxisSetForwardDeadZone(fDZ); } + void JoyAxisListSetReverseDeadZone(const size_t stAxisId, const float fDZ) + { JoyAxisListGetMod(stAxisId).AxisSetReverseDeadZone(fDZ); } + void JoyAxisListSetDeadZones(const size_t stAxisId, + const float fFDZ, const float fRDZ) + { // Get axis data and set the new values + JoyAxisInfo &jaiItem = JoyAxisListGetMod(stAxisId); + jaiItem.AxisSetForwardDeadZone(fFDZ); + jaiItem.AxisSetReverseDeadZone(fRDZ); + } + /* -- Set default positive deadzone -------------------------------------- */ + void JoyAxisListSetReverseDeadZone(const float fDZ) + { StdForEach(par_unseq, this->begin(), + this->end() + JoyAxisListSizeCountClamped(), + [fDZ](JoyAxisInfo &jaiItem) + { jaiItem.AxisSetReverseDeadZone(fDZ); }); } + /* -- Set default positive deadzone -------------------------------------- */ + void JoyAxisListSetForwardDeadZone(const float fDZ) + { StdForEach(par_unseq, this->begin(), + this->end() + JoyAxisListSizeCountClamped(), + [fDZ](JoyAxisInfo &jaiItem) + { jaiItem.AxisSetForwardDeadZone(fDZ); }); } + /* -- Iterators ---------------------------------------------------------- */ + Iterator JoyAxisListBegin(void) const + { return this->cbegin(); } + Iterator JoyAxisListEnd(void) const + { return this->cbegin() + JoyAxisListSizeCountClamped(); } + /* -- Default constructor ------------------------------------- */ protected: + JoyAxisList(void) : + /* -- Initialise joystick buttons -------------------------------------- */ +#define JAIX(x) JoyAxisInfo{ x } +#define JAI(x) JAIX(GLFW_GAMEPAD_AXIS_ ## x) + /* --------------------------------------------------------------------- */ + Container{{ // Initialise joystick axes ids + /* ------------------------------------------------------------------- */ + JAI(LEFT_X), JAI(LEFT_Y), JAI(RIGHT_X), JAI(RIGHT_Y), + JAI(LEFT_TRIGGER), JAI(RIGHT_TRIGGER), JAIX(7), JAIX(8) + /* ------------------------------------------------------------------- */ + }}, // End of joystick axes ids init + /* --------------------------------------------------------------------- */ +#undef JAI // Done with this macro +#undef JAIX // Done with this macro + /* --------------------------------------------------------------------- */ + iAxes(0) // Initialise axes count + /* -- No code ---------------------------------------------------------- */ + { } + /* ----------------------------------------------------------------------- */ + DELETECOPYCTORS(JoyAxisList) // Suppress default functions for safety +};/* ----------------------------------------------------------------------- */ + +/* -- Button class --------------------------------------------------------- */ +class JoyButtonInfo +{ /* -- Private variables ----------------------------------------- */ private: + const int iId; // Button unique identifier + unsigned int uiState; // Current buffered butn press state + /* -- Get button id ---------------------------------------------- */ public: + int ButtonGetId(void) const { return iId; } + /* -- Get buffered state (GLFW_RELEASE, GLFW_PRESS or GLFW_REPEAT) ------- */ + unsigned int ButtonGetState(void) const { return uiState; } + /* -- Clear button state ------------------------------------------------- */ + void ButtonClearState(void) { uiState = GLFW_RELEASE; } + /* -- Set button state --------------------------------------------------- */ + void ButtonSetState(const unsigned char*const ucpState) + { // Save unbuffered state and compare it + switch(const unsigned int uiUnbuffered = + static_cast(ucpState[ButtonGetId()])) + { // Button is released? + case GLFW_RELEASE: + // Reset button state if not released (0 = released) + if(uiState > GLFW_RELEASE) uiState = GLFW_RELEASE; + // Done + return; + // Button is pressed? Increase button state (1=pressed and 2=held) + case GLFW_PRESS: + // Set GLFW_PRESSED if GLFW_RELEASED or + // GLFW_REPEAT if GLFW_PRESSED. + if(uiState < GLFW_REPEAT) ++uiState; + // Done + return; + // Shouldn't get here + default: + // Reset to released + uiState = GLFW_RELEASE; + // Done + return; + } + } + /* -- Constructor with unique id ----------------------------------------- */ + explicit JoyButtonInfo(const int iNId) : + /* -- Initialisers ----------------------------------------------------- */ + iId(iNId), // Set unique id + uiState(GLFW_RELEASE) // Set default buffered state + /* -- No code ---------------------------------------------------------- */ + { } +};/* -- Button data list --------------------------------------------------- */ +template, + class Iterator = typename Container::const_iterator> + class JoyButtonList : private Container +{ /* ----------------------------------------------------------------------- */ + int iButtons; // Button count as int + /* -- Return button array size ----------------------------------- */ public: + int JoyButtonListSizeCountClamped(void) const { return iButtons & 0x7f; } + /* -- Return button array size ------------------------------------------- */ + size_t JoyButtonListSize(void) const { return this->size(); } + /* -- Return button count ------------------------------------------------ */ + size_t JoyButtonListCount(void) const + { return static_cast(iButtons); } + /* -- Return button class ------------------------------------------------ */ + const JoyButtonInfo &JoyButtonListGet(const size_t stId) const + { return (*this)[stId]; } + /* -- Clear button data -------------------------------------------------- */ + void JoyButtonListClear(void) + { StdForEach(par_unseq, this->begin(), + this->begin() + JoyButtonListSizeCountClamped(), + [](JoyButtonInfo& jbiRef) { jbiRef.ButtonClearState(); }); } + /* -- Refresh button data ------------------------------------------------ */ + void JoyButtonListRefresh(const int iJId) + { // Get joystick buttons and if found? Refresh button data for each one + if(const unsigned char*const ucpData = + GlFWGetJoystickButtons(iJId, iButtons)) + StdForEach(seq, this->begin(), + this->begin() + JoyButtonListSizeCountClamped(), + [ucpData](JoyButtonInfo &jbiData){ jbiData.ButtonSetState(ucpData); }); + else iButtons = 0; + } + /* -- Iterators ---------------------------------------------------------- */ + Iterator JoyButtonListBegin(void) const + { return this->cbegin(); } + Iterator JoyButtonListEnd(void) const + { return this->cbegin() + JoyButtonListSizeCountClamped(); } + /* -- Default constructor ------------------------------------- */ protected: + JoyButtonList(void) : + /* -- Initialise joystick buttons -------------------------------------- */ +#define JBLX(x) JoyButtonInfo{ x } +#define JBL(n) JBLX(GLFW_GAMEPAD_BUTTON_ ## n) + /* --------------------------------------------------------------------- */ + Container{{ // Initialise joystick buttons ids + /* ------------------------------------------------------------------- */ + JBL(A), JBL(B), JBL(X), JBL(Y), + JBL(LEFT_BUMPER), JBL(RIGHT_BUMPER), JBL(BACK), JBL(START), + JBL(GUIDE), JBL(LEFT_THUMB), JBL(RIGHT_THUMB), JBL(DPAD_UP), + JBL(DPAD_RIGHT), JBL(DPAD_DOWN), JBL(DPAD_LEFT), + JBLX( 15),JBLX( 16),JBLX( 17),JBLX( 18),JBLX( 19),JBLX( 20),JBLX( 21), + JBLX( 22),JBLX( 23),JBLX( 24),JBLX( 25),JBLX( 26),JBLX( 27),JBLX( 28), + JBLX( 29),JBLX( 30),JBLX( 31),JBLX( 32),JBLX( 33),JBLX( 34),JBLX( 35), + JBLX( 36),JBLX( 37),JBLX( 38),JBLX( 39),JBLX( 40),JBLX( 41),JBLX( 42), + JBLX( 43),JBLX( 44),JBLX( 45),JBLX( 46),JBLX( 47),JBLX( 48),JBLX( 49), + JBLX( 50),JBLX( 51),JBLX( 52),JBLX( 53),JBLX( 54),JBLX( 55),JBLX( 56), + JBLX( 57),JBLX( 58),JBLX( 59),JBLX( 60),JBLX( 61),JBLX( 62),JBLX( 63), + JBLX( 64),JBLX( 65),JBLX( 66),JBLX( 67),JBLX( 68),JBLX( 69),JBLX( 70), + JBLX( 71),JBLX( 72),JBLX( 73),JBLX( 74),JBLX( 75),JBLX( 76),JBLX( 77), + JBLX( 78),JBLX( 79),JBLX( 80),JBLX( 81),JBLX( 82),JBLX( 83),JBLX( 84), + JBLX( 85),JBLX( 86),JBLX( 87),JBLX( 88),JBLX( 89),JBLX( 90),JBLX( 91), + JBLX( 92),JBLX( 93),JBLX( 94),JBLX( 95),JBLX( 96),JBLX( 97),JBLX( 98), + JBLX( 99),JBLX(100),JBLX(101),JBLX(102),JBLX(103),JBLX(104),JBLX(105), + JBLX(106),JBLX(107),JBLX(108),JBLX(109),JBLX(110),JBLX(111),JBLX(112), + JBLX(113),JBLX(114),JBLX(115),JBLX(116),JBLX(117),JBLX(118),JBLX(119), + JBLX(120),JBLX(121),JBLX(122),JBLX(123),JBLX(124),JBLX(125),JBLX(126), + JBLX(127) + /* ------------------------------------------------------------------- */ + }}, // End of joystick button ids init + /* ------------------------------------------------------------------- */ +#undef JBL // Done with this macro +#undef JBX // Done with this macro + /* --------------------------------------------------------------------- */ + iButtons(0) // Initialise button count + /* -- No code ---------------------------------------------------------- */ + { } + /* ----------------------------------------------------------------------- */ + DELETECOPYCTORS(JoyButtonList) // Suppress default functions for safety +};/* ----------------------------------------------------------------------- */ +/* -- Joystick type typedef ------------------------------------------------ */ +BUILD_FLAGS(Joy, + /* ----------------------------------------------------------------------- */ + // No flags Joystick is connnected? + JF_NONE {Flag[0]}, JF_CONNECTED {Flag[1]}, + // Joystick is actually a gamepad + JF_GAMEPAD {Flag[2]} +);/* -- Joystick class ----------------------------------------------------- */ +class JoyInfo : + /* -- Base classes ------------------------------------------------------- */ + public JoyFlags, // Joystick flags + public Ident, // Joystick identifier + public JoyAxisList<>, // Joystick axes list + public JoyButtonList<> // Joystick button list +{ /* ----------------------------------------------------------------------- */ + const int iId; // Unique identifier of this + string strName, // Name of controller + strGuid; // Guid of controller + /* -- Return joystick id ----------------------------------------- */ public: + int JoyGetId(void) const { return iId; } + /* -- Return type of joystick -------------------------------------------- */ + const string_view &JoyGetGamepadOrJoystickString(void) const + { // Return if it is a gamepad or a joystick + static const string_view svGamepad{ "gamepad" }, + svJoystick{ "joystick" }; + return FlagIsSet(JF_GAMEPAD) ? svGamepad : svJoystick; + } + /* -- Refresh data ------------------------------------------------------- */ + void JoyRefreshData(void) + { JoyAxisListRefresh(JoyGetId()); JoyButtonListRefresh(JoyGetId()); } + /* -- Joystick is connected/disconnected? -------------------------------- */ + bool JoyIsConnected(void) const { return FlagIsSet(JF_CONNECTED); } + bool JoyIsDisconnected(void) const { return !JoyIsConnected(); } + /* -- Clear button state if connected ------------------------------------ */ + void JoyClearButtonStateIfConnected(void) + { if(JoyIsConnected()) JoyButtonListClear(); } + /* -- Clear buttons and axis state --------------------------------------- */ + void JoyClearState(void) { JoyAxisListClear(); JoyButtonListClear(); } + /* -- Refresh data if connected ------------------------------------------ */ + void JoyRefreshDataIfConnected(void) + { if(JoyIsConnected()) JoyRefreshData(); } + /* -- Return gamepad name ------------------------------------------------ */ + const string &JoyGamePadName(void) const { return strName; } + /* -- Return guid name --------------------------------------------------- */ + const string &JoyGUID(void) const { return strGuid; } + /* -- Return if joystick is a gamepad ------------------------------------ */ + bool JoyIsGamepad(void) const { return FlagIsSet(JF_GAMEPAD); } + /* -- Get/Set gamepad status --------------------------------------------- */ + void JoyConnect(void) + { // Now connected + FlagSet(JF_CONNECTED); + // Set gamepad status + FlagSetOrClear(JF_GAMEPAD, GlFWJoystickIsGamepad(JoyGetId())); + // Get joystick name and if it's not null? + if(const char*const cpName = GlFWGetJoystickName(JoyGetId())) + { // If monitor name is blank return blank name + if(*cpName) IdentSet(cpName); + // Return blank name + else IdentSet(cCommon->Unspec()); + } // Return null name + else IdentSet(cCommon->Null()); + // Refresh joystick data + JoyRefreshData(); + // We gained this joystick + cLog->LogInfoExSafe("Joystick detected $ '$' (I:$;B:$;A:$).", + JoyGetGamepadOrJoystickString(), IdentGet(), JoyGetId(), + JoyButtonListCount(), JoyAxisListCount()); + // Report unique identifier + if(const char*const cpIdent = GlFWGetJoystickGUID(JoyGetId())) + { // Save guid for future reference and log the identifier + strGuid = cpIdent; + cLog->LogDebugExSafe("- Identifier: $.", strGuid); + } // Clear guid + else strGuid = cCommon->Null(); + // Report name if gamepad + if(JoyIsGamepad()) + if(const char*const cpName = GlFWGetGamepadName(JoyGetId())) + { // Save name for future reference and log the identifier + strName = cpName; + cLog->LogDebugExSafe("- Gamepad Name: $.", strName); + } // Clear name + else strName = cCommon->Null(); + else strName.clear(); + } + /* -- Remove connected flag ---------------------------------------------- */ + void JoyDoDisconnect(void) { FlagClear(JF_CONNECTED); } + /* -- Reset data --------------------------------------------------------- */ + void JoyDisconnect(void) + { // Ignore if already disconnected + if(JoyIsDisconnected()) return; + // No longer connected + JoyDoDisconnect(); + // We lost the specified joystick + cLog->LogInfoExSafe("Joystick disconnected $ '$' (I:$).", + JoyGetGamepadOrJoystickString(), IdentGet(), JoyGetId()); + } + /* -- Detect joystick ---------------------------------------------------- */ + bool JoyIsPresent(void) { return GlFWJoystickPresent(JoyGetId()); } + /* -- Constructor -------------------------------------------------------- */ + explicit JoyInfo(const int iNId) : + /* -- Initialisers ----------------------------------------------------- */ + JoyFlags{ JF_NONE }, // Set no flags + /* -- Other initialisers ----------------------------------------------- */ + iId(iNId) // Set unique joystick id + /* -- No code ---------------------------------------------------------- */ + { } +};/* -- Joystick state typedefs -------------------------------------------- */ +typedef array JoyList; // Actual joystick data +typedef JoyList::const_iterator JoyListIt; // Iterator for vector of joys +/* ------------------------------------------------------------------------- */ +class Joystick : + /* -- Base classes ------------------------------------------------------- */ + public JoyList // Joystick list data classes +{ /* -- Variables ---------------------------------------------------------- */ + bool bPoll; // Poll joysticks? + LuaFunc lfOnJoyState; // Joystick lua event + size_t stConnected; // Joysticks connected + /* -- Event handler for 'glfwSetJoystickCallback' ------------------------ */ + static void OnGamePad(int iJId, int iEvent) + { cEvtMain->Add(EMC_INP_JOY_STATE, iJId, iEvent); } + /* -- Enable or disable joystick polling --------------------------------- */ + void JoyEnablePoll(void) { bPoll = true; } + void JoyDisablePoll(void) { bPoll = false; } + /* -- Dispatch connected event to lua ------------------------------------ */ + void JoyDispatchLuaEvent(const size_t stJoystickId, const bool bConnected) + { lfOnJoyState.LuaFuncDispatch(static_cast(stJoystickId), + bConnected); } + /* -- Joystick state changed ------------------------------------- */ public: + void OnJoyState(const EvtMainEvent &emeEvent) + { // Get reference to actual arguments vector + const EvtMainArgs &emaArgs = emeEvent.aArgs; + // Get joystick id as int + const int iJId = emaArgs[0].i, iEvent = emaArgs[1].i; + // Show warning if joystick id is out of range + if(static_cast(iJId) >= JoyGetCount()) + return cLog->LogWarningExSafe( + "Joystick event $ for id $ is out of range!", iEvent, iJId); + // What happened to the joystick? + switch(iEvent) + { // Connected? + case GLFW_CONNECTED: + // Increase connected count and enable polling if the first + if(++stConnected == 1) JoyEnablePoll(); + // Setup the joystick state and return + return JoySetupDispatch(static_cast(iJId)); + // Disconnected? + case GLFW_DISCONNECTED: + // Decrease connected count and disable polling if the last + if(!--stConnected) JoyDisablePoll(); + // Clear the joystick state and return + return JoyClearDispatch(static_cast(iJId)); + // Invalid code? + default: + // Log the bad joystick state and return + cLog->LogWarningExSafe("Joystick ignored bad state $$ for id $$!", + hex, iEvent, dec, iJId); + // No need to dispatch any events + return; + } + } + /* -- Poll joysticks if enabled ------------------------------------------ */ + void JoyPoll(void) + { if(bPoll) + for(JoyInfo &jiRef : *this) jiRef.JoyRefreshDataIfConnected(); } + /* -- Return event ------------------------------------------------------- */ + LuaFunc &JoyGetLuaEvent(void) { return lfOnJoyState; } + /* -- Return writable joystick data -------------------------------------- */ + JoyInfo &JoyGet(const size_t stJId) { return (*this)[stJId]; } + /* -- Return read-only joystick data ------------------------------------- */ + const JoyInfo &JoyGetConst(const size_t stJId) const + { return (*this)[stJId]; } + /* -- Get read-only acess to joystick list ------------------------------- */ + const JoyList &JoyListGetConst(void) const { return *this; } + /* -- Get connected count ----------------------------------------------- */ + size_t JoyGetConnected(void) const { return stConnected; } + /* -- Return joysticks count --------------------------------------------- */ + size_t JoyGetCount(void) const { return JoyListGetConst().size(); } + /* -- Return if joystick is connected ------------------------------------ */ + bool JoyIsConnected(const size_t stId) + { return JoyGetConst(stId).JoyIsConnected(); } + /* -- Clear buttons and axis state --------------------------------------- */ + void JoyClearStates(void) + { StdForEach(par_unseq, this->begin(), this->end(), + [](JoyInfo &jiRef) { jiRef.JoyClearButtonStateIfConnected(); }); } + /* -- DeInitialise a joystick -------------------------------------------- */ + void JoyClearDispatch(const size_t stJoystickId) + { // Get joystick data and ign ore if joystick wasn't originally connected + JoyInfo &jiRef = JoyGet(stJoystickId); + if(jiRef.JoyIsDisconnected()) return; + // Send lua event to let guest know joystick was disconnected + JoyDispatchLuaEvent(stJoystickId, false); + // Clear joystick, axis and button data + jiRef.JoyDisconnect(); + jiRef.JoyClearState(); + } + /* -- Initialise a new joystick ------------------------------------------ */ + void JoySetupDispatch(const size_t stJoystickId) + { // Get joystick data and ign ore if joystick wasn't originally connected + JoyInfo &jiRef = JoyGet(stJoystickId); + if(jiRef.JoyIsConnected()) return; + // Begin detection and refresh data + jiRef.JoyConnect(); + jiRef.JoyRefreshData(); + // Send lua event to let guest know joystick was connected and return + JoyDispatchLuaEvent(stJoystickId, true); + } + /* -- Return a joystick is present? -------------------------------------- */ + void JoyDetect(void) + { // Reset connected count + stConnected = 0; + // Enumerate joysticks and if joystick is present? + for(JoyInfo &jiRef : *this) + // If joystick is present? + if(jiRef.JoyIsPresent()) + { // Send event that the joystick was connected + JoySetupDispatch(static_cast(jiRef.JoyGetId())); + // Increase connected count + ++stConnected; + } // Send event that the joystick was disconnected + else JoyClearDispatch(static_cast(jiRef.JoyGetId())); + // If we did not find joysticks? + if(!JoyGetConnected()) + { // Disable polling to not waste CPU cycles + JoyDisablePoll(); + // Log no controllers + return cLog->LogDebugSafe("Joystick detected no controller devices."); + } // Enable polling + JoyEnablePoll(); + // Log result + cLog->LogDebugExSafe( + "Joystick enabling joystick polling as $ devices are detected.", + JoyGetConnected()); + } + /* -- Reset environment -------------------------------------------------- */ + void JoyReset(void) + { // For each joystick + for(JoyInfo &jiRef : *this) + { // Clear the connected flag and clear the state + jiRef.JoyDoDisconnect(); + jiRef.JoyClearState(); + } // No devices connected until the joystick event is set again. + stConnected = 0; + // Disable polling + JoyDisablePoll(); + } + /* -- Init/DeInit joystick callback -------------------------------------- */ + void JoyInit(void) const { glfwSetJoystickCallback(OnGamePad); } + void JoyDeInit(void) const { glfwSetJoystickCallback(nullptr); } + /* -- Constructor --------------------------------------------- */ protected: + Joystick(void) : + /* -- Init joystick ids ------------------------------------------------ */ + JoyList{{ JoyInfo{ GLFW_JOYSTICK_1 }, JoyInfo{ GLFW_JOYSTICK_2 }, + JoyInfo{ GLFW_JOYSTICK_3 }, JoyInfo{ GLFW_JOYSTICK_4 }, + JoyInfo{ GLFW_JOYSTICK_5 }, JoyInfo{ GLFW_JOYSTICK_6 }, + JoyInfo{ GLFW_JOYSTICK_7 }, JoyInfo{ GLFW_JOYSTICK_8 }, + JoyInfo{ GLFW_JOYSTICK_9 }, JoyInfo{ GLFW_JOYSTICK_10 }, + JoyInfo{ GLFW_JOYSTICK_11 }, JoyInfo{ GLFW_JOYSTICK_12 }, + JoyInfo{ GLFW_JOYSTICK_13 }, JoyInfo{ GLFW_JOYSTICK_14 }, + JoyInfo{ GLFW_JOYSTICK_15 }, JoyInfo{ GLFW_JOYSTICK_16 } }}, + /* -- More initialisers ------------------------------------------------ */ + bPoll(false), // Init disabled polling + lfOnJoyState{ "OnJoyState" }, // Init joy state lua event + stConnected(0) // Init joystick count to zero + /* -- No code ---------------------------------------------------------- */ + { } + /* -- Destructor --------------------------------------------------------- */ + ~Joystick(void) { JoyDeInit(); } + /* ----------------------------------------------------------------------- */ + DELETECOPYCTORS(Joystick) // Suppress default functions for safety + /* -- Handle a deadzone change ----------------------------------- */ public: + CVarReturn SetDefaultJoyDZ(const float fDZ, + const function &fcbCallBack) + { // Return if invalid deadzone else set it and return success + if(fDZ > 1) return DENY; + StdForEach(par_unseq, this->begin(), this->end(), fcbCallBack); + return ACCEPT; + } + /* -- Set default negative deadzone -------------------------------------- */ + CVarReturn SetDefaultJoyRevDZ(const float fNewDeadZone) + { return SetDefaultJoyDZ(fNewDeadZone, [fNewDeadZone](JoyInfo &jiRef) + { jiRef.JoyAxisListSetReverseDeadZone(fNewDeadZone); }); } + /* -- Set default positive deadzone -------------------------------------- */ + CVarReturn SetDefaultJoyFwdDZ(const float fNewDeadZone) + { return SetDefaultJoyDZ(fNewDeadZone, [fNewDeadZone](JoyInfo &jiRef) + { jiRef.JoyAxisListSetForwardDeadZone(fNewDeadZone); }); } +};/* ----------------------------------------------------------------------- */ +} // End of public module namespace +/* ------------------------------------------------------------------------- */ +} // End of private module namespace +/* == EoF =========================================================== EoF == */ diff --git a/src/json.hpp b/src/json.hpp index 9089596..c5b1ec0 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -104,7 +104,7 @@ CTOR_BEGIN_ASYNC_DUO(Jsons, Json, CLHelperUnsafe, ICHelperUnsafe), StdSort(par_unseq, rjvVal.MemberBegin(), rjvVal.MemberEnd(), SortType()); } /* -- When file data has loaded ---------------------------------- */ public: - void AsyncReady(FileMap &fmData) + void AsyncReady(const FileMap &fmData) { // The memory isn't null-terminated so we have to do that and also this // could be a file map so we can't modify it so we'll load it all properly // and null-terminate it and place it into a RapidJson StringStream object @@ -386,7 +386,7 @@ CTOR_BEGIN_ASYNC_DUO(Jsons, Json, CLHelperUnsafe, ICHelperUnsafe), /* -- No code ---------------------------------------------------------- */ { } /* -- Constructor from a filename ---------------------------------------- */ - Json(const string &strFile) : + explicit Json(const string &strFile) : /* -- Initialisers ----------------------------------------------------- */ Json{} // Use default initialisers /* -- Initialise from file --------------------------------------------- */ diff --git a/src/llcommon.hpp b/src/llcommon.hpp index 111c352..084d9b2 100644 --- a/src/llcommon.hpp +++ b/src/llcommon.hpp @@ -143,6 +143,7 @@ typedef AgIntegerL AgSizeTL; typedef AgIntegerLG AgSizeTLG; typedef AgIntegerLG AgSSizeTLG; typedef AgIntegerLG AgUIntLG; +typedef AgIntegerLGE AgIntLGE; typedef AgIntegerLGE AgSizeTLGE; typedef AgIntegerLGE AgSSizeTLGE; typedef AgIntegerLGE AgUIntLGE; diff --git a/src/llinput.hpp b/src/llinput.hpp index 7082bdd..041caad 100644 --- a/src/llinput.hpp +++ b/src/llinput.hpp @@ -18,8 +18,8 @@ namespace LLInput { // Input namespace /* -- Dependencies --------------------------------------------------------- */ using namespace IGlFW::P; using namespace IGlFWUtil::P; -using namespace IInput::P; using namespace ILua::P; -using namespace Common; +using namespace IInput::P; using namespace IJoystick::P; +using namespace ILua::P; using namespace Common; /* ========================================================================= ** ** ######################################################################### ** ** ## Input common helper classes ## ** @@ -27,16 +27,16 @@ using namespace Common; ** -- Get joystick index argument ------------------------------------------ */ struct AgJoystickId : public AgSizeTLGE { explicit AgJoystickId(lua_State*const lS, const int iArg) : - AgSizeTLGE{ lS, iArg, 0, cInput->GetJoyCount() }{} }; + AgSizeTLGE{ lS, iArg, 0, cInput->JoyGetCount() }{} }; /* -- Get joystick data from joystick index -------------------------------- */ struct AgJoystickData : public ArClass { explicit AgJoystickData(lua_State*const lS, const int iArg) : - ArClass{ cInput->GetJoyData(AgJoystickId{lS, iArg}()) }{} }; + ArClass{ cInput->JoyGet(AgJoystickId{lS, iArg}()) }{} }; /* -- Get axis data from joystick data ------------------------------------- */ struct AgJoystickAxis : public AgSizeTLGE { explicit AgJoystickAxis(lua_State*const lS, const int iArg, const JoyInfo &jiData) : - AgSizeTLGE{ lS, iArg, 0, jiData.GetAxisCount() }{} }; + AgSizeTLGE{ lS, iArg, 0, jiData.JoyAxisListCount() }{} }; /* -- Get DeadZone argument ------------------------------------------------ */ struct AgDeadZone : public AgNumberLGE { explicit AgDeadZone(lua_State*const lS, const int iArg) : @@ -56,7 +56,7 @@ LLFUNC(SetJoyAxisForwardDeadZone, 0, const AgJoystickData aData{lS, 1}; const AgJoystickAxis aAxis{lS, 2, aData}; const AgDeadZone aDeadZone{lS, 3}; - aData().SetAxisForwardDeadZone(aAxis, aDeadZone)) + aData().JoyAxisListSetForwardDeadZone(aAxis, aDeadZone)) /* ========================================================================= */ // $ Input.SetJoyAxisReverseDeadZone // > JId:integer=The joystick id. @@ -69,7 +69,7 @@ LLFUNC(SetJoyAxisReverseDeadZone, 0, const AgJoystickData aData{lS, 1}; const AgJoystickAxis aAxis{lS, 2, aData}; const AgDeadZone aDeadZone{lS, 3}; - aData().SetAxisReverseDeadZone(aAxis, aDeadZone)) + aData().JoyAxisListSetReverseDeadZone(aAxis, aDeadZone)) /* ========================================================================= */ // $ Input.SetJoyAxisDeadZones // > JId:integer=The joystick id. @@ -85,7 +85,7 @@ LLFUNC(SetJoyAxisDeadZones, 0, const AgJoystickAxis aAxis{lS, 2, aData}; const AgDeadZone aDeadZoneForward{lS, 3}, aDeadZoneReverse{lS, 4}; - aData().SetAxisDeadZones(aAxis, aDeadZoneForward, aDeadZoneReverse)) + aData().JoyAxisListSetDeadZones(aAxis, aDeadZoneForward, aDeadZoneReverse)) /* ========================================================================= */ // $ Input.SetCursorPos // > X:integer=The X co-ordinate of the mouse cursor. @@ -103,7 +103,7 @@ LLFUNC(SetCursorPos, 0, // ? Clears the keyboard, mouse and joystick states which wipes the current // ? state of all the control methods preventing input. /* ------------------------------------------------------------------------- */ -LLFUNC(ClearStates, 0, cInput->ClearJoystickButtons()) +LLFUNC(ClearStates, 0, cInput->JoyClearStates()) /* ========================================================================= */ // $ Input.CursorCentre // ? Sets the mouse cursor in the centre of the window. @@ -123,7 +123,7 @@ LLFUNC(SetCursor, 0, cInput->SetCursor(AgBoolean{lS, 1})) // ? Tests if the specified joystick exists. /* ------------------------------------------------------------------------- */ LLFUNC(JoyExists, 1, - LuaUtilPushVar(lS, cInput->JoystickExists(AgJoystickId{lS, 1}))) + LuaUtilPushVar(lS, cInput->JoyIsConnected(AgJoystickId{lS, 1}))) /* ========================================================================= */ // $ Input.GetJoyName // > Id:integer=The joystick id. @@ -138,7 +138,7 @@ LLFUNC(GetJoyName, 1, LuaUtilPushVar(lS, AgJoystickData{lS, 1}().IdentGet())) // ? Returns the number of buttons this joystick supports. /* ------------------------------------------------------------------------- */ LLFUNC(GetNumJoyButtons, 1, - LuaUtilPushVar(lS, AgJoystickData{lS, 1}().GetButtonCount())) + LuaUtilPushVar(lS, AgJoystickData{lS, 1}().JoyButtonListCount())) /* ========================================================================= */ // $ Input.GetNumJoyAxises // > Id:integer=The joystick id. @@ -146,7 +146,7 @@ LLFUNC(GetNumJoyButtons, 1, // ? Returns the number of axises this joystick supports. /* ------------------------------------------------------------------------- */ LLFUNC(GetNumJoyAxises, 1, - LuaUtilPushVar(lS, AgJoystickData{lS, 1}().GetAxisCount())) + LuaUtilPushVar(lS, AgJoystickData{lS, 1}().JoyAxisListCount())) /* ========================================================================= */ // $ Input.GetJoyButton // > Id:integer=The joystick id. @@ -156,12 +156,14 @@ LLFUNC(GetNumJoyAxises, 1, // ? // ? Result can be: // ? =0: The button is not held down. -// ? >0: The button was held down for this many game ticks. +// ? =1: The button was pressed. +// ? >1: The button is being held. /* ------------------------------------------------------------------------- */ LLFUNC(GetJoyButton, 1, const AgJoystickData aData{lS, 1}; - const AgSizeTLGE aJoystickButton{lS, 2, 0, aData().GetButtonCount()}; - LuaUtilPushVar(lS, aData().GetButtonState(aJoystickButton))) + const AgSizeTLGE aJoystickButton{lS, 2, 0, aData().JoyButtonListCount()}; + LuaUtilPushVar(lS, + aData().JoyButtonListGet(aJoystickButton()).ButtonGetState())) /* ========================================================================= */ // $ Input.GetJoyAxis // > Id:integer=The joystick id. @@ -172,7 +174,7 @@ LLFUNC(GetJoyButton, 1, LLFUNC(GetJoyAxis, 1, const AgJoystickData aData{lS, 1}; const AgJoystickAxis aAxis{lS, 2, aData}; - LuaUtilPushVar(lS, aData().GetAxisState(aAxis))) + LuaUtilPushVar(lS, aData().JoyAxisListGet(aAxis).AxisGetBufferedState())) /* ========================================================================= */ // $ Input.GetJoyAxisUB // > Id:integer=The joystick id. @@ -182,7 +184,7 @@ LLFUNC(GetJoyAxis, 1, LLFUNC(GetJoyAxisUB, 1, const AgJoystickData aData{lS, 1}; const AgJoystickAxis aAxis{lS, 2, aData}; - LuaUtilPushVar(lS, aData().GetUnbufferedAxisState(aAxis))) + LuaUtilPushVar(lS, aData().JoyAxisListGet(aAxis).AxisGetUnbufferedState())) /* ========================================================================= */ // $ Input.OnMouseFocus // > Func:function=The callback function to use @@ -242,8 +244,7 @@ LLFUNC(OnChar, 0, cLua->SetLuaRef(lS, cInput->lfOnChar)) // ? (false). /* ------------------------------------------------------------------------- */ LLFUNC(OnJoyState, 0, - if(cLua->SetLuaRef(lS, cInput->lfOnJoyState)) - cInput->AutoDetectJoystick()) + if(cLua->SetLuaRef(lS, cInput->JoyGetLuaEvent())) cInput->JoyDetect()) /* ========================================================================= */ // $ Input.OnKey // > Func:function=The callback function to use