From 5e7eaf9f75d72d8cbb338c35b43f2974440b3456 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 22 Apr 2018 19:59:03 -0400 Subject: rewrite input suppression (#453) This lets SMAPI intercept all input using the new Game1.hooks in SDV 1.3.0.32. However, intercepting mouse clicks needs a few more changes in the game code. --- src/SMAPI/Framework/Input/GamePadStateBuilder.cs | 153 +++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/SMAPI/Framework/Input/GamePadStateBuilder.cs (limited to 'src/SMAPI/Framework/Input/GamePadStateBuilder.cs') diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs new file mode 100644 index 00000000..5eeb7ef6 --- /dev/null +++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace StardewModdingAPI.Framework.Input +{ + /// An abstraction for manipulating controller state. + internal class GamePadStateBuilder + { + /********* + ** Properties + *********/ + /// The current button states. + private readonly IDictionary ButtonStates; + + /// The left trigger value. + private float LeftTrigger; + + /// The right trigger value. + private float RightTrigger; + + /// The left thumbstick position. + private Vector2 LeftStickPos; + + /// The left thumbstick position. + private Vector2 RightStickPos; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The initial controller state. + public GamePadStateBuilder(GamePadState state) + { + this.ButtonStates = new Dictionary + { + [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; + } + + /// Mark all matching buttons unpressed. + /// The buttons. + public void SuppressButtons(IEnumerable buttons) + { + foreach (SButton button in buttons) + this.SuppressButton(button); + } + + /// Mark a button unpressed. + /// The button. + 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; + } + } + + /// Construct an equivalent gamepad state. + public GamePadState ToGamePadState() + { + return new GamePadState( + leftThumbStick: this.LeftStickPos, + rightThumbStick: this.RightStickPos, + leftTrigger: this.LeftTrigger, + rightTrigger: this.RightTrigger, + buttons: this.GetPressedButtons().ToArray() + ); + } + + /********* + ** Private methods + *********/ + /// Get all pressed buttons. + private IEnumerable GetPressedButtons() + { + foreach (var pair in this.ButtonStates) + { + if (pair.Value == ButtonState.Pressed && pair.Key.TryGetController(out Buttons button)) + yield return button; + } + } + } +} -- cgit From fec6adf82d5eda99c6bf34a21b0e01adc2b10d22 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 29 Apr 2018 21:55:26 -0400 Subject: fix build error on Linux/Mac --- src/SMAPI/Framework/Input/GamePadStateBuilder.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/SMAPI/Framework/Input/GamePadStateBuilder.cs') diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs index 5eeb7ef6..33557385 100644 --- a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs +++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; @@ -133,7 +132,7 @@ namespace StardewModdingAPI.Framework.Input rightThumbStick: this.RightStickPos, leftTrigger: this.LeftTrigger, rightTrigger: this.RightTrigger, - buttons: this.GetPressedButtons().ToArray() + buttons: this.GetBitmask(this.GetPressedButtons()) // MonoDevelop requires one bitmask here; don't specify multiple values ); } @@ -149,5 +148,15 @@ namespace StardewModdingAPI.Framework.Input yield return button; } } + + /// Get a bitmask representing the given buttons. + /// The buttons to represent. + private Buttons GetBitmask(IEnumerable buttons) + { + Buttons flag = 0; + foreach (Buttons button in buttons) + flag |= button; + return flag; + } } } -- cgit