JDPeckham
#region
USINGS
using
System;
using
System.Collections.Generic;
using
Microsoft.Xna.Framework;
using
Microsoft.Xna.Framework.Design;
using
Microsoft.Xna.Framework.Input;
using
System.Diagnostics;
#endregion
namespace
Gbg.Input
{
public struct ButtonActionMapping
{
public ButtonActionEventHandler Action;
}
public struct AxisActionMapping
{
public AxisActionEventHandler Action;
}
public enum ControlAxis
{
X,
Y,
Z
}
public delegate void ButtonActionEventHandler();
public enum ActionButton
{
LeftMouse= 0,
RightMouse = 1,
MiddleMouse = 2,
a = (
int)Keys.A,
b = (
int)Keys.B,
c = (
int)Keys.C,
d = (
Int32)Keys.D,
e = (
Int32)Keys.E,
f = (
Int32)Keys.F,
g = (
Int32)Keys.G,
h = (
Int32)Keys.H,
i = (
Int32) Keys.I,
//and so on
}
public delegate void AxisActionEventHandler(int amount);
public sealed class InputManager : GameComponent
{
private ButtonActionMapping[] mouseDoubleClickActions = new ButtonActionMapping[3];
private Dictionary<ControlAxis, AxisActionMapping> axisActionMapLookup = new Dictionary<ControlAxis, AxisActionMapping>();
private Dictionary<ActionButton, ButtonActionMapping> buttonDownActionmapLookup = new Dictionary<ActionButton, ButtonActionMapping>();
private Dictionary<ActionButton, ButtonActionMapping> buttonUpActionmapLookup = new Dictionary<ActionButton, ButtonActionMapping>();
public void AddButtonDownAction(ActionButton button, ButtonActionMapping mapping)
{
if (!buttonDownActionmapLookup.ContainsKey(button))
{
buttonDownActionmapLookup.Add(button, mapping);
}
}
public void AddButtonUpAction(ActionButton button, ButtonActionMapping mapping)
{
if (!buttonUpActionmapLookup.ContainsKey(button))
{
buttonUpActionmapLookup.Add(button, mapping);
}
}
public void AddAxisAction(ControlAxis axis, AxisActionMapping mapping)
{
if (!axisActionMapLookup.ContainsKey(axis))
{
axisActionMapLookup.Add(axis, mapping);
}
}
public void SetDoubleClickAction(ActionButton button, ButtonActionMapping mapping)
{
if ((int)button < 0 || (int)button > 2) throw new ArgumentException("Only mouse buttons can be mapped");
mouseDoubleClickActions[(
int)button] = mapping;
}
public void ClearButtonDownActions()
{ buttonDownActionmapLookup.Clear(); }
public void ClearButtonUpActions()
{ buttonUpActionmapLookup.Clear(); }
public void ClearAxisActions()
{ axisActionMapLookup.Clear(); }
public void ClearDoubleClickActions()
{
mouseDoubleClickActions[0].Action =
null;
mouseDoubleClickActions[1].Action =
null;
mouseDoubleClickActions[2].Action =
null;
}
public void InitializeComponent()
{ }
private static InputManager _instance;
private static object syncRoot = new object();
private InputManager(Microsoft.Xna.Framework.Game game) : base (game)
{
InitKeyBoard();
InitMouse();
InitPads();
}
public static InputManager GetInstance(Microsoft.Xna.Framework.Game game)
{
lock (syncRoot)
{
if (_instance == null) _instance = new InputManager(game);
return _instance;
}
}
public override void Update(GameTime gameTime)
{
UpdateKeyBoardInput();
UpdateMouseInput(gameTime);
UpdateJoyPadInput(gameTime);
base.Update(gameTime);
}
#region
Keyboard
/// <summary>
/// Keys held down last frame
/// </summary>
Keys[] keysHeldLastFrame;
// Stored key-press lists to compare against.
/// <summary>
/// Keys newly pressed this frame
/// </summary>
List<Keys> keysPressedThisFrameList = new List<Keys>(5);
/// <summary>
/// Keys newly released this frame
/// </summary>
List<Keys> keysReleasedThisFrameList = new List<Keys>(5);
private void InitKeyBoard()
{
keysHeldLastFrame =
Keyboard.GetState().GetPressedKeys();
}
void UpdateKeyBoardInput()
{
// Clear our pressed and released lists.
keysPressedThisFrameList.Clear();
keysReleasedThisFrameList.Clear();
// Interpret pressed key data between arrays to
// figure out just-pressed and just-released keys.
KeyboardState currentState = Keyboard.GetState();
Keys[] currentKeys = currentState.GetPressedKeys();
// First loop, looking for keys just pressed.
for (int currentKey = 0; currentKey < currentKeys.Length; currentKey++)
{
bool found = false;
for (int previousKey = 0; previousKey < keysHeldLastFrame.Length; previousKey++)
{
if (currentKeys[currentKey] == keysHeldLastFrame[previousKey])
{
// The key was pressed both this frame and last; ignore.
found =
true;
break;
}
}
if (!found)
{
// The key was pressed this frame, but not last frame; it was just pressed.
keysPressedThisFrameList.Add(currentKeys[currentKey]);
}
}
// Second loop, looking for keys just released.
for (int previousKey = 0; previousKey < keysHeldLastFrame.Length; previousKey++)
{
bool found = false;
for (int currentKey = 0; currentKey < currentKeys.Length; currentKey++)
{
if (keysHeldLastFrame[previousKey] == currentKeys[currentKey])
{
// The key was pressed both this frame and last; ignore.
found =
true;
break;
}
}
if (!found)
{
// The key was pressed last frame, but not this frame; it was just released.
keysReleasedThisFrameList.Add(keysHeldLastFrame[previousKey]);
}
}
// Set the held state to the current state.
keysHeldLastFrame = currentKeys;
//fire events
foreach (Keys key in keysPressedThisFrameList)
{
if (buttonDownActionmapLookup.ContainsKey((ActionButton)key))
{
ButtonActionMapping mapping = buttonDownActionmapLookup[(ActionButton)key];
mapping.Action();
}
}
foreach (Keys key in keysReleasedThisFrameList)
{
if (buttonUpActionmapLookup.ContainsKey((ActionButton)key))
{
ButtonActionMapping mapping = buttonUpActionmapLookup[(ActionButton)key];
mapping.Action();
}
}
}
#endregion
#region
GamePad
//gamepad helpers
int pad1Xmoved, pad1Ymoved, pad1Zmoved;
/*
int pad2Xmoved, pad2Ymoved, pad2Zmoved;
int pad3Xmoved, pad3Ymoved, pad3Zmoved;
int pad4Xmoved, pad4Ymoved, pad4Zmoved;
* */
GamePadState oldPadState1;
/*
GamePadState oldPadState2;
GamePadState oldPadState3;
GamePadState oldPadState4;
* */
float gamePadScalingFactor = 0.025f;
private void InitPads()
{
oldPadState1 =
GamePad.GetState(PlayerIndex.One);
/*
oldPadState2 = GamePad.GetState(PlayerIndex.Two);
oldPadState3 = GamePad.GetState(PlayerIndex.Three);
oldPadState4 = GamePad.GetState(PlayerIndex.Four);
* */
}
private void UpdateJoyPadInput(GameTime gameTime)
{
//TODO: get joypad axis input and translate to amount of xyz moved this frame so we can fire actions
//TODO: Get joypad button input and record in list so we can fire joybutton input actions
//TODO: I don't have an xbox 360 so i can't test this stuff but here goes..
int ms = gameTime.ElapsedGameTime.Milliseconds;
GamePadState player1 = GamePad.GetState(PlayerIndex.One);
GamePadState player2= GamePad.GetState(PlayerIndex.Two);
GamePadState player3= GamePad.GetState(PlayerIndex.Three);
GamePadState player4 = GamePad.GetState(PlayerIndex.Four);
pad1Xmoved = (
int)((float)player1.ThumbSticks.Right.X * gamePadScalingFactor * (float)ms);
pad1Ymoved = (
int)((float)player1.ThumbSticks.Right.Y * gamePadScalingFactor *(float)ms);
int upValue = (int)((float)(player1.DPad.Up == ButtonState.Pressed -1 : 0) * gamePadScalingFactor * (float)ms);
int downValue = (int)((float)(player1.DPad.Down == ButtonState.Pressed 1 : 0) * gamePadScalingFactor * (float)ms);
pad1Zmoved = downValue + upValue;
//TODO: other players, put these into objects and a dictionary<PlayerIndex> for those objects
}
#endregion
#region
Mouse
//mouse helpers
MouseState oldMouseState;
double lastClick1, lastClick2, lastClick3;
double _dblClickSensitivity = 250;
public double DoubleClickSensitivity
{
get { return _dblClickSensitivity; }
set
{
_dblClickSensitivity =
value;
}
}
private void InitMouse()
{
oldMouseState =
Mouse.GetState();
}
private void UpdateMouseInput(GameTime gameTime)
{
int mouseXmoved, mouseYmoved, mouseZmoved;
//TODO: get mouse axis and translate to xyz this frame for axis action maps
//TODO: Get mouse buttons fired and record for mouse button input
MouseState mouseState = Mouse.GetState();
mouseXmoved = mouseState.X - oldMouseState.X;
mouseYmoved = mouseState.Y - oldMouseState.Y;
mouseZmoved = mouseState.ScrollWheelValue - oldMouseState.ScrollWheelValue;
if (mouseXmoved != 0)
{
if(axisActionMapLookup.ContainsKey(ControlAxis.X))
{
axisActionMapLookup[
ControlAxis.X].Action(mouseXmoved);
}
}
if(mouseYmoved != 0)
{
if(axisActionMapLookup.ContainsKey(ControlAxis.Y))
{
axisActionMapLookup[
ControlAxis.Y].Action(mouseYmoved);
}
}
if(mouseZmoved != 0)
{
if(axisActionMapLookup.ContainsKey(ControlAxis.Z))
{
axisActionMapLookup[
ControlAxis.Z].Action(mouseZmoved);
}
}
//get the mouse button pressed and released this frame flags
if (oldMouseState.LeftButton == ButtonState.Released && mouseState.LeftButton == ButtonState.Pressed)
{
if (buttonDownActionmapLookup.ContainsKey(ActionButton.LeftMouse))
{
ButtonActionMapping mapping = buttonDownActionmapLookup[ActionButton.LeftMouse];
mapping.Action();
}
}
if (oldMouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == ButtonState.Released)
{
if (buttonUpActionmapLookup.ContainsKey(ActionButton.LeftMouse))
{
ButtonActionMapping mapping = buttonUpActionmapLookup[ActionButton.LeftMouse];
mapping.Action();
}
if ((gameTime.TotalGameTime.TotalMilliseconds - lastClick1) < DoubleClickSensitivity && lastClick1 != 0)
{
if (mouseDoubleClickActions[(int)ActionButton.LeftMouse].Action != null)
{
mouseDoubleClickActions[(
int)ActionButton.LeftMouse].Action();
}
lastClick1 = 0;
}
else
{
lastClick1 = gameTime.TotalGameTime.TotalMilliseconds;
}
}
if (oldMouseState.RightButton == ButtonState.Released && mouseState.RightButton == ButtonState.Pressed)
{
if (buttonDownActionmapLookup.ContainsKey(ActionButton.RightMouse))
{
ButtonActionMapping mapping = buttonDownActionmapLookup[ActionButton.RightMouse];
mapping.Action();
}
}
if (oldMouseState.RightButton == ButtonState.Pressed && mouseState.RightButton == ButtonState.Released)
{
if (buttonUpActionmapLookup.ContainsKey(ActionButton.RightMouse))
{
ButtonActionMapping mapping = buttonUpActionmapLookup[ActionButton.RightMouse];
mapping.Action();
}
if ((gameTime.TotalGameTime.TotalMilliseconds - lastClick2) < DoubleClickSensitivity && lastClick2 != 0)
{
if (mouseDoubleClickActions[(int)ActionButton.RightMouse].Action != null)
{
mouseDoubleClickActions[(
int)ActionButton.RightMouse].Action();
}
lastClick2 = 0;
}
else
{
lastClick2 = gameTime.TotalGameTime.TotalMilliseconds;
}
}
if (oldMouseState.MiddleButton == ButtonState.Released && mouseState.MiddleButton == ButtonState.Pressed)
{
if (buttonDownActionmapLookup.ContainsKey(ActionButton.MiddleMouse))
{
ButtonActionMapping mapping = buttonDownActionmapLookup[ActionButton.MiddleMouse];
mapping.Action();
}
}
if (oldMouseState.MiddleButton == ButtonState.Pressed && mouseState.MiddleButton == ButtonState.Released)
{
if (buttonUpActionmapLookup.ContainsKey(ActionButton.MiddleMouse))
{
ButtonActionMapping mapping = buttonUpActionmapLookup[ActionButton.MiddleMouse];
mapping.Action();
}
if ((gameTime.TotalGameTime.TotalMilliseconds - lastClick3) < DoubleClickSensitivity && lastClick3 != 0)
{
if (mouseDoubleClickActions[(int)ActionButton.MiddleMouse].Action != null)
{
mouseDoubleClickActions[(
int)ActionButton.MiddleMouse].Action();
}
lastClick3 = 0;
}
else
{
lastClick3 = gameTime.TotalGameTime.TotalMilliseconds;
}
}
oldMouseState = mouseState;
}
#endregion
}
}