using System.Collections.Generic; 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.GetBitmask(this.GetPressedButtons()) // MonoDevelop requires one bitmask here; don't specify multiple values ); } /********* ** 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; } } /// 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; } } }