Bindings and Controllers #106
|
@ -19,6 +19,10 @@ namespace SHADE
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Static defines */
|
/* Static defines */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool SHInputManager::controllerInUse = false;
|
||||||
|
|
||||||
|
std::map<std::string, SHInputManager::SHLogicalBindingData> SHInputManager::bindings;
|
||||||
|
|
||||||
unsigned SHInputManager::keyCount = 0;
|
unsigned SHInputManager::keyCount = 0;
|
||||||
bool SHInputManager::keys[MAX_KEYS];
|
bool SHInputManager::keys[MAX_KEYS];
|
||||||
|
@ -41,6 +45,60 @@ namespace SHADE
|
||||||
int SHInputManager::mouseWheelVerticalDelta = 0;
|
int SHInputManager::mouseWheelVerticalDelta = 0;
|
||||||
int SHInputManager::mouseWheelVerticalDeltaPoll = 0;
|
int SHInputManager::mouseWheelVerticalDeltaPoll = 0;
|
||||||
|
|
||||||
|
unsigned char SHInputManager::controllersConnectedCount = 0;
|
||||||
|
unsigned SHInputManager::controllersInputCount[XUSER_MAX_COUNT];
|
||||||
|
unsigned SHInputManager::controllersButtonCount[XUSER_MAX_COUNT];
|
||||||
|
short SHInputManager::controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
short SHInputManager::controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
double SHInputManager::controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
double SHInputManager::controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
|
||||||
|
//Internal helper function for splitting between inputs
|
||||||
|
bool SHInputManager::controllerConsideredHeld(size_t inputIdx, short value) noexcept
|
||||||
|
{
|
||||||
|
if (inputIdx >= MAX_CONTROLLER_INPUT) return false; //Bounds check
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inputIdx < NUM_CONTROLLER_BUTTON)
|
||||||
|
{
|
||||||
|
return static_cast<bool>(value);
|
||||||
|
}
|
||||||
|
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER)
|
||||||
|
{
|
||||||
|
return (value > XINPUT_GAMEPAD_TRIGGER_THRESHOLD);
|
||||||
|
}
|
||||||
|
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER + NUM_CONTROLLER_TRIGGER)
|
||||||
|
{
|
||||||
|
return (std::abs(value) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (std::abs(value) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Internal helper function for getting normalised input value
|
||||||
|
double SHInputManager::controllerNormalisedValue(size_t inputIdx, short value) noexcept
|
||||||
|
{
|
||||||
|
if (inputIdx >= MAX_CONTROLLER_INPUT) return 0.0; //Bounds check
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inputIdx < NUM_CONTROLLER_BUTTON)
|
||||||
|
{
|
||||||
|
return static_cast<double>(value);
|
||||||
|
}
|
||||||
|
else if (inputIdx < NUM_CONTROLLER_BUTTON + NUM_CONTROLLER_TRIGGER) //8-bit triggers, 0 to 255
|
||||||
|
{
|
||||||
|
return static_cast<double>(value) / static_cast<double>(UCHAR_MAX);
|
||||||
|
}
|
||||||
|
else //16-bit thumbsticks, -32768 to 32767
|
||||||
|
{
|
||||||
|
return static_cast<double>(value) / static_cast<double>(SHRT_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SHInputManager::UpdateInput(double dt) noexcept
|
void SHInputManager::UpdateInput(double dt) noexcept
|
||||||
{
|
{
|
||||||
//Keyboard and Mouse Buttons////////////////////////////////////////////////
|
//Keyboard and Mouse Buttons////////////////////////////////////////////////
|
||||||
|
@ -120,6 +178,273 @@ namespace SHADE
|
||||||
mouseWheelVerticalDelta = 0;
|
mouseWheelVerticalDelta = 0;
|
||||||
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
|
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
|
||||||
mouseWheelVerticalDeltaPoll = 0;
|
mouseWheelVerticalDeltaPoll = 0;
|
||||||
|
|
||||||
|
//Controllers//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
controllersConnectedCount = 0;
|
||||||
|
|
||||||
|
//Set last controller states
|
||||||
|
memcpy(controllersLast, controllers, sizeof(controllers));
|
||||||
|
|
||||||
|
//Reset controller states
|
||||||
|
SecureZeroMemory(&controllers, sizeof(controllers));
|
||||||
|
|
||||||
|
//https://learn.microsoft.com/en-us/windows/win32/xinput/getting-started-with-xinput#getting-controller-state
|
||||||
|
for (DWORD c = 0; c < XUSER_MAX_COUNT; ++c)
|
||||||
|
{
|
||||||
|
controllersInputCount[c] = 0;
|
||||||
|
controllersButtonCount[c] = 0;
|
||||||
|
|
||||||
|
XINPUT_STATE state;
|
||||||
|
SecureZeroMemory(&state, sizeof(XINPUT_STATE));
|
||||||
|
|
||||||
|
//Get the state of controller from XInput
|
||||||
|
DWORD result = XInputGetState(c, &state);
|
||||||
|
|
||||||
|
//Write gamepad data
|
||||||
|
if (result == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
++controllersConnectedCount;
|
||||||
|
|
||||||
|
//DIGITAL BUTTONS///////////////////////////////////////
|
||||||
|
|
||||||
|
//DPAD UP
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_UP)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_UP)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//DPAD DOWN
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_DOWN)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_DOWN)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//DPAD LEFT
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_LEFT)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_LEFT)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//DPAD RIGHT
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_RIGHT)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::DPAD_RIGHT)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//START
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::START)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::START)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BACK
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::BACK)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::BACK)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//LEFT THUMBSTICK BUTTON
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//RIGHT THUMBSTICK BUTTON
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//LEFT SHOULDER BUTTON
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_SHOULDER)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_SHOULDER)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//RIGHT SHOULDER BUTTON
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_SHOULDER)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_SHOULDER)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//A
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::A)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::A)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//B
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::B)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::B)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//X
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::X)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::X)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Y
|
||||||
|
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::Y)] = 1;
|
||||||
|
++controllersInputCount[c];
|
||||||
|
++controllersButtonCount[c];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::Y)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//8 BIT VALUES (0 - 255)///////////////////////////////////
|
||||||
|
|
||||||
|
//LEFT TRIGGER
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_TRIGGER)] = state.Gamepad.bLeftTrigger;
|
||||||
|
if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
{
|
||||||
|
++controllersInputCount[c]; //Registered as held
|
||||||
|
}
|
||||||
|
|
||||||
|
//RIGHT TRIGGER
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_TRIGGER)] = state.Gamepad.bRightTrigger;
|
||||||
|
if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||||
|
{
|
||||||
|
++controllersInputCount[c]; //Registered as held
|
||||||
|
}
|
||||||
|
|
||||||
|
//16 BIT VALUES (0 - 65535)////////////////////////////////
|
||||||
|
|
||||||
|
//LEFT THUMBSTICK X
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK_X)] = state.Gamepad.sThumbLX;
|
||||||
|
if (std::abs(state.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
++controllersInputCount[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
//LEFT THUMBSTICK Y
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::LEFT_THUMBSTICK_Y)] = state.Gamepad.sThumbLY;
|
||||||
|
if (std::abs(state.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
++controllersInputCount[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
//RIGHT THUMBSTICK X
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK_X)] = state.Gamepad.sThumbRX;
|
||||||
|
if (std::abs(state.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
++controllersInputCount[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
//RIGHT THUMBSTICK Y
|
||||||
|
controllers[c][static_cast<size_t>(SH_CONTROLLERCODE::RIGHT_THUMBSTICK_Y)] = state.Gamepad.sThumbRY;
|
||||||
|
if (std::abs(state.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||||
|
{
|
||||||
|
++controllersInputCount[c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Timers and updating if controller is presently in use
|
||||||
|
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
|
||||||
|
{
|
||||||
|
if (controllerConsideredHeld(i, controllers[c][i])) //Considered on
|
||||||
|
{
|
||||||
|
controllerInUse = true;
|
||||||
|
if (!controllerConsideredHeld(i, controllersLast[c][i])) //Just on
|
||||||
|
{
|
||||||
|
controllersHeldTime[c][i] = 0.0; //Reset timer
|
||||||
|
}
|
||||||
|
controllersHeldTime[c][i] += dt; //Tick up
|
||||||
|
}
|
||||||
|
else //Considered off
|
||||||
|
{
|
||||||
|
if (controllerConsideredHeld(i, controllersLast[c][i])) //Just off
|
||||||
|
{
|
||||||
|
controllersReleasedTime[c][i] = 0.0; //Reset timer
|
||||||
|
}
|
||||||
|
controllersReleasedTime[c][i] += dt; //Tick up
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
|
bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
|
||||||
|
@ -161,4 +486,336 @@ namespace SHADE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Any controller input being held
|
||||||
|
//For analog, this means going being deadzone values
|
||||||
|
bool SHInputManager::AnyControllerInput(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
|
||||||
|
{
|
||||||
|
if (controllerConsideredHeld(i, controllers[cNum][i]))
|
||||||
|
{
|
||||||
|
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::AnyControllerInputDown(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
|
||||||
|
{
|
||||||
|
if (controllerConsideredHeld(i, controllers[cNum][i]) && !controllerConsideredHeld(i, controllersLast[cNum][i]))
|
||||||
|
{
|
||||||
|
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::AnyControllerInputUp(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
for (size_t i = 0; i < MAX_CONTROLLER_INPUT; ++i)
|
||||||
|
{
|
||||||
|
if (!controllerConsideredHeld(i, controllers[cNum][i]) && controllerConsideredHeld(i, controllersLast[cNum][i]))
|
||||||
|
{
|
||||||
|
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::AnyControllerButton(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
|
||||||
|
{
|
||||||
|
if (controllerConsideredHeld(i, controllers[cNum][i]))
|
||||||
|
{
|
||||||
|
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::AnyControllerButtonDown(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
|
||||||
|
{
|
||||||
|
if (controllerConsideredHeld(i, controllers[cNum][i]) && !controllerConsideredHeld(i, controllersLast[cNum][i]))
|
||||||
|
{
|
||||||
|
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::AnyControllerButtonUp(SH_CONTROLLERCODE* firstDetected, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
for (size_t i = 0; i < NUM_CONTROLLER_BUTTON; ++i)
|
||||||
|
{
|
||||||
|
if (!controllerConsideredHeld(i, controllers[cNum][i]) && controllerConsideredHeld(i, controllersLast[cNum][i]))
|
||||||
|
{
|
||||||
|
if (firstDetected) *firstDetected = static_cast<SH_CONTROLLERCODE>(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Only get of largest magnitude
|
||||||
|
double SHInputManager::GetBindingAxis(std::string 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingPositiveButton(std::string bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKey(k)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controller buttons
|
||||||
|
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
|
||||||
|
{
|
||||||
|
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingNegativeButton(std::string bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKey(k)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controller buttons
|
||||||
|
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
|
||||||
|
{
|
||||||
|
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingPositiveButtonDown(std::string bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKeyDown(k)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controller buttons
|
||||||
|
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
|
||||||
|
{
|
||||||
|
if (GetControllerInputDown(c, nullptr, cNum)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingNegativeButtonDown(std::string bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKeyDown(k)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controller buttons
|
||||||
|
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
|
||||||
|
{
|
||||||
|
if (GetControllerInputDown(c, nullptr, cNum)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingPositiveButtonUp(std::string bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKeyUp(k)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controller buttons
|
||||||
|
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
|
||||||
|
{
|
||||||
|
if (GetControllerInputUp(c, nullptr, cNum)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingNegativeButtonUp(std::string bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKeyUp(k)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controller buttons
|
||||||
|
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
|
||||||
|
{
|
||||||
|
if (GetControllerInputUp(c, nullptr, cNum)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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
|
} //namespace SHADE
|
|
@ -10,9 +10,12 @@
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
//#include <Xinput.h>
|
#include <Xinput.h>
|
||||||
//#include "../../SHADE_Managed/src/SHpch.h"
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include "../../SHADE_Managed/src/SHpch.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
#pragma comment(lib, "xinput.lib")
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -268,6 +271,58 @@ namespace SHADE
|
||||||
OEM_CLEAR
|
OEM_CLEAR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SH_CONTROLLERCODE
|
||||||
|
{
|
||||||
|
//Digital
|
||||||
|
DPAD_UP,
|
||||||
|
DPAD_DOWN,
|
||||||
|
DPAD_LEFT,
|
||||||
|
DPAD_RIGHT,
|
||||||
|
START,
|
||||||
|
BACK,
|
||||||
|
LEFT_THUMBSTICK,
|
||||||
|
RIGHT_THUMBSTICK,
|
||||||
|
LEFT_SHOULDER,
|
||||||
|
RIGHT_SHOULDER,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
|
||||||
|
//1 Byte Unsigned Analog
|
||||||
|
LEFT_TRIGGER,
|
||||||
|
RIGHT_TRIGGER,
|
||||||
|
|
||||||
|
//2 Byte Signed Analog
|
||||||
|
LEFT_THUMBSTICK_X,
|
||||||
|
LEFT_THUMBSTICK_Y,
|
||||||
|
RIGHT_THUMBSTICK_X,
|
||||||
|
RIGHT_THUMBSTICK_Y
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Struct for logical bindings */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
struct SH_API SHLogicalBindingData
|
||||||
|
{
|
||||||
|
//Key codes mapped to positive
|
||||||
|
std::set<SH_KEYCODE> positiveKeyCodes;
|
||||||
|
|
||||||
|
//Key codes mapped to negative
|
||||||
|
std::set<SH_KEYCODE> negativeKeyCodes;
|
||||||
|
|
||||||
|
//Controller Codes mapped to positive
|
||||||
|
std::set<SH_CONTROLLERCODE> positiveControllerCodes;
|
||||||
|
|
||||||
|
//Controller Codes mapped to negative
|
||||||
|
std::set<SH_CONTROLLERCODE> negativeControllerCodes;
|
||||||
|
|
||||||
|
//Mouse movement mapped to axes?
|
||||||
|
double mouseXPositiveMultiplier;
|
||||||
|
double mouseYPositiveMultiplier;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//Updates current state of the input, with dt to be fetched from FRC
|
//Updates current state of the input, with dt to be fetched from FRC
|
||||||
//TODO should dt be fixed or variable?
|
//TODO should dt be fixed or variable?
|
||||||
|
@ -392,7 +447,7 @@ namespace SHADE
|
||||||
keysToggleLast[static_cast<int>(key)]);
|
keysToggleLast[static_cast<int>(key)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mouse/////////////
|
//Mouse/////////////////////////////////////////////////////
|
||||||
|
|
||||||
//Get the mouse location with respect to the screen
|
//Get the mouse location with respect to the screen
|
||||||
static inline void GetMouseScreenPosition (int* x = nullptr,
|
static inline void GetMouseScreenPosition (int* x = nullptr,
|
||||||
|
@ -428,7 +483,95 @@ namespace SHADE
|
||||||
return mouseWheelVerticalDelta;
|
return mouseWheelVerticalDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
//GET INPUT TIMINGS///////////////////////////////////////////////////////////
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Input state accessors (KB & M) */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//How many controller inputs of any kind are being used now
|
||||||
|
static inline unsigned GetControllerInputCount(size_t cNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return 0;
|
||||||
|
return controllersInputCount[cNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
//How many controller buttons are being pressed now
|
||||||
|
//Subtract from getControllerInputCount() for analog triggers / thumbsticks
|
||||||
|
static inline unsigned GetControllerButtonCount(size_t cNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (cNum >= XUSER_MAX_COUNT) return 0;
|
||||||
|
return controllersButtonCount[cNum];
|
||||||
|
}
|
||||||
|
|
||||||
|
//Any controller input being held
|
||||||
|
//For analog, this means going being deadzone values
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static bool AnyControllerInput(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
|
||||||
|
|
||||||
|
//Any controller input activated in THIS FRAME ONLY
|
||||||
|
//For analog, this means going being deadzone values
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static bool AnyControllerInputDown(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
|
||||||
|
|
||||||
|
//Any controller input deactivated in THIS FRAME ONLY
|
||||||
|
//For analog, this means going below deadzone values
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static bool AnyControllerInputUp(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
|
||||||
|
|
||||||
|
//Any DIGITAL controller buttons being held
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static bool AnyControllerButton(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
|
||||||
|
|
||||||
|
//Any DIGITAL controller button activated in THIS FRAME ONLY
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static bool AnyControllerButtonDown(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
|
||||||
|
|
||||||
|
//Any DIGITAL controller button deactivated in THIS FRAME ONLY
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static bool AnyControllerButtonUp(SH_CONTROLLERCODE* firstDetected = nullptr, size_t controllerNum = 0) noexcept;
|
||||||
|
|
||||||
|
//If controller input is being held in the current frame
|
||||||
|
//normalisedValue is the value of the input between 0 and 1, relevant for trigger and thumbstick data
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static inline bool GetControllerInput(SH_CONTROLLERCODE input,
|
||||||
|
double* normalisedValue = nullptr,
|
||||||
|
double* heldTime = nullptr,
|
||||||
|
double* releasedTime = nullptr,
|
||||||
|
size_t controllerNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (controllerNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
if (normalisedValue) *normalisedValue = controllerNormalisedValue(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]);
|
||||||
|
if (heldTime) *heldTime = controllersHeldTime[controllerNum][static_cast<size_t>(input)];
|
||||||
|
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
|
||||||
|
return controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//If controller input was considered to be held down in THIS FRAME ONLY
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static inline bool GetControllerInputDown(SH_CONTROLLERCODE input,
|
||||||
|
double* releasedTime = nullptr,
|
||||||
|
size_t controllerNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (controllerNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
|
||||||
|
return (controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]) &&
|
||||||
|
!controllerConsideredHeld(static_cast<size_t>(input), controllersLast[controllerNum][static_cast<size_t>(input)]));
|
||||||
|
}
|
||||||
|
|
||||||
|
//If controller input was considered to be released in THIS FRAME ONLY
|
||||||
|
//controllerNum should be between 0 and 3
|
||||||
|
static inline bool GetControllerInputUp(SH_CONTROLLERCODE input,
|
||||||
|
double* releasedTime = nullptr,
|
||||||
|
size_t controllerNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (controllerNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
if (releasedTime) *releasedTime = controllersReleasedTime[controllerNum][static_cast<size_t>(input)];
|
||||||
|
return (!controllerConsideredHeld(static_cast<size_t>(input), controllers[controllerNum][static_cast<size_t>(input)]) &&
|
||||||
|
controllerConsideredHeld(static_cast<size_t>(input), controllersLast[controllerNum][static_cast<size_t>(input)]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Timing accessors */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
//Keyboard/////////////
|
//Keyboard/////////////
|
||||||
|
|
||||||
|
@ -456,6 +599,191 @@ namespace SHADE
|
||||||
return keysToggleOffTime[static_cast<int>(key)];
|
return keysToggleOffTime[static_cast<int>(key)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Controller//////////////////////
|
||||||
|
|
||||||
|
//How long has this controller input been considered to be held down for
|
||||||
|
static inline double GetControllerInputHeldTime(SH_CONTROLLERCODE code,
|
||||||
|
size_t controllerNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (controllerNum >= XUSER_MAX_COUNT) return 0.0;
|
||||||
|
return controllersHeldTime[controllerNum][static_cast<size_t>(code)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//How long has this controller input been considered to be released for
|
||||||
|
static inline double GetControllerInputReleasedTime(SH_CONTROLLERCODE code,
|
||||||
|
size_t controllerNum = 0) noexcept
|
||||||
|
{
|
||||||
|
if (controllerNum >= XUSER_MAX_COUNT) return 0.0;
|
||||||
|
return controllersReleasedTime[controllerNum][static_cast<size_t>(code)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Binding Functions */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//Add a new binding to the map
|
||||||
|
static inline void BindingsAdd(std::string newBindingName) noexcept
|
||||||
|
{
|
||||||
|
bindings.insert({ newBindingName, SHLogicalBindingData() });
|
||||||
|
}
|
||||||
|
|
||||||
|
//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
|
||||||
|
{
|
||||||
|
return bindings.erase(targetBindingName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clears all bindings from the list
|
||||||
|
static inline void BindingsClear() noexcept
|
||||||
|
{
|
||||||
|
bindings.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the number of bindings present
|
||||||
|
static inline size_t BindingsCount() noexcept
|
||||||
|
{
|
||||||
|
return bindings.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check positive keycodes to binding
|
||||||
|
static inline std::set<SH_KEYCODE> const& BindingsGetPositiveKeyCodes(std::string bindingName) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].positiveKeyCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add positive SH_KEYCODE to binding
|
||||||
|
static inline void BindingsAddPositiveKeyCode(std::string targetBindingName,
|
||||||
|
SH_KEYCODE toAdd) noexcept
|
||||||
|
{
|
||||||
|
bindings[targetBindingName].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,
|
||||||
|
SH_KEYCODE toRemove) noexcept
|
||||||
|
{
|
||||||
|
return bindings[targetBindingName].positiveKeyCodes.erase(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check negative keycodes to binding
|
||||||
|
static inline std::set<SH_KEYCODE> const& BindingsGetNegativeKeyCodes(std::string bindingName) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].negativeKeyCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add negative SH_KEYCODE to binding
|
||||||
|
static inline void BindingsAddNegativeKeyCode(std::string targetBindingName,
|
||||||
|
SH_KEYCODE toAdd) noexcept
|
||||||
|
{
|
||||||
|
bindings[targetBindingName].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,
|
||||||
|
SH_KEYCODE toRemove) noexcept
|
||||||
|
{
|
||||||
|
return bindings[targetBindingName].negativeKeyCodes.erase(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check positive controllercodes to binding
|
||||||
|
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetPositiveControllerCodes(std::string bindingName) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].positiveControllerCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add positive SH_CONTROLLERCODE to binding
|
||||||
|
static inline void BindingsAddPositiveControllerCode(std::string targetBindingName,
|
||||||
|
SH_CONTROLLERCODE toAdd) noexcept
|
||||||
|
{
|
||||||
|
bindings[targetBindingName].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,
|
||||||
|
SH_CONTROLLERCODE toRemove) noexcept
|
||||||
|
{
|
||||||
|
return bindings[targetBindingName].positiveControllerCodes.erase(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check negative controllercodes to binding
|
||||||
|
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetNegativeControllerCodes(std::string bindingName) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].negativeControllerCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add negative SH_CONTROLLERCODE to binding
|
||||||
|
static inline void BindingsAddNegativeControllerCode(std::string targetBindingName,
|
||||||
|
SH_CONTROLLERCODE toAdd) noexcept
|
||||||
|
{
|
||||||
|
bindings[targetBindingName].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,
|
||||||
|
SH_CONTROLLERCODE toRemove) noexcept
|
||||||
|
{
|
||||||
|
return bindings[targetBindingName].negativeControllerCodes.erase(toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Mouse movement bindings
|
||||||
|
|
||||||
|
static inline double const BindingsGetMouseXPositiveMultiplier(std::string bindingName) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].mouseXPositiveMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void BindingsSetMouseXPositiveMultiplier(std::string bindingName, double newValue) noexcept
|
||||||
|
{
|
||||||
|
bindings[bindingName].mouseXPositiveMultiplier = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Other Functions */
|
/* Other Functions */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
@ -482,10 +810,36 @@ namespace SHADE
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
static constexpr size_t MAX_KEYS = UCHAR_MAX + 1;
|
static constexpr size_t MAX_KEYS = UCHAR_MAX + 1;
|
||||||
|
|
||||||
|
//How many recognised controller inputs there are
|
||||||
|
//To see the list, see the enum class in this file
|
||||||
|
static constexpr size_t MAX_CONTROLLER_INPUT = 20;
|
||||||
|
|
||||||
|
//On/off button count
|
||||||
|
static constexpr size_t NUM_CONTROLLER_BUTTON = 14;
|
||||||
|
|
||||||
|
//8-bit trigger values
|
||||||
|
static constexpr size_t NUM_CONTROLLER_TRIGGER = 2;
|
||||||
|
|
||||||
|
//16-bit thumbstick values
|
||||||
|
static constexpr size_t NUM_CONTROLLER_THUMBSTICK = 4;
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//If the last input is from controller(s) or KB/M
|
||||||
|
//True if from controller(s), False if from KB/M
|
||||||
|
//Useful for switching control hints between controllers and KB/M
|
||||||
|
static bool controllerInUse;
|
||||||
|
|
||||||
|
//BINDINGS//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//Key is for binding names, they must be unique
|
||||||
|
//Multiple physical inputs per virtual/logical input are to be added to
|
||||||
|
//sets inside the logicalBinding values
|
||||||
|
//TODO make this an array of 4 / 5 users for multiplayer support
|
||||||
|
static std::map<std::string, SHLogicalBindingData> bindings;
|
||||||
|
|
||||||
//KEYBOARD AND MOUSE BUTTONS////////////////////////////////////////////////
|
//KEYBOARD AND MOUSE BUTTONS////////////////////////////////////////////////
|
||||||
|
|
||||||
//How many keys are presently being pressed
|
//How many keys are presently being pressed
|
||||||
|
@ -558,15 +912,48 @@ namespace SHADE
|
||||||
|
|
||||||
//CONTROLLER VARIABLES//////////////////////////////////////////////////////
|
//CONTROLLER VARIABLES//////////////////////////////////////////////////////
|
||||||
|
|
||||||
//OTHER VARIABLES///////////////////////////////////////////////////////////
|
//Count how many controllers are presently connected
|
||||||
|
//Useful for if the game is to decide to take in controller or KB/M input
|
||||||
|
//Between 0 and 4 (inclusive)
|
||||||
|
static unsigned char controllersConnectedCount;
|
||||||
|
|
||||||
//Axis bindings
|
//How many inputs (of any kind) on the controller are being used now
|
||||||
//X
|
//Includes analog triggers and thumbsticks
|
||||||
|
static unsigned controllersInputCount[XUSER_MAX_COUNT];
|
||||||
//Y
|
|
||||||
|
|
||||||
//Other mappings
|
//How many DIGITAL buttons on the controller are being pressed now
|
||||||
|
static unsigned controllersButtonCount[XUSER_MAX_COUNT];
|
||||||
|
|
||||||
//Buffer
|
//Current state of controllers
|
||||||
|
//First index is for controller number
|
||||||
|
//Second index is for input type
|
||||||
|
static short controllers[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
|
||||||
|
//State of controllers in the last frame
|
||||||
|
//First index is for controller number
|
||||||
|
//Second index is for input type
|
||||||
|
static short controllersLast[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
|
||||||
|
//Held and released times
|
||||||
|
|
||||||
|
//Controller held durations
|
||||||
|
//Stops ticking up when released
|
||||||
|
//Will be reset when held again
|
||||||
|
static double controllersHeldTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
|
||||||
|
//Key released durations
|
||||||
|
//Stops ticking up when held
|
||||||
|
//Will be reset when off again
|
||||||
|
static double controllersReleasedTime[XUSER_MAX_COUNT][MAX_CONTROLLER_INPUT];
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Internal Helper Functions */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//Internal helper function for checking if input is considered held or not
|
||||||
|
static bool controllerConsideredHeld(size_t inputIdx, short value) noexcept;
|
||||||
|
|
||||||
|
//Internal helper function for getting normalised controller value
|
||||||
|
static double controllerNormalisedValue(size_t inputIdx, short value) noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue