diff options
Diffstat (limited to 'V3/Input')
-rw-r--r-- | V3/Input/IInputManager.cs | 34 | ||||
-rw-r--r-- | V3/Input/IKeyEvent.cs | 20 | ||||
-rw-r--r-- | V3/Input/IMouseEvent.cs | 34 | ||||
-rw-r--r-- | V3/Input/IMouseEventHandler.cs | 14 | ||||
-rw-r--r-- | V3/Input/Internal/InputManager.cs | 141 | ||||
-rw-r--r-- | V3/Input/Internal/KeyEvent.cs | 32 | ||||
-rw-r--r-- | V3/Input/Internal/MouseEvent.cs | 57 | ||||
-rw-r--r-- | V3/Input/MouseButton.cs | 9 |
8 files changed, 341 insertions, 0 deletions
diff --git a/V3/Input/IInputManager.cs b/V3/Input/IInputManager.cs new file mode 100644 index 0000000..b092ebb --- /dev/null +++ b/V3/Input/IInputManager.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace V3.Input +{ + /// <summary> + /// Watches the state of the mouse and keyboard and creates events if a + /// change (key pressed or released) is detected. To use this class, call + /// Update in every update round. After the update, you may access the + /// generated events in KeyEvents and MouseEvents. The input manager only + /// watches the mouse buttons and keys listed in sWatchedKeys and + /// sWatchedButtons. + /// </summary> + public interface IInputManager + { + /// <summary> + /// The key events that were generated during the last update. Reset + /// in the next update. + /// </summary> + ICollection<IKeyEvent> KeyEvents { get; } + + /// <summary> + /// The mouse events that were generated during the last update. Reset in + /// the next update. + /// </summary> + ICollection<IMouseEvent> MouseEvents { get; } + + /// <summary> + /// Updates the keyboard and mouse status and generates the key and mouse + /// events in KeyEvents and MouseEvents if changes were detected. Should + /// be called once every update, before doing something else. + /// </summary> + void Update(); + } +}
\ No newline at end of file diff --git a/V3/Input/IKeyEvent.cs b/V3/Input/IKeyEvent.cs new file mode 100644 index 0000000..42b99c6 --- /dev/null +++ b/V3/Input/IKeyEvent.cs @@ -0,0 +1,20 @@ +using Microsoft.Xna.Framework.Input; + +namespace V3.Input +{ + /// <summary> + /// An event that is triggered if a key is pressed or released on the + /// keyboard. + /// </summary> + public interface IKeyEvent + { + /// <summary> + /// The key that was pressed or released. + /// </summary> + Keys Key { get; } + /// <summary> + /// The type of the event (key pressed or released?). + /// </summary> + KeyState KeyState { get; } + } +}
\ No newline at end of file diff --git a/V3/Input/IMouseEvent.cs b/V3/Input/IMouseEvent.cs new file mode 100644 index 0000000..37b221d --- /dev/null +++ b/V3/Input/IMouseEvent.cs @@ -0,0 +1,34 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace V3.Input +{ + /// <summary> + /// An event that is sent when a mouse button is pressed or released. + /// </summary> + public interface IMouseEvent + { + /// <summary> + /// The mouse button that was pressed or released. + /// </summary> + MouseButton MouseButton { get; } + /// <summary> + /// The state of the mouse button (pressed or released?). + /// </summary> + ButtonState ButtonState { get; } + /// <summary> + /// The position where the mouse button was pressed the last time. + /// </summary> + Point PositionPressed { get; } + /// <summary> + /// The position where the mouse button was released if this is a + /// release event, null otherwise. + /// </summary> + Point? PositionReleased { get; } + /// <summary> + /// True if PositionReleased is a valid on-screen position, otherwise + /// false. + /// </summary> + bool ReleasedOnScreen { get; } + } +} diff --git a/V3/Input/IMouseEventHandler.cs b/V3/Input/IMouseEventHandler.cs new file mode 100644 index 0000000..7c8701c --- /dev/null +++ b/V3/Input/IMouseEventHandler.cs @@ -0,0 +1,14 @@ +namespace V3.Input +{ + /// <summary> + /// Handles mouse events. + /// </summary> + public interface IMouseEventHandler + { + /// <summary> + /// Handle the given mouse event, if applicable. + /// </summary> + /// <param name="mouseEvent">the mouse event to handle</param> + void HandleMouseEvent(IMouseEvent mouseEvent); + } +} diff --git a/V3/Input/Internal/InputManager.cs b/V3/Input/Internal/InputManager.cs new file mode 100644 index 0000000..8e6ce2e --- /dev/null +++ b/V3/Input/Internal/InputManager.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using Ninject; + +namespace V3.Input.Internal +{ + /// <summary> + /// Watches the state of the mouse and keyboard and creates events if a + /// change (key pressed or released) is detected. To use this class, call + /// Update in every update round. After the update, you may access the + /// generated events in KeyEvents and MouseEvents. The input manager only + /// watches the mouse buttons and keys listed in sWatchedKeys and + /// sWatchedButtons. + /// </summary> + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class InputManager : IInputManager, IInitializable + { + /// <summary> + /// The key events that were generated during the last update. Reset + /// in the next update. + /// </summary> + public ICollection<IKeyEvent> KeyEvents { get; } = new HashSet<IKeyEvent>(); + /// <summary> + /// The mouse events that were generated during the last update. Reset in + /// the next update. + /// </summary> + public ICollection<IMouseEvent> MouseEvents { get; } = new HashSet<IMouseEvent>(); + + private static readonly ICollection<Keys> sWatchedKeys = new List<Keys> { Keys.Enter, Keys.Escape, Keys.E, Keys.L, Keys.Q, Keys.S, Keys.F1, Keys.F2 , Keys.F3, Keys.F4, Keys.F5, Keys.F6, Keys.F7, Keys.F8 }; + + private static readonly ICollection<MouseButton> sWatchedButtons = new List<MouseButton> { MouseButton.Left, MouseButton.Right, MouseButton.Middle }; + + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + + private readonly IDictionary<Keys, KeyState> mKeyStates = new Dictionary<Keys, KeyState>(); + + private readonly IDictionary<MouseButton, ButtonState> mButtonStates = new Dictionary<MouseButton, ButtonState>(); + + private readonly IDictionary<MouseButton, Point?> mButtonPositions = new Dictionary<MouseButton, Point?>(); + + /// <summary> + /// Creates a new input manager. + /// </summary> + public InputManager(GraphicsDeviceManager graphicsDeviceManager) + { + mGraphicsDeviceManager = graphicsDeviceManager; + } + + public void Initialize() + { + foreach (var key in sWatchedKeys) + mKeyStates.Add(key, KeyState.Up); + foreach (var button in sWatchedButtons) + { + mButtonStates.Add(button, ButtonState.Released); + mButtonPositions.Add(button, null); + } + } + + /// <summary> + /// Updates the keyboard and mouse status and generates the key and mouse + /// events in KeyEvents and MouseEvents if changes were detected. Should + /// be called once every update, before doing something else. + /// </summary> + public void Update() + { + UpdateKeyboard(); + UpdateMouse(); + } + + private void UpdateKeyboard() + { + KeyEvents.Clear(); + + var state = Keyboard.GetState(); + foreach (var key in sWatchedKeys) + { + var newState = state[key]; + if (newState != mKeyStates[key]) + { + mKeyStates[key] = newState; + KeyEvents.Add(new KeyEvent(key, newState)); + } + } + } + + private void UpdateMouse() + { + MouseEvents.Clear(); + + var state = Mouse.GetState(); + foreach (var button in sWatchedButtons) + { + var newState = GetButtonState(state, button); + if (newState != mButtonStates[button]) + { + var position = new Point(state.X, state.Y); + var positionPressed = position; + Point? positionReleased = null; + if (newState == ButtonState.Released) + { + if (mButtonPositions[button].HasValue) + positionPressed = mButtonPositions[button].Value; + positionReleased = position; + } + + mButtonStates[button] = newState; + mButtonPositions[button] = position; + + var releasedOnScreen = false; + if (positionReleased.HasValue) + releasedOnScreen = IsPointOnScreen(positionReleased.Value); + + MouseEvents.Add(new MouseEvent(button, newState, positionPressed, positionReleased, releasedOnScreen)); + } + } + } + + private bool IsPointOnScreen(Point point) + { + var viewport = mGraphicsDeviceManager.GraphicsDevice.Viewport; + return point.X >= 0 && point.X <= viewport.Width && point.Y >= 0 && point.Y <= viewport.Height; + } + + private static ButtonState GetButtonState(MouseState state, MouseButton button) + { + switch (button) + { + case MouseButton.Left: + return state.LeftButton; + case MouseButton.Right: + return state.RightButton; + case MouseButton.Middle: + return state.MiddleButton; + default: + return state.LeftButton; + } + } + } +} diff --git a/V3/Input/Internal/KeyEvent.cs b/V3/Input/Internal/KeyEvent.cs new file mode 100644 index 0000000..b4a450e --- /dev/null +++ b/V3/Input/Internal/KeyEvent.cs @@ -0,0 +1,32 @@ +using Microsoft.Xna.Framework.Input; + +namespace V3.Input.Internal +{ + /// <summary> + /// Default implementation of an event that is triggered if a key is + /// pressed or released on the keyboard. + /// </summary> + internal sealed class KeyEvent : IKeyEvent + { + /// <summary> + /// The key that was pressed or released. + /// </summary> + public Keys Key { get; } + /// <summary> + /// The type of the event (key pressed or released?). + /// </summary> + public KeyState KeyState { get; } + + /// <summary> + /// Creates a new key event with the given data. + /// </summary> + /// <param name="key">the key that was pressed or released</param> + /// <param name="keyState">the type of the event (presesd or + /// released?)</param> + public KeyEvent(Keys key, KeyState keyState) + { + Key = key; + KeyState = keyState; + } + } +} diff --git a/V3/Input/Internal/MouseEvent.cs b/V3/Input/Internal/MouseEvent.cs new file mode 100644 index 0000000..f8024aa --- /dev/null +++ b/V3/Input/Internal/MouseEvent.cs @@ -0,0 +1,57 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace V3.Input.Internal +{ + /// <summary> + /// Default implementation of an event that is sent when a mouse button is + /// pressed or released. + /// </summary> + internal sealed class MouseEvent : IMouseEvent + { + /// <summary> + /// The mouse button that was pressed or released. + /// </summary> + public MouseButton MouseButton { get; } + /// <summary> + /// The state of the mouse button (pressed or released?). + /// </summary> + public ButtonState ButtonState { get; } + /// <summary> + /// The position where the mouse button was pressed the last time. + /// </summary> + public Point PositionPressed { get; } + /// <summary> + /// The position where the mouse button was released if this is a + /// release event, null otherwise. + /// </summary> + public Point? PositionReleased { get; } + /// <summary> + /// True if PositionReleased is a valid on-screen position, otherwise + /// false. + /// </summary> + public bool ReleasedOnScreen { get; } + + /// <summary> + /// Creates a new mouse event with the given data. + /// </summary> + /// <param name="mouseButton">the mouse button that was pressed or + /// released</param> + /// <param name="buttonState">the type of the event (pressed or + /// released?)</param> + /// <param name="positionPressed">the position of the last press of + /// the button</param> + /// <param name="positionReleased">the position of the release of the + /// button if this is a release event, or null otherwise</param> + /// <param name="releasedOnScreen">true if positionReleased is a valid + /// on-screen position.</param> + public MouseEvent(MouseButton mouseButton, ButtonState buttonState, Point positionPressed, Point? positionReleased, bool releasedOnScreen) + { + MouseButton = mouseButton; + ButtonState = buttonState; + PositionPressed = positionPressed; + PositionReleased = positionReleased; + ReleasedOnScreen = releasedOnScreen; + } + } +} diff --git a/V3/Input/MouseButton.cs b/V3/Input/MouseButton.cs new file mode 100644 index 0000000..616872b --- /dev/null +++ b/V3/Input/MouseButton.cs @@ -0,0 +1,9 @@ +namespace V3.Input +{ + public enum MouseButton + { + Left, + Right, + Middle + } +} |