aboutsummaryrefslogtreecommitdiff
path: root/V3/Input
diff options
context:
space:
mode:
Diffstat (limited to 'V3/Input')
-rw-r--r--V3/Input/IInputManager.cs34
-rw-r--r--V3/Input/IKeyEvent.cs20
-rw-r--r--V3/Input/IMouseEvent.cs34
-rw-r--r--V3/Input/IMouseEventHandler.cs14
-rw-r--r--V3/Input/Internal/InputManager.cs141
-rw-r--r--V3/Input/Internal/KeyEvent.cs32
-rw-r--r--V3/Input/Internal/MouseEvent.cs57
-rw-r--r--V3/Input/MouseButton.cs9
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
+ }
+}