This commit is contained in:
nastys
2019-07-30 13:48:28 +02:00
parent 17b6c02aee
commit d1349cfebe
157 changed files with 0 additions and 0 deletions
@@ -0,0 +1,91 @@
#include "Binding.h"
namespace TLAC::Input
{
Binding::Binding()
{
}
Binding::~Binding()
{
for (auto& binding : InputBindings)
delete binding;
}
void Binding::AddBinding(IInputBinding* inputBinding)
{
InputBindings.push_back(inputBinding);
}
bool Binding::AnyDown()
{
for (const auto& binding : InputBindings)
{
if (binding->IsDown())
return true;
}
return false;
}
bool Binding::AnyTapped()
{
for (const auto& binding : InputBindings)
{
if (binding->IsTapped())
return true;
}
return false;
}
bool Binding::AnyReleased()
{
for (const auto& binding : InputBindings)
{
if (binding->IsReleased())
return true;
}
return false;
}
int Binding::GetDownCount()
{
int count = 0;
for (const auto& binding : InputBindings)
{
if (binding->IsDown())
count++;
}
return count;
}
int Binding::GetTappedCount()
{
int count = 0;
for (const auto& binding : InputBindings)
{
if (binding->IsTapped())
count++;
}
return count;
}
int Binding::GetReleasedCount()
{
int count = 0;
for (const auto& binding : InputBindings)
{
if (binding->IsReleased())
count++;
}
return count;
}
}
@@ -0,0 +1,26 @@
#pragma once
#include <vector>
#include "IInputBinding.h"
namespace TLAC::Input
{
class Binding
{
public:
std::vector<IInputBinding*> InputBindings;
Binding();
~Binding();
void AddBinding(IInputBinding* inputBinding);
bool AnyDown();
bool AnyTapped();
bool AnyReleased();
int GetDownCount();
int GetTappedCount();
int GetReleasedCount();
};
}
@@ -0,0 +1,29 @@
#include "Ds4Binding.h"
namespace TLAC::Input
{
#define Ds4InstanceCheckDefault(checkFunc) (DualShock4::InstanceInitialized() ? DualShock4::GetInstance()->checkFunc : false)
Ds4Binding::Ds4Binding(Ds4Button button) : Button(button)
{
}
Ds4Binding::~Ds4Binding()
{
}
bool Ds4Binding::IsDown()
{
return Ds4InstanceCheckDefault(IsDown(Button));
}
bool Ds4Binding::IsTapped()
{
return Ds4InstanceCheckDefault(IsTapped(Button));
}
bool Ds4Binding::IsReleased()
{
return Ds4InstanceCheckDefault(IsReleased(Button));
}
}
@@ -0,0 +1,19 @@
#pragma once
#include "IInputBinding.h"
#include "../DirectInput/Ds4/DualShock4.h"
namespace TLAC::Input
{
class Ds4Binding : public IInputBinding
{
public:
Ds4Button Button;
Ds4Binding(Ds4Button button);
~Ds4Binding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
};
}
@@ -0,0 +1,12 @@
#pragma once
namespace TLAC::Input
{
class IInputBinding
{
public:
virtual bool IsDown() = 0;
virtual bool IsTapped() = 0;
virtual bool IsReleased() = 0;
};
}
@@ -0,0 +1,27 @@
#include "KeyboardBinding.h"
namespace TLAC::Input
{
KeyboardBinding::KeyboardBinding(BYTE keycode) : Keycode(keycode)
{
}
KeyboardBinding::~KeyboardBinding()
{
}
bool KeyboardBinding::IsDown()
{
return Keyboard::GetInstance()->IsDown(Keycode);
}
bool KeyboardBinding::IsTapped()
{
return Keyboard::GetInstance()->IsTapped(Keycode);
}
bool KeyboardBinding::IsReleased()
{
return Keyboard::GetInstance()->IsReleased(Keycode);
}
}
@@ -0,0 +1,19 @@
#pragma once
#include "IInputBinding.h"
#include "../Keyboard/Keyboard.h"
namespace TLAC::Input
{
class KeyboardBinding : public IInputBinding
{
public:
BYTE Keycode;
KeyboardBinding(BYTE keycode);
~KeyboardBinding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
};
}
@@ -0,0 +1,70 @@
#include "MouseBinding.h"
#include "../Keyboard/Keyboard.h"
namespace TLAC::Input
{
MouseBinding::MouseBinding(MouseAction action) : Action(action)
{
}
MouseBinding::~MouseBinding()
{
}
bool MouseBinding::IsDown()
{
switch (Action)
{
case MouseAction_LeftButton:
return Keyboard::GetInstance()->IsDown(MK_LBUTTON);
case MouseAction_RightButton:
return Keyboard::GetInstance()->IsDown(MK_RBUTTON);
case MouseAction_MiddleButton:
return Keyboard::GetInstance()->IsDown(MK_MBUTTON);
case MouseAction_ScrollUp:
return Mouse::GetInstance()->GetIsScrolledUp();
case MouseAction_ScrollDown:
return Mouse::GetInstance()->GetIsScrolledDown();
default:
return false;
}
}
bool MouseBinding::IsTapped()
{
switch (Action)
{
case MouseAction_LeftButton:
return Keyboard::GetInstance()->IsTapped(MK_LBUTTON);
case MouseAction_RightButton:
return Keyboard::GetInstance()->IsTapped(MK_RBUTTON);
case MouseAction_MiddleButton:
return Keyboard::GetInstance()->IsTapped(MK_MBUTTON);
case MouseAction_ScrollUp:
return Mouse::GetInstance()->GetIsScrolledUp();
case MouseAction_ScrollDown:
return Mouse::GetInstance()->GetIsScrolledDown();
default:
return false;
}
}
bool MouseBinding::IsReleased()
{
switch (Action)
{
case MouseAction_LeftButton:
return Keyboard::GetInstance()->IsReleased(MK_LBUTTON);
case MouseAction_RightButton:
return Keyboard::GetInstance()->IsReleased(MK_RBUTTON);
case MouseAction_MiddleButton:
return Keyboard::GetInstance()->IsReleased(MK_MBUTTON);
case MouseAction_ScrollUp:
return Mouse::GetInstance()->GetWasScrolledUp();
case MouseAction_ScrollDown:
return Mouse::GetInstance()->GetWasScrolledDown();
default:
return false;
}
}
}
@@ -0,0 +1,28 @@
#pragma once
#include "IInputBinding.h"
#include "../Mouse/Mouse.h"
namespace TLAC::Input
{
enum MouseAction
{
MouseAction_LeftButton,
MouseAction_RightButton,
MouseAction_MiddleButton,
MouseAction_ScrollUp,
MouseAction_ScrollDown,
};
class MouseBinding : public IInputBinding
{
public:
MouseAction Action;
MouseBinding(MouseAction action);
~MouseBinding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
};
}
@@ -0,0 +1,33 @@
#include "XinputBinding.h"
#include "..\Xinput\Xinput.h"
namespace TLAC::Input
{
XinputBinding::XinputBinding(BYTE keycode) : Keycode(keycode)
{
}
XinputBinding::~XinputBinding()
{
}
bool XinputBinding::IsDown()
{
return Xinput::GetInstance()->IsDown(Keycode);
}
bool XinputBinding::IsTapped()
{
return Xinput::GetInstance()->IsTapped(Keycode);
}
bool XinputBinding::IsReleased()
{
return Xinput::GetInstance()->IsReleased(Keycode);
}
bool XinputBinding::IsDoubleTapped()
{
return Xinput::GetInstance()->IsDoubleTapped(Keycode);
}
}
@@ -0,0 +1,21 @@
#pragma once
#include "IInputBinding.h"
#include <windows.h>
#include <vector>
namespace TLAC::Input
{
class XinputBinding : public IInputBinding
{
public:
BYTE Keycode;
XinputBinding(BYTE keycode);
~XinputBinding();
bool IsDown() override;
bool IsTapped() override;
bool IsReleased() override;
bool IsDoubleTapped();
};
}
@@ -0,0 +1,13 @@
#include "Controller.h"
namespace TLAC::Input
{
Controller::Controller()
{
}
Controller::~Controller()
{
}
}
@@ -0,0 +1,12 @@
#pragma once
#include "DirectInputDevice.h"
namespace TLAC::Input
{
class Controller : public DirectInputDevice
{
protected:
Controller();
~Controller();
};
}
@@ -0,0 +1,26 @@
#include "DirectInput.h"
namespace TLAC::Input
{
IDirectInput8 *IDirectInputInstance = nullptr;
HRESULT InitializeDirectInput(HMODULE module)
{
HRESULT result = DirectInput8Create(module, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&IDirectInputInstance, nullptr);
return result;
}
bool DirectInputInitialized()
{
return IDirectInputInstance != nullptr;
}
void DisposeDirectInput()
{
if (IDirectInputInstance == nullptr)
return;
IDirectInputInstance->Release();
IDirectInputInstance = nullptr;
}
}
@@ -0,0 +1,12 @@
#pragma once
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
namespace TLAC::Input
{
extern IDirectInput8 *IDirectInputInstance;
HRESULT InitializeDirectInput(HMODULE module);
bool DirectInputInitialized();
void DisposeDirectInput();
}
@@ -0,0 +1,66 @@
#include "DirectInputDevice.h"
namespace TLAC::Input
{
HRESULT DirectInputDevice::DI_CreateDevice(const GUID &guid)
{
if (!DirectInputInitialized())
return DIERR_NOTINITIALIZED;
HRESULT result = IDirectInputInstance->CreateDevice(guid, &directInputdevice, NULL);
return result;
}
HRESULT DirectInputDevice::DI_SetDataFormat(LPCDIDATAFORMAT dataFormat)
{
HRESULT result = directInputdevice->SetDataFormat(dataFormat);
return result;
}
HRESULT DirectInputDevice::DI_SetCooperativeLevel(HWND windowHandle, DWORD flags)
{
HRESULT result = directInputdevice->SetCooperativeLevel(windowHandle, flags);
return result;
}
HRESULT DirectInputDevice::DI_Acquire()
{
HRESULT result = directInputdevice->Acquire();
return result;
}
HRESULT DirectInputDevice::DI_Unacquire()
{
HRESULT result = directInputdevice->Unacquire();
return result;
}
HRESULT DirectInputDevice::DI_Release()
{
HRESULT result = directInputdevice->Release();
return result;
}
HRESULT DirectInputDevice::DI_Poll()
{
HRESULT result = directInputdevice->Poll();
return result;
}
HRESULT DirectInputDevice::DI_GetDeviceState(DWORD size, LPVOID data)
{
HRESULT result = directInputdevice->GetDeviceState(size, data);
return result;
}
void DirectInputDevice::DI_Dispose()
{
if (directInputdevice == nullptr)
return;
HRESULT result = NULL;
result = DI_Unacquire();
result = DI_Release();
}
}
@@ -0,0 +1,22 @@
#pragma once
#include "DirectInput.h"
namespace TLAC::Input
{
class DirectInputDevice
{
protected:
IDirectInputDevice8 *directInputdevice;
HRESULT DI_CreateDevice(const GUID& guid);
HRESULT DI_SetDataFormat(LPCDIDATAFORMAT dataFormat);
HRESULT DI_SetCooperativeLevel(HWND windowHandle, DWORD flags);
HRESULT DI_Acquire();
HRESULT DI_Unacquire();
HRESULT DI_Release();
HRESULT DI_Poll();
HRESULT DI_GetDeviceState(DWORD size, LPVOID data);
void DI_Dispose();
};
}
@@ -0,0 +1,35 @@
#include "DirectInputMouse.h"
namespace TLAC::Input
{
DirectInputMouse::DirectInputMouse()
{
HRESULT result = NULL;
result = DI_CreateDevice(GUID_SysMouse);
if (FAILED(result))
return;
result = DI_SetDataFormat(&c_dfDIMouse);
result = DI_Acquire();
}
DirectInputMouse::~DirectInputMouse()
{
DI_Dispose();
}
bool DirectInputMouse::Poll()
{
if (!DirectInputInitialized())
return FALSE;
HRESULT result = NULL;
result = DI_Poll();
result = DI_GetDeviceState(sizeof(mouseState), &mouseState);
return !FAILED(result);
}
}
@@ -0,0 +1,21 @@
#pragma once
#include "DirectInputDevice.h"
namespace TLAC::Input
{
class DirectInputMouse : public DirectInputDevice
{
public:
DirectInputMouse();
~DirectInputMouse();
bool Poll();
inline long GetXPosition() { return mouseState.lX; };
inline long GetYPosition() { return mouseState.lY; };
inline long GetMouseWheel() { return mouseState.lZ; };
private:
DIMOUSESTATE mouseState;
};
}
@@ -0,0 +1,52 @@
#pragma once
namespace TLAC::Input
{
enum Direction
{
DIR_UP,
DIR_RIGHT,
DIR_DOWN,
DIR_LEFT
};
enum Ds4Button : int
{
DS4_SQUARE = 0,
DS4_CROSS = 1,
DS4_CIRCLE = 2,
DS4_TRIANGLE = 3,
DS4_L1 = 4,
DS4_R1 = 5,
DS4_L_TRIGGER = 6,
DS4_R_TRIGGER = 7,
DS4_SHARE = 8,
DS4_OPTIONS = 9,
DS4_L3 = 10,
DS4_R3 = 11,
DS4_PS = 12,
DS4_TOUCH = 13,
DS4_DPAD_UP,
DS4_DPAD_RIGHT,
DS4_DPAD_DOWN,
DS4_DPAD_LEFT,
DS4_L_STICK_UP,
DS4_L_STICK_RIGHT,
DS4_L_STICK_DOWN,
DS4_L_STICK_LEFT,
DS4_R_STICK_UP,
DS4_R_STICK_RIGHT,
DS4_R_STICK_DOWN,
DS4_R_STICK_LEFT,
DS4_BUTTON_MAX,
};
}
@@ -0,0 +1,14 @@
#include "Ds4State.h"
namespace TLAC::Input
{
Joystick::Joystick() : XAxis(0.0f), YAxis(0.0f)
{
return;
};
Joystick::Joystick(float xAxis, float yAxis) : XAxis(xAxis), YAxis(yAxis)
{
return;
};
}
@@ -0,0 +1,39 @@
#pragma once
#include "../DirectInput.h"
#include "Ds4Button.h"
namespace TLAC::Input
{
struct Joystick
{
FLOAT XAxis, YAxis;
Joystick();
Joystick(float xAxis, float yAxis);
};
struct Dpad
{
BOOL IsDown;
FLOAT Angle;
Joystick Stick;
};
struct Trigger
{
FLOAT Axis;
};
struct Ds4State
{
DIJOYSTATE2 DI_JoyState;
BYTE Buttons[DS4_BUTTON_MAX];
Dpad Dpad;
Joystick LeftStick;
Joystick RightStick;
Trigger LeftTrigger;
Trigger RightTrigger;
};
}
@@ -0,0 +1,169 @@
#include "DualShock4.h"
#include "../../../Utilities/Math.h"
#include "../../../framework.h"
#include <stdio.h>
namespace TLAC::Input
{
DualShock4* DualShock4::instance;
DualShock4::DualShock4()
{
}
DualShock4::~DualShock4()
{
DI_Dispose();
}
bool DualShock4::TryInitializeInstance()
{
if (InstanceInitialized())
return true;
if (!DirectInputInitialized())
return false;
DualShock4 *dualShock4 = new DualShock4();
bool success = dualShock4->Initialize();
instance = success ? dualShock4 : nullptr;
if (!success)
delete dualShock4;
return success;
}
bool DualShock4::Initialize()
{
HRESULT result = NULL;
const size_t guidCount = sizeof(GUID_Ds4) / sizeof(GUID);
for (size_t i = 0; i < guidCount; i++)
{
result = DI_CreateDevice(GUID_Ds4[i]);
if (!FAILED(result))
break;
else if (i == guidCount - 1)
return false;
}
if (FAILED(result = DI_SetDataFormat(&c_dfDIJoystick2)))
return false;
result = DI_Acquire();
return true;
}
bool DualShock4::PollInput()
{
lastState = currentState;
HRESULT result = NULL;
result = DI_Poll();
result = DI_GetDeviceState(sizeof(DIJOYSTATE2), &currentState.DI_JoyState);
if (result != DI_OK)
return false;
UpdateInternalDs4State(currentState);
for (int button = 0; button < DS4_BUTTON_MAX; button++)
currentState.Buttons[button] = GetButtonState(currentState, (Ds4Button)button);
return true;
}
void DualShock4::UpdateInternalDs4State(Ds4State &state)
{
if (state.Dpad.IsDown = state.DI_JoyState.rgdwPOV[0] != -1)
{
state.Dpad.Angle = (state.DI_JoyState.rgdwPOV[0] / 100.0f);
auto direction = Utilities::GetDirection(state.Dpad.Angle);
state.Dpad.Stick = { direction.Y, -direction.X };
}
else
{
state.Dpad.Angle = 0;
state.Dpad.Stick = Joystick();
}
state.LeftStick = NormalizeStick(state.DI_JoyState.lX, state.DI_JoyState.lY);
state.RightStick = NormalizeStick(state.DI_JoyState.lZ, state.DI_JoyState.lRz);
state.LeftTrigger = { NormalizeTrigger(state.DI_JoyState.lRx) };
state.RightTrigger = { NormalizeTrigger(state.DI_JoyState.lRy) };
}
bool DualShock4::IsDown(Ds4Button button)
{
return currentState.Buttons[button];
}
bool DualShock4::IsUp(Ds4Button button)
{
return !IsDown(button);
}
bool DualShock4::IsTapped(Ds4Button button)
{
return IsDown(button) && WasUp(button);
}
bool DualShock4::IsReleased(Ds4Button button)
{
return IsUp(button) && WasDown(button);
}
bool DualShock4::WasDown(Ds4Button button)
{
return lastState.Buttons[button];
}
bool DualShock4::WasUp(Ds4Button button)
{
return !WasDown(button);
}
bool DualShock4::MatchesDirection(Joystick joystick, Direction directionEnum, float threshold)
{
switch (directionEnum)
{
case TLAC::Input::DIR_UP:
return joystick.YAxis <= -threshold;
case TLAC::Input::DIR_RIGHT:
return joystick.XAxis >= +threshold;
case TLAC::Input::DIR_DOWN:
return joystick.YAxis >= +threshold;
case TLAC::Input::DIR_LEFT:
return joystick.XAxis <= -threshold;
default:
return false;
}
}
bool DualShock4::GetButtonState(Ds4State &state, Ds4Button button)
{
if (button >= DS4_SQUARE && button <= DS4_TOUCH)
return state.DI_JoyState.rgbButtons[button];
if (button >= DS4_DPAD_UP && button <= DS4_DPAD_LEFT)
return state.Dpad.IsDown ? MatchesDirection(state.Dpad.Stick, (Direction)(button - DS4_DPAD_UP), dpadThreshold) : false;
if (button >= DS4_L_STICK_UP && button <= DS4_L_STICK_LEFT)
return MatchesDirection(state.LeftStick, (Direction)(button - DS4_L_STICK_UP), joystickThreshold);
if (button >= DS4_R_STICK_UP && button <= DS4_R_STICK_LEFT)
return MatchesDirection(state.RightStick, (Direction)(button - DS4_R_STICK_UP), joystickThreshold);
return false;
}
}
@@ -0,0 +1,62 @@
#pragma once
#include "../Controller.h"
#include "../../IInputDevice.h"
#include "Ds4State.h"
namespace TLAC::Input
{
// DualShock 4 Wireless Controller Product GUIDs:
const GUID GUID_Ds4[2] =
{
// First Generation: {05C4054C-0000-0000-0000-504944564944}
{ 0x05C4054C, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
// Second Generation: {09CC054C-0000-0000-0000-504944564944}
{ 0x09CC054C, 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } },
};
class DualShock4 : public Controller, public IInputDevice
{
public:
DualShock4();
~DualShock4();
static bool TryInitializeInstance();
bool Initialize();
bool PollInput() override;
bool IsDown(Ds4Button button);
bool IsUp(Ds4Button button);
bool IsTapped(Ds4Button button);
bool IsReleased(Ds4Button button);
bool WasDown(Ds4Button button);
bool WasUp(Ds4Button button);
inline Joystick GetLeftStick() { return currentState.LeftStick; };
inline Joystick GetRightStick() { return currentState.RightStick; };
inline Joystick GetDpad() { return currentState.Dpad.Stick; };
static inline bool InstanceInitialized() { return instance != nullptr; };
static inline DualShock4* GetInstance() { return instance; };
static inline void DeleteInstance() { delete instance; instance = nullptr; };
private:
static DualShock4* instance;
Ds4State lastState;
Ds4State currentState;
const float triggerThreshold = 0.5f;
const float joystickThreshold = 0.5f;
const float dpadThreshold = 0.5f;
inline float NormalizeTrigger(long value) { return (float)value / USHRT_MAX; };
inline float NormalizeStick(long value) { return (float)value / USHRT_MAX * 2.0f - 1.0f; };
inline Joystick NormalizeStick(long x, long y) { return Joystick(NormalizeStick(x), NormalizeStick(y)); };
void UpdateInternalDs4State(Ds4State &state);
bool MatchesDirection(Joystick joystick, Direction directionEnum, float threshold);
bool GetButtonState(Ds4State &state, Ds4Button button);
};
}
@@ -0,0 +1,10 @@
#pragma once
namespace TLAC::Input
{
class IInputDevice
{
public:
virtual bool PollInput() = 0;
};
}
@@ -0,0 +1,275 @@
#include "Config.h"
#include "windows.h"
#include "../Bindings/KeyboardBinding.h"
#include "../Bindings/Ds4Binding.h"
#include "../../Utilities/Operations.h"
#include "../Bindings/XinputBinding.h"
#include "../../Constants.h"
namespace TLAC::Input::KeyConfig
{
KeycodeMap Config::Keymap =
{
// NumPad Keys
{ "NumPad0", VK_NUMPAD0 },
{ "NumPad1", VK_NUMPAD1 },
{ "NumPad2", VK_NUMPAD2 },
{ "NumPad3", VK_NUMPAD3 },
{ "NumPad4", VK_NUMPAD4 },
{ "NumPad5", VK_NUMPAD5 },
{ "NumPad6", VK_NUMPAD6 },
{ "NumPad7", VK_NUMPAD7 },
{ "NumPad8", VK_NUMPAD8 },
{ "NumPad9", VK_NUMPAD9 },
{ "Plus", VK_ADD },
{ "Minus", VK_SUBTRACT },
{ "Divide", VK_DIVIDE },
{ "Multiply", VK_MULTIPLY },
{ "Comma", VK_OEM_COMMA },
{ "Period", VK_OEM_PERIOD },
{ "Slash", VK_OEM_2 },
// F-Keys
{ "F1", VK_F1 },
{ "F2", VK_F2 },
{ "F3", VK_F3 },
{ "F4", VK_F4 },
{ "F5", VK_F5 },
{ "F6", VK_F6 },
{ "F7", VK_F7 },
{ "F8", VK_F8 },
{ "F9", VK_F9 },
{ "F10", VK_F10 },
{ "F11", VK_F11 },
{ "F12", VK_F12 },
{ "F13", VK_F13 },
{ "F14", VK_F14 },
{ "F15", VK_F15 },
{ "F16", VK_F16 },
{ "F17", VK_F17 },
{ "F18", VK_F18 },
{ "F19", VK_F19 },
{ "F20", VK_F20 },
{ "F21", VK_F21 },
{ "F22", VK_F22 },
{ "F23", VK_F23 },
{ "F24", VK_F24 },
// Shift Keys
{ "LeftShift", VK_LSHIFT },
{ "LShift", VK_LSHIFT },
{ "RightShift", VK_RSHIFT },
{ "RShift", VK_RSHIFT },
// Control Keys
{ "LeftControl", VK_LCONTROL },
{ "LControl", VK_LCONTROL },
{ "LCtrl", VK_LCONTROL },
{ "RightControl", VK_RCONTROL },
{ "RControl", VK_RCONTROL },
{ "RCtrl", VK_RCONTROL },
// Arrow Keys
{ "Up", VK_UP },
{ "Down", VK_DOWN },
{ "Left", VK_LEFT },
{ "Right", VK_RIGHT },
// Special Keys
{ "Enter", VK_RETURN },
{ "Return", VK_RETURN },
{ "Tab", VK_TAB },
{ "Back", VK_BACK },
{ "Backspace", VK_BACK },
{ "Insert", VK_INSERT },
{ "Ins", VK_INSERT },
{ "Delete", VK_DELETE },
{ "Del", VK_DELETE },
{ "Home", VK_HOME },
{ "End", VK_END },
{ "PageUp", VK_PRIOR },
{ "PageDown", VK_NEXT },
{ "ESC", VK_ESCAPE },
{ "Escape", VK_ESCAPE },
{ "Comma", VK_OEM_COMMA },
{ "Period", VK_OEM_PERIOD },
{ "Slash", VK_OEM_2 },
// Mouse buttons
{ "MouseLeft", VK_LBUTTON },
{ "MouseMiddle", VK_MBUTTON },
{ "MouseRight", VK_RBUTTON },
{ "MouseX1", VK_XBUTTON1 },
{ "MouseX2", VK_XBUTTON2 },
};
KeycodeMap Config::XinputMap =
{
//XINPUT
{ "XINPUT_A", XINPUT_A},
{ "XINPUT_B", XINPUT_B},
{ "XINPUT_X", XINPUT_X},
{ "XINPUT_Y", XINPUT_Y},
{ "XINPUT_UP", XINPUT_UP},
{ "XINPUT_DOWN", XINPUT_DOWN},
{ "XINPUT_LEFT", XINPUT_LEFT},
{ "XINPUT_RIGHT", XINPUT_RIGHT},
{ "XINPUT_START", XINPUT_START},
{ "XINPUT_BACK", XINPUT_BACK},
{ "XINPUT_LS", XINPUT_LS},
{ "XINPUT_RS", XINPUT_RS},
{ "XINPUT_LB", XINPUT_LS},
{ "XINPUT_RB", XINPUT_RS},
{ "XINPUT_LT", XINPUT_LT},
{ "XINPUT_RT", XINPUT_RT},
{ "XINPUT_LSB", XINPUT_LSB},
{ "XINPUT_RSB", XINPUT_RSB},
{ "XINPUT_LLEFT", XINPUT_LLEFT},
{ "XINPUT_LRIGHT", XINPUT_LRIGHT},
{ "XINPUT_RLEFT", XINPUT_RLEFT},
{ "XINPUT_RRIGHT", XINPUT_RRIGHT},
};
Ds4ButtonMap Config::Ds4Map =
{
// Face Buttons
{ "DS4_SQUARE", DS4_SQUARE },
{ "Ds4_Square", DS4_SQUARE },
{ "DS4_CROSS", DS4_CROSS },
{ "Ds4_Cross", DS4_CROSS },
{ "DS4_CIRCLE", DS4_CIRCLE },
{ "Ds4_Circle", DS4_CIRCLE },
{ "DS4_TRIANGLE", DS4_TRIANGLE },
{ "Ds4_Triangle", DS4_TRIANGLE },
// Standard Buttons
{ "DS4_SHARE", DS4_SHARE },
{ "Ds4_Share", DS4_SHARE },
{ "DS4_OPTIONS", DS4_OPTIONS },
{ "Ds4_Options", DS4_OPTIONS },
{ "DS4_PS", DS4_PS },
{ "Ds4_PS", DS4_PS },
{ "DS4_TOUCH", DS4_TOUCH },
{ "Ds4_Touch", DS4_TOUCH },
{ "DS4_L1", DS4_L1 },
{ "Ds4_L1", DS4_L1 },
{ "DS4_R1", DS4_R1 },
{ "Ds4_R1", DS4_R1 },
// D-Pad Directions
{ "DS4_DPAD_UP", DS4_DPAD_UP },
{ "Ds4_DPad_Up", DS4_DPAD_UP },
{ "DS4_DPAD_RIGHT", DS4_DPAD_RIGHT },
{ "Ds4_DPad_Right", DS4_DPAD_RIGHT },
{ "DS4_DPAD_DOWN", DS4_DPAD_DOWN },
{ "Ds4_DPad_Down", DS4_DPAD_DOWN },
{ "DS4_DPAD_LEFT", DS4_DPAD_LEFT },
{ "Ds4_DPad_Left", DS4_DPAD_LEFT },
// Trigger Buttons
{ "DS4_L_TRIGGER", DS4_L_TRIGGER },
{ "Ds4_L_Trigger", DS4_L_TRIGGER },
{ "DS4_R_TRIGGER", DS4_R_TRIGGER },
{ "Ds4_R_Trigger", DS4_R_TRIGGER },
// Joystick Buttons
{ "DS4_L3", DS4_L3 },
{ "Ds4_L3", DS4_L3 },
{ "DS4_R3", DS4_R3 },
{ "Ds4_R3", DS4_R3 },
// Left Joystick
{ "DS4_L_STICK_UP", DS4_L_STICK_UP },
{ "Ds4_L_Stick_Up", DS4_L_STICK_UP },
{ "DS4_L_STICK_RIGHT", DS4_L_STICK_RIGHT },
{ "Ds4_L_Stick_Right", DS4_L_STICK_RIGHT },
{ "DS4_L_STICK_DOWN", DS4_L_STICK_DOWN },
{ "Ds4_L_Stick_Down", DS4_L_STICK_DOWN },
{ "DS4_L_STICK_LEFT", DS4_L_STICK_LEFT },
{ "Ds4_L_Stick_Left", DS4_L_STICK_LEFT },
// Right Joystick
{ "DS4_R_STICK_UP", DS4_R_STICK_UP },
{ "Ds4_R_Stick_Up", DS4_R_STICK_UP },
{ "DS4_R_STICK_RIGHT", DS4_R_STICK_RIGHT },
{ "Ds4_R_Stick_Right", DS4_R_STICK_RIGHT },
{ "DS4_R_STICK_DOWN", DS4_R_STICK_DOWN },
{ "Ds4_R_Stick_Down", DS4_R_STICK_DOWN },
{ "DS4_R_STICK_LEFT", DS4_R_STICK_LEFT },
{ "Ds4_R_Stick_Left", DS4_R_STICK_LEFT },
};
void Config::BindConfigKeys(std::unordered_map<std::string, std::string> &configMap, const char *configKeyName, Binding &bindObj, std::vector<std::string> defaultKeys)
{
std::vector<std::string> keys;
auto configPair = configMap.find(configKeyName);
// config variable was found in the ini
if (configPair != configMap.end())
{
keys = Utilities::Split(configPair->second, ",");
}
else
{
keys = defaultKeys;
}
for (std::string key : keys)
{
Utilities::Trim(key);
// Applies only for Single-Character keys
if (key.length() == 1)
{
bindObj.AddBinding(new KeyboardBinding(key[0]));
}
else // for special key names
{
auto keycode = Config::Keymap.find(key.c_str());
// name is known in the special keys map
if (keycode != Config::Keymap.end())
{
bindObj.AddBinding(new KeyboardBinding(keycode->second));
}
else
{
auto xinputBtn = Config::XinputMap.find(key.c_str());
if (xinputBtn != Config::XinputMap.end())
{
bindObj.AddBinding(new XinputBinding(xinputBtn->second));
}
else
{
// just gonna be lazy for now and put this inside an else statement
auto ds4Button = Config::Ds4Map.find(key.c_str());
if (ds4Button != Config::Ds4Map.end())
{
bindObj.AddBinding(new Ds4Binding(ds4Button->second));
}
else
{
printf("[TLAC] Config::BindConfigKeys(): Unable to parse key: '%s'\n", key.c_str());
}
}
}
}
}
}
}
@@ -0,0 +1,23 @@
#pragma once
#include <unordered_map>
#include "KeyString.h"
#include "KeyStringHash.h"
#include "../Bindings/Binding.h"
#include "../DirectInput/Ds4/Ds4Button.h"
namespace TLAC::Input::KeyConfig
{
typedef std::unordered_map<KeyString, uint8_t, KeyStringHash> KeycodeMap;
typedef std::unordered_map<KeyString, Ds4Button, KeyStringHash> Ds4ButtonMap;
class Config
{
public:
static KeycodeMap Keymap;
static Ds4ButtonMap Ds4Map;
static KeycodeMap XinputMap;
static void BindConfigKeys(std::unordered_map<std::string, std::string> &configMap, const char *configKeyName, Binding &bindObj, std::vector<std::string> defaultKeys);
};
}
@@ -0,0 +1,13 @@
#include "KeyString.h"
namespace TLAC::Input::KeyConfig
{
KeyString::KeyString(const char* str) : value(str)
{
}
bool KeyString::operator==(const KeyString& rsv) const
{
return !_strcmpi(value.c_str(), rsv.value.c_str());
}
}
@@ -0,0 +1,14 @@
#pragma once
#include <string>
namespace TLAC::Input::KeyConfig
{
struct KeyString
{
std::string value;
KeyString(const char* str);
bool operator==(const KeyString& rsv) const;
};
}
@@ -0,0 +1,13 @@
#include "KeyStringHash.h"
#include <filesystem>
namespace TLAC::Input::KeyConfig
{
size_t KeyStringHash::operator()(const KeyString& key) const
{
std::string ret = key.value;
std::transform(ret.begin(), ret.end(), ret.begin(),
[](unsigned char c) { return std::tolower(c, std::locale()); });
return std::hash<std::string>()(ret);
}
}
@@ -0,0 +1,10 @@
#pragma once
#include "KeyString.h"
namespace TLAC::Input::KeyConfig
{
struct KeyStringHash
{
size_t operator()(const KeyString& key) const;
};
}
@@ -0,0 +1,100 @@
#include "Keyboard.h"
namespace TLAC::Input
{
Keyboard* Keyboard::instance;
Keyboard::Keyboard()
{
}
Keyboard* Keyboard::GetInstance()
{
if (instance == nullptr)
instance = new Keyboard();
return instance;
}
bool Keyboard::PollInput()
{
lastState = currentState;
float elapsed = keyIntervalWatch.Restart();
for (BYTE i = 0; i < KEYBOARD_KEYS; i++)
{
// DOWN
bool isDown = GetAsyncKeyState(i) < 0;
currentState.KeyStates[i] = isDown;
// DOUBLE TAPPED
bool isTapped = IsTapped(i);
keyDoubleTapStates[i] = isTapped ? keyDoubleTapWatches[i].Restart() <= DOUBLE_TAP_THRESHOLD : false;
// INTERVAL TAPPED
keyIntervalTapStates[i] = isTapped;
if (isTapped)
{
keyIntervalTapTimes[i] = 0;
keyIntervalInitials[i] = true;
}
else if (isDown)
{
float threshold = keyIntervalInitials[i] ? INTERVAL_TAP_DELAY_THRESHOLD : INTERVAL_TAP_THRESHOLD;
bool intervalTapped = (keyIntervalTapTimes[i] += elapsed) > threshold;
keyIntervalTapStates[i] = intervalTapped;
if (intervalTapped)
{
keyIntervalTapTimes[i] = 0;
keyIntervalInitials[i] = false;
}
}
}
return true;
}
bool Keyboard::IsDown(BYTE keycode)
{
return currentState.IsDown(keycode);
}
bool Keyboard::IsUp(BYTE keycode)
{
return !IsDown(keycode);
}
bool Keyboard::IsTapped(BYTE keycode)
{
return IsDown(keycode) && WasUp(keycode);
}
bool Keyboard::IsDoubleTapped(BYTE keycode)
{
return keyDoubleTapStates[keycode];
}
bool Keyboard::IsReleased(BYTE keycode)
{
return IsUp(keycode) && WasDown(keycode);
}
inline bool Keyboard::WasDown(BYTE keycode)
{
return lastState.IsDown(keycode);
}
inline bool Keyboard::WasUp(BYTE keycode)
{
return !WasDown(keycode);
}
bool Keyboard::IsIntervalTapped(BYTE keycode)
{
return keyIntervalTapStates[keycode];
}
}
@@ -0,0 +1,47 @@
#pragma once
#include "../IInputDevice.h"
#include "KeyboardState.h"
#include "../../Utilities/Stopwatch.h"
using Stopwatch = TLAC::Utilities::Stopwatch;
namespace TLAC::Input
{
constexpr float DOUBLE_TAP_THRESHOLD = 200.0f;
constexpr float INTERVAL_TAP_DELAY_THRESHOLD = 500.0f;
constexpr float INTERVAL_TAP_THRESHOLD = 75.0f;
class Keyboard : public IInputDevice
{
public:
static Keyboard* GetInstance();
bool PollInput() override;
bool IsDown(BYTE keycode);
bool IsUp(BYTE keycode);
bool IsTapped(BYTE keycode);
bool IsDoubleTapped(BYTE keycode);
bool IsReleased(BYTE keycode);
bool IsIntervalTapped(BYTE keycode);
bool WasDown(BYTE keycode);
bool WasUp(BYTE keycode);
private:
Keyboard();
KeyboardState lastState;
KeyboardState currentState;
Stopwatch keyIntervalWatch;
BYTE keyDoubleTapStates[KEYBOARD_KEYS];
Stopwatch keyDoubleTapWatches[KEYBOARD_KEYS];
BOOL keyIntervalInitials[KEYBOARD_KEYS];
BYTE keyIntervalTapStates[KEYBOARD_KEYS];
FLOAT keyIntervalTapTimes[KEYBOARD_KEYS];
static Keyboard* instance;
};
}
@@ -0,0 +1,9 @@
#include "KeyboardState.h"
namespace TLAC::Input
{
bool KeyboardState::IsDown(BYTE keycode)
{
return KeyStates[keycode];
}
}
@@ -0,0 +1,15 @@
#pragma once
#include <windows.h>
namespace TLAC::Input
{
const int KEYBOARD_KEYS = 0xFF;
struct KeyboardState
{
BYTE KeyStates[KEYBOARD_KEYS];
bool IsDown(BYTE keycode);
};
}
@@ -0,0 +1,135 @@
#include "Mouse.h"
#include "../../framework.h"
#include "../../Constants.h"
namespace TLAC::Input
{
Mouse* Mouse::instance;
Mouse::Mouse()
{
directInputMouse = new DirectInputMouse();
}
Mouse::~Mouse()
{
if (directInputMouse != nullptr)
delete directInputMouse;
}
Mouse* Mouse::GetInstance()
{
if (instance == nullptr)
instance = new Mouse();
return instance;
}
POINT Mouse::GetPosition()
{
return currentState.Position;
}
POINT Mouse::GetRelativePosition()
{
return currentState.RelativePosition;
}
POINT Mouse::GetDeltaPosition()
{
return
{
currentState.Position.x - lastState.Position.x,
currentState.Position.y - lastState.Position.y
};
}
long Mouse::GetMouseWheel()
{
return currentState.MouseWheel;
}
long Mouse::GetDeltaMouseWheel()
{
return currentState.MouseWheel - lastState.MouseWheel;
}
bool Mouse::HasMoved()
{
POINT delta = GetDeltaPosition();
return delta.x != 0 || delta.y != 0;
}
bool Mouse::GetIsScrolledUp()
{
return currentState.ScrolledUp;
}
bool Mouse::GetIsScrolledDown()
{
return currentState.ScrolledDown;
}
bool Mouse::GetWasScrolledUp()
{
return lastState.ScrolledUp;
}
bool Mouse::GetWasScrolledDown()
{
return lastState.ScrolledDown;
}
void Mouse::SetPosition(int x, int y)
{
lastState.Position.x = x;
lastState.Position.y = y;
SetCursorPos(x, y);
}
bool Mouse::PollInput()
{
lastState = currentState;
GetCursorPos(&currentState.Position);
currentState.RelativePosition = currentState.Position;
if (framework::DivaWindowHandle != NULL)
ScreenToClient(framework::DivaWindowHandle, &currentState.RelativePosition);
RECT hWindow;
GetClientRect(TLAC::framework::DivaWindowHandle, &hWindow);
gameHeight = (int*)RESOLUTION_HEIGHT_ADDRESS;
gameWidth = (int*)RESOLUTION_WIDTH_ADDRESS;
fbWidth = (int*)FB_WIDTH_ADDRESS;
fbHeight = (int*)FB_HEIGHT_ADDRESS;
if (directInputMouse != nullptr)
{
if (directInputMouse->Poll())
currentState.MouseWheel += directInputMouse->GetMouseWheel();
currentState.ScrolledUp = (GetDeltaMouseWheel() > 0);
currentState.ScrolledDown = (GetDeltaMouseWheel() < 0);
}
if ((fbWidth != gameWidth) && (fbHeight != gameHeight)) {
xoffset = ((float)16 / (float)9) * (hWindow.bottom - hWindow.top);
if (xoffset != (hWindow.right - hWindow.left))
{
scale = xoffset / (hWindow.right - hWindow.left);
xoffset = ((hWindow.right - hWindow.left) / 2) - (xoffset / 2);
}
else {
xoffset = 0;
scale = 1;
}
currentState.RelativePosition.x = ((currentState.RelativePosition.x - round(xoffset)) * *gameWidth / (hWindow.right - hWindow.left)) / scale;
currentState.RelativePosition.y = currentState.RelativePosition.y * *gameHeight / (hWindow.bottom - hWindow.top);
}
return true;
}
}
@@ -0,0 +1,49 @@
#pragma once
#include "../IInputDevice.h"
#include "../DirectInput/DirectInputMouse.h"
#include "MouseState.h"
namespace TLAC::Input
{
class Mouse : public IInputDevice
{
public:
~Mouse();
static Mouse* GetInstance();
bool PollInput() override;
POINT GetPosition();
POINT GetRelativePosition();
POINT GetDeltaPosition();
long GetMouseWheel();
long GetDeltaMouseWheel();
bool HasMoved();
bool GetIsScrolledUp();
bool GetIsScrolledDown();
bool GetWasScrolledUp();
bool GetWasScrolledDown();
void SetPosition(int x, int y);
private:
Mouse();
MouseState lastState;
MouseState currentState;
DirectInputMouse* directInputMouse = nullptr;
int* gameWidth;
int* gameHeight;
int* fbWidth;
int* fbHeight;
float xoffset;
float scale;
static Mouse* instance;
};
}
@@ -0,0 +1,15 @@
#pragma once
#include <windows.h>
namespace TLAC::Input
{
struct MouseState
{
POINT Position;
POINT RelativePosition;
long MouseWheel;
bool ScrolledUp;
bool ScrolledDown;
};
}
@@ -0,0 +1,266 @@
#include <windows.h>
#include "Xinput.h"
#include "../../Constants.h"
namespace TLAC::Input
{
Xinput* Xinput::instance;
Xinput::Xinput()
{
}
Xinput* Xinput::GetInstance()
{
if (instance == nullptr)
{
instance = new Xinput();
}
return instance;
}
void Xinput::SetTapStates(BYTE keycode, float elapsed)
{
KeyDoubleTapStates[keycode] = IsTapped(keycode) ? KeyDoubleTapWatches[keycode].Restart() <= DOUBLE_TAP_THRESHOLD : false;
bool isDown = currentState.KeyStates[keycode];
bool isTapped = IsTapped(keycode);
keyIntervalTapStates[keycode] = isTapped;
if (isTapped)
{
keyIntervalTapTimes[keycode] = 0;
keyIntervalInitials[keycode] = true;
}
else if (isDown)
{
float threshold = keyIntervalInitials[keycode] ? INTERVAL_TAP_DELAY_THRESHOLD : INTERVAL_TAP_THRESHOLD;
bool intervalTapped = (keyIntervalTapTimes[keycode] += elapsed) > threshold;
keyIntervalTapStates[keycode] = intervalTapped;
if (intervalTapped)
{
keyIntervalTapTimes[keycode] = 0;
keyIntervalInitials[keycode] = false;
}
}
}
bool Xinput::PollInput()
{
lastState = currentState;
ZeroMemory(&state, sizeof(XINPUT_STATE));
float elapsed = keyIntervalWatch.Restart();
if (XInputGetState(0, &state) == ERROR_SUCCESS)
{
BYTE i = XINPUT_A;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_DOWN;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_B;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RIGHT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_X;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LEFT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_Y;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_UP;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LS;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RS;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LSB;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RSB;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_START;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_BACK;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_LT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.bLeftTrigger > 230)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
i = XINPUT_RT;
{
currentState.KeyStates[i] = false;
if (state.Gamepad.bRightTrigger > 230)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
{
//float normLX = fmaxf(-1, (float)state.Gamepad.sThumbLX / 32767);
i = XINPUT_LRIGHT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbLX > 10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
i = XINPUT_LLEFT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbLX < -10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
{
//float normLX = fmaxf(-1, (float)state.Gamepad.sThumbRX / 32767);
i = XINPUT_RRIGHT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbRX > 10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
i = XINPUT_RLEFT;
currentState.KeyStates[i] = false;
if (state.Gamepad.sThumbRX < -10000)
currentState.KeyStates[i] = true;
SetTapStates(i, elapsed);
}
}
else {
ZeroMemory(&state, sizeof(XINPUT_STATE));
ZeroMemory(&currentState, sizeof(currentState));
}
return TRUE;
}
bool Xinput::IsDown(BYTE keycode)
{
return currentState.IsDown(keycode);
}
bool Xinput::IsUp(BYTE keycode)
{
return !IsDown(keycode);
}
bool Xinput::IsTapped(BYTE keycode)
{
return IsDown(keycode) && WasUp(keycode);
}
bool Xinput::IsDoubleTapped(BYTE keycode)
{
return KeyDoubleTapStates[keycode];
}
bool Xinput::IsReleased(BYTE keycode)
{
return IsUp(keycode) && WasDown(keycode);
}
inline bool Xinput::WasDown(BYTE keycode)
{
return lastState.IsDown(keycode);
}
inline bool Xinput::WasUp(BYTE keycode)
{
return !WasDown(keycode);
}
bool Xinput::IsIntervalTapped(BYTE keycode)
{
return keyIntervalTapStates[keycode];
}
}
@@ -0,0 +1,51 @@
#pragma once
#include "../IInputDevice.h"
#include <xinput.h>
#include "../../Utilities/Stopwatch.h"
#include "XinputState.h"
using Stopwatch = TLAC::Utilities::Stopwatch;
namespace TLAC::Input
{
class Xinput : public IInputDevice
{
const float DOUBLE_TAP_THRESHOLD = 200.0f;
const float INTERVAL_TAP_DELAY_THRESHOLD = 500.0f;
const float INTERVAL_TAP_THRESHOLD = 75.0f;
public:
static Xinput* GetInstance();
bool PollInput() override;
bool IsDown(BYTE keycode);
bool IsUp(BYTE keycode);
bool IsTapped(BYTE keycode);
bool IsReleased(BYTE keycode);
bool IsDoubleTapped(BYTE keycode);
bool IsIntervalTapped(BYTE keycode);
bool WasDown(BYTE keycode);
bool WasUp(BYTE keycode);
private:
Xinput();
XinputState lastState;
XinputState currentState;
XINPUT_STATE state;
BYTE KeyDoubleTapStates[0xFF];
Utilities::Stopwatch KeyDoubleTapWatches[0xFF];
Stopwatch keyIntervalWatch;
BOOL keyIntervalInitials[0xFF];
BYTE keyIntervalTapStates[0xFF];
FLOAT keyIntervalTapTimes[0xFF];
static Xinput* instance;
void SetTapStates(BYTE keycode, float elapsed);
};
}
@@ -0,0 +1,9 @@
#include "XinputState.h"
namespace TLAC::Input
{
bool XinputState::IsDown(BYTE keycode)
{
return KeyStates[keycode];
}
}
@@ -0,0 +1,12 @@
#pragma once
#include <windows.h>
namespace TLAC::Input
{
struct XinputState
{
bool KeyStates[0x8F];
bool IsDown(BYTE keycode);
};
}