// This file is part of the Noddybox.Emulation C# suite. // // Noddybox.Emulation is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Noddybox.Emulation is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // using System; using System.Collections.Generic; using System.Linq; using System.Text; using Noddybox.Emulation.Keyboard.Schema; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input.Touch; namespace Noddybox.Emulation.Xna.Keyboard { /// /// Displays and drives the keyboard. /// /// The enumerated type matching the symbols in the used keyboard definition. public class KeyboardDriver where T: struct,IConvertible { #region Event arguments /// /// Event data when a key is pressed or released. /// public class KeyPressEventArgs : EventArgs { /// /// The key that was pressed. /// public T Key {get;set;} /// /// True if the key was pressed. False if released. /// public bool Pressed {get; set;} } /// /// Event data when the screen is touched away from a key. /// public class TouchLocationEventArgs : EventArgs { /// /// The touch. /// public TouchLocation Location {get; set;} } #endregion #region Private data private class KeyState { public T Symbol {get;set;} public bool IsPressed {get; set;} public bool IsSticky {get; set;} public int TouchId {get; set;} } private Rectangle[] keymapPos; private KeyState[] keymapState; private int keymapSize; private KeyboardDefinition keyboard; private Texture2D image; private Vector2 position; private Texture2D overlay; #endregion #region Private members #endregion #region Public members /// /// Updates the keyboard. Note that this will consume all the key press events. /// public void Update() { foreach (TouchLocation t in TouchPanel.GetState()) { int x = (int)t.Position.X; int y = (int)t.Position.Y; int f = 0; KeyState key = null; if (t.State == TouchLocationState.Pressed) { for(f = 0; f < keymapSize && key == null; f++) { if (keymapPos[f].Contains(x, y)) { key = keymapState[f]; } } if (key != null) { key.TouchId = t.Id; if (key.IsSticky) { key.IsPressed = !key.IsPressed; } else { key.IsPressed = true; } if (KeyEvent != null) { KeyEvent(this, new KeyPressEventArgs() {Key = key.Symbol, Pressed = key.IsPressed}); } } } else if (t.State == TouchLocationState.Released) { for(f = 0; f < keymapSize && key == null; f++) { if (keymapState[f].TouchId == t.Id) { key = keymapState[f]; } } if (key != null) { if (!key.IsSticky) { key.IsPressed = false; if (KeyEvent != null) { KeyEvent(this, new KeyPressEventArgs() {Key = key.Symbol, Pressed = key.IsPressed}); } } } } // If no key handled, pass on the event // if (key == null && keymapState.Where(r => r.TouchId == t.Id).Count() == 0) { if (TouchEvent != null) { TouchEvent(this, new TouchLocationEventArgs() {Location = t}); } } } } /// /// Draw the keyboard /// /// public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(image, position, Color.White); for(int f = 0; f < keymapSize; f++) { if (keymapState[f].IsPressed) { spriteBatch.Draw(overlay, keymapPos[f], new Color(200, 200, 0, 25)); } } } #endregion #region Events public EventHandler KeyEvent; public EventHandler TouchEvent; #endregion #region Constructors /// /// Constructor. /// /// The graphics device to associate textures with. /// The image for the keyboard. /// Where to draw and offset the keyboard to. /// The keyboard to drive this from. public KeyboardDriver(GraphicsDevice graphics, Texture2D image, Vector2 position, KeyboardDefinition keyboard) { this.keyboard = keyboard; this.image = image; this.position = position; keymapSize = keyboard.Definitions.Count; keymapPos = new Rectangle[keymapSize]; keymapState = new KeyState[keymapSize]; for(int f = 0; f < keymapSize; f++) { KeyboardKey k = keyboard.Definitions[f]; keymapPos[f] = new Rectangle((int)position.X + k.X, (int)position.Y + k.Y, k.Width, k.Height); keymapState[f] = new KeyState() { Symbol = (T)Enum.Parse(typeof(T), k.KeySymbol, false), IsPressed = false, IsSticky = k.Sticky }; } Color c = Color.White; overlay = new Texture2D(graphics, 2, 2, false, SurfaceFormat.Color); overlay.SetData(new Color[] {c, c, c, c}); } #endregion } }