diff --git a/CentrED/Map/MapManager.cs b/CentrED/Map/MapManager.cs index 2a5b4346..da6e69bd 100644 --- a/CentrED/Map/MapManager.cs +++ b/CentrED/Map/MapManager.cs @@ -848,13 +848,21 @@ public Vector3 Unproject(int x, int y, int z) ); } - private bool CanDrawLand(LandObject lo) + public bool CanDrawLand(LandObject lo) { - if(!ShowLand || (lo.Tile.Id <= 2 && !ShowNoDraw)) + if(!ShowLand || (lo.Tile.Id <= 2 && !ShowNoDraw)) return false; return WithinZRange(lo.Tile.Z); } + // Tiles hidden by the view filter are read-only for tools; the virtual layer is always editable. + public bool CanEdit(TileObject? o) => o switch + { + LandObject lo => CanDrawLand(lo), + StaticObject so => CanDrawStatic(so), + _ => true, + }; + public bool CanDrawStatic(StaticObject so) { var tile = so.StaticTile; diff --git a/CentrED/Tools/AltitudeGradientTool.cs b/CentrED/Tools/AltitudeGradientTool.cs index 672c907c..aa544f16 100644 --- a/CentrED/Tools/AltitudeGradientTool.cs +++ b/CentrED/Tools/AltitudeGradientTool.cs @@ -481,6 +481,10 @@ private void ApplyGhostCommon(LandObject lo, int targetHeight) private void CreateGhostTile(LandObject lo, sbyte newZ) { + // Filtered tiles may be sampled for averages/gradients but never modified. + if (!MapManager.CanDrawLand(lo)) + return; + lo.Visible = false; var newTile = new LandTile(lo.LandTile.Id, lo.Tile.X, lo.Tile.Y, newZ); var ghostTile = new LandObject(newTile); diff --git a/CentrED/Tools/BaseTool.cs b/CentrED/Tools/BaseTool.cs index 07bf6808..3b70b9c1 100644 --- a/CentrED/Tools/BaseTool.cs +++ b/CentrED/Tools/BaseTool.cs @@ -114,14 +114,20 @@ public sealed override void OnMouseReleased(TileObject? o) { foreach (var to in MapManager.GetTiles(AreaStartTile, o, TopTilesOnly)) { - InternalApply(to); + if (MapManager.CanEdit(to)) + { + InternalApply(to); + } GhostClear(to); } OnAreaOperationEnd(); } else { - InternalApply(o); + if (MapManager.CanEdit(o)) + { + InternalApply(o); + } GhostClear(o); } } @@ -138,7 +144,7 @@ public sealed override void OnMouseEnter(TileObject? o) OnAreaOperationUpdate(o); foreach (var to in MapManager.GetTiles(AreaStartTile, o, TopTilesOnly)) { - if (Random.Shared.NextDouble() * 100 < _chance) + if (MapManager.CanEdit(to) && Random.Shared.NextDouble() * 100 < _chance) { GhostApply(to); } @@ -146,7 +152,7 @@ public sealed override void OnMouseEnter(TileObject? o) } else { - if (Random.Shared.NextDouble() * 100 < _chance) + if (MapManager.CanEdit(o) && Random.Shared.NextDouble() * 100 < _chance) { GhostApply(o); } @@ -164,7 +170,7 @@ public sealed override void OnMouseLeave(TileObject? o) GhostClear(to); } } - else + else if (MapManager.CanEdit(o)) { InternalApply(o); } @@ -174,6 +180,8 @@ public sealed override void OnMouseLeave(TileObject? o) public override void Apply(TileObject? o) { + if (!MapManager.CanEdit(o)) + return; GhostApply(o); InternalApply(o); } diff --git a/CentrED/Tools/CoastlineTool.cs b/CentrED/Tools/CoastlineTool.cs index be938d50..4573f388 100644 --- a/CentrED/Tools/CoastlineTool.cs +++ b/CentrED/Tools/CoastlineTool.cs @@ -137,6 +137,9 @@ protected override void GhostApply(TileObject? o) if (selectedTile == null) return; + if (!mapManager.CanDrawLand(selectedTile)) + return; + if (_terrainWaterTiles.Contains(selectedTile.Tile.Id)) return; @@ -161,8 +164,8 @@ protected override void GhostApply(TileObject? o) if (kvp.Value != null && _terrainWaterTiles.Contains(kvp.Value.Id)) { var waterLandObject = mapManager.LandTiles[kvp.Value.X, kvp.Value.Y]; - - if (waterLandObject != null) + + if (waterLandObject != null && mapManager.CanDrawLand(waterLandObject)) { if (!MapManager.GhostLandTiles.ContainsKey(waterLandObject)) { @@ -303,6 +306,8 @@ protected override void InternalApply(TileObject? o) { foreach (var existingObject in mapManager.StaticsManager.Get(o.Tile.X, o.Tile.Y)) { + if (!mapManager.CanDrawStatic(existingObject)) + continue; Client.Remove(existingObject.StaticTile); //Do we need to create a ghost for this? } } diff --git a/CentrED/Tools/DrawTool.cs b/CentrED/Tools/DrawTool.cs index 013b9aa4..6403ef26 100644 --- a/CentrED/Tools/DrawTool.cs +++ b/CentrED/Tools/DrawTool.cs @@ -142,6 +142,10 @@ protected override void GhostApply(TileObject? o) if (o == null) return; + // the virtual layer can resolve to a filtered tile + if (!MapManager.CanEdit(o)) + return; + if (!CanDrawOn(o)) return; @@ -234,6 +238,9 @@ protected override void InternalApply(TileObject? o) if (o == null) return; + if (!MapManager.CanEdit(o)) + return; + if (_drawMode == (int)DrawMode.REPLACE && o is StaticObject so) { Client.Remove(so.StaticTile); diff --git a/CentrED/Tools/MeshEditTool.cs b/CentrED/Tools/MeshEditTool.cs index ef1f4438..bd4a6176 100644 --- a/CentrED/Tools/MeshEditTool.cs +++ b/CentrED/Tools/MeshEditTool.cs @@ -615,6 +615,9 @@ protected override void GhostApply(TileObject? o) if (lo == null) continue; + if (!MapManager.CanDrawLand(lo)) + continue; + // Create ghost tile sbyte newZ = isBufferZone ? lo.Tile.Z : CalculateNewZ(lo, distance, centerZ); lo.Visible = false;