From 0a80175810c90ebbbe6e91d3d78f0e696e7bd0bb Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 25 Jan 2026 11:53:10 -0600 Subject: [PATCH] Continued testing Items now render without error in the map view, and repositioning the view works. --- .../Map/Layers/LayerPositionConfig.cs | 20 +++++++++++ NHSE.Sprites/Field/ItemLayerSprite.cs | 31 +++++++++-------- NHSE.Sprites/Field/MapRenderer.cs | 26 ++++++++------ .../Subforms/Map/FieldItemEditor.Designer.cs | 34 +++++++++---------- NHSE.WinForms/Subforms/Map/FieldItemEditor.cs | 26 +++++++------- 5 files changed, 81 insertions(+), 56 deletions(-) diff --git a/NHSE.Core/Structures/Map/Layers/LayerPositionConfig.cs b/NHSE.Core/Structures/Map/Layers/LayerPositionConfig.cs index 3dda6bd..091fe74 100644 --- a/NHSE.Core/Structures/Map/Layers/LayerPositionConfig.cs +++ b/NHSE.Core/Structures/Map/Layers/LayerPositionConfig.cs @@ -97,4 +97,24 @@ public bool IsCoordinateValidAbsolute(int absX, int absY) var (relX, relY) = GetCoordinatesRelative(absX, absY); return IsCoordinateValidRelative(relX, relY); } + + /// + /// Layer total width in tiles. + /// + public int LayerTotalWidth => CountWidth * TilesPerAcre; + + /// + /// Layer total height in tiles. + /// + public int LayerTotalHeight => CountHeight * TilesPerAcre; + + /// + /// Gets the total width of the map, in tiles. + /// + public int MapTotalWidth => MapAcreWidth * TilesPerAcre; + + /// + /// Gets the total height of the map, in tiles. + /// + public int MapTotalHeight => MapAcreHeight * TilesPerAcre; } \ No newline at end of file diff --git a/NHSE.Sprites/Field/ItemLayerSprite.cs b/NHSE.Sprites/Field/ItemLayerSprite.cs index 773503c..13cb494 100644 --- a/NHSE.Sprites/Field/ItemLayerSprite.cs +++ b/NHSE.Sprites/Field/ItemLayerSprite.cs @@ -21,25 +21,26 @@ public static class ItemLayerSprite /// List of items from which color values are extracted. The span must contain at least width × height elements. /// Pixel data for the bitmap. The span must have a length of at least width × height. /// Configuration for layer positioning. - /// The number of columns in the bitmap. Must be greater than zero. - /// The number of rows in the bitmap. Must be greater than zero. - private static void LoadBitmapLayer(ReadOnlySpan items, Span bmpData, in LayerPositionConfig cfg, int imgWidth, int imgHeight) + private static void LoadBitmapLayer(ReadOnlySpan items, Span bmpData, in LayerPositionConfig cfg) { var (shiftX, shiftY) = cfg.GetCoordinatesAbsolute(0, 0); // Iterate through the relative positions within the layer. // Then, map to absolute positions in the bitmap with the configured shift. - for (int x = 0; x < imgWidth; x++) + var width = cfg.LayerTotalWidth; + var height = cfg.LayerTotalHeight; + var mapWidth = cfg.MapTotalWidth; // 1px scale + for (int relX = 0; relX < width; relX++) { - var ix = x * imgHeight; - for (int y = 0; y < imgHeight; y++) + var absX = relX + shiftX; + for (int relY = 0; relY < height; relY++) { // Get the tile at this position. - var index = ix + y; - var tile = items[index]; + var tile = items[relY + relX * height]; // Get the actual shifted position in the bitmap. - var offset = ((y + shiftY) * imgWidth) + (x + shiftX); + var absY = relY + shiftY; + var offset = (absY * mapWidth) + absX; // Write the color to the bitmap data. bmpData[offset] = FieldItemColor.GetItemColor(tile).ToArgb(); @@ -104,10 +105,10 @@ private static void LoadViewport(LayerItem layer, in LayerPositionConfig cfg, Sp for (int y = 0; y < height; y++) { var baseIndex = (y * width); + var tileY = relY + y; for (int x = 0; x < width; x++) { var tileX = relX + x; - var tileY = relY + y; if (!cfg.IsCoordinateValidRelative(tileX, tileY)) continue; var tile = layer.GetTile(tileX, tileY); @@ -133,8 +134,8 @@ private static void LoadViewport(LayerItem layer, in LayerPositionConfig cfg, Sp Span data, int absX, int absY, int imgWidth, int imgScale) { - var width = layer.TileInfo.ViewWidth; - var height = layer.TileInfo.ViewHeight; + var width = cfg.TilesPerAcre; + var height = cfg.TilesPerAcre; var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY); @@ -381,15 +382,15 @@ public static void DrawGrid(Span data, int imgWidth, int imgHeight, int gri } /// - /// Loads an item layer into a viewport bitmap, drawing a view reticle over it. + /// Loads an item layer into a viewport bitmap. /// /// Configuration for layer positioning. /// Item layer to draw from. /// Pixel data of the final image. /// Optional transparency override color. - public static void LoadItemLayerDrawReticle(LayerPositionConfig cfg, LayerItem layer, Span data, int transparency = -1) + public static void LoadItemLayer1(LayerPositionConfig cfg, LayerItem layer, Span data, int transparency = -1) { - LoadBitmapLayer(layer.Tiles, data, cfg, layer.TileInfo.TotalWidth, layer.TileInfo.TotalHeight); + LoadBitmapLayer(layer.Tiles, data, cfg); if (transparency >>> 24 != 0xFF) ImageUtil.ClampAllTransparencyTo(data, transparency); } diff --git a/NHSE.Sprites/Field/MapRenderer.cs b/NHSE.Sprites/Field/MapRenderer.cs index d6b0bb8..9c539d3 100644 --- a/NHSE.Sprites/Field/MapRenderer.cs +++ b/NHSE.Sprites/Field/MapRenderer.cs @@ -53,23 +53,27 @@ public MapRenderer(MapEditor m) Map = m; // Initialize cached objects based on map size - // Get tile info from layer 0 (item layer is the tiniest cell we can render) - var l1 = m.Mutator.Manager.FieldItems.Layer0; - var info = l1.TileInfo; - - MapItemsReticleX = new int[info.TotalWidth * info.TotalHeight * MapScale * MapScale]; - MapItemsReticleImage = new Bitmap(info.TotalWidth * MapScale, info.TotalHeight * MapScale); + // Get tile info from item layer, it's the tiniest cell we can render + var cfg = m.Mutator.Manager.ConfigItems; + var mapW = cfg.MapTotalWidth * MapScale; + var mapH = cfg.MapTotalHeight * MapScale; + MapItemsReticleImage = new Bitmap(mapW, mapH); + MapItemsReticleX = new int[mapW * mapH]; MapTerrain1 = new int[MapItemsReticleX.Length / (MapScale * MapScale)]; MapTerrainX = new int[MapItemsReticleX.Length]; MapTerrainImage = new Bitmap(MapItemsReticleImage.Width, MapItemsReticleImage.Height); - ViewportItems1 = new int[info.ViewWidth * info.ViewHeight]; + // Render a single acre viewport + var tpa = cfg.TilesPerAcre; + ViewportItems1 = new int[tpa * tpa]; ViewportItemsX = new int[ViewportItems1.Length * ViewScale * ViewScale]; - ViewportItemsImage = new Bitmap(info.ViewWidth * ViewScale, info.ViewHeight * ViewScale); + ViewportItemsImage = new Bitmap(tpa * ViewScale, tpa * ViewScale); - ViewportTerrain1 = new int[16*16 * 16*16]; // each terrain tile is drawn as 16px, then we upscale - ViewportTerrainX = new int[ViewportItemsX.Length]; // 2x upscale + const byte pixelsPerTerrainTile = 16; + var dimTerrain = cfg.TilesPerAcre * pixelsPerTerrainTile; + ViewportTerrain1 = new int[dimTerrain * dimTerrain]; // each terrain tile is drawn as 16px, then we upscale + ViewportTerrainX = new int[ViewportItemsX.Length]; // 2x upscale (16px -> 32px) ViewportTerrainImage = new Bitmap(ViewportItemsImage.Width, ViewportItemsImage.Height); } @@ -123,7 +127,7 @@ public Bitmap UpdateViewportTerrain(Font f, byte transparencyBuilding, byte tran private Bitmap UpdateMapItemsReticle(LayerFieldItem layer, int absX, int absY, int transparency, bool drawReticle = true) { var cfg = Map.Mutator.Manager.ConfigItems; - ItemLayerSprite.LoadItemLayerDrawReticle(cfg, layer, MapItemsReticleX, transparency); + ItemLayerSprite.LoadItemLayer1(cfg, layer, MapItemsReticleX, transparency); MapItemsReticleImage.SetBitmapData(MapItemsReticleX); if (drawReticle) ItemLayerSprite.DrawViewReticle(MapItemsReticleImage, layer.TileInfo, absX, absY); diff --git a/NHSE.WinForms/Subforms/Map/FieldItemEditor.Designer.cs b/NHSE.WinForms/Subforms/Map/FieldItemEditor.Designer.cs index 666266d..2f1b5f8 100644 --- a/NHSE.WinForms/Subforms/Map/FieldItemEditor.Designer.cs +++ b/NHSE.WinForms/Subforms/Map/FieldItemEditor.Designer.cs @@ -48,7 +48,7 @@ private void InitializeComponent() NUD_Layer = new System.Windows.Forms.NumericUpDown(); L_Layer = new System.Windows.Forms.Label(); TT_Hover = new System.Windows.Forms.ToolTip(components); - PB_Acre = new System.Windows.Forms.PictureBox(); + PB_Viewport = new System.Windows.Forms.PictureBox(); TR_Transparency = new System.Windows.Forms.TrackBar(); CHK_NoOverwrite = new System.Windows.Forms.CheckBox(); CHK_AutoExtension = new System.Windows.Forms.CheckBox(); @@ -155,7 +155,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)PB_Map).BeginInit(); CM_Picture.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)NUD_Layer).BeginInit(); - ((System.ComponentModel.ISupportInitialize)PB_Acre).BeginInit(); + ((System.ComponentModel.ISupportInitialize)PB_Viewport).BeginInit(); ((System.ComponentModel.ISupportInitialize)TR_Transparency).BeginInit(); CM_Remove.SuspendLayout(); TC_Editor.SuspendLayout(); @@ -384,18 +384,18 @@ private void InitializeComponent() // // PB_Acre // - PB_Acre.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - PB_Acre.ContextMenuStrip = CM_Click; - PB_Acre.Location = new System.Drawing.Point(14, 16); - PB_Acre.Margin = new System.Windows.Forms.Padding(4); - PB_Acre.Name = "PB_Acre"; - PB_Acre.Size = new System.Drawing.Size(514, 514); - PB_Acre.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; - PB_Acre.TabIndex = 28; - PB_Acre.TabStop = false; - PB_Acre.MouseClick += PB_Acre_MouseClick; - PB_Acre.MouseDown += PB_Acre_MouseDown; - PB_Acre.MouseMove += PB_Acre_MouseMove; + PB_Viewport.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + PB_Viewport.ContextMenuStrip = CM_Click; + PB_Viewport.Location = new System.Drawing.Point(14, 16); + PB_Viewport.Margin = new System.Windows.Forms.Padding(4); + PB_Viewport.Name = "PB_Viewport"; + PB_Viewport.Size = new System.Drawing.Size(514, 514); + PB_Viewport.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; + PB_Viewport.TabIndex = 28; + PB_Viewport.TabStop = false; + PB_Viewport.MouseClick += ViewportMouseClick; + PB_Viewport.MouseDown += ViewportMouseDown; + PB_Viewport.MouseMove += ViewportMouseMove; // // TR_Transparency // @@ -1409,7 +1409,7 @@ private void InitializeComponent() Controls.Add(RB_Terrain); Controls.Add(RB_Item); Controls.Add(TC_Editor); - Controls.Add(PB_Acre); + Controls.Add(PB_Viewport); Controls.Add(L_Layer); Controls.Add(NUD_Layer); Controls.Add(L_Coordinates); @@ -1434,7 +1434,7 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)PB_Map).EndInit(); CM_Picture.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)NUD_Layer).EndInit(); - ((System.ComponentModel.ISupportInitialize)PB_Acre).EndInit(); + ((System.ComponentModel.ISupportInitialize)PB_Viewport).EndInit(); ((System.ComponentModel.ISupportInitialize)TR_Transparency).EndInit(); CM_Remove.ResumeLayout(false); TC_Editor.ResumeLayout(false); @@ -1490,7 +1490,7 @@ private void InitializeComponent() private System.Windows.Forms.NumericUpDown NUD_Layer; private System.Windows.Forms.Label L_Layer; private System.Windows.Forms.ToolTip TT_Hover; - private System.Windows.Forms.PictureBox PB_Acre; + private System.Windows.Forms.PictureBox PB_Viewport; private System.Windows.Forms.TrackBar TR_Transparency; private System.Windows.Forms.CheckBox CHK_NoOverwrite; private System.Windows.Forms.CheckBox CHK_AutoExtension; diff --git a/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs b/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs index 6b1c94c..a5d6878 100644 --- a/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs +++ b/NHSE.WinForms/Subforms/Map/FieldItemEditor.cs @@ -52,10 +52,10 @@ public FieldItemEditor(MainSave sav) this.TranslateInterface(GameInfo.CurrentLanguage); // Read the expected scale from the control. - var scale = (PB_Acre.Width - 2) / LayerFieldItem.TilesPerAcreDim; // 1px border + var scale = (PB_Viewport.Width - 2) / LayerFieldItem.TilesPerAcreDim; // 1px border SAV = sav; Editor = MapEditor.FromSaveFile(sav); - Editor.MapScale = scale; + Editor.MapScale = 1; Editor.ViewScale = scale; Renderer = new MapRenderer(Editor); @@ -128,7 +128,7 @@ private void ChangeViewToAcre(int acre) private void LoadItemGridAcre() { ReloadItems(); - ReloadAcreBackground(); + ReloadViewportBackground(); UpdateArrowVisibility(); } @@ -153,26 +153,26 @@ private void SetMapForegroundImage(Bitmap img) PB_Map.Image = img; } - private void ReloadAcreBackground() + private void ReloadViewportBackground() { var tbuild = (byte)TR_BuildingTransparency.Value; var tterrain = (byte)TR_Terrain.Value; var img = Renderer.UpdateViewportTerrain(L_Coordinates.Font, tbuild, tterrain, SelectedBuildingIndex); - PB_Acre.BackgroundImage = img; - PB_Acre.Invalidate(); // background image reassigning to same img doesn't redraw; force it + PB_Viewport.BackgroundImage = img; + PB_Viewport.Invalidate(); // background image reassigning to same img doesn't redraw; force it } - private void ReloadAcreItemGrid() => PB_Acre.Image = Renderer.UpdateViewportItems(GetItemTransparency()); + private void ReloadViewportItems() => PB_Viewport.Image = Renderer.UpdateViewportItems(GetItemTransparency()); public void ReloadItems() { - ReloadAcreItemGrid(); + ReloadViewportItems(); ReloadMapItemGrid(); } private void ReloadBuildingsTerrain() { - ReloadAcreBackground(); + ReloadViewportBackground(); ReloadMapBackground(); } @@ -184,7 +184,7 @@ private void UpdateArrowVisibility() B_Right.Enabled = View.CanRight; } - private void PB_Acre_MouseClick(object sender, MouseEventArgs e) + private void ViewportMouseClick(object sender, MouseEventArgs e) { if (IsDragOperationActive) { @@ -370,9 +370,9 @@ private void UpdateHoveredCoordinates(MouseEventArgs e) HoverY &= 0x1F; } - private void PB_Acre_MouseDown(object sender, MouseEventArgs e) => ResetDrag(); + private void ViewportMouseDown(object sender, MouseEventArgs e) => ResetDrag(); - private void PB_Acre_MouseMove(object sender, MouseEventArgs e) + private void ViewportMouseMove(object sender, MouseEventArgs e) { var l = CurrentLayer; if (e.Button == MouseButtons.Left && CHK_MoveOnDrag.Checked) @@ -409,7 +409,7 @@ private void PB_Acre_MouseMove(object sender, MouseEventArgs e) var isActive = flagLayer.GetIsActive(x, y); if (isActive) name = $"{name} [Active]"; - TT_Hover.SetToolTip(PB_Acre, name); + TT_Hover.SetToolTip(PB_Viewport, name); SetCoordinateText(x, y); }