Merge pull request #106 from SHADE-DP/SP3-10-input-management
Bindings and Controllers Logical bindings are stored in a map of strings (keys) and logical binding data (values). Logical binding data includes: Positive Key Codes Negative Key Codes Positive Controller Codes Negative Controller Codes Mouse X Positive Multiplier Mouse Y Positive Multiplier Bindings can only handle for one player for now. Up to four users can be implemented with relative ease, but that depends on whether we want to make the game multiplayer for some reason. Controller inputs are also handled, with 20 different inputs for the controller.
This commit is contained in:
commit
a484cb8e22
|
@ -20,6 +20,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];
|
||||||
bool SHInputManager::keysLast[MAX_KEYS];
|
bool SHInputManager::keysLast[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
|
//How many DIGITAL buttons on the controller are being pressed now
|
||||||
|
static unsigned controllersButtonCount[XUSER_MAX_COUNT];
|
||||||
|
|
||||||
//Other mappings
|
//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];
|
||||||
|
|
||||||
//Buffer
|
//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