2 // The Open Toolkit Library License
4 // Copyright (c) 2006 - 2009 the Open Toolkit library.
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights to
9 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 // the Software, and to permit persons to whom the Software is furnished to do
11 // so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
28 namespace OpenTK.Input
31 /// Encapsulates the state of a Keyboard device.
33 public struct KeyboardState : IEquatable<KeyboardState>
35 // Allocate enough ints to store all keyboard keys
36 private const int IntSize = sizeof(int) * 8;
38 private const int NumInts = ((int)Key.LastKey + IntSize - 1) / IntSize;
39 // The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
40 private unsafe fixed int Keys[NumInts];
43 /// Gets a <see cref="System.Boolean"/> indicating whether the specified
44 /// <see cref="OpenTK.Input.Key"/> is pressed.
46 /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
47 /// <returns>True if key is pressed; false otherwise.</returns>
48 public bool this[Key key]
50 get { return IsKeyDown(key); }
51 internal set { SetKeyState(key, value); }
55 /// Gets a <see cref="System.Boolean"/> indicating whether the specified
56 /// <see cref="OpenTK.Input.Key"/> is pressed.
58 /// <param name="code">The scancode to check.</param>
59 /// <returns>True if code is pressed; false otherwise.</returns>
60 public bool this[short code]
62 get { return IsKeyDown((Key)code); }
66 /// Gets a <see cref="System.Boolean"/> indicating whether this key is down.
68 /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
69 public bool IsKeyDown(Key key)
71 return ReadBit((int)key);
75 /// Gets a <see cref="System.Boolean"/> indicating whether this scan code is down.
77 /// <param name="code">The scan code to check.</param>
78 public bool IsKeyDown(short code)
80 return code >= 0 && code < (short)Key.LastKey && ReadBit(code);
84 /// Gets a <see cref="System.Boolean"/> indicating whether this key is up.
86 /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
87 public bool IsKeyUp(Key key)
89 return !ReadBit((int)key);
93 /// Gets a <see cref="System.Boolean"/> indicating whether this scan code is down.
95 /// <param name="code">The scan code to check.</param>
96 public bool IsKeyUp(short code)
98 return !IsKeyDown(code);
102 /// Gets a value indicating whether any key is down.
104 /// <value><c>true</c> if any key is down; otherwise, <c>false</c>.</value>
105 public bool IsAnyKeyDown
109 // If any bit is set then a key is down.
112 fixed (int* k = Keys)
114 for (int i = 0; i < NumInts; ++i)
129 /// Gets a <see cref="System.Boolean"/> indicating whether this keyboard
132 public bool IsConnected { get; internal set; }
135 // Disabled until the correct cross-platform API can be determined.
136 public bool IsLedOn(KeyboardLeds led)
141 public bool IsLedOff(KeyboardLeds led)
148 /// Checks whether two <see cref="KeyboardState" /> instances are equal.
150 /// <param name="left">
151 /// A <see cref="KeyboardState"/> instance.
153 /// <param name="right">
154 /// A <see cref="KeyboardState"/> instance.
157 /// True if both left is equal to right; false otherwise.
159 public static bool operator ==(KeyboardState left, KeyboardState right)
161 return left.Equals(right);
165 /// Checks whether two <see cref="KeyboardState" /> instances are not equal.
167 /// <param name="left">
168 /// A <see cref="KeyboardState"/> instance.
170 /// <param name="right">
171 /// A <see cref="KeyboardState"/> instance.
174 /// True if both left is not equal to right; false otherwise.
176 public static bool operator !=(KeyboardState left, KeyboardState right)
178 return !left.Equals(right);
182 /// Compares to an object instance for equality.
184 /// <param name="obj">
185 /// The <see cref="System.Object"/> to compare to.
188 /// True if this instance is equal to obj; false otherwise.
190 public override bool Equals(object obj)
192 if (obj is KeyboardState)
194 return this == (KeyboardState)obj;
203 /// Generates a hashcode for the current instance.
206 /// A <see cref="System.Int32"/> represting the hashcode for this instance.
208 public override int GetHashCode()
212 fixed (int* k = Keys)
215 for (int i = 0; i < NumInts; i++)
217 hashcode ^= (k + i)->GetHashCode();
224 internal void SetKeyState(Key key, bool down)
232 DisableBit((int)key);
236 internal bool ReadBit(int offset)
238 ValidateOffset(offset);
240 int int_offset = offset / IntSize;
241 int bit_offset = offset % IntSize;
244 fixed (int* k = Keys) { return (*(k + int_offset) & (1 << bit_offset)) != 0u; }
248 internal void EnableBit(int offset)
250 ValidateOffset(offset);
252 int int_offset = offset / IntSize;
253 int bit_offset = offset % IntSize;
256 fixed (int* k = Keys) { *(k + int_offset) |= 1 << bit_offset; }
260 internal void DisableBit(int offset)
262 ValidateOffset(offset);
264 int int_offset = offset / IntSize;
265 int bit_offset = offset % IntSize;
268 fixed (int* k = Keys) { *(k + int_offset) &= ~(1 << bit_offset); }
272 internal void MergeBits(KeyboardState other)
276 int* k2 = other.Keys;
277 fixed (int* k1 = Keys)
279 for (int i = 0; i < NumInts; i++)
281 *(k1 + i) |= *(k2 + i);
285 IsConnected |= other.IsConnected;
288 internal void SetIsConnected(bool value)
293 private static void ValidateOffset(int offset)
295 if (offset < 0 || offset >= NumInts * IntSize)
297 throw new ArgumentOutOfRangeException();
302 /// Compares two KeyboardState instances.
304 /// <param name="other">The instance to compare two.</param>
305 /// <returns>True, if both instances are equal; false otherwise.</returns>
306 public bool Equals(KeyboardState other)
311 int* k2 = other.Keys;
312 fixed (int* k1 = Keys)
314 for (int i = 0; equal && i < NumInts; i++)
316 equal &= *(k1 + i) == *(k2 + i);