fix cursor position incorrectly handling UI mode (#741)
This commit is contained in:
parent
251ee2121a
commit
456480ef91
|
@ -16,6 +16,7 @@
|
||||||
* For modders:
|
* For modders:
|
||||||
* When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason.
|
* When a mod is blocked by SMAPI's internal compatibility list, the `TRACE` messages while loading it now indicates that and specifies the reason.
|
||||||
* Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. This mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages.
|
* Message data from the `ModMessageReceived` event now uses the same serializer settings as the rest of SMAPI. This mainly adds support for sending crossplatform `Color`, `Point`, `Vector2`, `Rectangle`, and `SemanticVersion` fields through network messages.
|
||||||
|
* Fixed how the input API handles UI scaling. This mainly affects `ICursorPosition` values returned by the API; see [the wiki docs](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Input#ICursorPosition) for how to account for UI scaling.
|
||||||
|
|
||||||
## 3.8.1
|
## 3.8.1
|
||||||
Released 26 December 2020 for Stardew Valley 1.5.1 or later.
|
Released 26 December 2020 for Stardew Valley 1.5.1 or later.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using StardewValley;
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework
|
namespace StardewModdingAPI.Framework
|
||||||
{
|
{
|
||||||
|
@ -25,8 +26,8 @@ namespace StardewModdingAPI.Framework
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
/// <summary>Construct an instance.</summary>
|
/// <summary>Construct an instance.</summary>
|
||||||
/// <param name="absolutePixels">The pixel position relative to the top-left corner of the in-game map, adjusted for pixel zoom.</param>
|
/// <param name="absolutePixels">The pixel position relative to the top-left corner of the in-game map, adjusted for zoom but not UI scaling.</param>
|
||||||
/// <param name="screenPixels">The pixel position relative to the top-left corner of the visible screen, adjusted for pixel zoom.</param>
|
/// <param name="screenPixels">The pixel position relative to the top-left corner of the visible screen, adjusted for zoom but not UI scaling.</param>
|
||||||
/// <param name="tile">The tile position relative to the top-left corner of the map.</param>
|
/// <param name="tile">The tile position relative to the top-left corner of the map.</param>
|
||||||
/// <param name="grabTile">The tile position that the game considers under the cursor for purposes of clicking actions.</param>
|
/// <param name="grabTile">The tile position that the game considers under the cursor for purposes of clicking actions.</param>
|
||||||
public CursorPosition(Vector2 absolutePixels, Vector2 screenPixels, Vector2 tile, Vector2 grabTile)
|
public CursorPosition(Vector2 absolutePixels, Vector2 screenPixels, Vector2 tile, Vector2 grabTile)
|
||||||
|
@ -42,5 +43,21 @@ namespace StardewModdingAPI.Framework
|
||||||
{
|
{
|
||||||
return other != null && this.AbsolutePixels == other.AbsolutePixels;
|
return other != null && this.AbsolutePixels == other.AbsolutePixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Vector2 GetScaledAbsolutePixels()
|
||||||
|
{
|
||||||
|
return Game1.uiMode
|
||||||
|
? Utility.ModifyCoordinatesForUIScale(this.AbsolutePixels)
|
||||||
|
: this.AbsolutePixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Vector2 GetScaledScreenPixels()
|
||||||
|
{
|
||||||
|
return Game1.uiMode
|
||||||
|
? Utility.ModifyCoordinatesForUIScale(this.ScreenPixels)
|
||||||
|
: this.ScreenPixels;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,18 +63,16 @@ namespace StardewModdingAPI.Framework.Input
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
// update SMAPI extended data
|
// update SMAPI extended data
|
||||||
|
// note: Stardew Valley is *not* in UI mode when this code runs
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
float scale = Game1.options.uiScale;
|
float zoomMultiplier = (1f / Game1.options.zoomLevel);
|
||||||
|
|
||||||
// get real values
|
// get real values
|
||||||
var controller = new GamePadStateBuilder(base.GetGamePadState());
|
var controller = new GamePadStateBuilder(base.GetGamePadState());
|
||||||
var keyboard = new KeyboardStateBuilder(base.GetKeyboardState());
|
var keyboard = new KeyboardStateBuilder(base.GetKeyboardState());
|
||||||
var mouse = new MouseStateBuilder(base.GetMouseState());
|
var mouse = new MouseStateBuilder(base.GetMouseState());
|
||||||
Vector2 cursorAbsolutePos = new Vector2(
|
Vector2 cursorAbsolutePos = new Vector2((mouse.X * zoomMultiplier) + Game1.viewport.X, (mouse.Y * zoomMultiplier) + Game1.viewport.Y);
|
||||||
x: (mouse.X / scale) + Game1.uiViewport.X,
|
|
||||||
y: (mouse.Y / scale) + Game1.uiViewport.Y
|
|
||||||
);
|
|
||||||
Vector2? playerTilePos = Context.IsPlayerFree ? Game1.player.getTileLocation() : (Vector2?)null;
|
Vector2? playerTilePos = Context.IsPlayerFree ? Game1.player.getTileLocation() : (Vector2?)null;
|
||||||
HashSet<SButton> reallyDown = new HashSet<SButton>(this.GetPressedButtons(keyboard, mouse, controller));
|
HashSet<SButton> reallyDown = new HashSet<SButton>(this.GetPressedButtons(keyboard, mouse, controller));
|
||||||
|
|
||||||
|
@ -109,7 +107,7 @@ namespace StardewModdingAPI.Framework.Input
|
||||||
if (cursorAbsolutePos != this.CursorPositionImpl?.AbsolutePixels || playerTilePos != this.LastPlayerTile)
|
if (cursorAbsolutePos != this.CursorPositionImpl?.AbsolutePixels || playerTilePos != this.LastPlayerTile)
|
||||||
{
|
{
|
||||||
this.LastPlayerTile = playerTilePos;
|
this.LastPlayerTile = playerTilePos;
|
||||||
this.CursorPositionImpl = this.GetCursorPosition(this.MouseState, cursorAbsolutePos, scale);
|
this.CursorPositionImpl = this.GetCursorPosition(this.MouseState, cursorAbsolutePos, zoomMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
|
@ -202,11 +200,11 @@ namespace StardewModdingAPI.Framework.Input
|
||||||
/// <summary>Get the current cursor position.</summary>
|
/// <summary>Get the current cursor position.</summary>
|
||||||
/// <param name="mouseState">The current mouse state.</param>
|
/// <param name="mouseState">The current mouse state.</param>
|
||||||
/// <param name="absolutePixels">The absolute pixel position relative to the map, adjusted for pixel zoom.</param>
|
/// <param name="absolutePixels">The absolute pixel position relative to the map, adjusted for pixel zoom.</param>
|
||||||
/// <param name="scale">The UI scale applied to pixel coordinates.</param>
|
/// <param name="zoomMultiplier">The multiplier applied to pixel coordinates to adjust them for pixel zoom.</param>
|
||||||
private CursorPosition GetCursorPosition(MouseState mouseState, Vector2 absolutePixels, float scale)
|
private CursorPosition GetCursorPosition(MouseState mouseState, Vector2 absolutePixels, float zoomMultiplier)
|
||||||
{
|
{
|
||||||
Vector2 screenPixels = new Vector2(mouseState.X / scale, mouseState.Y / scale);
|
Vector2 screenPixels = new Vector2(mouseState.X * zoomMultiplier, mouseState.Y * zoomMultiplier);
|
||||||
Vector2 tile = new Vector2((int)((Game1.uiViewport.X + screenPixels.X) / Game1.tileSize), (int)((Game1.uiViewport.Y + screenPixels.Y) / Game1.tileSize));
|
Vector2 tile = new Vector2((int)((Game1.viewport.X + screenPixels.X) / Game1.tileSize), (int)((Game1.viewport.Y + screenPixels.Y) / Game1.tileSize));
|
||||||
Vector2 grabTile = (Game1.mouseCursorTransparency > 0 && Utility.tileWithinRadiusOfPlayer((int)tile.X, (int)tile.Y, 1, Game1.player)) // derived from Game1.pressActionButton
|
Vector2 grabTile = (Game1.mouseCursorTransparency > 0 && Utility.tileWithinRadiusOfPlayer((int)tile.X, (int)tile.Y, 1, Game1.player)) // derived from Game1.pressActionButton
|
||||||
? tile
|
? tile
|
||||||
: Game1.player.GetGrabTile();
|
: Game1.player.GetGrabTile();
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using StardewValley;
|
||||||
|
|
||||||
namespace StardewModdingAPI
|
namespace StardewModdingAPI
|
||||||
{
|
{
|
||||||
/// <summary>Represents a cursor position in the different coordinate systems.</summary>
|
/// <summary>Represents a cursor position in the different coordinate systems.</summary>
|
||||||
public interface ICursorPosition : IEquatable<ICursorPosition>
|
public interface ICursorPosition : IEquatable<ICursorPosition>
|
||||||
{
|
{
|
||||||
/// <summary>The pixel position relative to the top-left corner of the in-game map.</summary>
|
/*********
|
||||||
|
** Accessors
|
||||||
|
*********/
|
||||||
|
/// <summary>The pixel position relative to the top-left corner of the in-game map, adjusted for zoom but not UI scaling. See also <see cref="GetScaledAbsolutePixels"/>.</summary>
|
||||||
Vector2 AbsolutePixels { get; }
|
Vector2 AbsolutePixels { get; }
|
||||||
|
|
||||||
/// <summary>The pixel position relative to the top-left corner of the visible screen.</summary>
|
/// <summary>The pixel position relative to the top-left corner of the visible screen, adjusted for zoom but not UI scaling. See also <see cref="GetScaledScreenPixels"/>.</summary>
|
||||||
Vector2 ScreenPixels { get; }
|
Vector2 ScreenPixels { get; }
|
||||||
|
|
||||||
/// <summary>The tile position under the cursor relative to the top-left corner of the map.</summary>
|
/// <summary>The tile position under the cursor relative to the top-left corner of the map.</summary>
|
||||||
|
@ -17,5 +21,15 @@ namespace StardewModdingAPI
|
||||||
|
|
||||||
/// <summary>The tile position that the game considers under the cursor for purposes of clicking actions. This may be different than <see cref="Tile"/> if that's too far from the player.</summary>
|
/// <summary>The tile position that the game considers under the cursor for purposes of clicking actions. This may be different than <see cref="Tile"/> if that's too far from the player.</summary>
|
||||||
Vector2 GrabTile { get; }
|
Vector2 GrabTile { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********
|
||||||
|
** Public methods
|
||||||
|
*********/
|
||||||
|
/// <summary>Get the <see cref="AbsolutePixels"/>, adjusted for UI scaling if needed. This is only different if <see cref="Game1.uiMode"/> is true.</summary>
|
||||||
|
Vector2 GetScaledAbsolutePixels();
|
||||||
|
|
||||||
|
/// <summary>Get the <see cref="ScreenPixels"/>, adjusted for UI scaling if needed. This is only different if <see cref="Game1.uiMode"/> is true.</summary>
|
||||||
|
Vector2 GetScaledScreenPixels();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue