Merge pull request #50 from SHADE-DP/SP3-10-input-management

Input Manager System first version implemented
Presently able to handle:

Reading keyboard key presses, mouse movement (with movement speed recorded), buttons and scrolling (which needs connection to WM_MOUSEWHEEL to call PollWheelVerticalDelta(wParam))
Records how long buttons have been pressed / released, able to get values by functions
Checks if buttons are toggled on / off & how long they've been toggled on / off
Bool returning functions. Check if keys / mouse buttons are pressed / held / released or not in frameWhat should be added soon:
Reading and handling controller input via XInput
Key bindings
Axis bindings
Custom axis
Axis data-retrieval functions
Input Buffer
Editor BindingsFunctions tested to work in an isolated breadboard environment. Should be able to work in this engine's context.
This commit is contained in:
XiaoQiDigipen 2022-09-25 17:00:30 +08:00 committed by GitHub
commit f6ef5a443d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 770 additions and 0 deletions

View File

@ -23,6 +23,7 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h" #include "Scene/SHSceneManager.h"
#include "Math/Transform/SHTransformSystem.h" #include "Math/Transform/SHTransformSystem.h"
#include "Input/SHInputManagerSystem.h"
#include "Scenes/SBTestScene.h" #include "Scenes/SBTestScene.h"
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
@ -52,6 +53,7 @@ namespace Sandbox
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>(); SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>()); SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>();
// Create Routines // Create Routines
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
@ -72,6 +74,8 @@ namespace Sandbox
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>(); SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHInputManagerSystem, SHADE::SHInputManagerSystem::InputManagerRoutine>();
// Set up graphics system and windows // Set up graphics system and windows
graphicsSystem->SetWindow(&window); graphicsSystem->SetWindow(&window);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); sdlWindow = SDL_CreateWindowFrom(window.GetHWND());

View File

