#region --- License --- /* Copyright (c) 2007 Stefanos Apostolopoulos * See license.txt for license info */ #endregion #region --- Using directives --- using System; using OpenTK.Input; using System.Diagnostics; #endregion namespace OpenTK.Input { /// /// Represents a keyboard device and provides methods to query its status. /// public sealed class KeyboardDevice : IInputDevice { //private IKeyboard keyboard; private bool[] keys = new bool[(int)Key.LastKey]; private bool[] scancodes = new bool[256]; private string description; private int numKeys, numFKeys, numLeds; private IntPtr devID; private bool repeat; private KeyboardKeyEventArgs args = new KeyboardKeyEventArgs(); #region --- Constructors --- internal KeyboardDevice() { } #endregion #region --- IKeyboard members --- /// /// Gets a value indicating the status of the specified Key. /// /// The Key to check. /// True if the Key is pressed, false otherwise. public bool this[Key key] { get { return keys[(int)key]; } } /// /// Gets a value indicating the status of the specified Key. /// /// The scancode to check. /// True if the scancode is pressed, false otherwise. public bool this[uint scancode] { get { return scancodes[scancode]; } } /// /// Gets an integer representing the number of keys on this KeyboardDevice. /// public int NumberOfKeys { get { return numKeys; } internal set { numKeys = value; } } /// /// Gets an integer representing the number of function keys (F-keys) on this KeyboardDevice. /// public int NumberOfFunctionKeys { get { return numFKeys; } internal set { numFKeys = value; } } /// /// Gets a value indicating the number of led indicators on this KeyboardDevice. /// public int NumberOfLeds { get { return numLeds; } internal set { numLeds = value; } } /// /// Gets an IntPtr representing a device dependent ID. /// public IntPtr DeviceID { get { return devID; } internal set { devID = value; } } #region public bool KeyRepeat /// /// Gets or sets a System.Boolean indicating key repeat status. /// /// /// If KeyRepeat is true, multiple KeyDown events will be generated while a key is being held. /// Otherwise only one KeyDown event will be reported. /// /// The rate of the generated KeyDown events is controlled by the Operating System. Usually, /// one KeyDown event will be reported, followed by a small (250-1000ms) pause and several /// more KeyDown events (6-30 events per second). /// /// /// Set to true to handle text input (where keyboard repeat is desirable), but set to false /// for game input. /// /// public bool KeyRepeat { get { return repeat; } set { repeat = value; } } #endregion #region KeyDown /// /// Occurs when a key is pressed. /// public event EventHandler KeyDown; #endregion #region KeyUp /// /// Occurs when a key is released. /// public event EventHandler KeyUp; #endregion #endregion #region --- IInputDevice Members --- /// /// Gets a which describes this instance. /// public string Description { get { return description; } internal set { description = value; } } /// /// Gets the for this instance. /// public InputDeviceType DeviceType { get { return InputDeviceType.Keyboard; } } #endregion #region --- Public Methods --- /// Returns the hash code for this KeyboardDevice. /// A 32-bit signed integer hash code. public override int GetHashCode() { //return base.GetHashCode(); return (int)(numKeys ^ numFKeys ^ numLeds ^ devID.GetHashCode() ^ description.GetHashCode()); } /// /// Returns a System.String representing this KeyboardDevice. /// /// A System.String representing this KeyboardDevice. public override string ToString() { //return base.ToString(); return String.Format("ID: {0} ({1}). Keys: {2}, Function keys: {3}, Leds: {4}", DeviceID, Description, NumberOfKeys, NumberOfFunctionKeys, NumberOfLeds); } #endregion #region --- Internal Methods --- #region internal void ClearKeys() internal void ClearKeys() { for (int i = 0; i < keys.Length; i++) keys[i] = false; for (uint i = 0; i < scancodes.Length; i++) scancodes[i] = false; } #endregion internal void SetKey(Key key, uint scancode, bool state) { if (keys[(int)key] != state || KeyRepeat) { // limit scancode to 8bits, otherwise the assignment // below will crash randomly scancode &= 0xff; keys[(int)key] = scancodes[scancode] = state; if (state && KeyDown != null) { args.Key = key; args.ScanCode = scancode; args.Modifiers = GetModifiers(); KeyDown(this, args); } else if (!state && KeyUp != null) { args.Key = key; args.ScanCode = scancode; args.Modifiers = GetModifiers(); KeyUp(this, args); } } } internal KeyModifiers GetModifiers() { KeyModifiers mods = 0; if (this[Key.AltLeft] || this[Key.AltRight]) { mods |= KeyModifiers.Alt; } if (this[Key.ControlLeft] || this[Key.ControlRight]) { mods |= KeyModifiers.Control; } if (this[Key.ShiftLeft] || this[Key.ShiftRight]) { mods |= KeyModifiers.Shift; } return mods; } #endregion } }