Minor clean

This commit is contained in:
Kurt 2026-01-25 16:48:12 -06:00
parent 056514aef9
commit 3b56ea35e3
5 changed files with 108 additions and 47 deletions

View File

@ -62,6 +62,11 @@ namespace NHSE.Core;
#pragma warning restore CA1857
}
/// <summary>
/// Calculates the absolute map coordinates based on the specified relative X and Y coordinates within the layer.
/// </summary>
/// <param name="relX">The relative X-coordinate within the layer.</param>
/// <param name="relY">The relative Y-coordinate within the layer.</param>
public (int X, int Y) GetCoordinatesAbsolute(int relX, int relY)
{
var absX = relX + ((ShiftWidth * MetaTileSize) << TileBitShift);
@ -69,6 +74,17 @@ namespace NHSE.Core;
return (absX, absY);
}
/// <summary>
/// Gets the absolute coordinates of the layer's origin (0,0) in the map.
/// </summary>
public (int X, int Y) GetCoordinatesAbsolute() => GetCoordinatesAbsolute(0, 0);
/// <summary>
/// Calculates the relative coordinates within the layer, based on the specified absolute X and Y coordinates.
/// </summary>
/// <param name="absX">The absolute X coordinate to convert.</param>
/// <param name="absY">The absolute Y coordinate to convert.</param>
/// <returns>A tuple containing the X and Y coordinates relative to the layer.</returns>
public (int X, int Y) GetCoordinatesRelative(int absX, int absY)
{
var relX = absX - ((ShiftWidth * MetaTileSize) << TileBitShift);
@ -91,12 +107,6 @@ public bool IsCoordinateValidRelative(int relX, int relY)
return true;
}
public bool IsCoordinateValidAbsolute(int absX, int absY)
{
var (relX, relY) = GetCoordinatesRelative(absX, absY);
return IsCoordinateValidRelative(relX, relY);
}
/// <summary>
/// Layer total width in tiles.
/// </summary>
@ -116,11 +126,4 @@ public bool IsCoordinateValidAbsolute(int absX, int absY)
/// Gets the total height of the map, in tiles.
/// </summary>
public int MapTotalHeight => MapAcreHeight * TilesPerAcre;
public int GetAcreIndexRelative(int relX, int relY)
{
var acreX = relX >> TileBitShift;
var acreY = relY >> TileBitShift;
return (CountHeight * acreX) + acreY;
}
}

View File

