Skip to content

Commit

Permalink
Added Undo Redo to editor
Browse files Browse the repository at this point in the history
  • Loading branch information
teinarss committed Sep 15, 2019
1 parent 38ddc47 commit 5263eeb
Show file tree
Hide file tree
Showing 18 changed files with 1,114 additions and 148 deletions.
97 changes: 70 additions & 27 deletions OpenRA.Mods.Common/EditorBrushes/EditorActorBrush.cs
Expand Up @@ -24,6 +24,7 @@ public sealed class EditorActorBrush : IEditorBrush
readonly WorldRenderer worldRenderer;
readonly World world;
readonly EditorActorLayer editorLayer;
readonly EditorActionManager editorActionManager;
readonly EditorViewportControllerWidget editorWidget;
readonly ActorPreviewWidget preview;
readonly WVec centerOffset;
Expand All @@ -38,6 +39,7 @@ public EditorActorBrush(EditorViewportControllerWidget editorWidget, ActorInfo a
worldRenderer = wr;
world = wr.World;
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
editorActionManager = world.WorldActor.Trait<EditorActionManager>();

Actor = actor;
this.owner = owner;
Expand Down Expand Up @@ -101,33 +103,8 @@ public bool HandleMouseInput(MouseInput mi)
return true;

// Enforce first entry of ValidOwnerNames as owner if the actor has RequiresSpecificOwners
var ownerName = owner.Name;
var specificOwnerInfo = Actor.TraitInfoOrDefault<RequiresSpecificOwnersInfo>();
if (specificOwnerInfo != null && !specificOwnerInfo.ValidOwnerNames.Contains(ownerName))
ownerName = specificOwnerInfo.ValidOwnerNames.First();

var newActorReference = new ActorReference(Actor.Name);
newActorReference.Add(new OwnerInit(ownerName));

newActorReference.Add(new LocationInit(cell));

var ios = Actor.TraitInfoOrDefault<IOccupySpaceInfo>();
if (ios != null && ios.SharesCell)
{
var subcell = editorLayer.FreeSubCellAt(cell);
if (subcell != SubCell.Invalid)
newActorReference.Add(new SubCellInit(subcell));
}

var initDict = newActorReference.InitDict;

if (Actor.HasTraitInfo<IFacingInfo>())
initDict.Add(new FacingInit(facing));

if (Actor.HasTraitInfo<TurretedInfo>())
initDict.Add(new TurretFacingInit(facing));

editorLayer.Add(newActorReference);
var action = new AddActorAction(editorLayer, Actor, cell, owner, facing);
editorActionManager.Add(action);
}

return true;
Expand All @@ -151,4 +128,70 @@ public void Tick()

public void Dispose() { }
}

class AddActorAction : IEditorAction
{
readonly EditorActorLayer editorLayer;
readonly ActorInfo actor;
readonly CPos cell;
readonly PlayerReference owner;
readonly int facing;

EditorActorPreview editorActorPreview;

public AddActorAction(EditorActorLayer editorLayer, ActorInfo actor, CPos cell, PlayerReference owner, int facing)
{
this.editorLayer = editorLayer;
this.actor = actor;
this.cell = cell;
this.owner = owner;
this.facing = facing;
}

public void Execute()
{
Do();
}

public void Do()
{
var ownerName = owner.Name;
var specificOwnerInfo = actor.TraitInfoOrDefault<RequiresSpecificOwnersInfo>();
if (specificOwnerInfo != null && !specificOwnerInfo.ValidOwnerNames.Contains(ownerName))
ownerName = specificOwnerInfo.ValidOwnerNames.First();

var newActorReference = new ActorReference(actor.Name);
newActorReference.Add(new OwnerInit(ownerName));

newActorReference.Add(new LocationInit(cell));

var ios = actor.TraitInfoOrDefault<IOccupySpaceInfo>();
if (ios != null && ios.SharesCell)
{
var subcell = editorLayer.FreeSubCellAt(cell);
if (subcell != SubCell.Invalid)
newActorReference.Add(new SubCellInit(subcell));
}

var initDict = newActorReference.InitDict;

if (actor.HasTraitInfo<IFacingInfo>())
initDict.Add(new FacingInit(facing));

if (actor.HasTraitInfo<TurretedInfo>())
initDict.Add(new TurretFacingInit(facing));

editorActorPreview = editorLayer.Add(newActorReference);
}

public void Undo()
{
editorLayer.Remove(editorActorPreview);
}

public string Text
{
get { return "Actor added: {0}".F(editorActorPreview.DescriptiveName); }
}
}
}
122 changes: 109 additions & 13 deletions OpenRA.Mods.Common/EditorBrushes/EditorCopyPasteBrush.cs
Expand Up @@ -36,6 +36,7 @@ enum State { SelectFirst, SelectSecond, Paste }
readonly EditorSelectionLayer selectionLayer;
readonly EditorActorLayer editorLayer;
readonly Func<MapCopyFilters> getCopyFilters;
readonly EditorActionManager editorActionManager;

