using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; namespace BouncyCatIsBouncy { enum BindingType { Primary, Secondary, } enum MouseButton { None, LeftButton, RightButton, MiddleButton, Button4, Button5, ScrollUp, ScrollDown, } class Input { #region MouseBind struct private struct MouseBind { public MouseBind(MouseButton primary, MouseButton secondary) { Primary = primary; Secondary = secondary; } public MouseButton Primary; public MouseButton Secondary; } #endregion #region KeyBind struct /// /// Holds a pair of key binds /// private struct KeyBind { public KeyBind(Keys primary, Keys secondary) { Primary = primary; Secondary = secondary; } public Keys Primary; public Keys Secondary; } #endregion #region BindingData struct /// /// A struct that holds the data bound between keys and activities /// private struct BindingData { Keys[] m_keysPrimary, m_keysSecondary; MouseButton[] m_mousePrimary, m_mouseSecondary; public BindingData(int length) { m_keysPrimary = new Keys[length]; m_keysSecondary = new Keys[length]; m_mousePrimary = new MouseButton[length]; m_mouseSecondary = new MouseButton[length]; } public void AddPrimaryKeyBinding(Keys key, int index) { m_keysPrimary[index] = key; } public void AddSecondaryKeyBinding(Keys key, int index) { m_keysSecondary[index] = key; } public KeyBind GetKeyBindsFromIndex(int index) { return new KeyBind(m_keysPrimary[index], m_keysSecondary[index]); } public void AddPrimaryMouseBinding(MouseButton button, int index) { m_mousePrimary[index] = button; } public void AddSecondaryMouseBinding(MouseButton button, int index) { m_mouseSecondary[index] = button; } public MouseBind GetMouseBindsFromIndex(int index) { return new MouseBind(m_mousePrimary[index], m_mouseSecondary[index]); } } #endregion #region Private members KeyboardState m_currentKeyState; KeyboardState m_lastKeyState; MouseState m_lastMouseState; MouseState m_currentMouseState; BindingData m_bindings; int m_wheelDelta; #endregion public Input() { //C# doesn't allow for generic constraints to be of type Enum, run-time validation is required Type type = typeof(EnumType); if (!type.IsEnum) throw new ArgumentException("Type must be an enum", "EnumType"); int length = Enum.GetValues(type).Length; if (length == 0) throw new ArgumentException("Enum must have at least one entry", "EnumType"); m_bindings = new BindingData(length); } public void AddBinding(Keys key, EnumType activity, BindingType type) { //GetHashCode guarantees that the return value is the index of the enum int index = activity.GetHashCode(); switch (type) { case BindingType.Primary: m_bindings.AddPrimaryKeyBinding(key, index); break; case BindingType.Secondary: m_bindings.AddSecondaryKeyBinding(key, index); break; } } public void AddBinding(MouseButton button, EnumType activity, BindingType type) { //GetHashCode guarantees that the return value is the index of the enum int index = activity.GetHashCode(); switch (type) { case BindingType.Primary: m_bindings.AddPrimaryMouseBinding(button, index); break; case BindingType.Secondary: m_bindings.AddSecondaryMouseBinding(button, index); break; } } bool AreKeyBindsDown(EnumType activity) { KeyBind binds = m_bindings.GetKeyBindsFromIndex(activity.GetHashCode()); return m_currentKeyState.IsKeyDown(binds.Primary) || m_currentKeyState.IsKeyDown(binds.Secondary); } bool AreMouseBindsDown(EnumType activity) { MouseBind binds = m_bindings.GetMouseBindsFromIndex(activity.GetHashCode()); return m_currentMouseState.IsButtonDown(binds.Primary, m_wheelDelta) || m_currentMouseState.IsButtonDown(binds.Secondary, m_wheelDelta); } public bool IsActivityDown(EnumType activity) { return AreKeyBindsDown(activity) || AreMouseBindsDown(activity); } bool AreKeyBindsUp(EnumType activity) { KeyBind binds = m_bindings.GetKeyBindsFromIndex(activity.GetHashCode()); return m_currentKeyState.IsKeyUp(binds.Primary) || m_currentKeyState.IsKeyUp(binds.Secondary); } bool AreMouseBindsUp(EnumType activity) { MouseBind binds = m_bindings.GetMouseBindsFromIndex(activity.GetHashCode()); return m_currentMouseState.IsButtonUp(binds.Primary, m_wheelDelta) || m_currentMouseState.IsButtonUp(binds.Secondary, m_wheelDelta); } public bool IsActivityUp(EnumType activity) { return AreKeyBindsUp(activity) || AreMouseBindsUp(activity); } bool IsKeyPressed(Keys key) { return m_currentKeyState.IsKeyUp(key) && m_lastKeyState.IsKeyDown(key); } bool AreKeyBindsPressed(EnumType activity) { KeyBind binds = m_bindings.GetKeyBindsFromIndex(activity.GetHashCode()); return IsKeyPressed(binds.Primary) || IsKeyPressed(binds.Secondary); } bool IsMousePressed(MouseButton mouse) { return m_currentMouseState.IsButtonUp(mouse, m_wheelDelta) && m_lastMouseState.IsButtonDown(mouse, m_wheelDelta); } bool AreMouseBindsPressed(EnumType activity) { MouseBind binds = m_bindings.GetMouseBindsFromIndex(activity.GetHashCode()); return IsMousePressed(binds.Primary) || IsMousePressed(binds.Secondary); } public bool IsActivityPressed(EnumType activity) { return AreKeyBindsPressed(activity) || AreMouseBindsPressed(activity); } #region Cursor public Vector2 Cursor2DLocation { get { return new Vector2(m_currentMouseState.X, m_currentMouseState.Y); } } #endregion public void Update() { //Save old states m_lastKeyState = m_currentKeyState; m_lastMouseState = m_currentMouseState; //Get new states m_currentKeyState = Keyboard.GetState(); m_currentMouseState = Mouse.GetState(); m_wheelDelta = m_currentMouseState.ScrollWheelValue - m_lastMouseState.ScrollWheelValue; } } internal static class InputExtensions { #region Extensions #if !XBOX public static bool IsButtonUp(this MouseState state, MouseButton button, int scrollDelta) { switch (button) { case MouseButton.LeftButton: return state.LeftButton == ButtonState.Released; case MouseButton.RightButton: return state.RightButton == ButtonState.Released; case MouseButton.MiddleButton: return state.MiddleButton == ButtonState.Released; case MouseButton.Button4: return state.XButton1 == ButtonState.Released; case MouseButton.Button5: return state.XButton2 == ButtonState.Released; case MouseButton.ScrollDown: return scrollDelta >= 0; case MouseButton.ScrollUp: return scrollDelta <= 0; } return true; } public static bool IsButtonDown(this MouseState state, MouseButton button, int scrollDelta) { return !state.IsButtonUp(button, scrollDelta); } #endif #endregion } }