Add a preview to editor marker brush

This commit is contained in:
Gustas
2025-04-18 13:40:11 +03:00
committed by Paul Chote
parent d4a08e5b58
commit bd590dfcf4
2 changed files with 78 additions and 52 deletions

View File

@@ -10,6 +10,7 @@
#endregion
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits;
@@ -26,8 +27,9 @@ namespace OpenRA.Mods.Common.Widgets
readonly MarkerLayerOverlay markerLayerOverlay;
readonly EditorViewportControllerWidget editorWidget;
PaintMarkerTileEditorAction action;
readonly List<PaintMarkerTile> paintTiles = [];
bool painting;
CPos cell;
public EditorMarkerLayerBrush(EditorViewportControllerWidget editorWidget, int? id, WorldRenderer wr)
{
@@ -39,11 +41,11 @@ namespace OpenRA.Mods.Common.Widgets
markerLayerOverlay = world.WorldActor.Trait<MarkerLayerOverlay>();
Template = id;
action = new PaintMarkerTileEditorAction(Template, markerLayerOverlay);
}
public bool HandleMouseInput(MouseInput mi)
{
// Exclusively uses left and right mouse buttons, but nothing else.
if (mi.Button != MouseButton.Left && mi.Button != MouseButton.Right)
return false;
@@ -58,30 +60,71 @@ namespace OpenRA.Mods.Common.Widgets
return false;
}
if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up)
{
action.Add(worldRenderer.Viewport.ViewToWorld(mi.Location));
painting = true;
}
else if (painting && mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
{
if (action.DidPaintTiles)
editorActionManager.Add(action);
if (mi.Button != MouseButton.Left)
return true;
if (mi.Event == MouseInputEvent.Up)
{
UpdatePreview();
if (paintTiles.Count != 0)
{
editorActionManager.Add(new PaintMarkerTileEditorAction(Template, paintTiles.ToImmutableArray(), markerLayerOverlay));
paintTiles.Clear();
UpdatePreview(true);
}
action = new PaintMarkerTileEditorAction(Template, markerLayerOverlay);
painting = false;
}
else
{
painting = true;
UpdatePreview();
}
return true;
}
void IEditorBrush.TickRender(WorldRenderer wr, Actor self) { }
void UpdatePreview(bool forceRefresh = false)
{
var currentCell = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
if (!forceRefresh && cell == currentCell)
return;
cell = currentCell;
if (!painting)
{
foreach (var paintTile in paintTiles)
markerLayerOverlay.SetTile(paintTile.Cell, paintTile.Previous);
paintTiles.Clear();
}
foreach (var cell in markerLayerOverlay.CalculateMirrorPositions(cell))
{
if (paintTiles.Any(t => t.Cell == cell))
continue;
var existing = markerLayerOverlay.CellLayer[cell];
if (existing == Template)
continue;
paintTiles.Add(new PaintMarkerTile(cell, existing));
markerLayerOverlay.SetTile(cell, Template);
}
}
void IEditorBrush.TickRender(WorldRenderer wr, Actor self) { UpdatePreview(); }
IEnumerable<IRenderable> IEditorBrush.RenderAboveShroud(Actor self, WorldRenderer wr) { yield break; }
IEnumerable<IRenderable> IEditorBrush.RenderAnnotations(Actor self, WorldRenderer wr) { yield break; }
public void Tick() { }
public void Dispose() { }
public void Dispose()
{
foreach (var paintTile in paintTiles)
markerLayerOverlay.SetTile(paintTile.Cell, paintTile.Previous);
}
}
readonly struct PaintMarkerTile
@@ -104,27 +147,28 @@ namespace OpenRA.Mods.Common.Widgets
[FluentReference("count")]
const string RemovedMarkerTiles = "notification-removed-marker-tiles";
public string Text { get; private set; }
public string Text { get; }
readonly int? type;
readonly MarkerLayerOverlay markerLayerOverlay;
readonly List<PaintMarkerTile> paintTiles = [];
public bool DidPaintTiles => paintTiles.Count > 0;
readonly ImmutableArray<PaintMarkerTile> paintTiles = [];
public PaintMarkerTileEditorAction(
int? type,
ImmutableArray<PaintMarkerTile> paintTiles,
MarkerLayerOverlay markerLayerOverlay)
{
this.markerLayerOverlay = markerLayerOverlay;
this.type = type;
this.paintTiles = paintTiles;
this.markerLayerOverlay = markerLayerOverlay;
Text = type != null
? FluentProvider.GetMessage(AddedMarkerTiles, "count", paintTiles.Length, "type", type)
: FluentProvider.GetMessage(RemovedMarkerTiles, "count", paintTiles.Length);
}
public void Execute()
{
paintTiles.TrimExcess();
}
public void Execute() { }
public void Do()
{
@@ -137,23 +181,6 @@ namespace OpenRA.Mods.Common.Widgets
foreach (var paintTile in paintTiles)
markerLayerOverlay.SetTile(paintTile.Cell, paintTile.Previous);
}
public void Add(CPos target)
{
foreach (var cell in markerLayerOverlay.CalculateMirrorPositions(target))
{
var existing = markerLayerOverlay.CellLayer[cell];
if (existing == type)
continue;
paintTiles.Add(new PaintMarkerTile(cell, existing));
markerLayerOverlay.SetTile(cell, type);
}
Text = type != null
? FluentProvider.GetMessage(AddedMarkerTiles, "count", paintTiles.Count, "type", type)
: FluentProvider.GetMessage(RemovedMarkerTiles, "count", paintTiles.Count);
}
}
sealed class ClearSelectedMarkerTilesEditorAction : IEditorAction
@@ -164,7 +191,7 @@ namespace OpenRA.Mods.Common.Widgets
public string Text { get; }
readonly MarkerLayerOverlay markerLayerOverlay;
readonly HashSet<CPos> tiles;
readonly ImmutableArray<CPos> tiles;
readonly int tile;
public ClearSelectedMarkerTilesEditorAction(
@@ -174,9 +201,8 @@ namespace OpenRA.Mods.Common.Widgets
this.tile = tile;
this.markerLayerOverlay = markerLayerOverlay;
tiles = markerLayerOverlay.Tiles[tile].ToHashSet();
Text = FluentProvider.GetMessage(ClearedSelectedMarkerTiles, "count", tiles.Count, "type", tile);
tiles = markerLayerOverlay.Tiles[tile].ToImmutableArray();
Text = FluentProvider.GetMessage(ClearedSelectedMarkerTiles, "count", tiles.Length, "type", tile);
}
public void Execute()
@@ -191,7 +217,7 @@ namespace OpenRA.Mods.Common.Widgets
public void Undo()
{
markerLayerOverlay.SetSelected(tile, tiles);
markerLayerOverlay.SetSelected(tile, tiles.AsSpan());
}
}
@@ -203,15 +229,14 @@ namespace OpenRA.Mods.Common.Widgets
public string Text { get; }
readonly MarkerLayerOverlay markerLayerOverlay;
readonly Dictionary<int, HashSet<CPos>> tiles;
readonly ImmutableDictionary<int, ImmutableArray<CPos>> tiles;
public ClearAllMarkerTilesEditorAction(
MarkerLayerOverlay markerLayerOverlay)
{
this.markerLayerOverlay = markerLayerOverlay;
tiles = new Dictionary<int, HashSet<CPos>>(markerLayerOverlay.Tiles);
var allTilesCount = tiles.Values.Sum(x => x.Count);
tiles = markerLayerOverlay.Tiles.ToImmutableDictionary(t => t.Key, t => t.Value.ToImmutableArray());
var allTilesCount = tiles.Values.Sum(x => x.Length);
Text = FluentProvider.GetMessage(ClearedAllMarkerTiles, "count", allTilesCount);
}

View File

@@ -11,6 +11,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using OpenRA.Graphics;
@@ -172,7 +173,7 @@ namespace OpenRA.Mods.Common.Traits
NumSides = file.NumSides;
AxisAngle = file.AxisAngle;
SetAll(file.Tiles.ToDictionary(d => d.Key, d => new HashSet<CPos>(d.Value)));
SetAll(file.Tiles.ToImmutableDictionary(d => d.Key, d => d.Value.ToImmutableArray()));
}
catch (Exception e)
{
@@ -202,7 +203,7 @@ namespace OpenRA.Mods.Common.Traits
Tiles.Clear();
}
public void SetAll(Dictionary<int, HashSet<CPos>> newTiles)
public void SetAll(IImmutableDictionary<int, ImmutableArray<CPos>> newTiles)
{
ClearAll();
@@ -222,7 +223,7 @@ namespace OpenRA.Mods.Common.Traits
}
}
public void SetSelected(int tile, HashSet<CPos> newTiles)
public void SetSelected(int tile, ReadOnlySpan<CPos> newTiles)
{
var type = Tiles[tile];
foreach (var pos in type)