diff --git a/SHADE_Engine/src/Input/SHInputManager.cpp b/SHADE_Engine/src/Input/SHInputManager.cpp index 4849a772..cec78648 100644 --- a/SHADE_Engine/src/Input/SHInputManager.cpp +++ b/SHADE_Engine/src/Input/SHInputManager.cpp @@ -105,12 +105,12 @@ namespace SHADE //Write to lastKeys memcpy(keysLast, keys, sizeof(keys)); - //Poll + //Poll KB/M unsigned char keyboardState[MAX_KEYS] = {}; SecureZeroMemory(keyboardState, sizeof(keyboardState)); //if (GetKeyboardState(keyboardState) == false) return; bool keyboardStateGot = GetKeyboardState(keyboardState); - SHASSERT(keyboardStateGot, "SHInputManager:GetKeyboardState() failed ({})", GetLastError()); + SHASSERT(keyboardStateGot, "SHInputManager::GetKeyboardState() failed ({})", GetLastError()); keyCount = 0; keyToggleCount = 0; for (size_t i = 0; i < MAX_KEYS; ++i) @@ -159,7 +159,7 @@ namespace SHADE } } - //Mouse Positioning///////////////////////////////////// + //Mouse Positioning///////////////////////////////////////////////////////// //https://stackoverflow.com/a/6423739 //Set last positioning @@ -181,7 +181,7 @@ namespace SHADE mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll; mouseWheelVerticalDeltaPoll = 0; - //Controllers////////////////////////////////////////////////////////////// + //Controllers/////////////////////////////////////////////////////////////// controllersConnectedCount = 0; @@ -447,6 +447,200 @@ namespace SHADE } } } + + //Bindings////////////////////////////////////////////////////////////////// + for (auto& binding : bindings) + { + SHLogicalBindingData& data = binding.second; + + //Set last value + data.positiveInputHeldLast = data.positiveInputHeld; + data.negativeInputHeldLast = data.negativeInputHeld; + + //Reset held values + data.positiveInputHeld = false; + data.negativeInputHeld = false; + + if (data.bindingType == SHInputManager::SH_BINDINGTYPE::MOUSE_X) + { + double velX = 0.0; + GetMouseVelocity(&velX, nullptr); + if (data.value > 0.0) data.positiveInputHeld = true; + else if (data.value < 0.0) data.negativeInputHeld = true; + data.value = velX * data.sensitivity * (data.inverted ? -1.0 : 1.0); + } + else if (data.bindingType == SHInputManager::SH_BINDINGTYPE::MOUSE_Y) + { + double velY = 0.0; + GetMouseVelocity(nullptr, &velY); + if (data.value > 0.0) data.positiveInputHeld = true; + else if (data.value < 0.0) data.negativeInputHeld = true; + data.value = velY * data.sensitivity * (data.inverted ? -1.0 : 1.0); + } + else if (data.bindingType == SHInputManager::SH_BINDINGTYPE::MOUSE_SCROLL) + { + if (mouseWheelVerticalDelta > 0.0) data.positiveInputHeld = true; + else if (mouseWheelVerticalDelta < 0.0) data.negativeInputHeld = true; + data.value = mouseWheelVerticalDelta * data.sensitivity * (data.inverted ? -1.0 : 1.0); + } + else if (data.bindingType == SHInputManager::SH_BINDINGTYPE::KB_MB_CONTROLLER) + { + //Prioritise the largest magnitude + double largestMagnitude = 0.0; + + //If digital input was in, use sensitivity + bool digitalInput = false; + + //Over keycodes + for (SH_KEYCODE k : data.positiveKeyCodes) + { + if (GetKey(k)) + { + if (std::abs(1.0) > std::abs(largestMagnitude)) largestMagnitude = 1.0 * (data.inverted ? -1.0 : 1.0); + digitalInput = true; + data.positiveInputHeld = true; + } + } + for (SH_KEYCODE k : data.negativeKeyCodes) + { + if (GetKey(k)) + { + if (std::abs(-1.0) > std::abs(largestMagnitude)) largestMagnitude = -1.0 * (data.inverted ? -1.0 : 1.0); + digitalInput = true; + data.negativeInputHeld = true; + } + } + + //Over controllerCodes + for (SH_CONTROLLERCODE c : data.positiveControllerCodes) + { + double newValue = 0.0; + GetControllerInput(c, &newValue); + if (std::abs(newValue) > std::abs(data.dead)) + { + data.positiveInputHeld = true; + if (static_cast(c) < NUM_CONTROLLER_BUTTON) + { + digitalInput = true; + } + if (std::abs(newValue) > std::abs(largestMagnitude)) + largestMagnitude = newValue * data.sensitivity * (data.inverted ? -1.0 : 1.0); + } + } + + for (SH_CONTROLLERCODE c : data.negativeControllerCodes) + { + double newValue = 0.0; + GetControllerInput(c, &newValue); + if (std::abs(newValue) > std::abs(data.dead)) + { + data.negativeInputHeld = true; + if (static_cast(c) < NUM_CONTROLLER_BUTTON) + { + digitalInput = true; + } + if (std::abs(newValue) > std::abs(largestMagnitude)) + largestMagnitude = -newValue * data.sensitivity * (data.inverted ? -1.0 : 1.0); + } + } + + //If both positive and negative inputs read, do not modify value + if (data.positiveInputHeld && data.negativeInputHeld) + { + data.value = data.value; + } + else + { + //If no data received, use gravity + if (!data.positiveInputHeld && !data.negativeInputHeld) + { + if (data.value > 0.0) + { + data.value -= data.gravity * dt; + if (data.value < 0.0) data.value = 0.0; + } + if (data.value < 0.0) + { + data.value += data.gravity * dt; + if (data.value > 0.0) data.value = 0.0; + } + } + else //Either positive OR negative input was read + { + //If digital input was in, + //sensitivity is used as a rate at which the axis value is changed + if (digitalInput) + { + //If the input is opposite the current value, gravity works + //with the sensitivity + if (data.value > 0.0 && largestMagnitude < 0.0) + data.value -= data.gravity * dt; + if (data.value < 0.0 && largestMagnitude > 0.0) + data.value += data.gravity * dt; + + //Moved by sensitivity + data.value += data.sensitivity * largestMagnitude * dt; + + if (data.value > 1.0) data.value = 1.0; + else if (data.value < -1.0) data.value = -1.0; + } + //If analog input was in, + //sensitivity is instead used as a multiplier + else + { + data.value = largestMagnitude * data.sensitivity; + if (data.value > 1.0) data.value = 1.0; + else if (data.value < -1.0) data.value = -1.0; + } + + if (data.snap) //Snapping + { + if (data.value > 0.0 && data.negativeInputHeld) + data.value = 0.0; + if (data.value < 0.0 && data.positiveInputHeld) + data.value = 0.0; + } + } + } + } + + //Binding timings + + //Positivie bindings + if (data.positiveInputHeld) //Input is down + { + if (!data.positiveInputHeldLast) //Input was just pressed + { + data.positiveHeldTime = 0.0; //Reset timer + } + data.positiveHeldTime += dt; //Tick up + } + else //Input is up + { + if (data.positiveInputHeldLast) //Input was just released + { + data.positiveReleasedTime = 0.0; //Reset timer + } + data.positiveReleasedTime += dt; //Tick up + } + + if (data.negativeInputHeld) //Input is down + { + if (!data.negativeInputHeldLast) //Input was just pressed + { + data.negativeHeldTime = 0.0; //Reset timer + } + data.negativeHeldTime += dt; //Tick up + } + else //Input is up + { + if (data.negativeInputHeldLast) //Input was just released + { + data.negativeReleasedTime = 0.0; //Reset timer + } + data.negativeReleasedTime += dt; //Tick up + } + } } bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept @@ -574,40 +768,34 @@ namespace SHADE return false; } - //Only get of largest magnitude - double SHInputManager::GetBindingAxis(std::string bindingName, size_t cNum) noexcept + double SHInputManager::GetBindingAxis(std::string const& bindingName, size_t cNum) noexcept { - //Over keycodes, prioritise positive - for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes) - { - if (GetKey(k)) return 1.0; - } - for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes) - { - if (GetKey(k)) return -1.0; - } - - double largestMagnitude = 0.0; - - //Over controllerCodes - for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes) - { - double newValue = 0.0; - if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum)) - if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = newValue; - } - for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes) - { - double newValue = 0.0; - if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum)) - if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = -newValue; - } - - return largestMagnitude; + return bindings[bindingName].value; } - bool SHInputManager::GetBindingPositiveButton(std::string bindingName, size_t cNum) noexcept + double SHInputManager::GetBindingAxisRaw(std::string const& bindingName, size_t cNum) noexcept { + //Neutral if both positive and negative held + if (bindings[bindingName].positiveInputHeld && bindings[bindingName].negativeInputHeld) + { + return 0.0; + } + else if (bindings[bindingName].positiveInputHeld) + { + return 1.0; + } + else if (bindings[bindingName].negativeInputHeld) + { + return -1.0; + } + + //No input means neutral + return 0.0; + } + + bool SHInputManager::GetBindingPositiveButton(std::string const& bindingName, size_t cNum) noexcept + { + /* if (cNum >= XUSER_MAX_COUNT) return false; //Over keycodes @@ -622,11 +810,13 @@ namespace SHADE if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true; } - return false; + return false;*/ + return bindings[bindingName].positiveInputHeld; } - bool SHInputManager::GetBindingNegativeButton(std::string bindingName, size_t cNum) noexcept + bool SHInputManager::GetBindingNegativeButton(std::string const& bindingName, size_t cNum) noexcept { + /* if (cNum >= XUSER_MAX_COUNT) return false; //Over keycodes @@ -641,11 +831,13 @@ namespace SHADE if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true; } - return false; + return false;*/ + return bindings[bindingName].negativeInputHeld; } - bool SHInputManager::GetBindingPositiveButtonDown(std::string bindingName, size_t cNum) noexcept + bool SHInputManager::GetBindingPositiveButtonDown(std::string const& bindingName, size_t cNum) noexcept { + /* if (cNum >= XUSER_MAX_COUNT) return false; //Over keycodes @@ -660,11 +852,13 @@ namespace SHADE if (GetControllerInputDown(c, nullptr, cNum)) return true; } - return false; + return false;*/ + return (bindings[bindingName].positiveInputHeld && !bindings[bindingName].positiveInputHeldLast); } - bool SHInputManager::GetBindingNegativeButtonDown(std::string bindingName, size_t cNum) noexcept + bool SHInputManager::GetBindingNegativeButtonDown(std::string const& bindingName, size_t cNum) noexcept { + /* if (cNum >= XUSER_MAX_COUNT) return false; //Over keycodes @@ -679,11 +873,13 @@ namespace SHADE if (GetControllerInputDown(c, nullptr, cNum)) return true; } - return false; + return false;*/ + return (bindings[bindingName].negativeInputHeld && !bindings[bindingName].negativeInputHeldLast); } - bool SHInputManager::GetBindingPositiveButtonUp(std::string bindingName, size_t cNum) noexcept + bool SHInputManager::GetBindingPositiveButtonUp(std::string const& bindingName, size_t cNum) noexcept { + /* if (cNum >= XUSER_MAX_COUNT) return false; //Over keycodes @@ -698,11 +894,13 @@ namespace SHADE if (GetControllerInputUp(c, nullptr, cNum)) return true; } - return false; + return false;*/ + return (!bindings[bindingName].positiveInputHeld && bindings[bindingName].positiveInputHeldLast); } - bool SHInputManager::GetBindingNegativeButtonUp(std::string bindingName, size_t cNum) noexcept + bool SHInputManager::GetBindingNegativeButtonUp(std::string const& bindingName, size_t cNum) noexcept { + /* if (cNum >= XUSER_MAX_COUNT) return false; //Over keycodes @@ -717,107 +915,7 @@ namespace SHADE if (GetControllerInputUp(c, nullptr, cNum)) return true; } - return false; + return false;*/ + return (!bindings[bindingName].positiveInputHeld && bindings[bindingName].positiveInputHeldLast); } - - //Fetches longest hold time - double SHInputManager::GetBindingPositiveHeldTime(std::string bindingName, size_t cNum) noexcept - { - if (cNum >= XUSER_MAX_COUNT) return 0.0; - - double maxHeldTime = 0.0; - - //Over keycodes - for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes) - { - if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k); - } - - //Over controller buttons - for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes) - { - if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c); - } - - return maxHeldTime; - } - - double SHInputManager::GetBindingNegativeHeldTime(std::string bindingName, size_t cNum) noexcept - { - if (cNum >= XUSER_MAX_COUNT) return 0.0; - - double maxHeldTime = 0.0; - - //Over keycodes - for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes) - { - if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k); - } - - //Over controller buttons - for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes) - { - if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c); - } - - return maxHeldTime; - } - - //Fetches shortest release time - double SHInputManager::GetBindingPositiveReleasedTime(std::string bindingName, size_t cNum) noexcept - { - if (cNum >= XUSER_MAX_COUNT) return 0.0; - - double minReleaseTime = _HUGE_ENUF; - - //Over keycodes - for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes) - { - if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k); - } - - //Over controller buttons - for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes) - { - if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c); - } - - return minReleaseTime; - } - - double SHInputManager::GetBindingNegativeReleasedTime(std::string bindingName, size_t cNum) noexcept - { - if (cNum >= XUSER_MAX_COUNT) return 0.0; - - double minReleaseTime = _HUGE_ENUF; - - //Over keycodes - for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes) - { - if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k); - } - - //Over controller buttons - for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes) - { - if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c); - } - - return minReleaseTime; - } - - //Only for mouse movement - //Get largest delta - double SHInputManager::GetBindingMouseVelocity(std::string bindingName, size_t cNum) noexcept - { - if (cNum >= XUSER_MAX_COUNT) return 0.0; - - //Mouse velocity - double velX = 0.0; - double velY = 0.0; - GetMouseVelocity(&velX, &velY); - - return bindings[bindingName].mouseXPositiveMultiplier * velX + bindings[bindingName].mouseYPositiveMultiplier * velY; - } - } //namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Input/SHInputManager.h b/SHADE_Engine/src/Input/SHInputManager.h index 04e5871d..3f708124 100644 --- a/SHADE_Engine/src/Input/SHInputManager.h +++ b/SHADE_Engine/src/Input/SHInputManager.h @@ -300,12 +300,28 @@ namespace SHADE RIGHT_THUMBSTICK_Y }; + //BINDING TYPES/////////////////////////////////////////////////////////// + enum class SH_BINDINGTYPE + { + KB_MB_CONTROLLER, + MOUSE_X, + MOUSE_Y, + MOUSE_SCROLL + }; + private: /*------------------------------------------------------------------------*/ /* Struct for logical bindings */ /*------------------------------------------------------------------------*/ struct SH_API SHLogicalBindingData { + + + //BINDINGS//////////////////////////////////////////////////////////////// + + //The type of the binding + SH_BINDINGTYPE bindingType = SH_BINDINGTYPE::KB_MB_CONTROLLER; + //Key codes mapped to positive std::set positiveKeyCodes; @@ -318,9 +334,51 @@ namespace SHADE //Controller Codes mapped to negative std::set negativeControllerCodes; - //Mouse movement mapped to axes? - double mouseXPositiveMultiplier; - double mouseYPositiveMultiplier; + //VALUES////////////////////////////////////////////////////////////////// + + //The current value of the axis binding + double value = 0.0; + + bool positiveInputHeld = false; + bool negativeInputHeld = false; + + bool positiveInputHeldLast = false; + bool negativeInputHeldLast = false; + + //Whether the input is inverted, + //If so, positive bindings will make the value negative, + // negative bindings will make the value positive, + // moving the mouse up will make the value negative, + // scrolling the mousewheel up will make the value negative, + bool inverted = false; + + //When no input is present, how fast does the value fall back to neutral? + //Best to be non-negative + double gravity = 1.0; + + //How far the user needs to move an analog stick before application + //registers the movement + double dead = 0.2; + + //Speed in units per second that the axis will move toward target value for digital + //For mouse movement / scrolling, serves as multiplier + double sensitivity = 1.0; + + //If enabled, axis value will reset to zero when pressing a button + //that corresponds in the opposite direction + bool snap = false; + + //How long the positive binding has been held for + double positiveHeldTime = 0.0; + + //How long the positive binding has been released for + double positiveReleasedTime = 0.0; + + //How long the negative binding has been held for + double negativeHeldTime = 0.0; + + //How long the negative binding has been released for + double negativeReleasedTime = 0.0; }; public: @@ -350,6 +408,12 @@ namespace SHADE mouseWheelVerticalDeltaPoll += GET_WHEEL_DELTA_WPARAM(wParam); } + //Get if controller or KB/M is presently being used + static inline bool GetControllerInUse() noexcept + { + return controllerInUse; + } + //For testing purposes //static void PrintCurrentState() noexcept; @@ -484,7 +548,7 @@ namespace SHADE } /*------------------------------------------------------------------------*/ - /* Input state accessors (KB & M) */ + /* Input state accessors (Controller) */ /*------------------------------------------------------------------------*/ //How many controller inputs of any kind are being used now @@ -621,168 +685,347 @@ namespace SHADE /* Binding Functions */ /*------------------------------------------------------------------------*/ - //Add a new binding to the map - static inline void BindingsAdd(std::string newBindingName) noexcept + //Get a read-only map of the bindings + static inline std::map const& GetBindings() noexcept { - bindings.insert({ newBindingName, SHLogicalBindingData() }); + return bindings; } - //Remove a binding from the map - //Returns 1 if found and removed, 0 if not found - static inline size_t BindingsRemove(std::string targetBindingName) noexcept + //Add a new binding to the map with settings + //Binding type is between four different types, + //KB_MB_CONTROLLER Binding is connected to the keyboard, mouse and controller buttons and its analog inputs + //MOUSE_X Binding is connected to horizontal movement of the mouse + //MOUSE_Y Binding is connected to the vertical movement of the mouse + //MOUSE_SCROLL Binding is connected to the scrolling of the mouse wheel + //Inverted is whether positive inputs result in a negative value and vice-versa + //Snap is if inputting in the opposite direction results in the value snapping to 0 before continuing in the direction + //Sensitivity is how fast the value moves with input + //Dead is how much analogue input magnitude on a scale of 0 to 1 is required before being registered + //Gravity is how fast the value moves to neutral without input + static inline void AddBinding(std::string const& newBindingName, + SH_BINDINGTYPE const bindingType = SH_BINDINGTYPE::KB_MB_CONTROLLER, + bool const inverted = false, + bool const snap = false, + double const sensitivity = 1.0, + double const dead = 0.2, + double const gravity = 1.0) noexcept { - return bindings.erase(targetBindingName); + bindings.insert({ newBindingName, SHLogicalBindingData() }); + bindings[newBindingName].bindingType = bindingType; + bindings[newBindingName].inverted = inverted; + bindings[newBindingName].snap = snap; + bindings[newBindingName].sensitivity = sensitivity; + bindings[newBindingName].dead = dead; + bindings[newBindingName].gravity = gravity; + } + + //Remove a binding and all its associated inputs from the list + //Returns 1 if found and removed, 0 if not found + static inline size_t RemoveBinding(std::string const& bindingName) noexcept + { + return bindings.erase(bindingName); } //Clears all bindings from the list - static inline void BindingsClear() noexcept + static inline void ClearBindings() noexcept { bindings.clear(); } //Get the number of bindings present - static inline size_t BindingsCount() noexcept + static inline size_t CountBindings() noexcept { return bindings.size(); } + //BINDING VALUES//////////////////////////////////////////////////////////// + + //Get whether the binding is inverted or not + //If inverted, positive inputs subtract the value of the binding + // negative inputs add to the value of the binding + // Moving mouse up / right will be negative + // Scrolling the mouse wheel up will be negative + static inline bool GetBindingInverted(std::string const& bindingName) + { + return bindings[bindingName].inverted; + } + + //Set whether the binding is inverted or not + //If inverted, positive inputs subtract the value of the binding + // negative inputs add to the value of the binding + // Moving mouse up / right will be negative + // Scrolling the mouse wheel up will be negative + static inline void SetBindingInverted(std::string const& bindingName, bool const newValue) + { + bindings[bindingName].inverted = newValue; + } + + //Gets the gravity of the binding + //The rate at which the value moves to neutral if no input in the direction is read + //Should be non-negative + //Irrelevant for mouse movement and scrolling + static inline double GetBindingGravity(std::string const& bindingName) + { + return bindings[bindingName].gravity; + } + + //Sets the gravity of the binding + //The rate at which the value moves to neutral if no input in the direction is read + //Should be non-negative + //Irrelevant for mouse movement and scrolling + static inline void SetBindingGravity(std::string const& bindingName, double const newValue) + { + bindings[bindingName].gravity = newValue; + } + + //Get the dead zone of the binding on a scale of 0 to 1, + //Any positive or negative analog input with magnitude less than this will be registered as neutral + //Irrelvant for digital inputs, mouse movement and scrolling + static inline double GetBindingDead(std::string const& bindingName) + { + return bindings[bindingName].dead; + } + + //Get the dead zone of the binding on a scale of 0 to 1, + //Any positive or negative analog input with magnitude less than this will be registered as neutral + //Irrelvant for digital inputs, mouse movement and scrolling + static inline void SetBindingDead(std::string const& bindingName, double const newValue) + { + bindings[bindingName].dead = newValue; + } + + //Get the sensitivity of the binding + //Serves as a multiplier for mouse movement/scrolling + //For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative + //For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1 + static inline double GetBindingSensitivity(std::string const& bindingName) + { + return bindings[bindingName].sensitivity; + } + + //Set the sensitivity of the binding + //Serves as a multiplier for mouse movement/scrolling + //For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative + //For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1 + static inline void SetBindingSensitivity(std::string const& bindingName, double const newValue) + { + bindings[bindingName].sensitivity = newValue; + } + + //Gets the snap of the binding + //If no other input on the axis is present and a input is made in the opposite direction of the current value, + //the binding's value will jump to neutral 0 before resuming in the input direction + //Irrelevant for mouse movement and scrolling + static inline bool GetBindingSnap(std::string const& bindingName) + { + return bindings[bindingName].snap; + } + + //Sets the snap of the binding + //If no other input on the axis is present and a input is made in the opposite direction of the current value, + //the binding's value will jump to neutral 0 before resuming in the input direction + //Irrelevant for mouse movement and scrolling + static inline void SetBindingSnap(std::string const& bindingName, bool const newValue) + { + bindings[bindingName].snap = newValue; + } + + //BINDING TYPE////////////////////////////////////////////////////////////// + + //Get the type of the binding + //There are four types: + //KB_MB_CONTROLLER Binding is connected to the keyboard, mouse and controller buttons and its analog inputs + //MOUSE_X Binding is connected to horizontal movement of the mouse + //MOUSE_Y Binding is connected to the vertical movement of the mouse + //MOUSE_SCROLL Binding is connected to the scrolling of the mouse wheel + static inline SH_BINDINGTYPE GetBindingType(std::string const& bindingName) + { + return bindings[bindingName].bindingType; + } + + //Set the type of the binding + //There are four types: + //KB_MB_CONTROLLER Binding is connected to the keyboard, mouse and controller buttons and its analog inputs + //MOUSE_X Binding is connected to horizontal movement of the mouse + //MOUSE_Y Binding is connected to the vertical movement of the mouse + //MOUSE_SCROLL Binding is connected to the scrolling of the mouse wheel + static inline void SetBindingType(std::string const& bindingName, SH_BINDINGTYPE const newType) + { + bindings[bindingName].bindingType = newType; + } + + //POSITIVE KEYCODES///////////////////////////////////////////////////////// + //Check positive keycodes to binding - static inline std::set const& BindingsGetPositiveKeyCodes(std::string bindingName) noexcept + static inline std::set const& GetBindingPositiveKeyCodes(std::string const& bindingName) noexcept { return bindings[bindingName].positiveKeyCodes; } //Add positive SH_KEYCODE to binding - static inline void BindingsAddPositiveKeyCode(std::string targetBindingName, + static inline void AddBindingPositiveKeyCode(std::string const& bindingName, SH_KEYCODE toAdd) noexcept { - bindings[targetBindingName].positiveKeyCodes.insert(toAdd); + bindings[bindingName].positiveKeyCodes.insert(toAdd); } //Remove positive SH_KEYCODE from binding //If toRemove found and removed, returns 1. Otherwise, 0. - static inline size_t BindingsRemovePositiveKeyCode(std::string targetBindingName, + static inline size_t RemoveBindingPositiveKeyCode(std::string const& bindingName, SH_KEYCODE toRemove) noexcept { - return bindings[targetBindingName].positiveKeyCodes.erase(toRemove); + return bindings[bindingName].positiveKeyCodes.erase(toRemove); } + //Clear all positive SH_KEYCODEs from binding + static inline void ClearBindingPositiveKeyCodes(std::string const& bindingName) noexcept + { + bindings[bindingName].positiveKeyCodes.clear(); + } + + //NEGATIVE KEYCODES///////////////////////////////////////////////////////// + //Check negative keycodes to binding - static inline std::set const& BindingsGetNegativeKeyCodes(std::string bindingName) noexcept + static inline std::set const& GetBindingNegativeKeyCodes(std::string const& bindingName) noexcept { return bindings[bindingName].negativeKeyCodes; } //Add negative SH_KEYCODE to binding - static inline void BindingsAddNegativeKeyCode(std::string targetBindingName, + static inline void AddBindingNegativeKeyCode(std::string const& bindingName, SH_KEYCODE toAdd) noexcept { - bindings[targetBindingName].negativeKeyCodes.insert(toAdd); + bindings[bindingName].negativeKeyCodes.insert(toAdd); } //Remove negative SH_KEYCODE from binding //If toRemove found and removed, returns 1. Otherwise, 0. - static inline size_t BindingsRemoveNegativeKeyCode(std::string targetBindingName, + static inline size_t RemoveBindingNegativeKeyCode(std::string const& bindingName, SH_KEYCODE toRemove) noexcept { - return bindings[targetBindingName].negativeKeyCodes.erase(toRemove); + return bindings[bindingName].negativeKeyCodes.erase(toRemove); } + //Clear all negative SH_KEYCODEs from binding + static inline void ClearBindingNegativeKeyCodes(std::string const& bindingName) noexcept + { + bindings[bindingName].negativeKeyCodes.clear(); + } + + //POSITIVE CONTROLLERCODES////////////////////////////////////////////////// + //Check positive controllercodes to binding - static inline std::set const& BindingsGetPositiveControllerCodes(std::string bindingName) noexcept + static inline std::set const& GetBindingPositiveControllerCodes(std::string const& bindingName) noexcept { return bindings[bindingName].positiveControllerCodes; } //Add positive SH_CONTROLLERCODE to binding - static inline void BindingsAddPositiveControllerCode(std::string targetBindingName, + static inline void AddBindingPositiveControllerCode(std::string const& bindingName, SH_CONTROLLERCODE toAdd) noexcept { - bindings[targetBindingName].positiveControllerCodes.insert(toAdd); + bindings[bindingName].positiveControllerCodes.insert(toAdd); } //Remove positive SH_CONTROLLERCODE from binding //If toRemove found and removed, returns 1. Otherwise, 0. - static inline size_t BindingsRemovePositiveControllerCode(std::string targetBindingName, + static inline size_t RemoveBindingPositiveControllerCode(std::string const& bindingName, SH_CONTROLLERCODE toRemove) noexcept { - return bindings[targetBindingName].positiveControllerCodes.erase(toRemove); + return bindings[bindingName].positiveControllerCodes.erase(toRemove); } + //Clear all positive SH_CONTROLLERCODEs from binding + static inline void ClearBindingPositiveControllerCodes(std::string const& bindingName) noexcept + { + bindings[bindingName].positiveControllerCodes.clear(); + } + + //NEGATIVE CONTROLLERCODES////////////////////////////////////////////////// + //Check negative controllercodes to binding - static inline std::set const& BindingsGetNegativeControllerCodes(std::string bindingName) noexcept + static inline std::set const& GetBindingNegativeControllerCodes(std::string const& bindingName) noexcept { return bindings[bindingName].negativeControllerCodes; } //Add negative SH_CONTROLLERCODE to binding - static inline void BindingsAddNegativeControllerCode(std::string targetBindingName, + static inline void AddBindingNegativeControllerCode(std::string const& bindingName, SH_CONTROLLERCODE toAdd) noexcept { - bindings[targetBindingName].negativeControllerCodes.insert(toAdd); + bindings[bindingName].negativeControllerCodes.insert(toAdd); } //Remove negative SH_CONTROLLERCODE from binding //If toRemove found and removed, returns 1. Otherwise, 0. - static inline size_t BindingsRemoveNegativeControllerCode(std::string targetBindingName, + static inline size_t RemoveBindingNegativeControllerCode(std::string const& bindingName, SH_CONTROLLERCODE toRemove) noexcept { - return bindings[targetBindingName].negativeControllerCodes.erase(toRemove); + return bindings[bindingName].negativeControllerCodes.erase(toRemove); } - //Mouse movement bindings - - static inline double const BindingsGetMouseXPositiveMultiplier(std::string bindingName) noexcept + //Clear all negative SH_CONTROLLERCODEs from binding + static inline void ClearBindingNegativeControllerCodes(std::string const& bindingName) noexcept { - return bindings[bindingName].mouseXPositiveMultiplier; + bindings[bindingName].negativeControllerCodes.clear(); } - static inline void BindingsSetMouseXPositiveMultiplier(std::string bindingName, double newValue) noexcept - { - bindings[bindingName].mouseXPositiveMultiplier = newValue; - } + //Get the axis value of binding, between -1 and 1 for non-mouse movement/wheel + //For mouse movement/wheel, it won't be between -1 and 1. It will also be multiplied by sensitivity + //To avoid interference between mouse movement/wheel and keyboard/mouse/controller input, + //Set mouseXBound, mouseYBound and mouseScrollBound to false + //controllerNumber is not used + static double GetBindingAxis(std::string const& bindingName, size_t controllerNumber = 0) noexcept; - static inline double const BindingsGetMouseYPositiveMultiplier(std::string bindingName) noexcept - { - return bindings[bindingName].mouseXPositiveMultiplier; - } - - static inline void BindingsSetMouseYPositiveMultiplier(std::string bindingName, double newValue) noexcept - { - bindings[bindingName].mouseXPositiveMultiplier = newValue; - } - - //Get the axis value of binding, between -1 and 1 - static double GetBindingAxis(std::string bindingName, size_t controllerNumber = 0) noexcept; + //Get the axis value of binding, which will be fixed among -1, 0 and 1 for non-mouse movement/wheel + //No difference between this and GetBindingAxis for mouse movement/wheel + //But for other inputs, does not consider smoothing options such as gravity and sensitivity + //If both positive and negative input is detected, returns neutral 0 + //controllerNumber is not used + static double GetBindingAxisRaw(std::string const& bindingName, size_t controllerNumber = 0) noexcept; //Whether binding is being held or not - //Does not work for mouse movement - static bool GetBindingPositiveButton(std::string bindingName, size_t controllerNumber = 0) noexcept; - static bool GetBindingNegativeButton(std::string bindingName, size_t controllerNumber = 0) noexcept; + //Does not work for mouse movement or wheel + static bool GetBindingPositiveButton(std::string const& bindingName, size_t controllerNumber = 0) noexcept; + static bool GetBindingNegativeButton(std::string const& bindingName, size_t controllerNumber = 0) noexcept; //Whether binding is pressed down IN THIS FRAME ONLY - //Does not work for mouse movement - static bool GetBindingPositiveButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept; - static bool GetBindingNegativeButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept; + //Does not work for mouse movement or wheel + static bool GetBindingPositiveButtonDown(std::string const& bindingName, size_t controllerNumber = 0) noexcept; + static bool GetBindingNegativeButtonDown(std::string const& bindingName, size_t controllerNumber = 0) noexcept; //Whether binding is released IN THIS FRAME ONLY - //Does not work for mouse movement - static bool GetBindingPositiveButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept; - static bool GetBindingNegativeButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept; + //Does not work for mouse movement or wheel + static bool GetBindingPositiveButtonUp(std::string const& bindingName, size_t controllerNumber = 0) noexcept; + static bool GetBindingNegativeButtonUp(std::string const& bindingName, size_t controllerNumber = 0) noexcept; //Binding times - //Does not work for mouse movement - static double GetBindingPositiveHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept; - static double GetBindingNegativeHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept; + //Gets how long the binding has been considered positive + //Does not work for mouse movement or wheel + static inline double GetBindingPositiveHeldTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept + { + return bindings[bindingName].positiveHeldTime; + } + //Gets how long the binding has been considered negative + //Does not work for mouse movement or wheel + static inline double GetBindingNegativeHeldTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept + { + return bindings[bindingName].negativeHeldTime; + } - //Does not work for mouse movement - static double GetBindingPositiveReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept; - static double GetBindingNegativeReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept; - - //Binding mouse velocity - //Only for mouse movement - static double GetBindingMouseVelocity(std::string bindingName, size_t controllerNumber = 0) noexcept; + //Gets how long the binding has been not considered positive + //Does not work for mouse movement or wheel + static inline double GetBindingPositiveReleasedTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept + { + return bindings[bindingName].positiveReleasedTime; + } + //Gets how long the binding has been not considered negative + //Does not work for mouse movement or wheel + static inline double GetBindingNegativeReleasedTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept + { + return bindings[bindingName].negativeReleasedTime; + } /*------------------------------------------------------------------------*/ /* Other Functions */