Merge pull request #16 from bradjrenshaw/TileViewer

Tile viewer
master
Mohammad Shoaib 2022-05-11 13:00:04 +05:30 committed by GitHub
commit d27c7c749c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 258 additions and 29 deletions

View File

@ -41,32 +41,6 @@ namespace stardew_access.Features
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()
{
try

View File

@ -1,4 +1,4 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using StardewValley;
using StardewValley.Objects;

View File

@ -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;
}
}
}

View File

@ -25,7 +25,19 @@ namespace stardew_access
public KeybindList TimeNSeasonKey { get; set; } = KeybindList.Parse("Q");
public KeybindList ReadTileKey { get; set; } = KeybindList.Parse("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
// TODO Add the exclusion and focus list too

View File

@ -20,6 +20,7 @@ namespace stardew_access
private static StaticTiles? sTiles;
private static IScreenReader? screenReader;
private static IModHelper? modHelper;
private static TileViewer? tileViewer;
internal static ModConfig Config { get => config; set => config = value; }
public static IModHelper? ModHelper { get => modHelper; }
@ -62,6 +63,17 @@ namespace stardew_access
set => screenReader = value;
}
public static TileViewer TileViewer
{
get
{
if (tileViewer == null)
tileViewer = new TileViewer();
return tileViewer;
}
}
#endregion
/*********
@ -130,8 +142,8 @@ namespace stardew_access
// Narrate current location's name
Other.narrateCurrentLocation();
if (Config.SnapMouse)
Other.SnapMouseToPlayer();
//handle TileCursor update logic
TileViewer.update();
if (!ReadTile.isReadingTile && Config.ReadTile)
{
@ -256,6 +268,9 @@ namespace stardew_access
ReadTile.run(manuallyTriggered: true);
return;
}
// Tile viewing cursor keys
TileViewer.HandleInput();
}
public static void ErrorLog(string message)