summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/Input/GamePadStateBuilder.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-08-01 11:07:29 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-08-01 11:07:29 -0400
commit60b41195778af33fd609eab66d9ae3f1d1165e8f (patch)
tree7128b906d40e94c56c34ed6058f27bc31c31a08b /src/SMAPI/Framework/Input/GamePadStateBuilder.cs
parentb9bc1a6d17cafa0a97b46ffecda432cfc2f23b51 (diff)
parent52cf953f685c65b2b6814e375ec9a5ffa03c440a (diff)
downloadSMAPI-60b41195778af33fd609eab66d9ae3f1d1165e8f.tar.gz
SMAPI-60b41195778af33fd609eab66d9ae3f1d1165e8f.tar.bz2
SMAPI-60b41195778af33fd609eab66d9ae3f1d1165e8f.zip
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI/Framework/Input/GamePadStateBuilder.cs')
-rw-r--r--src/SMAPI/Framework/Input/GamePadStateBuilder.cs162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs
new file mode 100644
index 00000000..33557385
--- /dev/null
+++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs
@@ -0,0 +1,162 @@
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Framework.Input
+{
+ /// <summary>An abstraction for manipulating controller state.</summary>
+ internal class GamePadStateBuilder
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>The current button states.</summary>
+ private readonly IDictionary<SButton, ButtonState> ButtonStates;
+
+ /// <summary>The left trigger value.</summary>
+ private float LeftTrigger;
+
+ /// <summary>The right trigger value.</summary>
+ private float RightTrigger;
+
+ /// <summary>The left thumbstick position.</summary>
+ private Vector2 LeftStickPos;
+
+ /// <summary>The left thumbstick position.</summary>
+ private Vector2 RightStickPos;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="state">The initial controller state.</param>
+ public GamePadStateBuilder(GamePadState state)
+ {
+ this.ButtonStates = new Dictionary<SButton, ButtonState>
+ {
+ [SButton.DPadUp] = state.DPad.Up,
+ [SButton.DPadDown] = state.DPad.Down,
+ [SButton.DPadLeft] = state.DPad.Left,
+ [SButton.DPadRight] = state.DPad.Right,
+
+ [SButton.ControllerA] = state.Buttons.A,
+ [SButton.ControllerB] = state.Buttons.B,
+ [SButton.ControllerX] = state.Buttons.X,
+ [SButton.ControllerY] = state.Buttons.Y,
+ [SButton.LeftStick] = state.Buttons.LeftStick,
+ [SButton.RightStick] = state.Buttons.RightStick,
+ [SButton.LeftShoulder] = state.Buttons.LeftShoulder,
+ [SButton.RightShoulder] = state.Buttons.RightShoulder,
+ [SButton.ControllerBack] = state.Buttons.Back,
+ [SButton.ControllerStart] = state.Buttons.Start,
+ [SButton.BigButton] = state.Buttons.BigButton
+ };
+ this.LeftTrigger = state.Triggers.Left;
+ this.RightTrigger = state.Triggers.Right;
+ this.LeftStickPos = state.ThumbSticks.Left;
+ this.RightStickPos = state.ThumbSticks.Right;
+ }
+
+ /// <summary>Mark all matching buttons unpressed.</summary>
+ /// <param name="buttons">The buttons.</param>
+ public void SuppressButtons(IEnumerable<SButton> buttons)
+ {
+ foreach (SButton button in buttons)
+ this.SuppressButton(button);
+ }
+
+ /// <summary>Mark a button unpressed.</summary>
+ /// <param name="button">The button.</param>
+ public void SuppressButton(SButton button)
+ {
+ switch (button)
+ {
+ // left thumbstick
+ case SButton.LeftThumbstickUp:
+ if (this.LeftStickPos.Y > 0)
+ this.LeftStickPos.Y = 0;
+ break;
+ case SButton.LeftThumbstickDown:
+ if (this.LeftStickPos.Y < 0)
+ this.LeftStickPos.Y = 0;
+ break;
+ case SButton.LeftThumbstickLeft:
+ if (this.LeftStickPos.X < 0)
+ this.LeftStickPos.X = 0;
+ break;
+ case SButton.LeftThumbstickRight:
+ if (this.LeftStickPos.X > 0)
+ this.LeftStickPos.X = 0;
+ break;
+
+ // right thumbstick
+ case SButton.RightThumbstickUp:
+ if (this.RightStickPos.Y > 0)
+ this.RightStickPos.Y = 0;
+ break;
+ case SButton.RightThumbstickDown:
+ if (this.RightStickPos.Y < 0)
+ this.RightStickPos.Y = 0;
+ break;
+ case SButton.RightThumbstickLeft:
+ if (this.RightStickPos.X < 0)
+ this.RightStickPos.X = 0;
+ break;
+ case SButton.RightThumbstickRight:
+ if (this.RightStickPos.X > 0)
+ this.RightStickPos.X = 0;
+ break;
+
+ // triggers
+ case SButton.LeftTrigger:
+ this.LeftTrigger = 0;
+ break;
+ case SButton.RightTrigger:
+ this.RightTrigger = 0;
+ break;
+
+ // buttons
+ default:
+ if (this.ButtonStates.ContainsKey(button))
+ this.ButtonStates[button] = ButtonState.Released;
+ break;
+ }
+ }
+
+ /// <summary>Construct an equivalent gamepad state.</summary>
+ public GamePadState ToGamePadState()
+ {
+ return new GamePadState(
+ leftThumbStick: this.LeftStickPos,
+ rightThumbStick: this.RightStickPos,
+ leftTrigger: this.LeftTrigger,
+ rightTrigger: this.RightTrigger,
+ buttons: this.GetBitmask(this.GetPressedButtons()) // MonoDevelop requires one bitmask here; don't specify multiple values
+ );
+ }
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Get all pressed buttons.</summary>
+ private IEnumerable<Buttons> GetPressedButtons()
+ {
+ foreach (var pair in this.ButtonStates)
+ {
+ if (pair.Value == ButtonState.Pressed && pair.Key.TryGetController(out Buttons button))
+ yield return button;
+ }
+ }
+
+ /// <summary>Get a bitmask representing the given buttons.</summary>
+ /// <param name="buttons">The buttons to represent.</param>
+ private Buttons GetBitmask(IEnumerable<Buttons> buttons)
+ {
+ Buttons flag = 0;
+ foreach (Buttons button in buttons)
+ flag |= button;
+ return flag;
+ }
+ }
+}