Show More
Commit Description:
Add timers for Simulation and various engines...
Commit Description:
Add timers for Simulation and various engines
Starting to add additional timers for different stages of the process of
updating in order to get more insight into what is slowing it down.
The update takes 9ms, which is much longer than it used to.
Engine-specific timers are coming later.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Input/KeyboardState.cs
338 lines | 7.8 KiB | text/x-csharp | CSharpLexer
338 lines | 7.8 KiB | text/x-csharp | CSharpLexer
r0 | #region License | |||
/* FNA - XNA4 Reimplementation for Desktop Platforms | ||||
* Copyright 2009-2020 Ethan Lee and the MonoGame Team | ||||
* | ||||
* Released under the Microsoft Public License. | ||||
* See LICENSE for details. | ||||
*/ | ||||
#endregion | ||||
#region Using Statements | ||||
using System.Collections.Generic; | ||||
#endregion | ||||
namespace Microsoft.Xna.Framework.Input | ||||
{ | ||||
/// <summary> | ||||
/// Holds the state of keystrokes by a keyboard. | ||||
/// </summary> | ||||
public struct KeyboardState | ||||
{ | ||||
#region Public Properties | ||||
/// <summary> | ||||
/// Returns the state of a specified key. | ||||
/// </summary> | ||||
/// <param name="key">The key to query.</param> | ||||
/// <returns>The state of the key.</returns> | ||||
public KeyState this[Keys key] | ||||
{ | ||||
get | ||||
{ | ||||
return InternalGetKey(key) ? KeyState.Down : KeyState.Up; | ||||
} | ||||
} | ||||
#endregion | ||||
#region Private Variables | ||||
// Array of 256 bits: | ||||
uint keys0, keys1, keys2, keys3, keys4, keys5, keys6, keys7; | ||||
#endregion | ||||
#region Private Static Variables | ||||
// Used for the common situation where GetPressedKeys will return an empty array | ||||
static Keys[] empty = new Keys[0]; | ||||
#endregion | ||||
#region Public Constructor | ||||
/// <summary> | ||||
/// Initializes a new instance of the <see cref="KeyboardState"/> class. | ||||
/// </summary> | ||||
/// <param name="keys">List of keys to be flagged as pressed on initialization.</param> | ||||
public KeyboardState(params Keys[] keys) | ||||
{ | ||||
keys0 = 0; | ||||
keys1 = 0; | ||||
keys2 = 0; | ||||
keys3 = 0; | ||||
keys4 = 0; | ||||
keys5 = 0; | ||||
keys6 = 0; | ||||
keys7 = 0; | ||||
if (keys != null) | ||||
{ | ||||
foreach (Keys k in keys) | ||||
{ | ||||
InternalSetKey(k); | ||||
} | ||||
} | ||||
} | ||||
#endregion | ||||
#region Internal Constructor | ||||
/// <summary> | ||||
/// Initializes a new instance of the <see cref="KeyboardState"/> class. | ||||
/// </summary> | ||||
/// <param name="keys">List of keys to be flagged as pressed on initialization.</param> | ||||
internal KeyboardState(List<Keys> keys) | ||||
{ | ||||
keys0 = 0; | ||||
keys1 = 0; | ||||
keys2 = 0; | ||||
keys3 = 0; | ||||
keys4 = 0; | ||||
keys5 = 0; | ||||
keys6 = 0; | ||||
keys7 = 0; | ||||
if (keys != null) | ||||
{ | ||||
foreach (Keys k in keys) | ||||
{ | ||||
InternalSetKey(k); | ||||
} | ||||
} | ||||
} | ||||
#endregion | ||||
#region Public Methods | ||||
/// <summary> | ||||
/// Gets whether given key is currently being pressed. | ||||
/// </summary> | ||||
/// <param name="key">The key to query.</param> | ||||
/// <returns>true if the key is pressed; false otherwise.</returns> | ||||
public bool IsKeyDown(Keys key) | ||||
{ | ||||
return InternalGetKey(key); | ||||
} | ||||
/// <summary> | ||||
/// Gets whether given key is currently being not pressed. | ||||
/// </summary> | ||||
/// <param name="key">The key to query.</param> | ||||
/// <returns>true if the key is not pressed; false otherwise.</returns> | ||||
public bool IsKeyUp(Keys key) | ||||
{ | ||||
return !InternalGetKey(key); | ||||
} | ||||
/// <summary> | ||||
/// Returns an array of values holding keys that are currently being pressed. | ||||
/// </summary> | ||||
/// <returns>The keys that are currently being pressed.</returns> | ||||
public Keys[] GetPressedKeys() | ||||
{ | ||||
uint count = ( | ||||
CountBits(keys0) + | ||||
CountBits(keys1) + | ||||
CountBits(keys2) + | ||||
CountBits(keys3) + | ||||
CountBits(keys4) + | ||||
CountBits(keys5) + | ||||
CountBits(keys6) + | ||||
CountBits(keys7) | ||||
); | ||||
if (count == 0) | ||||
{ | ||||
return empty; | ||||
} | ||||
Keys[] keys = new Keys[count]; | ||||
int index = 0; | ||||
if (keys0 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys0, 0 * 32, keys, index); | ||||
} | ||||
if (keys1 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys1, 1 * 32, keys, index); | ||||
} | ||||
if (keys2 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys2, 2 * 32, keys, index); | ||||
} | ||||
if (keys3 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys3, 3 * 32, keys, index); | ||||
} | ||||
if (keys4 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys4, 4 * 32, keys, index); | ||||
} | ||||
if (keys5 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys5, 5 * 32, keys, index); | ||||
} | ||||
if (keys6 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys6, 6 * 32, keys, index); | ||||
} | ||||
if (keys7 != 0) | ||||
{ | ||||
index = AddKeysToArray(keys7, 7 * 32, keys, index); | ||||
} | ||||
return keys; | ||||
} | ||||
#endregion | ||||
#region Private Methods | ||||
bool InternalGetKey(Keys key) | ||||
{ | ||||
uint mask = (uint) 1 << (((int) key) & 0x1f); | ||||
uint element; | ||||
switch (((int) key) >> 5) | ||||
{ | ||||
case 0: element = keys0; break; | ||||
case 1: element = keys1; break; | ||||
case 2: element = keys2; break; | ||||
case 3: element = keys3; break; | ||||
case 4: element = keys4; break; | ||||
case 5: element = keys5; break; | ||||
case 6: element = keys6; break; | ||||
case 7: element = keys7; break; | ||||
default: element = 0; break; | ||||
} | ||||
return (element & mask) != 0; | ||||
} | ||||
void InternalSetKey(Keys key) | ||||
{ | ||||
uint mask = (uint) 1 << (((int) key) & 0x1f); | ||||
switch (((int) key) >> 5) | ||||
{ | ||||
case 0: keys0 |= mask; break; | ||||
case 1: keys1 |= mask; break; | ||||
case 2: keys2 |= mask; break; | ||||
case 3: keys3 |= mask; break; | ||||
case 4: keys4 |= mask; break; | ||||
case 5: keys5 |= mask; break; | ||||
case 6: keys6 |= mask; break; | ||||
case 7: keys7 |= mask; break; | ||||
} | ||||
} | ||||
void InternalClearKey(Keys key) | ||||
{ | ||||
uint mask = (uint) 1 << (((int) key) & 0x1f); | ||||
switch (((int) key) >> 5) | ||||
{ | ||||
case 0: keys0 &= ~mask; break; | ||||
case 1: keys1 &= ~mask; break; | ||||
case 2: keys2 &= ~mask; break; | ||||
case 3: keys3 &= ~mask; break; | ||||
case 4: keys4 &= ~mask; break; | ||||
case 5: keys5 &= ~mask; break; | ||||
case 6: keys6 &= ~mask; break; | ||||
case 7: keys7 &= ~mask; break; | ||||
} | ||||
} | ||||
void InternalClearAllKeys() | ||||
{ | ||||
keys0 = 0; | ||||
keys1 = 0; | ||||
keys2 = 0; | ||||
keys3 = 0; | ||||
keys4 = 0; | ||||
keys5 = 0; | ||||
keys6 = 0; | ||||
keys7 = 0; | ||||
} | ||||
#endregion | ||||
#region Public Static Operators and Override Methods | ||||
/// <summary> | ||||
/// Gets the hash code for <see cref="KeyboardState"/> instance. | ||||
/// </summary> | ||||
/// <returns>Hash code of the object.</returns> | ||||
public override int GetHashCode() | ||||
{ | ||||
return (int) (keys0 ^ keys1 ^ keys2 ^ keys3 ^ keys4 ^ keys5 ^ keys6 ^ keys7); | ||||
} | ||||
/// <summary> | ||||
/// Compares whether two <see cref="KeyboardState"/> instances are equal. | ||||
/// </summary> | ||||
/// <param name="a"><see cref="KeyboardState"/> instance to the left of the equality operator.</param> | ||||
/// <param name="b"><see cref="KeyboardState"/> instance to the right of the equality operator.</param> | ||||
/// <returns>true if the instances are equal; false otherwise.</returns> | ||||
public static bool operator ==(KeyboardState a, KeyboardState b) | ||||
{ | ||||
return ( a.keys0 == b.keys0 && | ||||
a.keys1 == b.keys1 && | ||||
a.keys2 == b.keys2 && | ||||
a.keys3 == b.keys3 && | ||||
a.keys4 == b.keys4 && | ||||
a.keys5 == b.keys5 && | ||||
a.keys6 == b.keys6 && | ||||
a.keys7 == b.keys7 ); | ||||
} | ||||
/// <summary> | ||||
/// Compares whether two <see cref="KeyboardState"/> instances are not equal. | ||||
/// </summary> | ||||
/// <param name="a"><see cref="KeyboardState"/> instance to the left of the inequality operator.</param> | ||||
/// <param name="b"><see cref="KeyboardState"/> instance to the right of the inequality operator.</param> | ||||
/// <returns>true if the instances are different; false otherwise.</returns> | ||||
public static bool operator !=(KeyboardState a, KeyboardState b) | ||||
{ | ||||
return !(a == b); | ||||
} | ||||
/// <summary> | ||||
/// Compares whether current instance is equal to specified object. | ||||
/// </summary> | ||||
/// <param name="obj">The <see cref="KeyboardState"/> to compare.</param> | ||||
/// <returns>true if the provided <see cref="KeyboardState"/> instance is same with current; false otherwise.</returns> | ||||
public override bool Equals(object obj) | ||||
{ | ||||
return obj is KeyboardState && this == (KeyboardState) obj; | ||||
} | ||||
#endregion | ||||
#region Private Static Methods | ||||
private static uint CountBits(uint v) | ||||
{ | ||||
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel | ||||
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary | ||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp | ||||
return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count | ||||
} | ||||
private static int AddKeysToArray(uint keys, int offset, Keys[] pressedKeys, int index) | ||||
{ | ||||
for (int i = 0; i < 32; i += 1) | ||||
{ | ||||
if ((keys & (1 << i)) != 0) | ||||
{ | ||||
pressedKeys[index++] = (Keys) (offset + i); | ||||
} | ||||
} | ||||
return index; | ||||
} | ||||
#endregion | ||||
} | ||||
} | ||||