Fix terrain brush popup

Closes #729
1. Dark mode now applied correctly (was previously lacking)
2. Fixed terrain brush action (brush active is higher priority than drag, fix tile fetch)
3. Fixed writing of Building/structure labels; apply after Terrain
4. Single terrain brush form allowed, center to Field Editor on launch

Somewhat related: fix Show() load for non-ShowDialog() forms to center to parent.
This commit is contained in:
Kurt
2026-01-30 22:55:26 -06:00
parent 5c51055a4c
commit e6f45d1805
11 changed files with 170 additions and 316 deletions

View File

@@ -114,9 +114,9 @@ private void InitializeComponent()
FLP_Transparency = new System.Windows.Forms.FlowLayoutPanel();
L_TerrainTileLabelTransparency = new System.Windows.Forms.Label();
TR_Terrain = new System.Windows.Forms.TrackBar();
TR_BuildingTransparency = new System.Windows.Forms.TrackBar();
L_BuildingTransparency = new System.Windows.Forms.Label();
L_FieldItemTransparency = new System.Windows.Forms.Label();
L_BuildingTransparency = new System.Windows.Forms.Label();
TR_BuildingTransparency = new System.Windows.Forms.TrackBar();
B_TerrainBrush = new System.Windows.Forms.Button();
PG_TerrainTile = new System.Windows.Forms.PropertyGrid();
B_DumpLoadTerrain = new System.Windows.Forms.Button();
@@ -1073,6 +1073,28 @@ private void InitializeComponent()
TR_Terrain.TickFrequency = 32;
TR_Terrain.Scroll += TR_Terrain_Scroll;
//
// L_FieldItemTransparency
//
L_FieldItemTransparency.AutoSize = true;
FLP_Transparency.SetFlowBreak(L_FieldItemTransparency, true);
L_FieldItemTransparency.Location = new System.Drawing.Point(4, 49);
L_FieldItemTransparency.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
L_FieldItemTransparency.Name = "L_FieldItemTransparency";
L_FieldItemTransparency.Size = new System.Drawing.Size(145, 17);
L_FieldItemTransparency.TabIndex = 42;
L_FieldItemTransparency.Text = "Field Item Transparency";
//
// L_BuildingTransparency
//
L_BuildingTransparency.AutoSize = true;
FLP_Transparency.SetFlowBreak(L_BuildingTransparency, true);
L_BuildingTransparency.Location = new System.Drawing.Point(4, 98);
L_BuildingTransparency.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
L_BuildingTransparency.Name = "L_BuildingTransparency";
L_BuildingTransparency.Size = new System.Drawing.Size(135, 17);
L_BuildingTransparency.TabIndex = 44;
L_BuildingTransparency.Text = "Building Transparency";
//
// TR_BuildingTransparency
//
TR_BuildingTransparency.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
@@ -1088,28 +1110,6 @@ private void InitializeComponent()
TR_BuildingTransparency.Value = 255;
TR_BuildingTransparency.Scroll += TR_BuildingTransparency_Scroll;
//
// L_BuildingTransparency
//
L_BuildingTransparency.AutoSize = true;
FLP_Transparency.SetFlowBreak(L_BuildingTransparency, true);
L_BuildingTransparency.Location = new System.Drawing.Point(4, 98);
L_BuildingTransparency.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
L_BuildingTransparency.Name = "L_BuildingTransparency";
L_BuildingTransparency.Size = new System.Drawing.Size(135, 17);
L_BuildingTransparency.TabIndex = 44;
L_BuildingTransparency.Text = "Building Transparency";
//
// L_FieldItemTransparency
//
L_FieldItemTransparency.AutoSize = true;
FLP_Transparency.SetFlowBreak(L_FieldItemTransparency, true);
L_FieldItemTransparency.Location = new System.Drawing.Point(4, 49);
L_FieldItemTransparency.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
L_FieldItemTransparency.Name = "L_FieldItemTransparency";
L_FieldItemTransparency.Size = new System.Drawing.Size(145, 17);
L_FieldItemTransparency.TabIndex = 42;
L_FieldItemTransparency.Text = "Field Item Transparency";
//
// B_TerrainBrush
//
B_TerrainBrush.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;

View File

