fix input suppression not working in some cases

This commit is contained in:
Jesse Plamondon-Willard 2018-05-05 02:27:43 -04:00
parent b8fd3aedfe
commit 30bf40ab2b
3 changed files with 73 additions and 66 deletions

View File

@ -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)):

View File

@ -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,61 +153,6 @@ namespace StardewModdingAPI.Framework.Input
return buttons.Any(button => this.IsDown(button.ToSButton()));
}
/// <summary>Apply input suppression for 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)
{
// 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>();
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);
else if (button.TryGetKeyboard(out Keys key))
keyboardButtons.Add(key);
else if (gamePadState.IsConnected && button.TryGetController(out Buttons _))
controllerButtons.Add(button);
}
// suppress keyboard keys
if (keyboardState.GetPressedKeys().Any() && keyboardButtons.Any())
keyboardState = new KeyboardState(keyboardState.GetPressedKeys().Except(keyboardButtons).ToArray());
// suppress controller keys
if (gamePadState.IsConnected && controllerButtons.Any())
{
GamePadStateBuilder builder = new GamePadStateBuilder(gamePadState);
builder.SuppressButtons(controllerButtons);
gamePadState = builder.ToGamePadState();
}
// suppress mouse buttons
if (mouseButtons.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
);
}
}
/*********
** Private methods
@ -210,6 +163,58 @@ namespace StardewModdingAPI.Framework.Input
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>
private void SuppressGivenStates(IDictionary<SButton, InputStatus> activeButtons, ref KeyboardState keyboardState, ref MouseState mouseState, ref GamePadState gamePadState)
{
if (this.SuppressButtons.Count == 0)
return;
// gather info
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)
suppressMouse.Add(button);
else if (button.TryGetKeyboard(out Keys key))
suppressKeys.Add(key);
else if (gamePadState.IsConnected && button.TryGetController(out Buttons _))
suppressButtons.Add(button);
}
// suppress keyboard keys
if (keyboardState.GetPressedKeys().Any() && suppressKeys.Any())
keyboardState = new KeyboardState(keyboardState.GetPressedKeys().Except(suppressKeys).ToArray());
// suppress controller keys
if (gamePadState.IsConnected && suppressButtons.Any())
{
GamePadStateBuilder builder = new GamePadStateBuilder(gamePadState);
builder.SuppressButtons(suppressButtons);
gamePadState = builder.ToGamePadState();
}
// suppress mouse buttons
if (suppressMouse.Any())
{
mouseState = new MouseState(
x: mouseState.X,
y: mouseState.Y,
scrollWheel: mouseState.ScrollWheelValue,
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
);
}
}
/// <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>

View File

@ -613,6 +613,7 @@ namespace StardewModdingAPI.Framework
/*********
** Game update
*********/
this.Input.UpdateSuppression();
try
{
base.Update(gameTime);