using System; using System.Diagnostics.CodeAnalysis; namespace NHSE.Core; /// /// Basic configuration of a narrow view for interacting with the larger manipulatable tile grid. /// /// Viewable amount of viewable tiles wide /// Viewable amount of viewable tiles high /// Columns of view available /// Rows of view available public readonly record struct TileGridViewport([ConstantExpected] byte ViewWidth, [ConstantExpected] byte ViewHeight, byte Columns, byte Rows) { /// /// Total width of the entire grid (including the view). /// public int TotalWidth => Columns * ViewWidth; /// /// Total height of the entire grid (including the view). /// public int TotalHeight => Rows * ViewHeight; /// /// Amount of tiles present in the grid. /// public int ViewCount => ViewWidth * ViewHeight; /// /// Amount of ALL tiles present in the entire grid (including the grid). /// public int TotalCount => TotalWidth * TotalHeight; public int GetTileIndex(int acreX, int acreY, int gridX, int gridY) { var x = (acreX * ViewWidth) + gridX; var y = (acreY * ViewHeight) + gridY; return GetTileIndex(x, y); } /// /// Gets the absolute index of the absolute tile in the grid based on the x/y coordinates. /// /// Absolute x coordinate of the tile in the grid /// Absolute y coordinate of the tile in the grid /// Absolute index of the tile in the grid public int GetTileIndex(in int x, in int y) => (TotalHeight * x) + y; public void ClampInside(ref int x, ref int y) => ClampCoordinatesTo(ref x, ref y, TotalWidth - 1, TotalHeight - 1); private static void ClampCoordinatesTo(ref int x, ref int y, int maxX, int maxY) { x = Math.Clamp(x, 0, maxX); y = Math.Clamp(y, 0, maxY); } public void GetViewAnchorCoordinates(ref int x, ref int y, in bool centerReticle) { // If we aren't snapping the reticle to the nearest acre // we want to put the middle of the reticle rectangle where the cursor is. // Adjust the view coordinate if (!centerReticle) { // Reticle size is GridWidth, center = /2 x -= ViewWidth / 2; y -= ViewWidth / 2; } // Clamp to viewport dimensions, and center to nearest acre if desired. // Clamp to boundaries so that we always have a full grid to view. SetTopLeftNearest(ref x, ref y); } private void SetTopLeftNearest(ref int x, ref int y) { int maxX = TotalWidth - ViewWidth; int maxY = TotalHeight - ViewHeight; ClampCoordinatesTo(ref x, ref y, maxX, maxY); } }