From 1300ecc18f02a6dcdf2f2603d61d721b3f08243b Mon Sep 17 00:00:00 2001 From: Gustas <37534529+PunkPun@users.noreply.github.com> Date: Wed, 6 Aug 2025 19:44:10 +0300 Subject: [PATCH] Fix TS copy paste --- .../EditorBrushes/EditorBlit.cs | 61 ++++++++++++++----- .../EditorBrushes/EditorCopyPasteBrush.cs | 21 +++++-- .../EditorBrushes/EditorDefaultBrush.cs | 6 +- .../EditorBrushes/EditorTilingPathBrush.cs | 4 +- .../EditorSelectionAnnotationRenderable.cs | 22 +++---- .../MapGenerator/CellLayerUtils.cs | 35 +++++++++++ .../Traits/World/TerrainRenderer.cs | 3 +- 7 files changed, 114 insertions(+), 38 deletions(-) diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorBlit.cs b/OpenRA.Mods.Common/EditorBrushes/EditorBlit.cs index 384d6a225d..35c3206e71 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorBlit.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorBlit.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using OpenRA.Graphics; +using OpenRA.Mods.Common.MapGenerator; using OpenRA.Mods.Common.Traits; using OpenRA.Support; @@ -110,9 +111,9 @@ namespace OpenRA.Mods.Common.EditorBrushes tiles.Add( cell, new BlitTile(mapTiles[cell], - mapResources[cell], - resourceLayer?.GetResource(cell), - mapHeight[cell])); + mapResources[cell], + resourceLayer?.GetResource(cell), + mapHeight[cell])); } } @@ -221,23 +222,24 @@ namespace OpenRA.Mods.Common.EditorBrushes EditorBlitSource blitSource, MapBlitFilters filters, CVec offset, - WorldRenderer wr) + WorldRenderer wr, + bool stickToGround) { var world = wr.World; var map = world.Map; - - var wOffset = map.CenterOfCell(CPos.Zero + offset) - map.CenterOfCell(CPos.Zero); + var mapHeight = map.Height; + var mapGrid = map.Grid; if (filters.HasFlag(MapBlitFilters.Terrain)) { var terrainRenderer = world.WorldActor.Trait(); - foreach (var (cpos, tile) in blitSource.Tiles) + foreach (var (pos, tile) in blitSource.Tiles) { - var preview = - terrainRenderer.RenderPreview( - wr, - tile.TerrainTile, - map.CenterOfCell(cpos + offset)); + var cPos = pos + offset; + var height = stickToGround ? (mapHeight.TryGetValue(cPos, out var isoHeight) ? isoHeight : byte.MinValue) : tile.Height; + var wPos = CellLayerUtils.CPosToWPos(cPos, height, mapGrid.Type); + var preview = terrainRenderer.RenderPreview(wr, tile.TerrainTile, wPos); + foreach (var renderable in preview) yield return renderable; } @@ -256,11 +258,26 @@ namespace OpenRA.Mods.Common.EditorBrushes if (!filters.HasFlag(MapBlitFilters.Terrain) && !resourceLayer.CanAddResource(tile.ResourceLayerContents.Value.Type, cPos)) continue; + byte height; + if (filters.HasFlag(MapBlitFilters.Terrain) && !stickToGround) + { + // We won't change relative tile height, use the saved value. + height = tile.Height; + } + else + { + if (!mapHeight.TryGetValue(cPos, out height)) + height = byte.MinValue; + + // If a tile has inherent height, we know it will raise terrain. + if (filters.HasFlag(MapBlitFilters.Terrain) && stickToGround) + height += map.Rules.TerrainInfo.GetTerrainInfo(tile.TerrainTile).Height; + } + + var wPos = CellLayerUtils.CPosToWPos(cPos, height, mapGrid.Type); var preview = resourceRenderers - .SelectMany(r => r.RenderPreview( - wr, - tile.ResourceLayerContents.Value.Type, - map.CenterOfCell(cPos))); + .SelectMany(r => r.RenderPreview(wr, tile.ResourceLayerContents.Value.Type, wPos)); + foreach (var renderable in preview) yield return renderable; } @@ -270,8 +287,20 @@ namespace OpenRA.Mods.Common.EditorBrushes { foreach (var (_, editorActorPreview) in blitSource.Actors) { + var useGround = stickToGround; + if (!filters.HasFlag(MapBlitFilters.Terrain) || !blitSource.Tiles.ContainsKey(editorActorPreview.Location)) + useGround = true; + + var wOffset = CellLayerUtils.CVecToWVec(offset, 0, mapGrid.Type); + if (useGround) + { + var actorPos = editorActorPreview.CenterPosition + wOffset; + wOffset -= new WVec(0, 0, map.DistanceAboveTerrain(actorPos).Length); + } + var preview = editorActorPreview.RenderWithOffset(wOffset) .OrderBy(WorldRenderer.RenderableZPositionComparisonKey); + foreach (var renderable in preview) yield return renderable; } diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorCopyPasteBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorCopyPasteBrush.cs index 57706910e8..f0b414d4f9 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorCopyPasteBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorCopyPasteBrush.cs @@ -90,19 +90,32 @@ namespace OpenRA.Mods.Common.Widgets void IEditorBrush.TickRender(WorldRenderer wr, Actor self) { } IEnumerable IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { + var filters = getCopyFilters(); + var stickToGround = !filters.HasFlag(MapBlitFilters.Terrain) +; var preview = EditorBlit.PreviewBlitSource( clipboard, - getCopyFilters(), + filters, PastePreviewPosition - Region.TopLeft, - wr); + wr, + stickToGround); foreach (var renderable in preview) yield return renderable; } IEnumerable IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr) { - yield return new EditorSelectionAnnotationRenderable(Region, editorWidget.SelectionAltColor, editorWidget.SelectionAltOffset, PastePreviewPosition); - yield return new EditorSelectionAnnotationRenderable(Region, editorWidget.PasteColor, int2.Zero, PastePreviewPosition); + yield return new EditorSelectionAnnotationRenderable( + Region, + editorWidget.SelectionAltColor, + editorWidget.SelectionAltOffset, + PastePreviewPosition - Region.TopLeft); + + yield return new EditorSelectionAnnotationRenderable( + Region, + editorWidget.PasteColor, + int2.Zero, + PastePreviewPosition - Region.TopLeft); } public void Tick() diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs index 9c9902ec00..2a999d7f5a 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs @@ -279,10 +279,10 @@ namespace OpenRA.Mods.Common.Widgets IEnumerable IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { yield break; } IEnumerable IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr) { - if (CurrentDragBounds != null) + if (CurrentDragBounds.HasValue) { - yield return new EditorSelectionAnnotationRenderable(CurrentDragBounds.Value, editorWidget.SelectionAltColor, editorWidget.SelectionAltOffset, null); - yield return new EditorSelectionAnnotationRenderable(CurrentDragBounds.Value, editorWidget.SelectionMainColor, int2.Zero, null); + yield return new EditorSelectionAnnotationRenderable(CurrentDragBounds.Value, editorWidget.SelectionAltColor, editorWidget.SelectionAltOffset, CVec.Zero); + yield return new EditorSelectionAnnotationRenderable(CurrentDragBounds.Value, editorWidget.SelectionMainColor, int2.Zero, CVec.Zero); } } diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs index 8b7e6a8dfb..a316ece07b 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorTilingPathBrush.cs @@ -203,11 +203,13 @@ namespace OpenRA.Mods.Common.Widgets if (tool.EditorBlitSource == null) yield break; + var stickToGround = tool.EditorBlitSource.Value.Tiles.Count == 0; var preview = EditorBlit.PreviewBlitSource( tool.EditorBlitSource.Value, MapBlitFilters.Terrain | MapBlitFilters.Actors, CVec.Zero, - wr); + wr, + stickToGround); foreach (var renderable in preview) yield return renderable; } diff --git a/OpenRA.Mods.Common/Graphics/EditorSelectionAnnotationRenderable.cs b/OpenRA.Mods.Common/Graphics/EditorSelectionAnnotationRenderable.cs index 4542bacb08..e68a225a8e 100644 --- a/OpenRA.Mods.Common/Graphics/EditorSelectionAnnotationRenderable.cs +++ b/OpenRA.Mods.Common/Graphics/EditorSelectionAnnotationRenderable.cs @@ -22,9 +22,9 @@ namespace OpenRA.Mods.Common.Graphics readonly Color color; readonly CellCoordsRegion bounds; readonly int2 altPixelOffset; - readonly CPos? offset; + readonly CVec offset; - public EditorSelectionAnnotationRenderable(CellCoordsRegion bounds, Color color, int2 altPixelOffset, CPos? offset) + public EditorSelectionAnnotationRenderable(CellCoordsRegion bounds, Color color, int2 altPixelOffset, CVec offset) { this.bounds = bounds; this.color = color; @@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Graphics public bool IsDecoration => true; public IRenderable WithZOffset(int newOffset) { return this; } - public IRenderable OffsetBy(in WVec vec) { return new EditorSelectionAnnotationRenderable(bounds, color, new int2(vec.X, vec.Y), offset); } + public IRenderable OffsetBy(in WVec vec) { return this; } public IRenderable AsDecoration() { return this; } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } @@ -46,29 +46,27 @@ namespace OpenRA.Mods.Common.Graphics { const int Width = 1; var map = wr.World.Map; - var originalWPos = map.CenterOfCell(bounds.TopLeft); - var wposOffset = offset.HasValue ? map.CenterOfCell(offset.Value) - originalWPos : WVec.Zero; - foreach (var cellPos in bounds) { - var uv = cellPos.ToMPos(map); + var pos = cellPos + offset; + var uv = pos.ToMPos(map); if (!map.Height.Contains(uv)) continue; var ramp = map.Grid.Ramps[map.Ramp[uv]]; - var pos = map.CenterOfCell(cellPos) - new WVec(0, 0, ramp.CenterHeightOffset); + var wPos = map.CenterOfCell(pos) - new WVec(0, 0, ramp.CenterHeightOffset); foreach (var p in ramp.Polygons) { for (var i = 0; i < p.Length; i++) { var j = (i + 1) % p.Length; - var start = pos + p[i]; - var end = pos + p[j]; + var start = wPos + p[i]; + var end = wPos + p[j]; Game.Renderer.RgbaColorRenderer.DrawLine( - wr.Viewport.WorldToViewPx(wr.ScreenPosition(start + wposOffset)) + altPixelOffset, - wr.Viewport.WorldToViewPx(wr.Screen3DPosition(end + wposOffset)) + altPixelOffset, + wr.Viewport.WorldToViewPx(wr.ScreenPosition(start)) + altPixelOffset, + wr.Viewport.WorldToViewPx(wr.Screen3DPosition(end)) + altPixelOffset, Width, color, color); } } diff --git a/OpenRA.Mods.Common/MapGenerator/CellLayerUtils.cs b/OpenRA.Mods.Common/MapGenerator/CellLayerUtils.cs index f0930e6406..95b5a98816 100644 --- a/OpenRA.Mods.Common/MapGenerator/CellLayerUtils.cs +++ b/OpenRA.Mods.Common/MapGenerator/CellLayerUtils.cs @@ -139,6 +139,26 @@ namespace OpenRA.Mods.Common.MapGenerator } } + /// Get the WVec representing the same translation as the given CVec, with a height offset. + public static WVec CVecToWVec(CVec cvec, int dz, MapGridType gridType) + { + switch (gridType) + { + case MapGridType.Rectangular: + return new WVec( + cvec.X * 1024, + cvec.Y * 1024, + 0); + case MapGridType.RectangularIsometric: + return new WVec( + (cvec.X - cvec.Y) * 724, + (cvec.X + cvec.Y) * 724, + 724 * dz); + default: + throw new NotImplementedException(); + } + } + /// Get the WPos center of a CPos cell. public static WPos CPosToWPos(CPos cpos, MapGridType gridType) { @@ -154,6 +174,21 @@ namespace OpenRA.Mods.Common.MapGenerator } } + /// Get the WPos center of a CPos cell with a height offset. + public static WPos CPosToWPos(CPos cpos, int dz, MapGridType gridType) + { + var wvec = CVecToWVec(new CVec(cpos.X, cpos.Y), dz, gridType); + switch (gridType) + { + case MapGridType.Rectangular: + return new WPos(512, 512, 0) + wvec; + case MapGridType.RectangularIsometric: + return new WPos(724, 724, 0) + wvec; + default: + throw new NotImplementedException(); + } + } + /// /// Find the CPos cell in which a WPos position lies. WPos positions on /// an edge or corner match the CPos with higher X and/or Y positions. diff --git a/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs b/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs index d78c7cc7dd..e22f267a06 100644 --- a/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs +++ b/OpenRA.Mods.Common/Traits/World/TerrainRenderer.cs @@ -214,10 +214,9 @@ namespace OpenRA.Mods.Common.Traits yield break; var sprite = tileCache.TileSprite(tile, 0); - var offset = map.Offset(new CVec(0, 0), template[tile.Index].Height); var palette = wr.Palette(((DefaultTerrainTemplateInfo)template)?.Palette ?? terrainInfo.Palette); - yield return new SpriteRenderable(sprite, origin, offset, 0, palette, 1f, 1f, float3.Ones, TintModifiers.None, false); + yield return new SpriteRenderable(sprite, origin, WVec.Zero, 0, palette, 1f, 1f, float3.Ones, TintModifiers.None, false); } } }