@@ -1,4 +1,8 @@
using System;
using NHSE.Core;
using NHSE.Sprites;
using NHSE.WinForms.Subforms.Map;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
@@ -6,9 +10,6 @@
using System.IO;
using System.Linq;
using System.Windows.Forms;
using NHSE.Core;
using NHSE.Sprites;
using NHSE.WinForms.Subforms.Map;
namespace NHSE.WinForms;
@@ -237,16 +238,23 @@ private void OmniTileTerrain(MouseEventArgs e)
List<TerrainTile> selectedTiles = [];
int radius = tbeForm.Slider_thickness.Value;
int threshold = (radius * radius) / 2;
var cfg = Editor.Mutator.Manager.ConfigTerrain;
for (int i = -radius; i < radius; i++)
{
for (int j = -radius; j < radius; j++)
{
if ((i * i) + (j * j) < threshold)
selectedTiles.Add(Editor.Terrain.GetTile(relX + i, relY + j));
{
var x = relX + i;
var y = relY + j;
if (cfg.IsCoordinateValidRelative(x, y))
selectedTiles.Add(Editor.Terrain.GetTile(x, y));
}
}
}
SetTiles(selectedTiles);
if (selectedTiles.Count != 0)
SetTiles(selectedTiles);
}
private void OmniTile(Item tile, int relX, int relY)
@@ -349,7 +357,7 @@ 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;
var cfg = Editor.Mutator.Manager.ConfigTerrain;
var (relX, relY) = cfg.GetCoordinatesRelative(absX, absY);
if (!cfg.IsCoordinateValidRelative(relX, relY))
{
@@ -375,17 +383,21 @@ private void UpdateHoveredCoordinates(MouseEventArgs e)
private void ViewportMouseMove(object sender, MouseEventArgs e)
{
var l = CurrentLayer;
if (e.Button == MouseButtons.Left && CHK_MoveOnDrag.Checked)
if (e.Button == MouseButtons.Left)
{
MoveDrag(e);
return;
}
if (e.Button == MouseButtons.Left && tbeForm?.IsBrushSelected == true)
{
OmniTileTerrain(e);
if (tbeForm?.IsBrushSelected == true)
{
OmniTileTerrain(e);
return;
}
if (CHK_MoveOnDrag.Checked)
{
MoveDrag(e);
return;
}
}
var l = CurrentLayer;
// Update hover tooltip if it is a different tile
// Can't compare coordinates if redirection of extension tiles hijacks to return the root tile.
// Just check the (root) tile returns for each.
@@ -1260,14 +1272,13 @@ private void Menu_Bulk_Click(object sender, EventArgs e)
private void B_TerrainBrush_Click(object sender, EventArgs e)
{
tbeForm = new TerrainBrushEditor(PG_TerrainTile, this);
tbeForm.Show();
if (tbeForm is null || tbeForm.IsDisposed)
tbeForm = new TerrainBrushEditor(PG_TerrainTile, this);
tbeForm.Show(this);
tbeForm.BringToFront();
}
private void FieldItemEditor_FormClosed(object sender, FormClosedEventArgs e)
{
tbeForm?.Close();
}
private void FieldItemEditor_FormClosed(object sender, FormClosedEventArgs e) => tbeForm?.Close();
}
public interface IItemLayerEditor

View File

@@ -1,6 +1,7 @@
using NHSE.Core;
using System;
using System.Windows.Forms;
using static NHSE.Core.TerrainUnitModel;
namespace NHSE.WinForms.Subforms.Map;
@@ -20,265 +21,84 @@ public TerrainBrushEditor(PropertyGrid pG_TerrainTile, FieldItemEditor fieWindow
PG_TerrainTile = pG_TerrainTile;
FIEWindow = fieWindow;
InitializeComponent();
this.TranslateInterface(GameInfo.CurrentLanguage);
}
protected override void OnLoad(EventArgs e)
{
CenterToParent();
base.OnLoad(e);
}
#region Tiles buttons
#region Dirt tiles
private void NW_Rounded_Tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3B,
LandMakingAngle = 0,
Elevation = (ushort)slider_elevation.Value,
};
private void NW_Rounded_Tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3B);
private void N_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff5B, 3);
private void NE_rounded_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3B, 3);
private void W_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff5B);
private void Middle_tile_Click(object sender, EventArgs e) => SelectTerrainTile();
private void E_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff5B, 2);
private void SW_rounded_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3B, 1);
private void S_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff5B, 1);
private void SE_rounded_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3B, 2);
private void NW_angular_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3C);
private void NE_angular_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3C, 3);
private void SW_angular_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3C, 1);
private void SE_angular_tile_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff3C, 2);
private void N_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff5B,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void NE_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3B,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void W_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff5B,
LandMakingAngle = 0,
Elevation = (ushort)slider_elevation.Value,
};
private void Middle_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
Elevation = (ushort)slider_elevation.Value,
};
private void E_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff5B,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void SW_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3B,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void S_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff5B,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void SE_rounded_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3B,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void NW_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3C,
Elevation = (ushort)slider_elevation.Value,
};
private void NE_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3C,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void SW_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3C,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void SE_angular_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff3C,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void TR_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff7A,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void DL_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff7A,
Elevation = (ushort)slider_elevation.Value,
};
private void DR_dirt_inside_Click(object sender, EventArgs e)
{
PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff7A,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
}
private void TR_dirt_inside_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff7A, 2);
private void DL_dirt_inside_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff7A);
private void DR_dirt_inside_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff7A, 1);
#endregion Dirt tiles
#region Water tiles
private void NW_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3B,
Elevation = (ushort)slider_elevation.Value,
};
private void N_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River5B,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void NE_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3B,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void W_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River5B,
Elevation = (ushort)slider_elevation.Value,
};
private void Center_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River8A,
Elevation = (ushort)slider_elevation.Value,
};
private void e_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River5B,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void sw_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3B,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void s_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River5B,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void SE_diagonal_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3B,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void NW_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3C,
Elevation = (ushort)slider_elevation.Value,
};
private void NE_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3C,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void SW_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3C,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void SE_angular_water_tile_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River3C,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void TL_dirt_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.Cliff7A,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void TL_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River7A,
LandMakingAngle = 3,
Elevation = (ushort)slider_elevation.Value,
};
private void TR_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River7A,
LandMakingAngle = 2,
Elevation = (ushort)slider_elevation.Value,
};
private void DL_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River7A,
Elevation = (ushort)slider_elevation.Value,
};
private void DR_water_inside_Click(object sender, EventArgs e) => PG_TerrainTile.SelectedObject = new TerrainTile
{
UnitModel = TerrainUnitModel.River7A,
LandMakingAngle = 1,
Elevation = (ushort)slider_elevation.Value,
};
private void NW_diagonal_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3B);
private void N_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River5B, 3);
private void NE_diagonal_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3B, 3);
private void W_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River5B);
private void Center_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River8A);
private void e_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River5B, 2);
private void sw_diagonal_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3B, 1);
private void s_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River5B, 1);
private void SE_diagonal_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3B, 2);
private void NW_angular_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3C);
private void NE_angular_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3C, 3);
private void SW_angular_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3C, 1);
private void SE_angular_water_tile_Click(object sender, EventArgs e) => SelectTerrainTile(River3C, 2);
private void TL_dirt_inside_Click(object sender, EventArgs e) => SelectTerrainTile(Cliff7A, 3);
private void TL_water_inside_Click(object sender, EventArgs e) => SelectTerrainTile(River7A, 3);
private void TR_water_inside_Click(object sender, EventArgs e) => SelectTerrainTile(River7A, 2);
private void DL_water_inside_Click(object sender, EventArgs e) => SelectTerrainTile(River7A);
private void DR_water_inside_Click(object sender, EventArgs e) => SelectTerrainTile(River7A, 1);
#endregion Water tiles
#endregion Tiles buttons
private void SliderThicknessValueChanged(object sender, EventArgs e)
{
lbl_size_count.Text = slider_thickness.Value.ToString();
}
private void SliderThicknessValueChanged(object sender, EventArgs e) => lbl_size_count.Text = slider_thickness.Value.ToString();
private void SliderElevationValueChanged(object sender, EventArgs e)
{
lbl_elevation_count.Text = slider_elevation.Value.ToString();
TerrainTile currentTile = (TerrainTile)PG_TerrainTile.SelectedObject!;
var currentTile = (TerrainTile)PG_TerrainTile.SelectedObject!;
currentTile.Elevation = (ushort)slider_elevation.Value;
PG_TerrainTile.SelectedObject = currentTile;
}
private TerrainTile CreateTerrainTile(TerrainUnitModel unitModel = Base, ushort landMakingAngle = 0) => new()
{
Elevation = (ushort)slider_elevation.Value,
UnitModel = unitModel,
LandMakingAngle = landMakingAngle
};
private void SelectTerrainTile(TerrainUnitModel unitModel = Base, ushort landMakingAngle = 0)
=> PG_TerrainTile.SelectedObject = CreateTerrainTile(unitModel, landMakingAngle);
private void B_Brush_Click(object sender, EventArgs e) => IsBrushSelected = true;
private void TerrainBrushEditor_FormClosed(object sender, FormClosedEventArgs e) => IsBrushSelected = false;
private void B_Normal_Click(object sender, EventArgs e) => IsBrushSelected = false;