using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; namespace StardewModdingAPI.Framework.Input { /// Manipulates controller state. internal class GamePadStateBuilder { /********* ** Fields *********/ /// 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 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; } /// Override the states for a set of buttons. /// The button state overrides. public GamePadStateBuilder OverrideButtons(IDictionary overrides) { foreach (var pair in overrides) { bool isDown = pair.Value.IsDown(); switch (pair.Key) { // left thumbstick case SButton.LeftThumbstickUp: this.LeftStickPos.Y = isDown ? 1 : 0; break; case SButton.LeftThumbstickDown: this.LeftStickPos.Y = isDown ? 1 : 0; break; case SButton.LeftThumbstickLeft: this.LeftStickPos.X = isDown ? 1 : 0; break; case SButton.LeftThumbstickRight: this.LeftStickPos.X = isDown ? 1 : 0; break; // right thumbstick case SButton.RightThumbstickUp: this.RightStickPos.Y = isDown ? 1 : 0; break; case SButton.RightThumbstickDown: this.RightStickPos.Y = isDown ? 1 : 0; break; case SButton.RightThumbstickLeft: this.RightStickPos.X = isDown ? 1 : 0; break; case SButton.RightThumbstickRight: this.RightStickPos.X = isDown ? 1 : 0; break; // triggers case SButton.LeftTrigger: this.LeftTrigger = isDown ? 1 : 0; break; case SButton.RightTrigger: this.RightTrigger = isDown ? 1 : 0; break; // buttons default: if (this.ButtonStates.ContainsKey(pair.Key)) this.ButtonStates[pair.Key] = isDown ? ButtonState.Pressed : ButtonState.Released; break; } } return this; } /// Construct an equivalent state. public GamePadState ToState() { 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; } } }