@ -0,0 +1,186 @@
/*********************************************************************
* \file SHInputManagerSystem.cpp
* \author Ryan Wang Nian Jing
* \brief Definition of input manager.
* Handles input from keyboard and mouse. Soon to include controller.
*
* \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction
or disclosure of this file or its contents without the prior written
consent of DigiPen Institute of Technology is prohibited.
*********************************************************************/
#pragma once
#include <SHpch.h>
#include "SHInputManagerSystem.h"
namespace SHADE
{
/*------------------------------------------------------------------------*/
/* Static defines */
/*------------------------------------------------------------------------*/
unsigned SHInputManagerSystem::keyCount = 0;
bool SHInputManagerSystem::keys[MAX_KEYS];
bool SHInputManagerSystem::keysLast[MAX_KEYS];
double SHInputManagerSystem::keysHeldTime[MAX_KEYS];
double SHInputManagerSystem::keysReleasedTime[MAX_KEYS];
unsigned SHInputManagerSystem::keyToggleCount = 0;
bool SHInputManagerSystem::keysToggle[MAX_KEYS];
bool SHInputManagerSystem::keysToggleLast[MAX_KEYS];
double SHInputManagerSystem::keysToggleOnTime[MAX_KEYS];
double SHInputManagerSystem::keysToggleOffTime[MAX_KEYS];
int SHInputManagerSystem::mouseScreenX = 0;
int SHInputManagerSystem::mouseScreenY = 0;
int SHInputManagerSystem::mouseScreenXLast = 0;
int SHInputManagerSystem::mouseScreenYLast = 0;
double SHInputManagerSystem::mouseVelocityX = 0;
double SHInputManagerSystem::mouseVelocityY = 0;
int SHInputManagerSystem::mouseWheelVerticalDelta = 0;
int SHInputManagerSystem::mouseWheelVerticalDeltaPoll = 0;
void SHInputManagerSystem::Init()
{
keyCount = 0;
SecureZeroMemory(keys, sizeof(keys));
SecureZeroMemory(keysLast, sizeof(keysLast));
SecureZeroMemory(keysHeldTime, sizeof(keysHeldTime));
SecureZeroMemory(keysReleasedTime, sizeof(keysReleasedTime));
keyToggleCount = 0;
SecureZeroMemory(keysToggle, sizeof(keysToggle));
SecureZeroMemory(keysToggleLast, sizeof(keysToggleLast));
SecureZeroMemory(keysToggleOnTime, sizeof(keysToggleOnTime));
SecureZeroMemory(keysToggleOffTime, sizeof(keysToggleOffTime));
mouseScreenX = 0;
mouseScreenY = 0;
mouseScreenXLast = 0;
mouseScreenYLast = 0;
mouseWheelVerticalDelta = 0;
mouseWheelVerticalDeltaPoll = 0;
}
void SHInputManagerSystem::Exit()
{
//No dynamically allocated memory. Nothing to do here.
}
void SHInputManagerSystem::InputManagerRoutine::
FixedExecute(double dt) noexcept
{
//Keyboard and Mouse Buttons////////////////////////////////////////////////
//Poll
unsigned char keyboardState[MAX_KEYS];
GetKeyboardState(keyboardState);
keyCount = 0;
keyToggleCount = 0;
for (size_t i = 0; i < MAX_KEYS; ++i)
{
//Ignore shift, ctrl and alt since they are split to left and right
if (static_cast<SH_KEYCODE>(i) == SH_KEYCODE::SHIFT ||
static_cast<SH_KEYCODE>(i) == SH_KEYCODE::CTRL ||
static_cast<SH_KEYCODE>(i) == SH_KEYCODE::ALT)
continue;
//Pressed state
if (keyboardState[i] & 0b10000000)
{
++keyCount;
keys[i] = true;
}
else keys[i] = false;
//Toggle state
if (keyboardState[i] & 0b00000001)
{
++keyToggleCount;
keysToggle[i] = true;
}
else keysToggle[i] = false;
}
//Timers
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (keys[i]) //Key is down
{
if (!keysLast[i]) //Key was just pressed
{
keysHeldTime[i] = 0.0; //Reset timer
}
keysHeldTime[i] += dt; //Tick up
}
else //Key is up
{
if (keysLast[i]) //Key was just released
{
keysReleasedTime[i] = 0.0; //Reset timer
}
keysReleasedTime[i] += dt; //Tick up
}
}
//Write to lastKeys
memcpy(keysLast, keys, sizeof(keys));
//Mouse Positioning/////////////////////////////////////
//https://stackoverflow.com/a/6423739
//Set last positioning
mouseScreenXLast = mouseScreenX;
mouseScreenYLast = mouseScreenY;
//Get cursor position, even when it is outside window
POINT p;
GetCursorPos(&p);
mouseScreenX = p.x;
mouseScreenY = p.y;
//Mouse wheel vertical delta updating
mouseWheelVerticalDelta = 0;
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
mouseWheelVerticalDeltaPoll = 0;
}
bool SHInputManagerSystem::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
{
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (keys[i] && !keysLast[i])
{
if (firstDetected) *firstDetected = static_cast<SH_KEYCODE>(i);
return true;
}
}
return false;
}
bool SHInputManagerSystem::AnyKey(SH_KEYCODE* firstDetected) noexcept
{
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (keys[i])
{
if (firstDetected) *firstDetected = static_cast<SH_KEYCODE>(i);
return true;
}
}
return false;
}
bool SHInputManagerSystem::AnyKeyUp(SH_KEYCODE* firstDetected) noexcept
{
for (size_t i = 0; i < MAX_KEYS; ++i)
{
if (!keys[i] && keysLast[i])
{
if (firstDetected) *firstDetected = static_cast<SH_KEYCODE>(i);
return true;
}
}
return false;
}
} //namespace SHADE

View File