State state;
CPos start;
Expand All @@ -46,6 +47,8 @@ public EditorCopyPasteBrush(EditorViewportControllerWidget editorWidget, WorldRe
this.editorWidget = editorWidget;
worldRenderer = wr;

editorActionManager = wr.World.WorldActor.Trait<EditorActionManager>();

selectionLayer = wr.World.WorldActor.Trait<EditorSelectionLayer>();
editorLayer = wr.World.WorldActor.Trait<EditorActorLayer>();
this.getCopyFilters = getCopyFilters;
Expand Down Expand Up @@ -143,8 +146,74 @@ void Copy(CellRegion source, CVec offset)
}
}

var action = new CopyPasteEditorAction(copyFilters, worldRenderer.World.Map, tiles, previews, editorLayer, dest);
editorActionManager.Add(action);
}

public void Tick()
{
var cell = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
if (state == State.Paste)
{
selectionLayer.SetPasteRegion(cell + (start - end), cell);
return;
}

if (state == State.SelectFirst)
start = end = cell;
else if (state == State.SelectSecond)
end = cell;

selectionLayer.SetCopyRegion(start, end);
}

public void Dispose()
{
selectionLayer.Clear();
}
}

class CopyPasteEditorAction : IEditorAction
{
readonly MapCopyFilters copyFilters;
readonly Dictionary<CPos, Tuple<TerrainTile, ResourceTile, byte>> tiles;
readonly Dictionary<string, ActorReference> previews;
readonly EditorActorLayer editorLayer;
readonly CellRegion dest;
readonly CellLayer<TerrainTile> mapTiles;
readonly CellLayer<byte> mapHeight;
readonly CellLayer<ResourceTile> mapResources;

readonly Queue<UndoCopyPaste> undoCopyPastes = new Queue<UndoCopyPaste>();
readonly Queue<EditorActorPreview> removedActors = new Queue<EditorActorPreview>();
readonly Queue<EditorActorPreview> addedActorPreviews = new Queue<EditorActorPreview>();

public CopyPasteEditorAction(MapCopyFilters copyFilters, Map map,
Dictionary<CPos, Tuple<TerrainTile, ResourceTile, byte>> tiles, Dictionary<string, ActorReference> previews,
EditorActorLayer editorLayer, CellRegion dest)
{
this.copyFilters = copyFilters;
this.tiles = tiles;
this.previews = previews;
this.editorLayer = editorLayer;
this.dest = dest;

mapTiles = map.Tiles;
mapHeight = map.Height;
mapResources = map.Resources;
}

public void Execute()
{
Do();
}

public void Do()
{
foreach (var kv in tiles)
{
undoCopyPastes.Enqueue(new UndoCopyPaste(kv.Key, mapTiles[kv.Key], mapResources[kv.Key], mapHeight[kv.Key]));

if (copyFilters.HasFlag(MapCopyFilters.Terrain))
mapTiles[kv.Key] = kv.Value.Item1;

Expand All @@ -158,33 +227,60 @@ void Copy(CellRegion source, CVec offset)
{
var removeActors = dest.SelectMany(editorLayer.PreviewsAt).Distinct().ToList();
foreach (var preview in removeActors)
{
removedActors.Enqueue(preview);
editorLayer.Remove(preview);
}
}

foreach (var kv in previews)
editorLayer.Add(kv.Value);
addedActorPreviews.Enqueue(editorLayer.Add(kv.Value));
}

public void Tick()
public void Undo()
{
var cell = worldRenderer.Viewport.ViewToWorld(Viewport.LastMousePos);
if (state == State.Paste)
while (undoCopyPastes.Count > 0)
{
selectionLayer.SetPasteRegion(cell + (start - end), cell);
return;
var undoCopyPaste = undoCopyPastes.Dequeue();

var cell = undoCopyPaste.Cell;

if (copyFilters.HasFlag(MapCopyFilters.Terrain))
mapTiles[cell] = undoCopyPaste.MapTile;

if (copyFilters.HasFlag(MapCopyFilters.Resources))
mapResources[cell] = undoCopyPaste.ResourceTile;

mapHeight[cell] = undoCopyPaste.Height;
}

if (state == State.SelectFirst)
start = end = cell;
else if (state == State.SelectSecond)
end = cell;
while (addedActorPreviews.Count > 0)
editorLayer.Remove(addedActorPreviews.Dequeue());

selectionLayer.SetCopyRegion(start, end);
if (copyFilters.HasFlag(MapCopyFilters.Actors))
while (removedActors.Count > 0)
editorLayer.Add(removedActors.Dequeue());
}

public void Dispose()
public string Text
{
selectionLayer.Clear();
get { return "Copied {0} tiles".F(tiles.Count); }
}
}

internal class UndoCopyPaste
{
public CPos Cell { get; private set; }
public TerrainTile MapTile { get; private set; }
public ResourceTile ResourceTile { get; private set; }
public byte Height { get; private set; }

public UndoCopyPaste(CPos cell, TerrainTile mapTile, ResourceTile resourceTile, byte height)
{
Cell = cell;
MapTile = mapTile;
ResourceTile = resourceTile;
Height = height;
}
}
}

0 comments on commit 5263eeb

Please sign in to comment.