@ -38,11 +38,10 @@ public int ModifyFieldItems(Func<int, int, int, int, int> action, in bool wholeM
}
else
{
(xMin, yMin) = (View.X, View.Y);
// Convert absolute to relative coordinates
if (!Manager.ConfigItems.IsCoordinateValidAbsolute(xMin, yMin))
(xMin, yMin) = Manager.ConfigItems.GetCoordinatesRelative(View.X, View.Y);
if (!Manager.ConfigItems.IsCoordinateValidRelative(xMin, yMin))
return 0;
(xMin, yMin) = Manager.ConfigItems.GetCoordinatesRelative(xMin, yMin);
var info = layerField.TileInfo;
(width, height) = info.DimAcre;
@ -69,11 +68,10 @@ private int ReplaceFieldItems(Item oldItem, Item newItem, bool wholeMap, LayerFi
}
else
{
(xMin, yMin) = (View.X, View.Y);
// Convert absolute to relative coordinates
if (!Manager.ConfigItems.IsCoordinateValidAbsolute(xMin, yMin))
(xMin, yMin) = Manager.ConfigItems.GetCoordinatesRelative(View.X, View.Y);
if (!Manager.ConfigItems.IsCoordinateValidRelative(xMin, yMin))
return 0;
(xMin, yMin) = Manager.ConfigItems.GetCoordinatesRelative(xMin, yMin);
var info = layerField.TileInfo;
(width, height) = info.DimAcre;

View File

@ -23,7 +23,7 @@ public static class ItemLayerSprite
/// <param name="cfg">Configuration for layer positioning.</param>
private static void LoadBitmapLayer(ReadOnlySpan<Item> items, Span<int> bmpData, in LayerPositionConfig cfg)
{
var (shiftX, shiftY) = cfg.GetCoordinatesAbsolute(0, 0);
var (shiftX, shiftY) = cfg.GetCoordinatesAbsolute();
// Iterate through the relative positions within the layer.
// Then, map to absolute positions in the bitmap with the configured shift.
@ -395,6 +395,14 @@ public static void LoadItemLayer1(LayerPositionConfig cfg, LayerItem layer, Span
ImageUtil.ClampAllTransparencyTo(data, transparency);
}
/// <summary>
/// Draws a square reticle on the specified map image to indicate the current viewport area.
/// </summary>
/// <param name="map">The bitmap image on which to draw the reticle.</param>
/// <param name="g">The viewport describing the area of the map present within the viewport.</param>
/// <param name="absX">The absolute X-coordinate, in tile units, of the top-left corner of the viewport.</param>
/// <param name="absY">The absolute Y-coordinate, in tile units, of the top-left corner of the viewport.</param>
/// <param name="scale">The image upscale scale factor to apply to the reticle's size and position. Must be a positive integer. The default is 1.</param>
public static void DrawViewReticle(Bitmap map, TileGridViewport g, int absX, int absY, int scale = 1)
{
using var gfx = Graphics.FromImage(map);

View File

@ -32,7 +32,15 @@ public static class TerrainSprite
private const int PlazaWidth = 6 * Scale;
private const int PlazaHeight = 5 * Scale;
public static void GenerateMap(Bitmap map, MapMutator mut, Span<int> scale1, Span<int> scaleX, int imgScale)
/// <summary>
/// Generates a terrain map by loading, scaling, and applying terrain data to the specified bitmap.
/// </summary>
/// <param name="map">The bitmap to which the generated terrain map will be applied.</param>
/// <param name="mut">The map information manager that provides access to terrain configuration and management.</param>
/// <param name="scale1">A span of integers used as a buffer for the initial terrain pixel data.</param>
/// <param name="scaleX">A span of integers used as a buffer for the upscaled terrain pixel data.</param>
/// <param name="imgScale">The scaling factor to apply when upscaling the terrain image. Must be a positive integer.</param>
private static void GenerateMapTerrainAndUpscale(Bitmap map, MapMutator mut, Span<int> scale1, Span<int> scaleX, int imgScale)
{
// Load the terrain pixels, then upscale.
var mgr = mut.Manager.LayerTerrain;
@ -41,10 +49,29 @@ public static void GenerateMap(Bitmap map, MapMutator mut, Span<int> scale1, Spa
map.SetBitmapData(scaleX);
}
/// <summary>
/// Draws the map with all buildings and the plaza overlay onto the specified bitmap, using the provided map editor
/// and scaling information.
/// </summary>
/// <remarks>
/// The method modifies the provided bitmap in place.
/// The scaling spans must be properly initialized to match the expected map dimensions.
/// If a specific building index is provided, only that building may be highlighted or rendered differently;
/// otherwise, all buildings are drawn normally.
/// </remarks>
/// <param name="map">The bitmap on which the map, buildings, and plaza will be rendered.</param>
/// <param name="m">The map editor instance containing map data, building information, and scaling parameters.</param>
/// <param name="scale1">A span representing the primary scaling factors for rendering the map.</param>
/// <param name="scaleX">A span representing the secondary scaling factors for rendering the map.</param>
/// <param name="buildingIndex">
/// The index of a specific building to highlight or focus on.
/// Set to -1 to render all buildings without highlighting any particular one.
/// </param>
/// <returns>The bitmap with the map, plaza, and buildings drawn onto it. The same instance as the input bitmap is returned.</returns>
public static Bitmap GetMapWithBuildings(Bitmap map, MapEditor m, Span<int> scale1, Span<int> scaleX, int buildingIndex = -1)
{
var imgScale = m.MapScale * 2; // because terrain is 16px per tile, items are 32px per tile
GenerateMap(map, m.Mutator, scale1, scaleX, imgScale);
GenerateMapTerrainAndUpscale(map, m.Mutator, scale1, scaleX, imgScale);
using var gfx = Graphics.FromImage(map);
var plaza = m.Mutator.Manager.Plaza;
@ -53,6 +80,31 @@ public static Bitmap GetMapWithBuildings(Bitmap map, MapEditor m, Span<int> scal
return map;
}
/// <summary>
/// Renders the current map viewport onto the specified bitmap, including terrain, buildings, grid overlays, and labels.
/// </summary>
/// <remarks>
/// This method draws both graphical and textual elements of the map viewport, including overlays and labels.
/// It should be called whenever the viewport needs to be refreshed, such as after map edits or navigation.
/// The method modifies the provided bitmap in place.
/// </remarks>
/// <param name="img">The bitmap onto which the viewport will be drawn.</param>
/// <param name="m">The map editor instance providing map data, building information, and viewport configuration.</param>
/// <param name="f">The font used to render building and terrain tile names within the viewport.</param>
/// <param name="scale1">A span representing the primary scaling factors for rendering terrain pixels.</param>
/// <param name="scaleX">A span used for horizontal scaling and pixel data manipulation during rendering.</param>
/// <param name="selectedBuildingIndex">
/// The index of the currently selected building.
/// Used to highlight or annotate the selected building in the viewport.
/// </param>
/// <param name="transparencyBuilding">
/// The transparency level to apply when rendering buildings.
/// A value of 0xFF is fully opaque; lower values increase transparency.
/// </param>
/// <param name="transTerrain">
/// The transparency level to apply when rendering terrain tile names.
/// A value of 0xFF is fully opaque; lower values increase transparency.
/// </param>
public static void LoadViewport(Bitmap img, MapEditor m, Font f,
Span<int> scale1, Span<int> scaleX,
int selectedBuildingIndex, byte transparencyBuilding, byte transTerrain)
@ -99,7 +151,7 @@ public static Bitmap GetMapWithBuildings(Bitmap map, MapEditor m, Span<int> scal
// Draw Text of Terrain Tile Names
if (transTerrain != 0)
DrawViewTerrainTileNames(gfx, m.Terrain, cfg, f, relX, relY, m.ViewScale * 2, transTerrain);
gfx.DrawViewTerrainTileNames(m.Terrain, cfg, f, relX, relY, m.ViewScale * 2, transTerrain);
// Done.
}
@ -124,7 +176,7 @@ private static void DrawViewBuildings(this Graphics gfx, MapEditor m, int select
private static void LoadTerrainPixels(LayerTerrain mgr, LayerPositionConfig cfg, Span<int> pixels)
{
var (shiftX, shiftY) = cfg.GetCoordinatesAbsolute(0, 0);
var (shiftX, shiftY) = cfg.GetCoordinatesAbsolute();
// Iterate through the relative positions within the layer.
// Then, map to absolute positions in the bitmap with the configured shift.
@ -238,7 +290,7 @@ private static void GetViewTerrain1(LayerTerrain t, LayerPositionConfig cfg, int
}
}
private static void DrawViewTerrainTileNames(Graphics gfx, LayerTerrain t, LayerPositionConfig cfg, Font f,
private static void DrawViewTerrainTileNames(this Graphics gfx, LayerTerrain t, LayerPositionConfig cfg, Font f,
int relX, int relY, int scale, byte transparency)
{
var pen = Tile;

View File

@ -328,15 +328,15 @@ private bool GetTile(MouseEventArgs e, LayerFieldItem layerField, [NotNullWhen(t
private bool GetTile(LayerFieldItem layerField, int absX, int absY, [NotNullWhen(true)] out TileCheck<Item>? item)
{
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
item = null;
return false;
}
var rel = cfg.GetCoordinatesRelative(absX, absY);
var tile = layerField.GetTile(rel.X, rel.Y);
item = new TileCheck<Item>(tile, absX, absY, rel.X, rel.Y);
var tile = layerField.GetTile(relX, relY);
item = new TileCheck<Item>(tile, absX, absY, relX, relY);
return true;
}
@ -350,15 +350,15 @@ private bool GetTile(MouseEventArgs e, LayerTerrain layerField, [NotNullWhen(tru
private bool GetTile(LayerTerrain layerField, int absX, int absY, [NotNullWhen(true)] out TileCheck<TerrainTile>? item)
{
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
item = null;
return false;
}
var rel = cfg.GetCoordinatesRelative(absX, absY);
var tile = layerField.GetTile(rel.X, rel.Y);
item = new TileCheck<TerrainTile>(tile, absX, absY, rel.X, rel.Y);
var tile = layerField.GetTile(relX, relY);
item = new TileCheck<TerrainTile>(tile, absX, absY, relX, relY);
return true;
}
@ -644,13 +644,13 @@ private void Menu_View_Click(object sender, EventArgs e)
{
var (absX, absY) = GetAbsoluteCoordinatesHover();
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
System.Media.SystemSounds.Asterisk.Play();
return;
}
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (RB_Item.Checked)
{
var tile = CurrentLayer.GetTile(relX, relY);
@ -669,12 +669,12 @@ private void Menu_Set_Click(object sender, EventArgs e)
{
var (absX, absY) = GetAbsoluteCoordinatesHover();
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
System.Media.SystemSounds.Asterisk.Play();
return;
}
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
var tile = CurrentLayer.GetTile(relX, relY);
SetTile(tile, relX, relY);
@ -683,13 +683,13 @@ private void Menu_Set_Click(object sender, EventArgs e)
{
var (absX, absY) = GetAbsoluteCoordinatesHoverTerrain();
var cfg = Editor.Mutator.Manager.ConfigTerrain;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
System.Media.SystemSounds.Asterisk.Play();
return;
}
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
var tile = Editor.Terrain.GetTile(relX, relY);
SetTile(tile);
}
@ -701,12 +701,12 @@ private void Menu_Reset_Click(object sender, EventArgs e)
{
var (absX, absY) = GetAbsoluteCoordinatesHover();
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
System.Media.SystemSounds.Asterisk.Play();
return;
}
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
var tile = CurrentLayer.GetTile(relX, relY);
DeleteTile(tile, relX, relY);
@ -715,13 +715,13 @@ private void Menu_Reset_Click(object sender, EventArgs e)
{
var (absX, absY) = GetAbsoluteCoordinatesHoverTerrain();
var cfg = Editor.Mutator.Manager.ConfigTerrain;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
System.Media.SystemSounds.Asterisk.Play();
return;
}
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
var tile = Editor.Terrain.GetTile(relX, relY);
DeleteTile(tile);
}
@ -739,10 +739,10 @@ private void CM_Click_Opening(object sender, System.ComponentModel.CancelEventAr
var (absX, absY) = GetAbsoluteCoordinatesHover();
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
return;
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
var flagLayer = NUD_Layer.Value == 0 ? Map.LayerItemFlag0 : Map.LayerItemFlag1;
var isActive = flagLayer.GetIsActive(relX, relY);
Menu_Activate.Text = isActive ? "Inactivate" : "Activate";
@ -754,10 +754,10 @@ private void Menu_Activate_Click(object sender, EventArgs e)
{
var (absX, absY) = GetAbsoluteCoordinatesHover();
var cfg = Editor.Mutator.Manager.ConfigItems;
if (!cfg.IsCoordinateValidAbsolute(absX, absY))
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
return;
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
var flagLayer = NUD_Layer.Value == 0 ? Map.LayerItemFlag0 : Map.LayerItemFlag1;
var isActive = flagLayer.GetIsActive(relX, relY);
flagLayer.SetIsActive(relX, relY, !isActive);