Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

398 lines
11 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "Keyboard.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include <tier0/memdbgon.h>
  11. //
  12. // Defines key state bit masks.
  13. //
  14. #define KEYSTATE_DOWN 0x0000FFFF
  15. #define KEYSTATE_IMPULSE_DOWN 0x00010000
  16. #define KEYSTATE_IMPULSE_UP 0x00020000
  17. //
  18. // List of allowed modifier keys and their associated bit masks.
  19. //
  20. static KeyMap_t ModifierKeyTable[] =
  21. {
  22. { VK_SHIFT, KEY_MOD_SHIFT, 0 },
  23. { VK_CONTROL, KEY_MOD_CONTROL, 0 },
  24. { VK_MENU, KEY_MOD_ALT, 0 }
  25. };
  26. //-----------------------------------------------------------------------------
  27. // Purpose: Constructor.
  28. //-----------------------------------------------------------------------------
  29. CKeyboard::CKeyboard(void)
  30. {
  31. g_uKeyMaps = 0;
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Purpose: Destructor.
  35. //-----------------------------------------------------------------------------
  36. CKeyboard::~CKeyboard(void)
  37. {
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Adds a key binding to the
  41. // Input : uChar - The virtual keycode of the primary key that must be held down.
  42. // uModifierKeys - Bitflags specifying which modifier keys must be
  43. // held down along with the key specified by uChar.
  44. // uLogicalKey - An application-specific value that indicates which
  45. // logical function
  46. //-----------------------------------------------------------------------------
  47. void CKeyboard::AddKeyMap(unsigned int uChar, unsigned int uModifierKeys, unsigned int uLogicalKey)
  48. {
  49. g_uKeyMap[g_uKeyMaps].uChar = uChar;
  50. g_uKeyMap[g_uKeyMaps].uModifierKeys = uModifierKeys;
  51. g_uKeyMap[g_uKeyMaps].uLogicalKey = uLogicalKey;
  52. g_uKeyMaps++;
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Purpose: Clears the KEYSTATE_IMPULSE_UP and KEYSTATE_IMPULSE_DOWN flags from
  56. // all physical and logical keys.
  57. //-----------------------------------------------------------------------------
  58. void CKeyboard::ClearImpulseFlags(void)
  59. {
  60. int nKey;
  61. //
  62. // Clear the impulse flags for all the physical keys.
  63. //
  64. for (nKey = 0; nKey < sizeof(g_uPhysicalKeyState) / sizeof(g_uPhysicalKeyState[0]); nKey++)
  65. {
  66. g_uPhysicalKeyState[nKey] &= ~(KEYSTATE_IMPULSE_DOWN | KEYSTATE_IMPULSE_UP);
  67. }
  68. //
  69. // Clear the impulse flags for all the logical keys.
  70. //
  71. for (nKey = 0; nKey < sizeof(g_uLogicalKeyState) / sizeof(g_uLogicalKeyState[0]); nKey++)
  72. {
  73. g_uLogicalKeyState[nKey] &= ~(KEYSTATE_IMPULSE_DOWN | KEYSTATE_IMPULSE_UP);
  74. }
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Purpose: Zeros out the key state for all physical and logical keys.
  78. //-----------------------------------------------------------------------------
  79. void CKeyboard::ClearKeyStates(void)
  80. {
  81. int nKey;
  82. //
  83. // Clear the physical key states.
  84. //
  85. for (nKey = 0; nKey < sizeof(g_uPhysicalKeyState) / sizeof(g_uPhysicalKeyState[0]); nKey++)
  86. {
  87. g_uPhysicalKeyState[nKey] = 0;
  88. }
  89. //
  90. // Clear the logical key states.
  91. //
  92. for (nKey = 0; nKey < sizeof(g_uLogicalKeyState) / sizeof(g_uLogicalKeyState[0]); nKey++)
  93. {
  94. g_uLogicalKeyState[nKey] = 0;
  95. }
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Purpose: Gets a floating point value indicating about how long the logical
  99. // key has been held down during this sample period.
  100. // Input : uLogicalKey - Logical key to check.
  101. // Output : Returns one of the following values:
  102. // 0.25 if a key was pressed and released during the sample period,
  103. // 0.5 if it was pressed and held,
  104. // 0 if held then released, and
  105. // 1.0 if held for the entire time.
  106. //-----------------------------------------------------------------------------
  107. float CKeyboard::GetKeyScale(unsigned int uLogicalKey)
  108. {
  109. if (uLogicalKey >= MAX_LOGICAL_KEYS)
  110. {
  111. return(0);
  112. }
  113. unsigned int uKeyState = g_uLogicalKeyState[uLogicalKey];
  114. bool bImpulseDown = (uKeyState & KEYSTATE_IMPULSE_DOWN) != 0;
  115. bool bImpulseUp = (uKeyState & KEYSTATE_IMPULSE_UP) != 0;
  116. bool bDown = (uKeyState & KEYSTATE_DOWN) != 0;
  117. float fValue = 0;
  118. //
  119. // If we have a leading edge and no trailing edge, the key should be down.
  120. //
  121. if (bImpulseDown && !bImpulseUp)
  122. {
  123. if (bDown)
  124. {
  125. //
  126. // Pressed and held this frame.
  127. //
  128. fValue = 0.5;
  129. }
  130. }
  131. //
  132. // If we have a trailing edge and no leading edge, the key should be up.
  133. //
  134. if (bImpulseUp && !bImpulseDown)
  135. {
  136. if (!bDown)
  137. {
  138. //
  139. // Released this frame.
  140. //
  141. fValue = 0;
  142. }
  143. }
  144. //
  145. // If we have neither a leading edge nor a trailing edge, the key was either
  146. // up the whole frame or down the whole frame.
  147. //
  148. if (!bImpulseDown && !bImpulseUp)
  149. {
  150. if (bDown)
  151. {
  152. //
  153. // Held the entire frame
  154. //
  155. fValue = 1.0;
  156. }
  157. else
  158. {
  159. //
  160. // Up the entire frame.
  161. //
  162. fValue = 0;
  163. }
  164. }
  165. //
  166. // If we have both a leading and trailing edge, it was either released and repressed
  167. // this frame, or pressed and released this frame.
  168. //
  169. if (bImpulseDown && bImpulseUp)
  170. {
  171. if (bDown)
  172. {
  173. //
  174. // Released and re-pressed this frame.
  175. //
  176. fValue = 0.75;
  177. }
  178. else
  179. {
  180. //
  181. // Pressed and released this frame.
  182. //
  183. fValue = 0.25;
  184. }
  185. }
  186. return fValue;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // Purpose: Returns the bit mask associated with the given modifier key.
  190. // Input : uModifierKey - The virtual key code corresponding to the modifier key.
  191. // Output : The modifier key's bitmask.
  192. //-----------------------------------------------------------------------------
  193. unsigned int CKeyboard::GetModifierKeyBit(unsigned int uChar)
  194. {
  195. for (int nKey = 0; nKey < sizeof(ModifierKeyTable) / sizeof(ModifierKeyTable[0]); nKey++)
  196. {
  197. if (ModifierKeyTable[nKey].uChar == uChar)
  198. {
  199. return(ModifierKeyTable[nKey].uModifierKeys);
  200. }
  201. }
  202. return(0);
  203. }
  204. //-----------------------------------------------------------------------------
  205. // Purpose: Checks to see if all of the modifier keys specified by bits in uModifierKeys
  206. // are currently held down.
  207. // Input : uModifierKeys - Contains bits indicating which modifier keys to check:
  208. // KEY_MOD_SHIFT
  209. // KEY_MOD_CONTROL
  210. // KEY_MOD_ALT
  211. // Output : Returns true on success, false on failure.
  212. //-----------------------------------------------------------------------------
  213. bool CKeyboard::IsKeyPressed(unsigned int uChar, unsigned int uModifierKeys)
  214. {
  215. if (!(g_uPhysicalKeyState[uChar] & KEYSTATE_DOWN))
  216. {
  217. return(false);
  218. }
  219. bool bKeyPressed = true;
  220. for (int nKey = 0; nKey < sizeof(ModifierKeyTable) / sizeof(ModifierKeyTable[0]); nKey++)
  221. {
  222. if (g_uPhysicalKeyState[ModifierKeyTable[nKey].uChar] & KEYSTATE_DOWN)
  223. {
  224. if (!(uModifierKeys & ModifierKeyTable[nKey].uModifierKeys))
  225. {
  226. bKeyPressed = false;
  227. }
  228. }
  229. else if (uModifierKeys & ModifierKeyTable[nKey].uModifierKeys)
  230. {
  231. bKeyPressed = false;
  232. }
  233. }
  234. return(bKeyPressed);
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Purpose: Determines whether a key is an allowed modifier key, ie, whether it
  238. // can be used in conjunction with other keys when performing key
  239. // bindings.
  240. // Input : uChar - Virtual key to check.
  241. // Output : Returns true if this key is a modifier key, false if not.
  242. //-----------------------------------------------------------------------------
  243. bool CKeyboard::IsModifierKey(unsigned int uChar)
  244. {
  245. return((uChar == VK_SHIFT) || (uChar == VK_CONTROL) || (uChar == VK_MENU));
  246. }
  247. //-----------------------------------------------------------------------------
  248. // Purpose: Given a key press/release event, updates the status of all logical
  249. // keys.
  250. // Input : uChar - The key whose state has changed.
  251. // bPressed - True if the key was pressed, false if it was released.
  252. //-----------------------------------------------------------------------------
  253. void CKeyboard::UpdateLogicalKeys(unsigned int uChar, bool bPressed)
  254. {
  255. //
  256. // Determine whether the key is a modifier key. If so, find its modifier bit.
  257. //
  258. bool bIsModifierKey = IsModifierKey(uChar);
  259. unsigned int uModifierKeyBit = 0;
  260. if (bIsModifierKey)
  261. {
  262. uModifierKeyBit = GetModifierKeyBit(uChar);
  263. }
  264. //
  265. // For every key in the keymap that depends upon this physical key, update
  266. // the state of the corresponding logical key based on this event.
  267. //
  268. for (unsigned int nKey = 0; nKey < g_uKeyMaps; nKey++)
  269. {
  270. unsigned int uPhysicalKey = g_uKeyMap[nKey].uChar;
  271. unsigned int uLogicalKey = g_uKeyMap[nKey].uLogicalKey;
  272. unsigned int uModifierKeys = g_uKeyMap[nKey].uModifierKeys;
  273. if ((uPhysicalKey == uChar) || (uModifierKeys & uModifierKeyBit))
  274. {
  275. //
  276. // Check the state of all modifier keys to which this logical key
  277. // is bound to determine whether the logical key is pressed or not.
  278. //
  279. bool bLogicalKeyPressed = IsKeyPressed(g_uKeyMap[nKey].uChar, g_uKeyMap[nKey].uModifierKeys);
  280. //
  281. // Update the logical key state.
  282. //
  283. if (bPressed)
  284. {
  285. if (bLogicalKeyPressed)
  286. {
  287. if (!(g_uLogicalKeyState[uLogicalKey] & KEYSTATE_DOWN))
  288. {
  289. g_uLogicalKeyState[uLogicalKey] |= KEYSTATE_IMPULSE_DOWN;
  290. }
  291. g_uLogicalKeyState[uLogicalKey]++;
  292. }
  293. }
  294. else
  295. {
  296. if (g_uLogicalKeyState[uLogicalKey] & KEYSTATE_DOWN)
  297. {
  298. g_uLogicalKeyState[uLogicalKey]--;
  299. }
  300. if (!(g_uLogicalKeyState[uLogicalKey] & KEYSTATE_DOWN))
  301. {
  302. g_uLogicalKeyState[uLogicalKey] |= KEYSTATE_IMPULSE_UP;
  303. }
  304. }
  305. }
  306. }
  307. }
  308. //-----------------------------------------------------------------------------
  309. // Purpose: Called by the client when a WM_KEYDOWN message is received.
  310. // Input : Per CWnd::OnKeyDown.
  311. //-----------------------------------------------------------------------------
  312. void CKeyboard::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  313. {
  314. if ((!(nFlags & 0x4000)) || (!(g_uPhysicalKeyState[nChar] & KEYSTATE_DOWN)))
  315. {
  316. g_uPhysicalKeyState[nChar] |= KEYSTATE_DOWN;
  317. g_uPhysicalKeyState[nChar] |= KEYSTATE_IMPULSE_DOWN;
  318. UpdateLogicalKeys(nChar, true);
  319. }
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Purpose: Called by the client when a WM_KEYUP message is received.
  323. // Input : Per CWnd::OnKeyDown.
  324. //-----------------------------------------------------------------------------
  325. void CKeyboard::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  326. {
  327. if (g_uPhysicalKeyState[nChar] & KEYSTATE_DOWN)
  328. {
  329. g_uPhysicalKeyState[nChar] &= ~KEYSTATE_DOWN;
  330. }
  331. g_uPhysicalKeyState[nChar] |= KEYSTATE_IMPULSE_UP;
  332. UpdateLogicalKeys(nChar, false);
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose: Deletes all key bindings.
  336. //-----------------------------------------------------------------------------
  337. void CKeyboard::RemoveAllKeyMaps(void)
  338. {
  339. g_uKeyMaps = 0;
  340. }