diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/keyboard.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/keyboard.cpp')
| -rw-r--r-- | hammer/keyboard.cpp | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/hammer/keyboard.cpp b/hammer/keyboard.cpp new file mode 100644 index 0000000..764bfdd --- /dev/null +++ b/hammer/keyboard.cpp @@ -0,0 +1,398 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include "Keyboard.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + +// +// Defines key state bit masks. +// +#define KEYSTATE_DOWN 0x0000FFFF +#define KEYSTATE_IMPULSE_DOWN 0x00010000 +#define KEYSTATE_IMPULSE_UP 0x00020000 + + +// +// List of allowed modifier keys and their associated bit masks. +// +static KeyMap_t ModifierKeyTable[] = +{ + { VK_SHIFT, KEY_MOD_SHIFT, 0 }, + { VK_CONTROL, KEY_MOD_CONTROL, 0 }, + { VK_MENU, KEY_MOD_ALT, 0 } +}; + + +//----------------------------------------------------------------------------- +// Purpose: Constructor. +//----------------------------------------------------------------------------- +CKeyboard::CKeyboard(void) +{ + g_uKeyMaps = 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor. +//----------------------------------------------------------------------------- +CKeyboard::~CKeyboard(void) +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Adds a key binding to the +// Input : uChar - The virtual keycode of the primary key that must be held down. +// uModifierKeys - Bitflags specifying which modifier keys must be +// held down along with the key specified by uChar. +// uLogicalKey - An application-specific value that indicates which +// logical function +//----------------------------------------------------------------------------- +void CKeyboard::AddKeyMap(unsigned int uChar, unsigned int uModifierKeys, unsigned int uLogicalKey) +{ + g_uKeyMap[g_uKeyMaps].uChar = uChar; + g_uKeyMap[g_uKeyMaps].uModifierKeys = uModifierKeys; + g_uKeyMap[g_uKeyMaps].uLogicalKey = uLogicalKey; + g_uKeyMaps++; +} + + +//----------------------------------------------------------------------------- +// Purpose: Clears the KEYSTATE_IMPULSE_UP and KEYSTATE_IMPULSE_DOWN flags from +// all physical and logical keys. +//----------------------------------------------------------------------------- +void CKeyboard::ClearImpulseFlags(void) +{ + int nKey; + + // + // Clear the impulse flags for all the physical keys. + // + for (nKey = 0; nKey < sizeof(g_uPhysicalKeyState) / sizeof(g_uPhysicalKeyState[0]); nKey++) + { + g_uPhysicalKeyState[nKey] &= ~(KEYSTATE_IMPULSE_DOWN | KEYSTATE_IMPULSE_UP); + } + + // + // Clear the impulse flags for all the logical keys. + // + for (nKey = 0; nKey < sizeof(g_uLogicalKeyState) / sizeof(g_uLogicalKeyState[0]); nKey++) + { + g_uLogicalKeyState[nKey] &= ~(KEYSTATE_IMPULSE_DOWN | KEYSTATE_IMPULSE_UP); + } +} + + + +//----------------------------------------------------------------------------- +// Purpose: Zeros out the key state for all physical and logical keys. +//----------------------------------------------------------------------------- +void CKeyboard::ClearKeyStates(void) +{ + int nKey; + + // + // Clear the physical key states. + // + for (nKey = 0; nKey < sizeof(g_uPhysicalKeyState) / sizeof(g_uPhysicalKeyState[0]); nKey++) + { + g_uPhysicalKeyState[nKey] = 0; + } + + // + // Clear the logical key states. + // + for (nKey = 0; nKey < sizeof(g_uLogicalKeyState) / sizeof(g_uLogicalKeyState[0]); nKey++) + { + g_uLogicalKeyState[nKey] = 0; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets a floating point value indicating about how long the logical +// key has been held down during this sample period. +// Input : uLogicalKey - Logical key to check. +// Output : Returns one of the following values: +// 0.25 if a key was pressed and released during the sample period, +// 0.5 if it was pressed and held, +// 0 if held then released, and +// 1.0 if held for the entire time. +//----------------------------------------------------------------------------- +float CKeyboard::GetKeyScale(unsigned int uLogicalKey) +{ + if (uLogicalKey >= MAX_LOGICAL_KEYS) + { + return(0); + } + + unsigned int uKeyState = g_uLogicalKeyState[uLogicalKey]; + + bool bImpulseDown = (uKeyState & KEYSTATE_IMPULSE_DOWN) != 0; + bool bImpulseUp = (uKeyState & KEYSTATE_IMPULSE_UP) != 0; + bool bDown = (uKeyState & KEYSTATE_DOWN) != 0; + float fValue = 0; + + // + // If we have a leading edge and no trailing edge, the key should be down. + // + if (bImpulseDown && !bImpulseUp) + { + if (bDown) + { + // + // Pressed and held this frame. + // + fValue = 0.5; + } + } + + // + // If we have a trailing edge and no leading edge, the key should be up. + // + if (bImpulseUp && !bImpulseDown) + { + if (!bDown) + { + // + // Released this frame. + // + fValue = 0; + } + } + + // + // If we have neither a leading edge nor a trailing edge, the key was either + // up the whole frame or down the whole frame. + // + if (!bImpulseDown && !bImpulseUp) + { + if (bDown) + { + // + // Held the entire frame + // + fValue = 1.0; + } + else + { + // + // Up the entire frame. + // + fValue = 0; + } + } + + // + // If we have both a leading and trailing edge, it was either released and repressed + // this frame, or pressed and released this frame. + // + if (bImpulseDown && bImpulseUp) + { + if (bDown) + { + // + // Released and re-pressed this frame. + // + fValue = 0.75; + } + else + { + // + // Pressed and released this frame. + // + fValue = 0.25; + } + } + + return fValue; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the bit mask associated with the given modifier key. +// Input : uModifierKey - The virtual key code corresponding to the modifier key. +// Output : The modifier key's bitmask. +//----------------------------------------------------------------------------- +unsigned int CKeyboard::GetModifierKeyBit(unsigned int uChar) +{ + for (int nKey = 0; nKey < sizeof(ModifierKeyTable) / sizeof(ModifierKeyTable[0]); nKey++) + { + if (ModifierKeyTable[nKey].uChar == uChar) + { + return(ModifierKeyTable[nKey].uModifierKeys); + } + } + + return(0); +} + + +//----------------------------------------------------------------------------- +// Purpose: Checks to see if all of the modifier keys specified by bits in uModifierKeys +// are currently held down. +// Input : uModifierKeys - Contains bits indicating which modifier keys to check: +// KEY_MOD_SHIFT +// KEY_MOD_CONTROL +// KEY_MOD_ALT +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CKeyboard::IsKeyPressed(unsigned int uChar, unsigned int uModifierKeys) +{ + if (!(g_uPhysicalKeyState[uChar] & KEYSTATE_DOWN)) + { + return(false); + } + + bool bKeyPressed = true; + + for (int nKey = 0; nKey < sizeof(ModifierKeyTable) / sizeof(ModifierKeyTable[0]); nKey++) + { + if (g_uPhysicalKeyState[ModifierKeyTable[nKey].uChar] & KEYSTATE_DOWN) + { + if (!(uModifierKeys & ModifierKeyTable[nKey].uModifierKeys)) + { + bKeyPressed = false; + } + } + else if (uModifierKeys & ModifierKeyTable[nKey].uModifierKeys) + { + bKeyPressed = false; + } + } + + return(bKeyPressed); +} + + +//----------------------------------------------------------------------------- +// Purpose: Determines whether a key is an allowed modifier key, ie, whether it +// can be used in conjunction with other keys when performing key +// bindings. +// Input : uChar - Virtual key to check. +// Output : Returns true if this key is a modifier key, false if not. +//----------------------------------------------------------------------------- +bool CKeyboard::IsModifierKey(unsigned int uChar) +{ + return((uChar == VK_SHIFT) || (uChar == VK_CONTROL) || (uChar == VK_MENU)); +} + + +//----------------------------------------------------------------------------- +// Purpose: Given a key press/release event, updates the status of all logical +// keys. +// Input : uChar - The key whose state has changed. +// bPressed - True if the key was pressed, false if it was released. +//----------------------------------------------------------------------------- +void CKeyboard::UpdateLogicalKeys(unsigned int uChar, bool bPressed) +{ + // + // Determine whether the key is a modifier key. If so, find its modifier bit. + // + bool bIsModifierKey = IsModifierKey(uChar); + unsigned int uModifierKeyBit = 0; + if (bIsModifierKey) + { + uModifierKeyBit = GetModifierKeyBit(uChar); + } + + // + // For every key in the keymap that depends upon this physical key, update + // the state of the corresponding logical key based on this event. + // + for (unsigned int nKey = 0; nKey < g_uKeyMaps; nKey++) + { + unsigned int uPhysicalKey = g_uKeyMap[nKey].uChar; + unsigned int uLogicalKey = g_uKeyMap[nKey].uLogicalKey; + unsigned int uModifierKeys = g_uKeyMap[nKey].uModifierKeys; + + if ((uPhysicalKey == uChar) || (uModifierKeys & uModifierKeyBit)) + { + // + // Check the state of all modifier keys to which this logical key + // is bound to determine whether the logical key is pressed or not. + // + bool bLogicalKeyPressed = IsKeyPressed(g_uKeyMap[nKey].uChar, g_uKeyMap[nKey].uModifierKeys); + + // + // Update the logical key state. + // + if (bPressed) + { + if (bLogicalKeyPressed) + { + if (!(g_uLogicalKeyState[uLogicalKey] & KEYSTATE_DOWN)) + { + g_uLogicalKeyState[uLogicalKey] |= KEYSTATE_IMPULSE_DOWN; + } + + g_uLogicalKeyState[uLogicalKey]++; + } + } + else + { + if (g_uLogicalKeyState[uLogicalKey] & KEYSTATE_DOWN) + { + g_uLogicalKeyState[uLogicalKey]--; + } + + if (!(g_uLogicalKeyState[uLogicalKey] & KEYSTATE_DOWN)) + { + g_uLogicalKeyState[uLogicalKey] |= KEYSTATE_IMPULSE_UP; + } + } + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Called by the client when a WM_KEYDOWN message is received. +// Input : Per CWnd::OnKeyDown. +//----------------------------------------------------------------------------- +void CKeyboard::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if ((!(nFlags & 0x4000)) || (!(g_uPhysicalKeyState[nChar] & KEYSTATE_DOWN))) + { + g_uPhysicalKeyState[nChar] |= KEYSTATE_DOWN; + g_uPhysicalKeyState[nChar] |= KEYSTATE_IMPULSE_DOWN; + + UpdateLogicalKeys(nChar, true); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Called by the client when a WM_KEYUP message is received. +// Input : Per CWnd::OnKeyDown. +//----------------------------------------------------------------------------- +void CKeyboard::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if (g_uPhysicalKeyState[nChar] & KEYSTATE_DOWN) + { + g_uPhysicalKeyState[nChar] &= ~KEYSTATE_DOWN; + } + + g_uPhysicalKeyState[nChar] |= KEYSTATE_IMPULSE_UP; + + UpdateLogicalKeys(nChar, false); +} + + + +//----------------------------------------------------------------------------- +// Purpose: Deletes all key bindings. +//----------------------------------------------------------------------------- +void CKeyboard::RemoveAllKeyMaps(void) +{ + g_uKeyMaps = 0; +} + |