284 lines
9.8 KiB
C++
284 lines
9.8 KiB
C++
#include "Input.h"
|
|
|
|
// Singleton requirement
|
|
Input* Input::instance;
|
|
|
|
// --------------- Basic usage -----------------
|
|
//
|
|
// The keyboard functions all take a single character
|
|
// like 'W', ' ' or '8' (which will implicitly cast
|
|
// to an int) or a pre-defined virtual key code like
|
|
// VK_SHIFT, VK_ESCAPE or VK_TAB. These virtual key
|
|
// codes are are accessible through the Windows.h
|
|
// file (already included in Input.h). See the
|
|
// following for a complete list of virtual key codes:
|
|
// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
|
//
|
|
// Checking if various keys are down or up:
|
|
//
|
|
// if (Input::GetInstance().KeyDown('W')) { }
|
|
// if (Input::GetInstance().KeyUp('2')) { }
|
|
// if (Input::GetInstance().KeyDown(VK_SHIFT)) { }
|
|
//
|
|
//
|
|
// Checking if a key was initially pressed or released
|
|
// this frame:
|
|
//
|
|
// if (Input::GetInstance().KeyPressed('Q')) { }
|
|
// if (Input::GetInstance().KeyReleased(' ')) { }
|
|
//
|
|
// (Note that these functions will only return true on
|
|
// the FIRST frame that a key is pressed or released.)
|
|
//
|
|
//
|
|
// Checking for mouse input:
|
|
//
|
|
// if (Input::GetInstance().MouseLeftDown()) { }
|
|
// if (Input::GetInstance().MouseRightDown()) { }
|
|
// if (Input::GetInstance().MouseMiddleUp()) { }
|
|
// if (Input::GetInstance().MouseLeftPressed()) { }
|
|
// if (Input::GetInstance().MouseRightReleased()) { }
|
|
//
|
|
// ---------------------------------------------
|
|
|
|
// -------------- Less verbose -----------------
|
|
//
|
|
// If you'd rather not have to type Input::GetInstance()
|
|
// over and over, you can save the reference in a variable:
|
|
//
|
|
// Input& input = Input::GetInstance();
|
|
// if (input.KeyDown('W')) { }
|
|
// if (input.KeyDown('A')) { }
|
|
// if (input.KeyDown('S')) { }
|
|
// if (input.KeyDown('D')) { }
|
|
//
|
|
// ---------------------------------------------
|
|
|
|
|
|
// --------------------------
|
|
// Cleans up the key arrays
|
|
// --------------------------
|
|
Input::~Input()
|
|
{
|
|
delete[] kbState;
|
|
delete[] prevKbState;
|
|
}
|
|
|
|
// ---------------------------------------------------
|
|
// Initializes the input variables and sets up the
|
|
// initial arrays of key states
|
|
//
|
|
// windowHandle - the handle (id) of the window,
|
|
// which is necessary for mouse input
|
|
// ---------------------------------------------------
|
|
void Input::Initialize(HWND windowHandle)
|
|
{
|
|
kbState = new unsigned char[256];
|
|
prevKbState = new unsigned char[256];
|
|
|
|
memset(kbState, 0, sizeof(unsigned char) * 256);
|
|
memset(prevKbState, 0, sizeof(unsigned char) * 256);
|
|
|
|
wheelDelta = 0.0f;
|
|
mouseX = 0; mouseY = 0;
|
|
prevMouseX = 0; prevMouseY = 0;
|
|
mouseXDelta = 0; mouseYDelta = 0;
|
|
|
|
this->windowHandle = windowHandle;
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Updates the input manager for this frame. This should
|
|
// be called at the beginning of every Game::Update(),
|
|
// before anything that might need input
|
|
// ----------------------------------------------------------
|
|
void Input::Update()
|
|
{
|
|
// Copy the old keys so we have last frame's data
|
|
memcpy(prevKbState, kbState, sizeof(unsigned char) * 256);
|
|
|
|
// Get the latest keys (from Windows)
|
|
// Note the use of (void), which denotes to the compiler
|
|
// that we're intentionally ignoring the return value
|
|
(void)GetKeyboardState(kbState);
|
|
|
|
// Get the current mouse position then make it relative to the window
|
|
POINT mousePos = {};
|
|
GetCursorPos(&mousePos);
|
|
ScreenToClient(windowHandle, &mousePos);
|
|
|
|
// Save the previous mouse position, then the current mouse
|
|
// position and finally calculate the change from the previous frame
|
|
prevMouseX = mouseX;
|
|
prevMouseY = mouseY;
|
|
mouseX = mousePos.x;
|
|
mouseY = mousePos.y;
|
|
mouseXDelta = mouseX - prevMouseX;
|
|
mouseYDelta = mouseY - prevMouseY;
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Resets the mouse wheel value at the end of the frame.
|
|
// This cannot occur earlier in the frame, since the wheel
|
|
// input comes from Win32 windowing messages, which are
|
|
// handled between frames.
|
|
// ----------------------------------------------------------
|
|
void Input::EndOfFrame()
|
|
{
|
|
// Reset wheel value
|
|
wheelDelta = 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Get the mouse's current position in pixels relative
|
|
// to the top left corner of the window.
|
|
// ----------------------------------------------------------
|
|
int Input::GetMouseX() { return mouseX; }
|
|
int Input::GetMouseY() { return mouseY; }
|
|
|
|
|
|
// ---------------------------------------------------------------
|
|
// Get the mouse's change (delta) in position since last
|
|
// frame in pixels relative to the top left corner of the window.
|
|
// ---------------------------------------------------------------
|
|
int Input::GetMouseXDelta() { return mouseXDelta; }
|
|
int Input::GetMouseYDelta() { return mouseYDelta; }
|
|
|
|
|
|
// ---------------------------------------------------------------
|
|
// Get the mouse wheel delta for this frame. Note that there is
|
|
// no absolute position for the mouse wheel; this is either a
|
|
// positive number, a negative number or zero.
|
|
// ---------------------------------------------------------------
|
|
float Input::GetMouseWheel() { return wheelDelta; }
|
|
|
|
|
|
// ---------------------------------------------------------------
|
|
// Sets the mouse wheel delta for this frame. This is called
|
|
// by DXCore whenever an OS-level mouse wheel message is sent
|
|
// to the application. You'll never need to call this yourself.
|
|
// ---------------------------------------------------------------
|
|
void Input::SetWheelDelta(float delta)
|
|
{
|
|
wheelDelta = delta;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// Is the given key down this frame?
|
|
//
|
|
// key - The key to check, which could be a single character
|
|
// like 'W' or '3', or a virtual key code like VK_TAB,
|
|
// VK_ESCAPE or VK_SHIFT.
|
|
// ----------------------------------------------------------
|
|
bool Input::KeyDown(int key)
|
|
{
|
|
if (key < 0 || key > 255) return false;
|
|
|
|
return (kbState[key] & 0x80) != 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Is the given key up this frame?
|
|
//
|
|
// key - The key to check, which could be a single character
|
|
// like 'W' or '3', or a virtual key code like VK_TAB,
|
|
// VK_ESCAPE or VK_SHIFT.
|
|
// ----------------------------------------------------------
|
|
bool Input::KeyUp(int key)
|
|
{
|
|
if (key < 0 || key > 255) return false;
|
|
|
|
return !(kbState[key] & 0x80);
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Was the given key initially pressed this frame?
|
|
//
|
|
// key - The key to check, which could be a single character
|
|
// like 'W' or '3', or a virtual key code like VK_TAB,
|
|
// VK_ESCAPE or VK_SHIFT.
|
|
// ----------------------------------------------------------
|
|
bool Input::KeyPress(int key)
|
|
{
|
|
if (key < 0 || key > 255) return false;
|
|
|
|
return
|
|
kbState[key] & 0x80 && // Down now
|
|
!(prevKbState[key] & 0x80); // Up last frame
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Was the given key initially released this frame?
|
|
//
|
|
// key - The key to check, which could be a single character
|
|
// like 'W' or '3', or a virtual key code like VK_TAB,
|
|
// VK_ESCAPE or VK_SHIFT.
|
|
// ----------------------------------------------------------
|
|
bool Input::KeyRelease(int key)
|
|
{
|
|
if (key < 0 || key > 255) return false;
|
|
|
|
return
|
|
!(kbState[key] & 0x80) && // Up now
|
|
prevKbState[key] & 0x80; // Down last frame
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// A utility function to fill a given array of booleans
|
|
// with the current state of the keyboard. This is most
|
|
// useful when hooking the engine's input up to another
|
|
// system, such as a user interface library. (You probably
|
|
// won't use this very much, if at all!)
|
|
//
|
|
// keyArray - pointer to a boolean array which will be
|
|
// filled with the current keyboard state
|
|
// size - the size of the boolean array (up to 256)
|
|
//
|
|
// Returns true if the size parameter was valid and false
|
|
// if it was <= 0 or > 256
|
|
// ----------------------------------------------------------
|
|
bool Input::GetKeyArray(bool* keyArray, int size)
|
|
{
|
|
if (size <= 0 || size > 256) return false;
|
|
|
|
// Loop through the given size and fill the
|
|
// boolean array. Note that the double exclamation
|
|
// point is on purpose; it's a quick way to
|
|
// convert any number to a boolean.
|
|
for (int i = 0; i < size; i++)
|
|
keyArray[i] = !!(kbState[i] & 0x80);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// Is the specific mouse button down this frame?
|
|
// ----------------------------------------------------------
|
|
bool Input::MouseLeftDown() { return (kbState[VK_LBUTTON] & 0x80) != 0; }
|
|
bool Input::MouseRightDown() { return (kbState[VK_RBUTTON] & 0x80) != 0; }
|
|
bool Input::MouseMiddleDown() { return (kbState[VK_MBUTTON] & 0x80) != 0; }
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// Is the specific mouse button up this frame?
|
|
// ----------------------------------------------------------
|
|
bool Input::MouseLeftUp() { return !(kbState[VK_LBUTTON] & 0x80); }
|
|
bool Input::MouseRightUp() { return !(kbState[VK_RBUTTON] & 0x80); }
|
|
bool Input::MouseMiddleUp() { return !(kbState[VK_MBUTTON] & 0x80); }
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// Was the specific mouse button initially
|
|
// pressed or released this frame?
|
|
// ----------------------------------------------------------
|
|
bool Input::MouseLeftPress() { return kbState[VK_LBUTTON] & 0x80 && !(prevKbState[VK_LBUTTON] & 0x80); }
|
|
bool Input::MouseLeftRelease() { return !(kbState[VK_LBUTTON] & 0x80) && prevKbState[VK_LBUTTON] & 0x80; }
|
|
|
|
bool Input::MouseRightPress() { return kbState[VK_RBUTTON] & 0x80 && !(prevKbState[VK_RBUTTON] & 0x80); }
|
|
bool Input::MouseRightRelease() { return !(kbState[VK_RBUTTON] & 0x80) && prevKbState[VK_RBUTTON] & 0x80; }
|
|
|
|
bool Input::MouseMiddlePress() { return kbState[VK_MBUTTON] & 0x80 && !(prevKbState[VK_MBUTTON] & 0x80); }
|
|
bool Input::MouseMiddleRelease() { return !(kbState[VK_MBUTTON] & 0x80) && prevKbState[VK_MBUTTON] & 0x80; }
|