commit
d27c7c749c
|
@ -41,32 +41,6 @@ namespace stardew_access.Features
|
||||||
MainClass.ScreenReader.Say($"{currentLocation.Name} Entered", true);
|
MainClass.ScreenReader.Say($"{currentLocation.Name} Entered", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SnapMouseToPlayer()
|
|
||||||
{
|
|
||||||
int x = Game1.player.GetBoundingBox().Center.X - Game1.viewport.X;
|
|
||||||
int y = Game1.player.GetBoundingBox().Center.Y - Game1.viewport.Y;
|
|
||||||
|
|
||||||
int offset = 64;
|
|
||||||
|
|
||||||
switch (Game1.player.FacingDirection)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
y -= offset;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
x += offset;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
y += offset;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
x -= offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Game1.setMousePosition(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void narrateHudMessages()
|
public static void narrateHudMessages()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Objects;
|
using StardewValley.Objects;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using xTile;
|
||||||
|
using StardewValley;
|
||||||
|
using StardewValley.Menus;
|
||||||
|
using stardew_access.Features;
|
||||||
|
|
||||||
|
namespace stardew_access.Features
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows browsing of the map and snapping mouse to tiles with the arrow keys
|
||||||
|
/// </summary>
|
||||||
|
public class TileViewer
|
||||||
|
{
|
||||||
|
|
||||||
|
//None of these positions take viewport into account; other functions are responsible later
|
||||||
|
private Vector2 ViewingOffset = Vector2.Zero;
|
||||||
|
private Vector2 relativeOffsetLockPosition = Vector2.Zero;
|
||||||
|
private Boolean relativeOffsetLock = false;
|
||||||
|
private Vector2 prevPlayerPosition = Vector2.Zero, prevFacing = Vector2.Zero;
|
||||||
|
|
||||||
|
private Vector2 PlayerFacingVector
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Game1.player.FacingDirection)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return new Vector2(0, -Game1.tileSize);
|
||||||
|
case 1:
|
||||||
|
return new Vector2(Game1.tileSize, 0);
|
||||||
|
case 2:
|
||||||
|
return new Vector2(0, Game1.tileSize);
|
||||||
|
case 3:
|
||||||
|
return new Vector2(-Game1.tileSize, 0);
|
||||||
|
default:
|
||||||
|
return Vector2.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 PlayerPosition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int x = Game1.player.GetBoundingBox().Center.X;
|
||||||
|
int y = Game1.player.GetBoundingBox().Center.Y;
|
||||||
|
return new Vector2(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the position of the tile cursor in pixels from the upper-left corner of the map.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Vector2</returns>
|
||||||
|
public Vector2 GetTileCursorPosition()
|
||||||
|
{
|
||||||
|
Vector2 target = this.PlayerPosition;
|
||||||
|
if (this.relativeOffsetLock)
|
||||||
|
{
|
||||||
|
target += this.relativeOffsetLockPosition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target += this.PlayerFacingVector + this.ViewingOffset;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the tile at the position of the tile cursor.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Vector2</returns>
|
||||||
|
public Vector2 GetViewingTile()
|
||||||
|
{
|
||||||
|
Vector2 position = this.GetTileCursorPosition();
|
||||||
|
return new Vector2((int)position.X / Game1.tileSize, (int)position.Y / Game1.tileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle keyboard input related to the tile viewer.
|
||||||
|
/// </summary>
|
||||||
|
public void HandleInput()
|
||||||
|
{
|
||||||
|
if (MainClass.Config.ToggleRelativeCursorLockKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.relativeOffsetLock = !this.relativeOffsetLock;
|
||||||
|
if (this.relativeOffsetLock)
|
||||||
|
{
|
||||||
|
this.relativeOffsetLockPosition = this.PlayerFacingVector + this.ViewingOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.relativeOffsetLockPosition = Vector2.Zero;
|
||||||
|
}
|
||||||
|
MainClass.ScreenReader.Say("Relative cursor lock " + (this.relativeOffsetLock ? "enabled" : "disabled") + ".", true);
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorPreciseUpKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(0, -MainClass.Config.TileCursorPreciseMovementDistance), true);
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorPreciseRightKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(MainClass.Config.TileCursorPreciseMovementDistance, 0), true);
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorPreciseDownKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(0, MainClass.Config.TileCursorPreciseMovementDistance), true);
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorPreciseLeftKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(-MainClass.Config.TileCursorPreciseMovementDistance, 0), true);
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorUpKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(0, -Game1.tileSize));
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorRightKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(Game1.tileSize, 0));
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorDownKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(0, Game1.tileSize));
|
||||||
|
}
|
||||||
|
else if (MainClass.Config.TileCursorLeftKey.JustPressed())
|
||||||
|
{
|
||||||
|
this.cursorMoveInput(new Vector2(-Game1.tileSize, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cursorMoveInput(Vector2 delta, Boolean precise = false)
|
||||||
|
{
|
||||||
|
if (!tryMoveTileView(delta)) return;
|
||||||
|
Vector2 position = this.GetTileCursorPosition();
|
||||||
|
Vector2 tile = this.GetViewingTile();
|
||||||
|
String? name = TileInfo.getNameAtTile(tile);
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
// Report if a tile is empty or blocked if there is nothing on it
|
||||||
|
if (TileInfo.isCollidingAtTile((int)tile.X, (int)tile.Y))
|
||||||
|
{
|
||||||
|
name = "blocked";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = "empty";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (precise)
|
||||||
|
{
|
||||||
|
MainClass.ScreenReader.Say($"{name}, {position.X}, {position.Y}", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainClass.ScreenReader.Say($"{name}, {(int)(position.X / Game1.tileSize)}, {(int)(position.Y / Game1.tileSize)}", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool tryMoveTileView(Vector2 delta)
|
||||||
|
{
|
||||||
|
Vector2 dest = this.GetTileCursorPosition() + delta;
|
||||||
|
if (!isPositionOnMap(dest)) return false;
|
||||||
|
if ((MainClass.Config.LimitTileCursorToScreen && Utility.isOnScreen(dest, 0)) || !MainClass.Config.LimitTileCursorToScreen)
|
||||||
|
{
|
||||||
|
if (this.relativeOffsetLock)
|
||||||
|
{
|
||||||
|
this.relativeOffsetLockPosition += delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.ViewingOffset += delta;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SnapMouseToPlayer()
|
||||||
|
{
|
||||||
|
Vector2 cursorPosition = this.GetTileCursorPosition();
|
||||||
|
if (allowMouseSnap(cursorPosition))
|
||||||
|
// Must account for viewport here
|
||||||
|
Game1.setMousePosition((int)cursorPosition.X - Game1.viewport.X, (int)cursorPosition.Y - Game1.viewport.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle tile viewer logic.
|
||||||
|
/// </summary>
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
//Reset the viewing cursor to the player when they turn or move. This will not reset the locked offset relative cursor position.
|
||||||
|
if (this.prevFacing != this.PlayerFacingVector || this.prevPlayerPosition != this.PlayerPosition)
|
||||||
|
{
|
||||||
|
this.ViewingOffset = Vector2.Zero;
|
||||||
|
}
|
||||||
|
this.prevFacing = this.PlayerFacingVector;
|
||||||
|
this.prevPlayerPosition = this.PlayerPosition;
|
||||||
|
if (MainClass.Config.SnapMouse)
|
||||||
|
this.SnapMouseToPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool allowMouseSnap(Vector2 point)
|
||||||
|
{
|
||||||
|
// Utility.isOnScreen treats a vector as a pixel position, not a tile position
|
||||||
|
if (!Utility.isOnScreen(point, 0)) return false;
|
||||||
|
|
||||||
|
//prevent mousing over the toolbar or any other UI component with the tile cursor
|
||||||
|
foreach (IClickableMenu menu in Game1.onScreenMenus)
|
||||||
|
{
|
||||||
|
//must account for viewport here
|
||||||
|
if (menu.isWithinBounds((int)point.X - Game1.viewport.X, (int)point.Y - Game1.viewport.Y)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool isPositionOnMap(Vector2 position)
|
||||||
|
{
|
||||||
|
//position does not take viewport into account since the entire map needs to be checked.
|
||||||
|
Map map = Game1.currentLocation.map;
|
||||||
|
if (position.X < 0 || position.X > map.Layers[0].DisplayWidth) return false;
|
||||||
|
if (position.Y < 0 || position.Y > map.Layers[0].DisplayHeight) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,19 @@ namespace stardew_access
|
||||||
public KeybindList TimeNSeasonKey { get; set; } = KeybindList.Parse("Q");
|
public KeybindList TimeNSeasonKey { get; set; } = KeybindList.Parse("Q");
|
||||||
public KeybindList ReadTileKey { get; set; } = KeybindList.Parse("J");
|
public KeybindList ReadTileKey { get; set; } = KeybindList.Parse("J");
|
||||||
public KeybindList ReadStandingTileKey { get; set; } = KeybindList.Parse("LeftAlt + J");
|
public KeybindList ReadStandingTileKey { get; set; } = KeybindList.Parse("LeftAlt + J");
|
||||||
|
public bool LimitTileCursorToScreen { get; set; } = false;
|
||||||
|
public int TileCursorPreciseMovementDistance { get; set; } = 8;
|
||||||
|
|
||||||
|
//Tile viewer keys
|
||||||
|
public KeybindList TileCursorUpKey { get; set; } = KeybindList.Parse("Up");
|
||||||
|
public KeybindList TileCursorRightKey { get; set; } = KeybindList.Parse("Right");
|
||||||
|
public KeybindList TileCursorDownKey { get; set; } = KeybindList.Parse("Down");
|
||||||
|
public KeybindList TileCursorLeftKey { get; set; } = KeybindList.Parse("Left");
|
||||||
|
public KeybindList TileCursorPreciseUpKey { get; set; } = KeybindList.Parse("LeftShift + Up");
|
||||||
|
public KeybindList TileCursorPreciseRightKey { get; set; } = KeybindList.Parse("LeftShift + Right");
|
||||||
|
public KeybindList TileCursorPreciseDownKey { get; set; } = KeybindList.Parse("LeftShift + Down");
|
||||||
|
public KeybindList TileCursorPreciseLeftKey { get; set; } = KeybindList.Parse("LeftShift + Left");
|
||||||
|
public KeybindList ToggleRelativeCursorLockKey { get; set; } = KeybindList.Parse("L");
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// TODO Add the exclusion and focus list too
|
// TODO Add the exclusion and focus list too
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace stardew_access
|
||||||
private static StaticTiles? sTiles;
|
private static StaticTiles? sTiles;
|
||||||
private static IScreenReader? screenReader;
|
private static IScreenReader? screenReader;
|
||||||
private static IModHelper? modHelper;
|
private static IModHelper? modHelper;
|
||||||
|
private static TileViewer? tileViewer;
|
||||||
|
|
||||||
internal static ModConfig Config { get => config; set => config = value; }
|
internal static ModConfig Config { get => config; set => config = value; }
|
||||||
public static IModHelper? ModHelper { get => modHelper; }
|
public static IModHelper? ModHelper { get => modHelper; }
|
||||||
|
@ -62,6 +63,17 @@ namespace stardew_access
|
||||||
|
|
||||||
set => screenReader = value;
|
set => screenReader = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TileViewer TileViewer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (tileViewer == null)
|
||||||
|
tileViewer = new TileViewer();
|
||||||
|
return tileViewer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
|
@ -130,8 +142,8 @@ namespace stardew_access
|
||||||
// Narrate current location's name
|
// Narrate current location's name
|
||||||
Other.narrateCurrentLocation();
|
Other.narrateCurrentLocation();
|
||||||
|
|
||||||
if (Config.SnapMouse)
|
//handle TileCursor update logic
|
||||||
Other.SnapMouseToPlayer();
|
TileViewer.update();
|
||||||
|
|
||||||
if (!ReadTile.isReadingTile && Config.ReadTile)
|
if (!ReadTile.isReadingTile && Config.ReadTile)
|
||||||
{
|
{
|
||||||
|
@ -256,6 +268,9 @@ namespace stardew_access
|
||||||
ReadTile.run(manuallyTriggered: true);
|
ReadTile.run(manuallyTriggered: true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tile viewing cursor keys
|
||||||
|
TileViewer.HandleInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ErrorLog(string message)
|
public static void ErrorLog(string message)
|
||||||
|
|
Loading…
Reference in New Issue