diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI/Framework/Input/SInputState.cs | 89 | ||||
-rw-r--r-- | src/SMAPI/Framework/SGame.cs | 1 |
3 files changed, 49 insertions, 42 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index ece388c7..d1a78aaa 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -23,6 +23,7 @@ * Fixed error if a mod loads a PNG while the game is loading (e.g. custom map tilesheets via `IAssetLoader`). * Fixed assets loaded by temporary content managers not being editable by mods. * Fixed assets not reloaded consistently when the player switches language. + * Fixed input suppression not working consistently for clicks. * Fixed console command input not saved to the log. * Fixed `helper.ModRegistry.GetApi` interface validation errors not mentioning which interface caused the issue. * **Breaking changes** (see [migration guide](https://stardewvalleywiki.com/Modding:Migrate_to_Stardew_Valley_1.3)): diff --git a/src/SMAPI/Framework/Input/SInputState.cs b/src/SMAPI/Framework/Input/SInputState.cs index 1b224737..5e8efa62 100644 --- a/src/SMAPI/Framework/Input/SInputState.cs +++ b/src/SMAPI/Framework/Input/SInputState.cs @@ -81,22 +81,16 @@ namespace StardewModdingAPI.Framework.Input Point mousePosition = new Point((int)(this.RealMouse.X * (1.0 / Game1.options.zoomLevel)), (int)(this.RealMouse.Y * (1.0 / Game1.options.zoomLevel))); // derived from Game1::getMouseX var activeButtons = this.DeriveStatuses(this.ActiveButtons, realKeyboard, realMouse, realController); - // get suppressed states - GamePadState suppressedController = realController; - KeyboardState suppressedKeyboard = realKeyboard; - MouseState suppressedMouse = realMouse; - if (this.SuppressButtons.Count > 0) - this.UpdateSuppression(activeButtons, ref suppressedKeyboard, ref suppressedMouse, ref suppressedController); - - // update + // update real states this.ActiveButtons = activeButtons; this.RealController = realController; this.RealKeyboard = realKeyboard; this.RealMouse = realMouse; - this.SuppressedController = suppressedController; - this.SuppressedKeyboard = suppressedKeyboard; - this.SuppressedMouse = suppressedMouse; this.MousePosition = mousePosition; + + // update suppressed states + this.SuppressButtons.RemoveWhere(p => !this.GetStatus(activeButtons, p).IsDown()); + this.UpdateSuppression(); } catch (InvalidOperationException) { @@ -104,6 +98,20 @@ namespace StardewModdingAPI.Framework.Input } } + /// <summary>Apply input suppression to current input.</summary> + public void UpdateSuppression() + { + GamePadState suppressedController = this.RealController; + KeyboardState suppressedKeyboard = this.RealKeyboard; + MouseState suppressedMouse = this.RealMouse; + + this.SuppressGivenStates(this.ActiveButtons, ref suppressedKeyboard, ref suppressedMouse, ref suppressedController); + + this.SuppressedController = suppressedController; + this.SuppressedKeyboard = suppressedKeyboard; + this.SuppressedMouse = suppressedMouse; + } + /// <summary>Get the gamepad state visible to the game.</summary> [Obsolete("This method should only be called by the game itself.")] public override GamePadState GetGamePadState() @@ -145,71 +153,68 @@ namespace StardewModdingAPI.Framework.Input return buttons.Any(button => this.IsDown(button.ToSButton())); } - /// <summary>Apply input suppression for the given input states.</summary> + + /********* + ** Private methods + *********/ + /// <summary>Whether input should be suppressed in the current context.</summary> + private bool ShouldSuppressNow() + { + return Game1.chatBox != null && !Game1.chatBox.isActive(); + } + + /// <summary>Apply input suppression to the given input states.</summary> /// <param name="activeButtons">The current button states to check.</param> /// <param name="keyboardState">The game's keyboard state for the current tick.</param> /// <param name="mouseState">The game's mouse state for the current tick.</param> /// <param name="gamePadState">The game's controller state for the current tick.</param> - public void UpdateSuppression(IDictionary<SButton, InputStatus> activeButtons, ref KeyboardState keyboardState, ref MouseState mouseState, ref GamePadState gamePadState) + private void SuppressGivenStates(IDictionary<SButton, InputStatus> activeButtons, ref KeyboardState keyboardState, ref MouseState mouseState, ref GamePadState gamePadState) { - // stop suppressing buttons once released - if (this.SuppressButtons.Count != 0) - this.SuppressButtons.RemoveWhere(p => !this.GetStatus(activeButtons, p).IsDown()); if (this.SuppressButtons.Count == 0) return; // gather info - HashSet<Keys> keyboardButtons = new HashSet<Keys>(); - HashSet<SButton> controllerButtons = new HashSet<SButton>(); - HashSet<SButton> mouseButtons = new HashSet<SButton>(); + HashSet<Keys> suppressKeys = new HashSet<Keys>(); + HashSet<SButton> suppressButtons = new HashSet<SButton>(); + HashSet<SButton> suppressMouse = new HashSet<SButton>(); foreach (SButton button in this.SuppressButtons) { if (button == SButton.MouseLeft || button == SButton.MouseMiddle || button == SButton.MouseRight || button == SButton.MouseX1 || button == SButton.MouseX2) - mouseButtons.Add(button); + suppressMouse.Add(button); else if (button.TryGetKeyboard(out Keys key)) - keyboardButtons.Add(key); + suppressKeys.Add(key); else if (gamePadState.IsConnected && button.TryGetController(out Buttons _)) - controllerButtons.Add(button); + suppressButtons.Add(button); } // suppress keyboard keys - if (keyboardState.GetPressedKeys().Any() && keyboardButtons.Any()) - keyboardState = new KeyboardState(keyboardState.GetPressedKeys().Except(keyboardButtons).ToArray()); + if (keyboardState.GetPressedKeys().Any() && suppressKeys.Any()) + keyboardState = new KeyboardState(keyboardState.GetPressedKeys().Except(suppressKeys).ToArray()); // suppress controller keys - if (gamePadState.IsConnected && controllerButtons.Any()) + if (gamePadState.IsConnected && suppressButtons.Any()) { GamePadStateBuilder builder = new GamePadStateBuilder(gamePadState); - builder.SuppressButtons(controllerButtons); + builder.SuppressButtons(suppressButtons); gamePadState = builder.ToGamePadState(); } // suppress mouse buttons - if (mouseButtons.Any()) + if (suppressMouse.Any()) { mouseState = new MouseState( x: mouseState.X, y: mouseState.Y, scrollWheel: mouseState.ScrollWheelValue, - leftButton: mouseButtons.Contains(SButton.MouseLeft) ? ButtonState.Pressed : mouseState.LeftButton, - middleButton: mouseButtons.Contains(SButton.MouseMiddle) ? ButtonState.Pressed : mouseState.MiddleButton, - rightButton: mouseButtons.Contains(SButton.MouseRight) ? ButtonState.Pressed : mouseState.RightButton, - xButton1: mouseButtons.Contains(SButton.MouseX1) ? ButtonState.Pressed : mouseState.XButton1, - xButton2: mouseButtons.Contains(SButton.MouseX2) ? ButtonState.Pressed : mouseState.XButton2 + leftButton: suppressMouse.Contains(SButton.MouseLeft) ? ButtonState.Released : mouseState.LeftButton, + middleButton: suppressMouse.Contains(SButton.MouseMiddle) ? ButtonState.Released : mouseState.MiddleButton, + rightButton: suppressMouse.Contains(SButton.MouseRight) ? ButtonState.Released : mouseState.RightButton, + xButton1: suppressMouse.Contains(SButton.MouseX1) ? ButtonState.Released : mouseState.XButton1, + xButton2: suppressMouse.Contains(SButton.MouseX2) ? ButtonState.Released : mouseState.XButton2 ); } } - - /********* - ** Private methods - *********/ - /// <summary>Whether input should be suppressed in the current context.</summary> - private bool ShouldSuppressNow() - { - return Game1.chatBox != null && !Game1.chatBox.isActive(); - } - /// <summary>Get the status of all pressed or released buttons relative to their previous status.</summary> /// <param name="previousStatuses">The previous button statuses.</param> /// <param name="keyboard">The keyboard state.</param> diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index c8c30834..63f7f073 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -613,6 +613,7 @@ namespace StardewModdingAPI.Framework /********* ** Game update *********/ + this.Input.UpdateSuppression(); try { base.Update(gameTime); |