using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using StardewValley;
namespace StardewModdingAPI.Framework.Input
{
/// A summary of input changes during an update frame.
internal class InputState
{
/*********
** Accessors
*********/
/// The underlying controller state.
public GamePadState ControllerState { get; }
/// The underlying keyboard state.
public KeyboardState KeyboardState { get; }
/// The underlying mouse state.
public MouseState MouseState { get; }
/// The mouse position on the screen adjusted for the zoom level.
public Point MousePosition { get; }
/// The buttons which were pressed, held, or released.
public IDictionary ActiveButtons { get; } = new Dictionary();
/*********
** Public methods
*********/
/// Construct an empty instance.
public InputState() { }
/// Construct an instance.
/// The previous input state.
/// The current controller state.
/// The current keyboard state.
/// The current mouse state.
public InputState(InputState previousState, GamePadState controllerState, KeyboardState keyboardState, MouseState mouseState)
{
// init properties
this.ControllerState = controllerState;
this.KeyboardState = keyboardState;
this.MouseState = mouseState;
this.MousePosition = new Point((int)(mouseState.X * (1.0 / Game1.options.zoomLevel)), (int)(mouseState.Y * (1.0 / Game1.options.zoomLevel))); // derived from Game1::getMouseX
// get button states
SButton[] down = InputState.GetPressedButtons(keyboardState, mouseState, controllerState).ToArray();
foreach (SButton button in down)
this.ActiveButtons[button] = this.GetStatus(previousState.GetStatus(button), isDown: true);
foreach (KeyValuePair prev in previousState.ActiveButtons)
{
if (prev.Value.IsDown() && !this.ActiveButtons.ContainsKey(prev.Key))
this.ActiveButtons[prev.Key] = InputStatus.Released;
}
}
/// Get the status of a button.
/// The button to check.
public InputStatus GetStatus(SButton button)
{
return this.ActiveButtons.TryGetValue(button, out InputStatus status) ? status : InputStatus.None;
}
/// Get whether a given button was pressed or held.
/// The button to check.
public bool IsDown(SButton button)
{
return this.GetStatus(button).IsDown();
}
/// Get the current input state.
/// The previous input state.
public static InputState GetState(InputState previousState)
{
GamePadState controllerState = GamePad.GetState(PlayerIndex.One);
KeyboardState keyboardState = Keyboard.GetState();
MouseState mouseState = Mouse.GetState();
return new InputState(previousState, controllerState, keyboardState, mouseState);
}
/*********
** Private methods
*********/
/// Get the status of a button.
/// The previous button status.
/// Whether the button is currently down.
public InputStatus GetStatus(InputStatus oldStatus, bool isDown)
{
if (isDown && oldStatus.IsDown())
return InputStatus.Held;
if (isDown)
return InputStatus.Pressed;
return InputStatus.Released;
}
/// Get the buttons pressed in the given stats.
/// The keyboard state.
/// The mouse state.
/// The controller state.
private static IEnumerable GetPressedButtons(KeyboardState keyboard, MouseState mouse, GamePadState controller)
{
// keyboard
foreach (Keys key in keyboard.GetPressedKeys())
yield return key.ToSButton();
// mouse
if (mouse.LeftButton == ButtonState.Pressed)
yield return SButton.MouseLeft;
if (mouse.RightButton == ButtonState.Pressed)
yield return SButton.MouseRight;
if (mouse.MiddleButton == ButtonState.Pressed)
yield return SButton.MouseMiddle;
if (mouse.XButton1 == ButtonState.Pressed)
yield return SButton.MouseX1;
if (mouse.XButton2 == ButtonState.Pressed)
yield return SButton.MouseX2;
// controller
if (controller.IsConnected)
{
if (controller.Buttons.A == ButtonState.Pressed)
yield return SButton.ControllerA;
if (controller.Buttons.B == ButtonState.Pressed)
yield return SButton.ControllerB;
if (controller.Buttons.Back == ButtonState.Pressed)
yield return SButton.ControllerBack;
if (controller.Buttons.BigButton == ButtonState.Pressed)
yield return SButton.BigButton;
if (controller.Buttons.LeftShoulder == ButtonState.Pressed)
yield return SButton.LeftShoulder;
if (controller.Buttons.LeftStick == ButtonState.Pressed)
yield return SButton.LeftStick;
if (controller.Buttons.RightShoulder == ButtonState.Pressed)
yield return SButton.RightShoulder;
if (controller.Buttons.RightStick == ButtonState.Pressed)
yield return SButton.RightStick;
if (controller.Buttons.Start == ButtonState.Pressed)
yield return SButton.ControllerStart;
if (controller.Buttons.X == ButtonState.Pressed)
yield return SButton.ControllerX;
if (controller.Buttons.Y == ButtonState.Pressed)
yield return SButton.ControllerY;
if (controller.DPad.Up == ButtonState.Pressed)
yield return SButton.DPadUp;
if (controller.DPad.Down == ButtonState.Pressed)
yield return SButton.DPadDown;
if (controller.DPad.Left == ButtonState.Pressed)
yield return SButton.DPadLeft;
if (controller.DPad.Right == ButtonState.Pressed)
yield return SButton.DPadRight;
if (controller.Triggers.Left > 0.2f)
yield return SButton.LeftTrigger;
if (controller.Triggers.Right > 0.2f)
yield return SButton.RightTrigger;
}
}
}
}