@ -0,0 +1,580 @@
/*********************************************************************
* \file SHInputManagerSystem.h
* \author Ryan Wang Nian Jing
* \brief Declaration of input manager.
* Handles input from keyboard and mouse. Soon to include controller.
*
* \copyright Copyright (c) 2022 DigiPen Institute of Technology. Reproduction
or disclosure of this file or its contents without the prior written
consent of DigiPen Institute of Technology is prohibited.
*********************************************************************/
#pragma once
//#include <Xinput.h>
//#include "../../SHADE_Managed/src/SHpch.h"
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHFixedSystemRoutine.h"
namespace SHADE
{
class SH_API SHInputManagerSystem : public SHSystem
{
public:
class SH_API InputManagerRoutine : public SHFixedSystemRoutine
{
public:
virtual void FixedExecute(double dt) noexcept override final;
};
public:
/*------------------------------------------------------------------------*/
/* Enumerations */
/*------------------------------------------------------------------------*/
enum class SH_KEYCODE
{
LMB = 0X01,
RMB = 0X02,
CANCEL = 0X03,
MMB = 0X04,
XMB1 = 0X05,
XMB2 = 0X06,
BACKSPACE = 0X08,
TAB = 0X09,
CLEAR = 0X0C,
ENTER = 0X0D,
SHIFT = 0X10, //USE LEFT OR RIGHT SHIFT INSTEAD
CTRL = 0X11, //USE LEFT OR RIGHT CTRL INSTEAD
ALT = 0X12, //USE LEFT OR RIGHT ALT INSTEAD
PAUSE = 0X13,
CAPS_LOCK = 0X14,
IME_KANA = 0X15,
IME_HANGUL = 0X15,
IME_ON = 0X16,
IME_JUNJA = 0X17,
IME_FINAL = 0X18,
IME_HANJA = 0X19,
IME_KANJI = 0X19,
IME_OFF = 0X1A,
ESCAPE = 0X1B,
IME_CONVERT = 0X1C,
IME_NONCONVERT = 0X1D,
IME_ACCEPT = 0X1E,
IME_MODECHANGE = 0X1F,
SPACE = 0X20,
PAGE_UP = 0X21,
PAGE_DOWN = 0X22,
END = 0X23,
HOME = 0X24,
LEFT_ARROW = 0X25,
UP_ARROW = 0X26,
RIGHT_ARROW = 0X27,
DOWN_ARROW = 0X28,
SELECT = 0X29,
PRINT = 0X2A,
EXECUTE = 0X2B,
PRINT_SCREEN = 0X2C,
INSERT = 0X2D,
DEL = 0X2E,
HELP = 0X2F,
NUMBER_0 = 0X30,
NUMBER_1,
NUMBER_2,
NUMBER_3,
NUMBER_4,
NUMBER_5,
NUMBER_6,
NUMBER_7,
NUMBER_8,
NUMBER_9,
A = 0X41,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
LEFT_WINDOWS = 0X5B,
RIGHT_WINDOWS,
APPS,
SLEEP = 0X5F,
NUMPAD_0 = 0X60,
NUMPAD_1,
NUMPAD_2,
NUMPAD_3,
NUMPAD_4,
NUMPAD_5,
NUMPAD_6,
NUMPAD_7,
NUMPAD_8,
NUMPAD_9,
MULTIPLY = 0X6A,
ADD,
SEPARATOR,
SUBTRACT,
DECIMAL,
DIVIDE,
F1 = 0X70,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
F16,
F17,
F18,
F19,
F20,
F21,
F22,
F23,
F24,
NUM_LOCK = 0X90,
SCROLL_LOCK = 0X91,
OEM_PC98_NUMPAD_EQUAL = 0X92,
OEM_FUJITSU_DICTIONARY = 0X92,
OEM_FUJITSU_UNREGISTER,
OEM_FUJITSU_REGISTER,
OEM_FUJITSU_LEFT_THUMB,
OEM_FUJITSU_RIGHT_THUMB,
LEFT_SHIFT = 0XA0,
RIGHT_SHIFT,
LEFT_CTRL,
RIGHT_CTRL,
LEFT_ALT,
RIGHT_ALT,
BROWSER_BACK,
BROWSER_FORWARD,
BROWSER_REFRESH,
BROWSER_STOP,
BROWSER_SEARCH,
BROWSER_FAVOURITES,
BROWSER_HOME,
VOLUME_MUTE,
VOLUME_DOWN,
VOLUME_UP,
MEDIA_NEXT_TRACK,
MEDIA_PREVIOUS_TRACK,
MEDIA_STOP,
MEDIA_PLAY_PAUSE,
LAUNCH_MAIL,
LAUNCH_MEDIA_SELECT,
LAUNCH_APP_1,
LAUNCH_APP_2,
OEM_1 = 0XBA,
OEM_PLUS,
OEM_COMMA,
OEM_MINUS,
OEM_PERIOD,
OEM_2,
OEM_3,
GAMEPAD_A = 0XC3,
GAMEPAD_B,
GAMEPAD_X,
GAMEPAD_Y,
GAMEPAD_RIGHTSHOULDER,
GAMEPAD_LEFTSHOULDER,
GAMEPAD_LEFTTRIGGER,
GAMEPAD_RIGHTTRIGGER,
GAMEPAD_DPAD_UP,
GAMEPAD_DPAD_DOWN,
GAMEPAD_DPAD_LEFT,
GAMEPAD_DPAD_RIGHT,
GAMEPAD_MENU,
GAMEPAD_VIEW,
GAMEPAD_LEFT_THUMBSTICK_BUTTON,
GAMEPAD_RIGHT_THUMBSTICK_BUTTON,
GAMEPAD_LEFT_THUMBSTICK_UP,
GAMEPAD_LEFT_THUMBSTICK_DOWN,
GAMEPAD_LEFT_THUMBSTICK_RIGHT,
GAMEPAD_LEFT_THUMBSTICK_LEFT,
GAMEPAD_RIGHT_THUMBSTICK_UP,
GAMEPAD_RIGHT_THUMBSTICK_DOWN,
GAMEPAD_RIGHT_THUMBSTICK_RIGHT,
GAMEPAD_RIGHT_THUMBSTICK_LEFT,
OEM_4,
OEM_5,
OEM_6,
OEM_7,
OEM_8,
OEM_AX = 0XE1,
OEM_102,
OEM_ICO_HELP,
OEM_ICO_00,
IME_PROCESS,
OEM_ICO_CLEAR,
PACKET,
OEM_RESET = 0XE9,
OEM_JUMP,
OEM_PA1,
OEM_PA2,
OEM_PA3,
OEM_WSCTRL,
OEM_CUSEL,
OEM_ATTN,
OEM_FINISH,
OEM_COPY,
OEM_AUTO,
OEM_ENLW,
OEM_BACKTAB,
ATTN,
CRSEL,
EXSEL,
EREOF,
PLAY,
ZOOM,
NONAME,
PA_1,
OEM_CLEAR
};
public:
/*------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*------------------------------------------------------------------------*/
SHInputManagerSystem() noexcept = default;
~SHInputManagerSystem() noexcept = default;
SHInputManagerSystem(const SHInputManagerSystem&) = delete;
SHInputManagerSystem(SHInputManagerSystem&&) = delete;
SHInputManagerSystem& operator= (const SHInputManagerSystem&) = delete;
SHInputManagerSystem& operator= (SHInputManagerSystem&&) = delete;
/*------------------------------------------------------------------------*/
/* SHSystem Overrides */
/*------------------------------------------------------------------------*/
virtual void Init() override final;
virtual void Exit() override final;
/*------------------------------------------------------------------------*/
/* Member Functions */
/*------------------------------------------------------------------------*/
//Needs to be linked to WM_MOUSEWHEEL in wndProc
static inline void PollWheelVerticalDelta(WPARAM wParam) noexcept
{
mouseWheelVerticalDeltaPoll += GET_WHEEL_DELTA_WPARAM(wParam);
}
//For testing purposes
//static void PrintCurrentState() noexcept;
/*------------------------------------------------------------------------*/
/* Input state accessors (KB & M) */
/*------------------------------------------------------------------------*/
//Get how many keys are presently down
static inline unsigned GetKeyCount() noexcept
{
return keyCount;
}
//How many keys are presently toggled
static inline unsigned GetKeyToggleCount() noexcept
{
return keyToggleCount;
}
//Any key pressed in THIS FRAME ONLY
//Keys being held beforehand don't count
//Output parameter is which key was first to be detected
static bool AnyKeyDown(SH_KEYCODE* firstKey = nullptr) noexcept;
//Any key is being held down
//Return false if no key being held
//Output parameter is which key was first to be detected
static bool AnyKey(SH_KEYCODE* firstKey = nullptr) noexcept;
//Any key released in THIS FRAME ONLY
//Keys that are released beforehand don't count
//Output parameter is which key was first to be detected
static bool AnyKeyUp(SH_KEYCODE* firstKey = nullptr) noexcept;
//Check if a particular key was pressed down in THIS FRAME ONLY
//Keys being held beforehand don't count
//Output parameter is how long the key has been released for prior
static inline bool GetKeyDown (SH_KEYCODE key,
double* releasedTime = nullptr) noexcept
{
if (releasedTime) *releasedTime = keysReleasedTime[static_cast<int>(key)];
return (keys[static_cast<int>(key)] && !keysLast[static_cast<int>(key)]);
}
//Check if a particular key was toggled on in THIS FRAME ONLY
//Keys that stay toggled on afterwards don't count
//Output parameter is how long the key has been toggled off for prior
static inline bool GetKeyToggleOn (SH_KEYCODE key,
double* toggleOffTime = nullptr) noexcept
{
if (toggleOffTime)
*toggleOffTime = keysToggleOffTime[static_cast<int>(key)];
return (keysToggle[static_cast<int>(key)] &&
!keysToggleLast[static_cast<int>(key)]);
}
//Check if a particular key is presently being held down on
//Output parameter is how long the key has been held and released
static inline bool GetKey(SH_KEYCODE key,
double* heldTime = nullptr, double* releasedTime = nullptr) noexcept
{
if (heldTime) *heldTime = keysHeldTime[static_cast<int>(key)];
if (releasedTime) *releasedTime = keysReleasedTime[static_cast<int>(key)];
return keys[static_cast<int>(key)];
}
//Check if a particular key is presently toggled on
//Output parameter is how long the key has been toggled on and off
static inline bool GetKeyToggle(SH_KEYCODE key,
double* onTime = nullptr, double* offTime = nullptr) noexcept
{
if (onTime) *onTime = keysToggleOnTime[static_cast<int>(key)];
if (offTime) *offTime = keysToggleOffTime[static_cast<int>(key)];
return keysToggle[static_cast<int>(key)];
}
//Check if a particular key was released in THIS FRAME ONLY
//Keys already released beforehand don't count
//Output parameter is how long the key has been held for prior
static inline bool GetKeyUp(SH_KEYCODE key,
double* heldTime = nullptr) noexcept
{
if (heldTime) *heldTime = keysHeldTime[static_cast<int>(key)];
return (!keys[static_cast<int>(key)] && keysLast[static_cast<int>(key)]);
}
//Check if a particular key was toggled off in THIS FRAME ONLY
//Keys that stay toggled off afterwards don't count
//Output parameter is how long the key has been toggled on for prior
static inline bool GetKeyToggleOff(SH_KEYCODE key,
double* toggleOnTime = nullptr) noexcept
{
if (toggleOnTime)
*toggleOnTime = keysToggleOnTime[static_cast<int>(key)];
return (!keysToggle[static_cast<int>(key)] &&
keysToggleLast[static_cast<int>(key)]);
}
//Mouse/////////////
//Get the mouse location with respect to the screen
static inline void GetMouseScreenPosition (int* x = nullptr,
int* y = nullptr) noexcept
{
if (x) *x = mouseScreenX;
if (y) *y = mouseScreenY;
}
//Get the mouse location with respect to current window
static inline void GetMouseWindowPosition (int* x = nullptr,
int* y = nullptr) noexcept
{
POINT p{ mouseScreenX, mouseScreenY };
ScreenToClient(GetActiveWindow(), &p);
if (x) *x = mouseScreenX;
if (y) *y = mouseScreenY;
}
//Get the mouse velocity
//Two output parameters for x and y velocitites
//In pixels per second for both
static inline void GetMouseVelocity(double* x = nullptr,
double* y = nullptr) noexcept
{
if (x) *x = mouseVelocityX;
if (y) *y = mouseVelocityY;
}
//Get the mouse wheel vertical delta
static inline int GetMouseWheelVerticalDelta() noexcept
{
return mouseWheelVerticalDelta;
}
//GET INPUT TIMINGS///////////////////////////////////////////////////////////
//Keyboard/////////////
//How long has this key been held down for
static inline double GetKeyHeldTime(SH_KEYCODE key) noexcept
{
return keysHeldTime[static_cast<int>(key)];
}
//How long has this key been released for
static inline double GetKeyReleasedTime(SH_KEYCODE key) noexcept
{
return keysReleasedTime[static_cast<int>(key)];
}
//How long has this key been toggled on for
static inline double GetKeyToggleOnTime(SH_KEYCODE key) noexcept
{
return keysToggleOnTime[static_cast<int>(key)];
}
//How long has this keen been toggled off for
static inline double GetKeyToggleOffTime(SH_KEYCODE key) noexcept
{
return keysToggleOffTime[static_cast<int>(key)];
}
/*------------------------------------------------------------------------*/
/* Other Functions */
/*------------------------------------------------------------------------*/
//Mouse////////////////////////
//Move mouse cursor to a position on the screen
static inline void SetMouseScreenPosition(int x = 0, int y = 0) noexcept
{
SetCursorPos(x, y);
}
//Move mouse cursor to a position on the active window
static inline void SetMouseWindowPosition(int x = 0, int y = 0) noexcept
{
POINT p{ x, y };
ClientToScreen(GetActiveWindow(), &p);
SetCursorPos(p.x, p.y);
}
private:
/*------------------------------------------------------------------------*/
/* Constants */
/*------------------------------------------------------------------------*/
static constexpr size_t MAX_KEYS = UCHAR_MAX + 1;
/*------------------------------------------------------------------------*/
/* Data Members */
/*------------------------------------------------------------------------*/
//KEYBOARD AND MOUSE BUTTONS////////////////////////////////////////////////
//How many keys are presently being pressed
static unsigned keyCount;
//Key states of all keys presently
//true for being pressed, false for released
static bool keys[MAX_KEYS];
//Key states of all keys in the last frame
//true for being pressed, false for released
static bool keysLast[MAX_KEYS];
//Key held durations
//Stops ticking up when released
//Will be reset when held again
static double keysHeldTime[MAX_KEYS];
//Key released durations
//Stops ticking up when held
//Will be reset when off again
static double keysReleasedTime[MAX_KEYS];
//How many keys are presently being toggled
static unsigned keyToggleCount;
//Toggle key states of keys (not neccessarily just caps/num/scroll locks)
static bool keysToggle[MAX_KEYS];
//Toggle key states of keys in the last frame
static bool keysToggleLast[MAX_KEYS];
//Key toggle durations
//Stops ticking up when untoggled
//Will be reset when toggled again
static double keysToggleOnTime[MAX_KEYS];
//Key untoggle durations
//Stops ticking up when toggled
//Will be reset when untoggled again
static double keysToggleOffTime[MAX_KEYS];
//MOUSE VARIABLES///////////////////////////////////////////////////////////
//Present horizontal positioning of the mouse WRT the screen
//Increasing rightwards
static int mouseScreenX;
//Present vertical positioning of the mouse WRT the screen
//Increasing downwards
static int mouseScreenY;
//Horizontal positioning of the mouse WRT screen in last frame
//Increasing rightwards
static int mouseScreenXLast;
//Vertical positioning of the mouse WRT screen in the last frame
//Increasing downwards
static int mouseScreenYLast;
//The velocity at which the mouse is being moved horizontally (px/s)
//Rightwards is positive
static double mouseVelocityX;
//The velocity at which the mouse is being moved vertically (px/s)
//Downwards is positive
static double mouseVelocityY;
//For polling mouse wheel events, not to be read
static int mouseWheelVerticalDeltaPoll;
//Mouse wheel vertical rotation speed. Positive is rotation AWAY from user
static int mouseWheelVerticalDelta;
//CONTROLLER VARIABLES//////////////////////////////////////////////////////
//OTHER VARIABLES///////////////////////////////////////////////////////////
//Axis bindings
//X
//Y
//Other mappings
//Buffer
};
}