aboutsummaryrefslogtreecommitdiff
path: root/V3/Input/Internal/InputManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'V3/Input/Internal/InputManager.cs')
-rw-r--r--V3/Input/Internal/InputManager.cs141
1 files changed, 141 insertions, 0 deletions
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;
+ }
+ }
+ }
+}