Added Undo Redo to editor
This commit is contained in:
@@ -24,6 +24,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
readonly World world;
|
readonly World world;
|
||||||
readonly EditorActorLayer editorLayer;
|
readonly EditorActorLayer editorLayer;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly ActorPreviewWidget preview;
|
readonly ActorPreviewWidget preview;
|
||||||
readonly WVec centerOffset;
|
readonly WVec centerOffset;
|
||||||
@@ -38,6 +39,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
worldRenderer = wr;
|
worldRenderer = wr;
|
||||||
world = wr.World;
|
world = wr.World;
|
||||||
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
Actor = actor;
|
Actor = actor;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
@@ -101,33 +103,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Enforce first entry of ValidOwnerNames as owner if the actor has RequiresSpecificOwners
|
// Enforce first entry of ValidOwnerNames as owner if the actor has RequiresSpecificOwners
|
||||||
var ownerName = owner.Name;
|
var action = new AddActorAction(editorLayer, Actor, cell, owner, facing);
|
||||||
var specificOwnerInfo = Actor.TraitInfoOrDefault<RequiresSpecificOwnersInfo>();
|
editorActionManager.Add(action);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -151,4 +128,69 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AddActorAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Text = "Added {0} ({1})".F(editorActorPreview.Info.Name, editorActorPreview.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
editorLayer.Remove(editorActorPreview);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly EditorSelectionLayer selectionLayer;
|
readonly EditorSelectionLayer selectionLayer;
|
||||||
readonly EditorActorLayer editorLayer;
|
readonly EditorActorLayer editorLayer;
|
||||||
readonly Func<MapCopyFilters> getCopyFilters;
|
readonly Func<MapCopyFilters> getCopyFilters;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
|
||||||
State state;
|
State state;
|
||||||
CPos start;
|
CPos start;
|
||||||
@@ -46,6 +47,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
this.editorWidget = editorWidget;
|
this.editorWidget = editorWidget;
|
||||||
worldRenderer = wr;
|
worldRenderer = wr;
|
||||||
|
|
||||||
|
editorActionManager = wr.World.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
selectionLayer = wr.World.WorldActor.Trait<EditorSelectionLayer>();
|
selectionLayer = wr.World.WorldActor.Trait<EditorSelectionLayer>();
|
||||||
editorLayer = wr.World.WorldActor.Trait<EditorActorLayer>();
|
editorLayer = wr.World.WorldActor.Trait<EditorActorLayer>();
|
||||||
this.getCopyFilters = getCopyFilters;
|
this.getCopyFilters = getCopyFilters;
|
||||||
@@ -143,26 +146,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var kv in tiles)
|
var action = new CopyPasteEditorAction(copyFilters, worldRenderer.World.Map, tiles, previews, editorLayer, dest);
|
||||||
{
|
editorActionManager.Add(action);
|
||||||
if (copyFilters.HasFlag(MapCopyFilters.Terrain))
|
|
||||||
mapTiles[kv.Key] = kv.Value.Item1;
|
|
||||||
|
|
||||||
if (copyFilters.HasFlag(MapCopyFilters.Resources))
|
|
||||||
mapResources[kv.Key] = kv.Value.Item2;
|
|
||||||
|
|
||||||
mapHeight[kv.Key] = kv.Value.Item3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
|
||||||
{
|
|
||||||
var removeActors = dest.SelectMany(editorLayer.PreviewsAt).Distinct().ToList();
|
|
||||||
foreach (var preview in removeActors)
|
|
||||||
editorLayer.Remove(preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kv in previews)
|
|
||||||
editorLayer.Add(kv.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
@@ -187,4 +172,114 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
selectionLayer.Clear();
|
selectionLayer.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CopyPasteEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
Text = "Copied {0} tiles".F(tiles.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (copyFilters.HasFlag(MapCopyFilters.Resources))
|
||||||
|
mapResources[kv.Key] = kv.Value.Item2;
|
||||||
|
|
||||||
|
mapHeight[kv.Key] = kv.Value.Item3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
||||||
|
{
|
||||||
|
var removeActors = dest.SelectMany(editorLayer.PreviewsAt).Distinct().ToList();
|
||||||
|
foreach (var preview in removeActors)
|
||||||
|
{
|
||||||
|
removedActors.Enqueue(preview);
|
||||||
|
editorLayer.Remove(preview);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kv in previews)
|
||||||
|
addedActorPreviews.Enqueue(editorLayer.Add(kv.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
while (undoCopyPastes.Count > 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (addedActorPreviews.Count > 0)
|
||||||
|
editorLayer.Remove(addedActorPreviews.Dequeue());
|
||||||
|
|
||||||
|
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
||||||
|
while (removedActors.Count > 0)
|
||||||
|
editorLayer.Add(removedActors.Dequeue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly EditorActorLayer editorLayer;
|
readonly EditorActorLayer editorLayer;
|
||||||
readonly Dictionary<int, ResourceType> resources;
|
readonly Dictionary<int, ResourceType> resources;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
|
||||||
public EditorActorPreview SelectedActor;
|
public EditorActorPreview SelectedActor;
|
||||||
int2 worldPixel;
|
int2 worldPixel;
|
||||||
|
|
||||||
@@ -45,6 +47,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
editorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
resources = world.WorldActor.TraitsImplementing<ResourceType>()
|
resources = world.WorldActor.TraitsImplementing<ResourceType>()
|
||||||
.ToDictionary(r => r.Info.ResourceType, r => r);
|
.ToDictionary(r => r.Info.ResourceType, r => r);
|
||||||
|
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
long CalculateActorSelectionPriority(EditorActorPreview actor)
|
long CalculateActorSelectionPriority(EditorActorPreview actor)
|
||||||
@@ -74,7 +78,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
var underCursor = editorLayer.PreviewsAt(worldPixel).MinByOrDefault(CalculateActorSelectionPriority);
|
var underCursor = editorLayer.PreviewsAt(worldPixel).MinByOrDefault(CalculateActorSelectionPriority);
|
||||||
|
|
||||||
var mapResources = world.Map.Resources;
|
var mapResources = world.Map.Resources;
|
||||||
ResourceType type;
|
ResourceType type = null;
|
||||||
if (underCursor != null)
|
if (underCursor != null)
|
||||||
editorWidget.SetTooltip(underCursor.Tooltip);
|
editorWidget.SetTooltip(underCursor.Tooltip);
|
||||||
else if (mapResources.Contains(cell) && resources.TryGetValue(mapResources[cell].Type, out type))
|
else if (mapResources.Contains(cell) && resources.TryGetValue(mapResources[cell].Type, out type))
|
||||||
@@ -97,10 +101,10 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
editorWidget.SetTooltip(null);
|
editorWidget.SetTooltip(null);
|
||||||
|
|
||||||
if (underCursor != null && underCursor != SelectedActor)
|
if (underCursor != null && underCursor != SelectedActor)
|
||||||
editorLayer.Remove(underCursor);
|
editorActionManager.Add(new RemoveActorAction(editorLayer, underCursor));
|
||||||
|
|
||||||
if (mapResources.Contains(cell) && mapResources[cell].Type != 0)
|
if (mapResources.Contains(cell) && mapResources[cell].Type != 0)
|
||||||
mapResources[cell] = default(ResourceTile);
|
editorActionManager.Add(new RemoveResourceAction(mapResources, cell, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -109,4 +113,69 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
public void Tick() { }
|
public void Tick() { }
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RemoveActorAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
readonly EditorActorLayer editorActorLayer;
|
||||||
|
readonly EditorActorPreview actor;
|
||||||
|
|
||||||
|
public RemoveActorAction(EditorActorLayer editorActorLayer, EditorActorPreview actor)
|
||||||
|
{
|
||||||
|
this.editorActorLayer = editorActorLayer;
|
||||||
|
this.actor = actor;
|
||||||
|
|
||||||
|
Text = "Removed {0} ({1})".F(actor.Info.Name, actor.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
editorActorLayer.Remove(actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
editorActorLayer.Add(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RemoveResourceAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
readonly CellLayer<ResourceTile> mapResources;
|
||||||
|
readonly CPos cell;
|
||||||
|
|
||||||
|
ResourceTile resourceTile;
|
||||||
|
|
||||||
|
public RemoveResourceAction(CellLayer<ResourceTile> mapResources, CPos cell, ResourceType type)
|
||||||
|
{
|
||||||
|
this.mapResources = mapResources;
|
||||||
|
this.cell = cell;
|
||||||
|
|
||||||
|
Text = "Removed {0}".F(type.Info.TerrainType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
resourceTile = mapResources[cell];
|
||||||
|
mapResources[cell] = default(ResourceTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
mapResources[cell] = resourceTile;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
@@ -23,6 +24,10 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly World world;
|
readonly World world;
|
||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly SpriteWidget preview;
|
readonly SpriteWidget preview;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
|
||||||
|
AddResourcesEditorAction action;
|
||||||
|
bool resourceAdded;
|
||||||
|
|
||||||
public EditorResourceBrush(EditorViewportControllerWidget editorWidget, ResourceTypeInfo resource, WorldRenderer wr)
|
public EditorResourceBrush(EditorViewportControllerWidget editorWidget, ResourceTypeInfo resource, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
@@ -30,6 +35,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
ResourceType = resource;
|
ResourceType = resource;
|
||||||
worldRenderer = wr;
|
worldRenderer = wr;
|
||||||
world = wr.World;
|
world = wr.World;
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
action = new AddResourcesEditorAction(world.Map, ResourceType);
|
||||||
|
|
||||||
preview = editorWidget.Get<SpriteWidget>("DRAG_LAYER_PREVIEW");
|
preview = editorWidget.Get<SpriteWidget>("DRAG_LAYER_PREVIEW");
|
||||||
preview.Palette = resource.Palette;
|
preview.Palette = resource.Palette;
|
||||||
@@ -65,11 +72,18 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
|
||||||
if (mi.Button == MouseButton.Left && AllowResourceAt(cell))
|
if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up && AllowResourceAt(cell))
|
||||||
{
|
{
|
||||||
var type = (byte)ResourceType.ResourceType;
|
var type = (byte)ResourceType.ResourceType;
|
||||||
var index = (byte)ResourceType.MaxDensity;
|
var index = (byte)ResourceType.MaxDensity;
|
||||||
world.Map.Resources[cell] = new ResourceTile(type, index);
|
action.Add(new CellResource(cell, world.Map.Resources[cell], new ResourceTile(type, index)));
|
||||||
|
resourceAdded = true;
|
||||||
|
}
|
||||||
|
else if (resourceAdded && mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
|
||||||
|
{
|
||||||
|
editorActionManager.Add(action);
|
||||||
|
action = new AddResourcesEditorAction(world.Map, ResourceType);
|
||||||
|
resourceAdded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -112,4 +126,63 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CellResource
|
||||||
|
{
|
||||||
|
public readonly CPos Cell;
|
||||||
|
public readonly ResourceTile ResourceTile;
|
||||||
|
public readonly ResourceTile NewResourceTile;
|
||||||
|
|
||||||
|
public CellResource(CPos cell, ResourceTile resourceTile, ResourceTile newResourceTile)
|
||||||
|
{
|
||||||
|
Cell = cell;
|
||||||
|
ResourceTile = resourceTile;
|
||||||
|
NewResourceTile = newResourceTile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddResourcesEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
readonly Map map;
|
||||||
|
readonly ResourceTypeInfo resourceType;
|
||||||
|
readonly List<CellResource> cellResources = new List<CellResource>();
|
||||||
|
|
||||||
|
public AddResourcesEditorAction(Map map, ResourceTypeInfo resourceType)
|
||||||
|
{
|
||||||
|
this.map = map;
|
||||||
|
this.resourceType = resourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
foreach (var resourceCell in cellResources)
|
||||||
|
SetTile(resourceCell.Cell, resourceCell.NewResourceTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTile(CPos cell, ResourceTile tile)
|
||||||
|
{
|
||||||
|
map.Resources[cell] = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
foreach (var resourceCell in cellResources)
|
||||||
|
SetTile(resourceCell.Cell, resourceCell.ResourceTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(CellResource cellResource)
|
||||||
|
{
|
||||||
|
SetTile(cellResource.Cell, cellResource.NewResourceTile);
|
||||||
|
cellResources.Add(cellResource);
|
||||||
|
|
||||||
|
var cellText = cellResources.Count != 1 ? "cells" : "cell";
|
||||||
|
Text = "Added {0} {1} of {2}".F(cellResources.Count, cellText, resourceType.TerrainType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
@@ -26,6 +27,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly EditorViewportControllerWidget editorWidget;
|
readonly EditorViewportControllerWidget editorWidget;
|
||||||
readonly TerrainTemplatePreviewWidget preview;
|
readonly TerrainTemplatePreviewWidget preview;
|
||||||
readonly Rectangle bounds;
|
readonly Rectangle bounds;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
|
||||||
bool painting;
|
bool painting;
|
||||||
|
|
||||||
@@ -36,6 +38,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
worldRenderer = wr;
|
worldRenderer = wr;
|
||||||
world = wr.World;
|
world = wr.World;
|
||||||
|
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
preview = editorWidget.Get<TerrainTemplatePreviewWidget>("DRAG_TILE_PREVIEW");
|
preview = editorWidget.Get<TerrainTemplatePreviewWidget>("DRAG_TILE_PREVIEW");
|
||||||
preview.GetScale = () => worldRenderer.Viewport.Zoom;
|
preview.GetScale = () => worldRenderer.Viewport.Zoom;
|
||||||
preview.IsVisible = () => editorWidget.CurrentBrush == this;
|
preview.IsVisible = () => editorWidget.CurrentBrush == this;
|
||||||
@@ -97,33 +101,13 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
void PaintCell(CPos cell, bool isMoving)
|
void PaintCell(CPos cell, bool isMoving)
|
||||||
{
|
{
|
||||||
var map = world.Map;
|
var map = world.Map;
|
||||||
var mapTiles = map.Tiles;
|
|
||||||
var mapHeight = map.Height;
|
|
||||||
|
|
||||||
var tileset = map.Rules.TileSet;
|
var tileset = map.Rules.TileSet;
|
||||||
var template = tileset.Templates[Template];
|
var template = tileset.Templates[Template];
|
||||||
var baseHeight = mapHeight.Contains(cell) ? mapHeight[cell] : (byte)0;
|
|
||||||
|
|
||||||
if (isMoving && PlacementOverlapsSameTemplate(template, cell))
|
if (isMoving && PlacementOverlapsSameTemplate(template, cell))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var i = 0;
|
editorActionManager.Add(new PaintTileEditorAction(Template, map, cell));
|
||||||
for (var y = 0; y < template.Size.Y; y++)
|
|
||||||
{
|
|
||||||
for (var x = 0; x < template.Size.X; x++, i++)
|
|
||||||
{
|
|
||||||
if (template.Contains(i) && template[i] != null)
|
|
||||||
{
|
|
||||||
var index = template.PickAny ? (byte)Game.CosmeticRandom.Next(0, template.TilesCount) : (byte)i;
|
|
||||||
var c = cell + new CVec(x, y);
|
|
||||||
if (!mapTiles.Contains(c))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mapTiles[c] = new TerrainTile(Template, index);
|
|
||||||
mapHeight[c] = (byte)(baseHeight + template[index].Height).Clamp(0, map.Grid.MaximumTerrainHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloodFillWithBrush(CPos cell, bool isMoving)
|
void FloodFillWithBrush(CPos cell, bool isMoving)
|
||||||
@@ -239,4 +223,87 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PaintTileEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
readonly ushort template;
|
||||||
|
readonly Map map;
|
||||||
|
readonly CPos cell;
|
||||||
|
|
||||||
|
readonly Queue<UndoTile> undoTiles = new Queue<UndoTile>();
|
||||||
|
readonly TerrainTemplateInfo terrainTemplate;
|
||||||
|
|
||||||
|
public PaintTileEditorAction(ushort template, Map map, CPos cell)
|
||||||
|
{
|
||||||
|
this.template = template;
|
||||||
|
this.map = map;
|
||||||
|
this.cell = cell;
|
||||||
|
|
||||||
|
var tileset = map.Rules.TileSet;
|
||||||
|
terrainTemplate = tileset.Templates[template];
|
||||||
|
Text = "Added tile {0}".F(terrainTemplate.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
var mapTiles = map.Tiles;
|
||||||
|
var mapHeight = map.Height;
|
||||||
|
var baseHeight = mapHeight.Contains(cell) ? mapHeight[cell] : (byte)0;
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
for (var y = 0; y < terrainTemplate.Size.Y; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < terrainTemplate.Size.X; x++, i++)
|
||||||
|
{
|
||||||
|
if (terrainTemplate.Contains(i) && terrainTemplate[i] != null)
|
||||||
|
{
|
||||||
|
var index = terrainTemplate.PickAny ? (byte)Game.CosmeticRandom.Next(0, terrainTemplate.TilesCount) : (byte)i;
|
||||||
|
var c = cell + new CVec(x, y);
|
||||||
|
if (!mapTiles.Contains(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
undoTiles.Enqueue(new UndoTile(c, mapTiles[c], mapHeight[c]));
|
||||||
|
|
||||||
|
mapTiles[c] = new TerrainTile(template, index);
|
||||||
|
mapHeight[c] = (byte)(baseHeight + terrainTemplate[index].Height).Clamp(0, map.Grid.MaximumTerrainHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
var mapTiles = map.Tiles;
|
||||||
|
var mapHeight = map.Height;
|
||||||
|
|
||||||
|
while (undoTiles.Count > 0)
|
||||||
|
{
|
||||||
|
var undoTile = undoTiles.Dequeue();
|
||||||
|
|
||||||
|
mapTiles[undoTile.Cell] = undoTile.MapTile;
|
||||||
|
mapHeight[undoTile.Cell] = undoTile.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UndoTile
|
||||||
|
{
|
||||||
|
public CPos Cell { get; private set; }
|
||||||
|
public TerrainTile MapTile { get; private set; }
|
||||||
|
public byte Height { get; private set; }
|
||||||
|
|
||||||
|
public UndoTile(CPos cell, TerrainTile mapTile, byte height)
|
||||||
|
{
|
||||||
|
Cell = cell;
|
||||||
|
MapTile = mapTile;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
172
OpenRA.Mods.Common/Traits/World/EditorActionManager.cs
Normal file
172
OpenRA.Mods.Common/Traits/World/EditorActionManager.cs
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Traits
|
||||||
|
{
|
||||||
|
public class EditorActionManagerInfo : TraitInfo<EditorActionManager> { }
|
||||||
|
|
||||||
|
public class EditorActionManager : IWorldLoaded
|
||||||
|
{
|
||||||
|
readonly Stack<EditorActionContainer> undoStack = new Stack<EditorActionContainer>();
|
||||||
|
readonly Stack<EditorActionContainer> redoStack = new Stack<EditorActionContainer>();
|
||||||
|
|
||||||
|
public event Action<EditorActionContainer> ItemAdded;
|
||||||
|
public event Action<EditorActionContainer> ItemRemoved;
|
||||||
|
public event Action OnChange;
|
||||||
|
|
||||||
|
int nextId;
|
||||||
|
|
||||||
|
public void WorldLoaded(World w, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
Add(new OpenMapAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(IEditorAction editorAction)
|
||||||
|
{
|
||||||
|
editorAction.Execute();
|
||||||
|
|
||||||
|
if (undoStack.Count > 0)
|
||||||
|
undoStack.Peek().Status = EditorActionStatus.History;
|
||||||
|
|
||||||
|
var actionContainer = new EditorActionContainer(nextId++, editorAction);
|
||||||
|
|
||||||
|
ClearRedo();
|
||||||
|
undoStack.Push(actionContainer);
|
||||||
|
|
||||||
|
if (ItemAdded != null)
|
||||||
|
ItemAdded(actionContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
if (!HasUndos())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var editorAction = undoStack.Pop();
|
||||||
|
undoStack.Peek().Status = EditorActionStatus.Active;
|
||||||
|
editorAction.Action.Undo();
|
||||||
|
editorAction.Status = EditorActionStatus.Future;
|
||||||
|
redoStack.Push(editorAction);
|
||||||
|
|
||||||
|
if (OnChange != null)
|
||||||
|
OnChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearRedo()
|
||||||
|
{
|
||||||
|
while (HasRedos())
|
||||||
|
{
|
||||||
|
var item = redoStack.Pop();
|
||||||
|
|
||||||
|
if (ItemRemoved != null)
|
||||||
|
ItemRemoved(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Redo()
|
||||||
|
{
|
||||||
|
if (!HasRedos())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var editorAction = redoStack.Pop();
|
||||||
|
|
||||||
|
editorAction.Status = EditorActionStatus.Active;
|
||||||
|
editorAction.Action.Do();
|
||||||
|
undoStack.Peek().Status = EditorActionStatus.History;
|
||||||
|
undoStack.Push(editorAction);
|
||||||
|
|
||||||
|
if (OnChange != null)
|
||||||
|
OnChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasUndos()
|
||||||
|
{
|
||||||
|
// Preserve the initial OpenMapAction.
|
||||||
|
return undoStack.Count > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasRedos()
|
||||||
|
{
|
||||||
|
return redoStack.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rewind(int id)
|
||||||
|
{
|
||||||
|
while (undoStack.Peek().Id != id)
|
||||||
|
Undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Forward(int id)
|
||||||
|
{
|
||||||
|
while (undoStack.Peek().Id != id)
|
||||||
|
Redo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EditorActionStatus
|
||||||
|
{
|
||||||
|
History,
|
||||||
|
Active,
|
||||||
|
Future,
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IEditorAction
|
||||||
|
{
|
||||||
|
void Execute();
|
||||||
|
void Do();
|
||||||
|
void Undo();
|
||||||
|
|
||||||
|
string Text { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class OpenMapAction : IEditorAction
|
||||||
|
{
|
||||||
|
public OpenMapAction()
|
||||||
|
{
|
||||||
|
Text = "Opened";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
public EditorActionStatus Status { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EditorActionContainer
|
||||||
|
{
|
||||||
|
public int Id { get; private set; }
|
||||||
|
public IEditorAction Action { get; private set; }
|
||||||
|
public EditorActionStatus Status { get; set; }
|
||||||
|
|
||||||
|
public EditorActionContainer(int id, IEditorAction action)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Action = action;
|
||||||
|
Status = EditorActionStatus.Active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -110,8 +110,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var owner = Players.Players[reference.InitDict.Get<OwnerInit>().PlayerName];
|
var owner = Players.Players[reference.InitDict.Get<OwnerInit>().PlayerName];
|
||||||
|
|
||||||
var preview = new EditorActorPreview(worldRenderer, id, reference, owner);
|
var preview = new EditorActorPreview(worldRenderer, id, reference, owner);
|
||||||
previews.Add(preview);
|
|
||||||
|
|
||||||
|
Add(preview, initialSetup);
|
||||||
|
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(EditorActorPreview preview, bool initialSetup = false)
|
||||||
|
{
|
||||||
|
previews.Add(preview);
|
||||||
if (!preview.Bounds.IsEmpty)
|
if (!preview.Bounds.IsEmpty)
|
||||||
screenMap.Add(preview, preview.Bounds);
|
screenMap.Add(preview, preview.Bounds);
|
||||||
|
|
||||||
@@ -126,11 +133,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
UpdateNeighbours(preview.Footprint);
|
UpdateNeighbours(preview.Footprint);
|
||||||
|
|
||||||
if (reference.Type == "mpspawn")
|
if (preview.Actor.Type == "mpspawn")
|
||||||
SyncMultiplayerCount();
|
SyncMultiplayerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
return preview;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(EditorActorPreview preview)
|
public void Remove(EditorActorPreview preview)
|
||||||
@@ -262,7 +267,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
string NextActorName()
|
string NextActorName()
|
||||||
{
|
{
|
||||||
var id = previews.Count();
|
var id = previews.Count;
|
||||||
var possibleName = "Actor" + id.ToString();
|
var possibleName = "Actor" + id.ToString();
|
||||||
|
|
||||||
while (previews.Any(p => p.ID == possibleName))
|
while (previews.Any(p => p.ID == possibleName))
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
public class EditorActorPreview
|
public class EditorActorPreview : IEquatable<EditorActorPreview>
|
||||||
{
|
{
|
||||||
public readonly string DescriptiveName;
|
public readonly string DescriptiveName;
|
||||||
public readonly ActorInfo Info;
|
public readonly ActorInfo Info;
|
||||||
@@ -28,6 +28,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public readonly IReadOnlyDictionary<CPos, SubCell> Footprint;
|
public readonly IReadOnlyDictionary<CPos, SubCell> Footprint;
|
||||||
public readonly Rectangle Bounds;
|
public readonly Rectangle Bounds;
|
||||||
public readonly SelectionBoxRenderable SelectionBox;
|
public readonly SelectionBoxRenderable SelectionBox;
|
||||||
|
public readonly ActorReference Actor;
|
||||||
|
|
||||||
public string Tooltip
|
public string Tooltip
|
||||||
{
|
{
|
||||||
@@ -43,7 +44,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public SubCell SubCell { get; private set; }
|
public SubCell SubCell { get; private set; }
|
||||||
public bool Selected { get; set; }
|
public bool Selected { get; set; }
|
||||||
|
|
||||||
readonly ActorReference actor;
|
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
readonly TooltipInfoBase tooltip;
|
readonly TooltipInfoBase tooltip;
|
||||||
IActorPreview[] previews;
|
IActorPreview[] previews;
|
||||||
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference actor, PlayerReference owner)
|
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference actor, PlayerReference owner)
|
||||||
{
|
{
|
||||||
ID = id;
|
ID = id;
|
||||||
this.actor = actor;
|
Actor = actor;
|
||||||
Owner = owner;
|
Owner = owner;
|
||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
|
|
||||||
@@ -120,25 +120,25 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public void ReplaceInit<T>(T init)
|
public void ReplaceInit<T>(T init)
|
||||||
{
|
{
|
||||||
var original = actor.InitDict.GetOrDefault<T>();
|
var original = Actor.InitDict.GetOrDefault<T>();
|
||||||
if (original != null)
|
if (original != null)
|
||||||
actor.InitDict.Remove(original);
|
Actor.InitDict.Remove(original);
|
||||||
|
|
||||||
actor.InitDict.Add(init);
|
Actor.InitDict.Add(init);
|
||||||
GeneratePreviews();
|
GeneratePreviews();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveInit<T>()
|
public void RemoveInit<T>()
|
||||||
{
|
{
|
||||||
var original = actor.InitDict.GetOrDefault<T>();
|
var original = Actor.InitDict.GetOrDefault<T>();
|
||||||
if (original != null)
|
if (original != null)
|
||||||
actor.InitDict.Remove(original);
|
Actor.InitDict.Remove(original);
|
||||||
GeneratePreviews();
|
GeneratePreviews();
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Init<T>()
|
public T Init<T>()
|
||||||
{
|
{
|
||||||
return actor.InitDict.GetOrDefault<T>();
|
return Actor.InitDict.GetOrDefault<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiniYaml Save()
|
public MiniYaml Save()
|
||||||
@@ -154,7 +154,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
return actor.Save(saveInit);
|
return Actor.Save(saveInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
WPos PreviewPosition(World world, TypeDictionary init)
|
WPos PreviewPosition(World world, TypeDictionary init)
|
||||||
@@ -167,7 +167,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
var cell = init.Get<LocationInit>().Value(world);
|
var cell = init.Get<LocationInit>().Value(world);
|
||||||
var offset = WVec.Zero;
|
var offset = WVec.Zero;
|
||||||
|
|
||||||
var subCellInit = actor.InitDict.GetOrDefault<SubCellInit>();
|
var subCellInit = Actor.InitDict.GetOrDefault<SubCellInit>();
|
||||||
var subCell = subCellInit != null ? subCellInit.Value(worldRenderer.World) : SubCell.Any;
|
var subCell = subCellInit != null ? subCellInit.Value(worldRenderer.World) : SubCell.Any;
|
||||||
|
|
||||||
var buildingInfo = Info.TraitInfoOrDefault<BuildingInfo>();
|
var buildingInfo = Info.TraitInfoOrDefault<BuildingInfo>();
|
||||||
@@ -182,7 +182,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
void GeneratePreviews()
|
void GeneratePreviews()
|
||||||
{
|
{
|
||||||
var init = new ActorPreviewInitializer(Info, worldRenderer, actor.InitDict);
|
var init = new ActorPreviewInitializer(Info, worldRenderer, Actor.InitDict);
|
||||||
previews = Info.TraitInfos<IRenderActorPreviewInfo>()
|
previews = Info.TraitInfos<IRenderActorPreviewInfo>()
|
||||||
.SelectMany(rpi => rpi.RenderPreview(init))
|
.SelectMany(rpi => rpi.RenderPreview(init))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -190,12 +190,39 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public ActorReference Export()
|
public ActorReference Export()
|
||||||
{
|
{
|
||||||
return new ActorReference(actor.Type, actor.Save().ToDictionary());
|
return new ActorReference(Actor.Type, Actor.Save().ToDictionary());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return "{0} {1}".F(Info.Name, ID);
|
return "{0} {1}".F(Info.Name, ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Equals(EditorActorPreview other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other))
|
||||||
|
return false;
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return string.Equals(ID, other.ID, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj))
|
||||||
|
return false;
|
||||||
|
if (ReferenceEquals(this, obj))
|
||||||
|
return true;
|
||||||
|
if (obj.GetType() != GetType())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Equals((EditorActorPreview)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ID != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(ID) : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets
|
namespace OpenRA.Mods.Common.Widgets
|
||||||
@@ -25,6 +26,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
readonly Lazy<TooltipContainerWidget> tooltipContainer;
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
|
||||||
bool enableTooltips;
|
bool enableTooltips;
|
||||||
|
|
||||||
@@ -34,6 +36,14 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
tooltipContainer = Exts.Lazy(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
|
tooltipContainer = Exts.Lazy(() => Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
|
||||||
CurrentBrush = DefaultBrush = new EditorDefaultBrush(this, worldRenderer);
|
CurrentBrush = DefaultBrush = new EditorDefaultBrush(this, worldRenderer);
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
|
editorActionManager.OnChange += EditorActionManagerOnChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorActionManagerOnChange()
|
||||||
|
{
|
||||||
|
DefaultBrush.SelectedActor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearBrush() { SetBrush(null); }
|
public void ClearBrush() { SetBrush(null); }
|
||||||
@@ -109,5 +119,11 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
cachedViewportPosition = worldRenderer.Viewport.CenterPosition;
|
cachedViewportPosition = worldRenderer.Viewport.CenterPosition;
|
||||||
CurrentBrush.Tick();
|
CurrentBrush.Tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Removed()
|
||||||
|
{
|
||||||
|
base.Removed();
|
||||||
|
editorActionManager.OnChange -= EditorActionManagerOnChange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
readonly EditorActorLayer editorActorLayer;
|
readonly EditorActorLayer editorActorLayer;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
readonly EditorViewportControllerWidget editor;
|
readonly EditorViewportControllerWidget editor;
|
||||||
readonly BackgroundWidget actorEditPanel;
|
readonly BackgroundWidget actorEditPanel;
|
||||||
readonly LabelWidget typeLabel;
|
readonly LabelWidget typeLabel;
|
||||||
@@ -48,6 +49,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
string initialActorID;
|
string initialActorID;
|
||||||
|
|
||||||
EditorActorPreview currentActorInner;
|
EditorActorPreview currentActorInner;
|
||||||
|
EditActorPreview editActorPreview;
|
||||||
|
|
||||||
EditorActorPreview CurrentActor
|
EditorActorPreview CurrentActor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -61,7 +64,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (currentActorInner != null)
|
if (currentActorInner != null)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
currentActorInner.Selected = false;
|
currentActorInner.Selected = false;
|
||||||
|
}
|
||||||
|
|
||||||
currentActorInner = value;
|
currentActorInner = value;
|
||||||
if (currentActorInner != null)
|
if (currentActorInner != null)
|
||||||
@@ -74,6 +80,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
editorActorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
editorActorLayer = world.WorldActor.Trait<EditorActorLayer>();
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
editor = widget.Parent.Get<EditorViewportControllerWidget>("MAP_EDITOR");
|
||||||
actorEditPanel = editor.Get<BackgroundWidget>("ACTOR_EDIT_PANEL");
|
actorEditPanel = editor.Get<BackgroundWidget>("ACTOR_EDIT_PANEL");
|
||||||
|
|
||||||
@@ -88,7 +96,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
initContainer.RemoveChildren();
|
initContainer.RemoveChildren();
|
||||||
|
|
||||||
var deleteButton = actorEditPanel.Get<ButtonWidget>("DELETE_BUTTON");
|
var deleteButton = actorEditPanel.Get<ButtonWidget>("DELETE_BUTTON");
|
||||||
var closeButton = actorEditPanel.Get<ButtonWidget>("CLOSE_BUTTON");
|
var cancelButton = actorEditPanel.Get<ButtonWidget>("CANCEL_BUTTON");
|
||||||
|
var okButton = actorEditPanel.Get<ButtonWidget>("OK_BUTTON");
|
||||||
|
|
||||||
actorIDErrorLabel = actorEditPanel.Get<LabelWidget>("ACTOR_ID_ERROR_LABEL");
|
actorIDErrorLabel = actorEditPanel.Get<LabelWidget>("ACTOR_ID_ERROR_LABEL");
|
||||||
actorIDErrorLabel.IsVisible = () => actorIDStatus != ActorIDStatus.Normal;
|
actorIDErrorLabel.IsVisible = () => actorIDStatus != ActorIDStatus.Normal;
|
||||||
@@ -99,7 +108,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
if (logicArgs.TryGetValue("EditPanelPadding", out yaml))
|
if (logicArgs.TryGetValue("EditPanelPadding", out yaml))
|
||||||
editPanelPadding = FieldLoader.GetValue<int>("EditPanelPadding", yaml.Value);
|
editPanelPadding = FieldLoader.GetValue<int>("EditPanelPadding", yaml.Value);
|
||||||
|
|
||||||
closeButton.OnClick = Close;
|
okButton.IsDisabled = () => !IsValid() || !editActorPreview.IsDirty;
|
||||||
|
okButton.OnClick = Save;
|
||||||
|
cancelButton.OnClick = Cancel;
|
||||||
deleteButton.OnClick = Delete;
|
deleteButton.OnClick = Delete;
|
||||||
actorEditPanel.IsVisible = () => CurrentActor != null
|
actorEditPanel.IsVisible = () => CurrentActor != null
|
||||||
&& editor.CurrentBrush == editor.DefaultBrush
|
&& editor.CurrentBrush == editor.DefaultBrush
|
||||||
@@ -113,15 +124,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
actorIDField.OnTextEdited = () =>
|
actorIDField.OnTextEdited = () =>
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(actorIDField.Text))
|
var actorId = actorIDField.Text.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(actorId))
|
||||||
{
|
{
|
||||||
nextActorIDStatus = ActorIDStatus.Empty;
|
nextActorIDStatus = ActorIDStatus.Empty;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for duplicate actor ID
|
// Check for duplicate actor ID
|
||||||
var actorId = actorIDField.Text.ToLowerInvariant();
|
if (CurrentActor.ID.Equals(actorId, StringComparison.OrdinalIgnoreCase))
|
||||||
if (CurrentActor.ID.ToLowerInvariant() != actorId)
|
|
||||||
{
|
{
|
||||||
if (editorActorLayer[actorId] != null)
|
if (editorActorLayer[actorId] != null)
|
||||||
{
|
{
|
||||||
@@ -130,23 +141,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetActorID(world, actorId);
|
SetActorID(actorId);
|
||||||
|
nextActorIDStatus = ActorIDStatus.Normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
actorIDField.OnLoseFocus = () =>
|
actorIDField.OnLoseFocus = () =>
|
||||||
{
|
{
|
||||||
// Reset invalid IDs back to their starting value
|
// Reset invalid IDs back to their starting value
|
||||||
if (actorIDStatus != ActorIDStatus.Normal)
|
if (actorIDStatus != ActorIDStatus.Normal)
|
||||||
SetActorID(world, initialActorID);
|
SetActorID(initialActorID);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetActorID(World world, string actorId)
|
void SetActorID(string actorId)
|
||||||
{
|
{
|
||||||
CurrentActor.ID = actorId;
|
editActorPreview.SetActorID(actorId);
|
||||||
|
|
||||||
nextActorIDStatus = ActorIDStatus.Normal;
|
nextActorIDStatus = ActorIDStatus.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsValid()
|
||||||
|
{
|
||||||
|
return nextActorIDStatus == ActorIDStatus.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Tick()
|
public override void Tick()
|
||||||
{
|
{
|
||||||
if (actorIDStatus != nextActorIDStatus)
|
if (actorIDStatus != nextActorIDStatus)
|
||||||
@@ -183,6 +201,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
lastScrollTime = 0; // Ensure visible
|
lastScrollTime = 0; // Ensure visible
|
||||||
CurrentActor = actor;
|
CurrentActor = actor;
|
||||||
|
|
||||||
|
editActorPreview = new EditActorPreview(CurrentActor);
|
||||||
|
|
||||||
initialActorID = actorIDField.Text = actor.ID;
|
initialActorID = actorIDField.Text = actor.ID;
|
||||||
|
|
||||||
var font = Game.Renderer.Fonts[typeLabel.Font];
|
var font = Game.Renderer.Fonts[typeLabel.Font];
|
||||||
@@ -203,13 +223,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var ownerDropdown = ownerContainer.Get<DropDownButtonWidget>("OPTION");
|
var ownerDropdown = ownerContainer.Get<DropDownButtonWidget>("OPTION");
|
||||||
var selectedOwner = actor.Owner;
|
var selectedOwner = actor.Owner;
|
||||||
|
|
||||||
|
Action<EditorActorPreview, PlayerReference> updateOwner = (preview, reference) =>
|
||||||
|
{
|
||||||
|
preview.Owner = reference;
|
||||||
|
preview.ReplaceInit(new OwnerInit(reference.Name));
|
||||||
|
};
|
||||||
|
|
||||||
|
var ownerHandler = new EditorActorOptionActionHandle<PlayerReference>(updateOwner, actor.Owner);
|
||||||
|
editActorPreview.Add(ownerHandler);
|
||||||
|
|
||||||
Func<PlayerReference, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
Func<PlayerReference, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
|
||||||
{
|
{
|
||||||
var item = ScrollItemWidget.Setup(template, () => selectedOwner == option, () =>
|
var item = ScrollItemWidget.Setup(template, () => selectedOwner == option, () =>
|
||||||
{
|
{
|
||||||
selectedOwner = option;
|
selectedOwner = option;
|
||||||
CurrentActor.Owner = selectedOwner;
|
updateOwner(CurrentActor, selectedOwner);
|
||||||
CurrentActor.ReplaceInit(new OwnerInit(selectedOwner.Name));
|
ownerHandler.OnChange(option);
|
||||||
});
|
});
|
||||||
|
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => option.Name;
|
item.Get<LabelWidget>("LABEL").GetText = () => option.Name;
|
||||||
@@ -248,8 +277,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
slider.MaximumValue = so.MaxValue;
|
slider.MaximumValue = so.MaxValue;
|
||||||
slider.Ticks = so.Ticks;
|
slider.Ticks = so.Ticks;
|
||||||
|
|
||||||
|
var editorActionHandle = new EditorActorOptionActionHandle<float>(so.OnChange, so.GetValue(actor));
|
||||||
|
editActorPreview.Add(editorActionHandle);
|
||||||
|
|
||||||
slider.GetValue = () => so.GetValue(actor);
|
slider.GetValue = () => so.GetValue(actor);
|
||||||
slider.OnChange += value => so.OnChange(actor, value);
|
slider.OnChange += value => so.OnChange(actor, value);
|
||||||
|
slider.OnChange += value => editorActionHandle.OnChange(value);
|
||||||
|
|
||||||
initContainer.AddChild(sliderContainer);
|
initContainer.AddChild(sliderContainer);
|
||||||
}
|
}
|
||||||
@@ -261,12 +294,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
initContainer.Bounds.Height += dropdownContainer.Bounds.Height;
|
initContainer.Bounds.Height += dropdownContainer.Bounds.Height;
|
||||||
dropdownContainer.Get<LabelWidget>("LABEL").GetText = () => ddo.Name;
|
dropdownContainer.Get<LabelWidget>("LABEL").GetText = () => ddo.Name;
|
||||||
|
|
||||||
|
var editorActionHandle = new EditorActorOptionActionHandle<string>(ddo.OnChange, ddo.GetValue(actor));
|
||||||
|
editActorPreview.Add(editorActionHandle);
|
||||||
|
|
||||||
var dropdown = dropdownContainer.Get<DropDownButtonWidget>("OPTION");
|
var dropdown = dropdownContainer.Get<DropDownButtonWidget>("OPTION");
|
||||||
Func<KeyValuePair<string, string>, ScrollItemWidget, ScrollItemWidget> dropdownSetup = (option, template) =>
|
Func<KeyValuePair<string, string>, ScrollItemWidget, ScrollItemWidget> dropdownSetup = (option, template) =>
|
||||||
{
|
{
|
||||||
var item = ScrollItemWidget.Setup(template,
|
var item = ScrollItemWidget.Setup(template,
|
||||||
() => ddo.GetValue(actor) == option.Key,
|
() => ddo.GetValue(actor) == option.Key,
|
||||||
() => ddo.OnChange(actor, option.Key));
|
() =>
|
||||||
|
{
|
||||||
|
ddo.OnChange(actor, option.Key);
|
||||||
|
editorActionHandle.OnChange(option.Key);
|
||||||
|
});
|
||||||
|
|
||||||
item.Get<LabelWidget>("LABEL").GetText = () => option.Value;
|
item.Get<LabelWidget>("LABEL").GetText = () => option.Value;
|
||||||
return item;
|
return item;
|
||||||
@@ -298,16 +338,180 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
void Delete()
|
void Delete()
|
||||||
{
|
{
|
||||||
if (CurrentActor != null)
|
if (CurrentActor != null)
|
||||||
editorActorLayer.Remove(CurrentActor);
|
editorActionManager.Add(new RemoveActorAction(editorActorLayer, CurrentActor));
|
||||||
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cancel()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
if (editActorPreview != null)
|
||||||
|
editActorPreview.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
void Close()
|
void Close()
|
||||||
{
|
{
|
||||||
actorIDField.YieldKeyboardFocus();
|
actorIDField.YieldKeyboardFocus();
|
||||||
editor.DefaultBrush.SelectedActor = null;
|
editor.DefaultBrush.SelectedActor = null;
|
||||||
CurrentActor = null;
|
CurrentActor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Save()
|
||||||
|
{
|
||||||
|
editorActionManager.Add(new EditActorEditorAction(editorActorLayer, CurrentActor, editActorPreview.GetDirtyHandles()));
|
||||||
|
editActorPreview = null;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EditorActorOptionActionHandle<T> : IEditActorHandle
|
||||||
|
{
|
||||||
|
readonly Action<EditorActorPreview, T> change;
|
||||||
|
T value;
|
||||||
|
readonly T initialValue;
|
||||||
|
|
||||||
|
public EditorActorOptionActionHandle(Action<EditorActorPreview, T> change, T value)
|
||||||
|
{
|
||||||
|
this.change = change;
|
||||||
|
this.value = value;
|
||||||
|
initialValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnChange(T value)
|
||||||
|
{
|
||||||
|
IsDirty = !EqualityComparer<T>.Default.Equals(initialValue, value);
|
||||||
|
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do(EditorActorPreview actor)
|
||||||
|
{
|
||||||
|
change(actor, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo(EditorActorPreview actor)
|
||||||
|
{
|
||||||
|
change(actor, initialValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDirty { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IEditActorHandle
|
||||||
|
{
|
||||||
|
void Do(EditorActorPreview actor);
|
||||||
|
void Undo(EditorActorPreview actor);
|
||||||
|
bool IsDirty { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditActorEditorAction : IEditorAction
|
||||||
|
{
|
||||||
|
public string Text { get; private set; }
|
||||||
|
|
||||||
|
readonly IEnumerable<IEditActorHandle> handles;
|
||||||
|
readonly EditorActorLayer editorActorLayer;
|
||||||
|
EditorActorPreview actor;
|
||||||
|
readonly string actorId;
|
||||||
|
|
||||||
|
public EditActorEditorAction(EditorActorLayer editorActorLayer, EditorActorPreview actor, IEnumerable<IEditActorHandle> handles)
|
||||||
|
{
|
||||||
|
this.editorActorLayer = editorActorLayer;
|
||||||
|
actorId = actor.ID;
|
||||||
|
this.actor = actor;
|
||||||
|
this.handles = handles;
|
||||||
|
Text = "Edited {0} ({1})".F(actor.Info.Name, actor.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do()
|
||||||
|
{
|
||||||
|
actor = editorActorLayer[actorId.ToLowerInvariant()];
|
||||||
|
foreach (var editorActionHandle in handles)
|
||||||
|
editorActionHandle.Do(actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo()
|
||||||
|
{
|
||||||
|
foreach (var editorActionHandle in handles)
|
||||||
|
editorActionHandle.Undo(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EditActorPreview
|
||||||
|
{
|
||||||
|
readonly EditorActorPreview actor;
|
||||||
|
readonly SetActorIdAction setActorIdAction;
|
||||||
|
readonly List<IEditActorHandle> handles = new List<IEditActorHandle>();
|
||||||
|
|
||||||
|
public EditActorPreview(EditorActorPreview actor)
|
||||||
|
{
|
||||||
|
this.actor = actor;
|
||||||
|
setActorIdAction = new SetActorIdAction(actor.ID);
|
||||||
|
handles.Add(setActorIdAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDirty
|
||||||
|
{
|
||||||
|
get { return handles.Any(h => h.IsDirty); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetActorID(string actorID)
|
||||||
|
{
|
||||||
|
setActorIdAction.Set(actorID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(IEditActorHandle editActor)
|
||||||
|
{
|
||||||
|
handles.Add(editActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IEditActorHandle> GetDirtyHandles()
|
||||||
|
{
|
||||||
|
return handles.Where(h => h.IsDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
foreach (var handle in handles.Where(h => h.IsDirty))
|
||||||
|
handle.Undo(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SetActorIdAction : IEditActorHandle
|
||||||
|
{
|
||||||
|
readonly string initial;
|
||||||
|
string newID;
|
||||||
|
|
||||||
|
public void Set(string actorId)
|
||||||
|
{
|
||||||
|
IsDirty = initial != actorId;
|
||||||
|
newID = actorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetActorIdAction(string initial)
|
||||||
|
{
|
||||||
|
this.initial = initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do(EditorActorPreview actor)
|
||||||
|
{
|
||||||
|
actor.ID = newID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Undo(EditorActorPreview actor)
|
||||||
|
{
|
||||||
|
actor.ID = initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDirty { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
71
OpenRA.Mods.Common/Widgets/Logic/Editor/HistoryLogLogic.cs
Normal file
71
OpenRA.Mods.Common/Widgets/Logic/Editor/HistoryLogLogic.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
|
{
|
||||||
|
public class HistoryLogLogic : ChromeLogic
|
||||||
|
{
|
||||||
|
readonly ScrollPanelWidget panel;
|
||||||
|
readonly EditorActionManager editorActionManager;
|
||||||
|
readonly ScrollItemWidget template;
|
||||||
|
|
||||||
|
readonly Dictionary<EditorActionContainer, ScrollItemWidget> states = new Dictionary<EditorActionContainer, ScrollItemWidget>();
|
||||||
|
|
||||||
|
[ObjectCreator.UseCtor]
|
||||||
|
public HistoryLogLogic(Widget widget, World world, WorldRenderer worldRenderer, Dictionary<string, MiniYaml> logicArgs)
|
||||||
|
{
|
||||||
|
panel = widget.Get<ScrollPanelWidget>("HISTORY_LIST");
|
||||||
|
template = panel.Get<ScrollItemWidget>("HISTORY_TEMPLATE");
|
||||||
|
editorActionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
|
||||||
|
editorActionManager.ItemAdded += ItemAdded;
|
||||||
|
editorActionManager.ItemRemoved += ItemRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemAdded(EditorActionContainer editorAction)
|
||||||
|
{
|
||||||
|
var item = ScrollItemWidget.Setup(template, () => false, () =>
|
||||||
|
{
|
||||||
|
if (editorAction.Status == EditorActionStatus.History)
|
||||||
|
editorActionManager.Rewind(editorAction.Id);
|
||||||
|
else if (editorAction.Status == EditorActionStatus.Future)
|
||||||
|
editorActionManager.Forward(editorAction.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
var titleLabel = item.Get<LabelWidget>("TITLE");
|
||||||
|
var textColor = template.TextColor;
|
||||||
|
var futureTextColor = template.TextColorDisabled;
|
||||||
|
|
||||||
|
titleLabel.GetText = () => editorAction.Action.Text;
|
||||||
|
titleLabel.GetColor = () => editorAction.Status == EditorActionStatus.Future ? futureTextColor : textColor;
|
||||||
|
|
||||||
|
item.IsSelected = () => editorAction.Status == EditorActionStatus.Active;
|
||||||
|
panel.AddChild(item);
|
||||||
|
|
||||||
|
states[editorAction] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemRemoved(EditorActionContainer editorAction)
|
||||||
|
{
|
||||||
|
var widget = states[editorAction];
|
||||||
|
|
||||||
|
panel.RemoveChild(widget);
|
||||||
|
|
||||||
|
states.Remove(editorAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -128,6 +128,21 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
if (reslayer != null)
|
if (reslayer != null)
|
||||||
cashLabel.GetText = () => "$ {0}".F(reslayer.NetWorth);
|
cashLabel.GetText = () => "$ {0}".F(reslayer.NetWorth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var actionManager = world.WorldActor.Trait<EditorActionManager>();
|
||||||
|
var undoButton = widget.GetOrNull<ButtonWidget>("UNDO_BUTTON");
|
||||||
|
if (undoButton != null)
|
||||||
|
{
|
||||||
|
undoButton.IsDisabled = () => !actionManager.HasUndos();
|
||||||
|
undoButton.OnClick = () => actionManager.Undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
var redoButton = widget.GetOrNull<ButtonWidget>("REDO_BUTTON");
|
||||||
|
if (redoButton != null)
|
||||||
|
{
|
||||||
|
redoButton.IsDisabled = () => !actionManager.HasRedos();
|
||||||
|
redoButton.OnClick = () => actionManager.Redo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget CreateCategoriesPanel()
|
Widget CreateCategoriesPanel()
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
readonly Widget widget;
|
readonly Widget widget;
|
||||||
|
|
||||||
protected enum MenuType { Tiles, Layers, Actors }
|
protected enum MenuType { Tiles, Layers, Actors, History }
|
||||||
protected MenuType menuType = MenuType.Tiles;
|
protected MenuType menuType = MenuType.Tiles;
|
||||||
readonly Widget tabContainer;
|
readonly Widget tabContainer;
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
SetupTab("TILES_TAB", "TILE_WIDGETS", MenuType.Tiles);
|
SetupTab("TILES_TAB", "TILE_WIDGETS", MenuType.Tiles);
|
||||||
SetupTab("OVERLAYS_TAB", "LAYER_WIDGETS", MenuType.Layers);
|
SetupTab("OVERLAYS_TAB", "LAYER_WIDGETS", MenuType.Layers);
|
||||||
SetupTab("ACTORS_TAB", "ACTOR_WIDGETS", MenuType.Actors);
|
SetupTab("ACTORS_TAB", "ACTOR_WIDGETS", MenuType.Actors);
|
||||||
|
SetupTab("HISTORY_TAB", "HISTORY_WIDGETS", MenuType.History);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupTab(string buttonId, string tabId, MenuType tabType)
|
void SetupTab(string buttonId, string tabId, MenuType tabType)
|
||||||
|
|||||||
@@ -292,15 +292,21 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Children:
|
Children:
|
||||||
Button@DELETE_BUTTON:
|
Button@DELETE_BUTTON:
|
||||||
X: 4
|
X: 4
|
||||||
Width: 85
|
Width: 75
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Delete
|
Text: Delete
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@CLOSE_BUTTON:
|
Button@CANCEL_BUTTON:
|
||||||
X: 180
|
X: 110
|
||||||
Width: 85
|
Width: 75
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Close
|
Text: Cancel
|
||||||
|
Font: Bold
|
||||||
|
Button@OK_BUTTON:
|
||||||
|
X: 190
|
||||||
|
Width: 75
|
||||||
|
Height: 25
|
||||||
|
Text: OK
|
||||||
Font: Bold
|
Font: Bold
|
||||||
ViewportController:
|
ViewportController:
|
||||||
Width: WINDOW_RIGHT
|
Width: WINDOW_RIGHT
|
||||||
@@ -318,10 +324,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
BookmarkRestoreKeyPrefix: MapBookmarkRestore
|
BookmarkRestoreKeyPrefix: MapBookmarkRestore
|
||||||
BookmarkKeyCount: 4
|
BookmarkKeyCount: 4
|
||||||
Background@RADAR_BG:
|
Background@RADAR_BG:
|
||||||
X: WINDOW_RIGHT - 255
|
X: WINDOW_RIGHT - 295
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 250
|
Width: 290
|
||||||
Height: 250
|
Height: 290
|
||||||
Background: panel-gray
|
Background: panel-gray
|
||||||
Children:
|
Children:
|
||||||
Radar@INGAME_RADAR:
|
Radar@INGAME_RADAR:
|
||||||
@@ -332,7 +338,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
MenuButton@OPTIONS_BUTTON:
|
MenuButton@OPTIONS_BUTTON:
|
||||||
Logic: MenuButtonsChromeLogic
|
Logic: MenuButtonsChromeLogic
|
||||||
Key: escape
|
Key: escape
|
||||||
X: WINDOW_RIGHT - 254 - WIDTH
|
X: WINDOW_RIGHT - 294 - WIDTH
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 30
|
Width: 30
|
||||||
Height: 25
|
Height: 25
|
||||||
@@ -346,10 +352,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
ImageName: options
|
ImageName: options
|
||||||
Container@TILE_WIDGETS:
|
Container@TILE_WIDGETS:
|
||||||
Logic: TileSelectorLogic
|
Logic: TileSelectorLogic
|
||||||
X: WINDOW_RIGHT - 255
|
X: WINDOW_RIGHT - 295
|
||||||
Y: 278
|
Y: 318
|
||||||
Width: 250
|
Width: 290
|
||||||
Height: WINDOW_BOTTOM - 370
|
Height: WINDOW_BOTTOM - 410
|
||||||
ClickThrough: false
|
ClickThrough: false
|
||||||
Children:
|
Children:
|
||||||
Container@TILES_BG:
|
Container@TILES_BG:
|
||||||
@@ -402,10 +408,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Y: 4
|
Y: 4
|
||||||
Container@LAYER_WIDGETS:
|
Container@LAYER_WIDGETS:
|
||||||
Logic: LayerSelectorLogic
|
Logic: LayerSelectorLogic
|
||||||
X: WINDOW_RIGHT - 255
|
X: WINDOW_RIGHT - 295
|
||||||
Y: 278
|
Y: 318
|
||||||
Width: 250
|
Width: 290
|
||||||
Height: WINDOW_BOTTOM - 370
|
Height: WINDOW_BOTTOM - 410
|
||||||
ClickThrough: false
|
ClickThrough: false
|
||||||
Children:
|
Children:
|
||||||
Container@LAYERS_BG:
|
Container@LAYERS_BG:
|
||||||
@@ -429,10 +435,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Visible: false
|
Visible: false
|
||||||
Container@ACTOR_WIDGETS:
|
Container@ACTOR_WIDGETS:
|
||||||
Logic: ActorSelectorLogic
|
Logic: ActorSelectorLogic
|
||||||
X: WINDOW_RIGHT - 255
|
X: WINDOW_RIGHT - 295
|
||||||
Y: 278
|
Y: 318
|
||||||
Width: 250
|
Width: 290
|
||||||
Height: WINDOW_BOTTOM - 370
|
Height: WINDOW_BOTTOM - 410
|
||||||
ClickThrough: false
|
ClickThrough: false
|
||||||
Children:
|
Children:
|
||||||
Container@ACTORS_BG:
|
Container@ACTORS_BG:
|
||||||
@@ -499,33 +505,72 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
X: 4
|
X: 4
|
||||||
Y: 4
|
Y: 4
|
||||||
Visible: true
|
Visible: true
|
||||||
|
Container@HISTORY_WIDGETS:
|
||||||
|
Logic: HistoryLogLogic
|
||||||
|
X: WINDOW_RIGHT - 295
|
||||||
|
Y: 318
|
||||||
|
Width: 290
|
||||||
|
Height: WINDOW_BOTTOM - 410
|
||||||
|
ClickThrough: false
|
||||||
|
Children:
|
||||||
|
Container@HISTORY_BG:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Children:
|
||||||
|
ScrollPanel@HISTORY_LIST:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
CollapseHiddenChildren: True
|
||||||
|
TopBottomSpacing: 4
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@HISTORY_TEMPLATE:
|
||||||
|
X: 4
|
||||||
|
Visible: false
|
||||||
|
Width: PARENT_RIGHT - 31
|
||||||
|
Height: 25
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
TextColor: ffffff
|
||||||
|
TextColorDisabled: 8f8f8f
|
||||||
|
Children:
|
||||||
|
Label@TITLE:
|
||||||
|
X: 5
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
Container@MAP_EDITOR_TAB_CONTAINER:
|
Container@MAP_EDITOR_TAB_CONTAINER:
|
||||||
Logic: MapEditorTabsLogic
|
Logic: MapEditorTabsLogic
|
||||||
X: WINDOW_RIGHT - 255
|
X: WINDOW_RIGHT - 295
|
||||||
Y: 254
|
Y: 294
|
||||||
Width: 250
|
Width: 290
|
||||||
Height: 25
|
Height: 25
|
||||||
ClickThrough: false
|
ClickThrough: false
|
||||||
Children:
|
Children:
|
||||||
Button@TILES_TAB:
|
Button@TILES_TAB:
|
||||||
Width: 81
|
Width: 71
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Tiles
|
Text: Tiles
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@OVERLAYS_TAB:
|
Button@OVERLAYS_TAB:
|
||||||
X: 80
|
X: 70
|
||||||
Width: 90
|
Width: 80
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Overlays
|
Text: Overlays
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@ACTORS_TAB:
|
Button@ACTORS_TAB:
|
||||||
X: 169
|
X: 149
|
||||||
Width: 81
|
Width: 71
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Actors
|
Text: Actors
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Button@HISTORY_TAB:
|
||||||
|
X: 219
|
||||||
|
Width: 71
|
||||||
|
Height: 25
|
||||||
|
Text: History
|
||||||
|
Font: Bold
|
||||||
Button@GRID_BUTTON:
|
Button@GRID_BUTTON:
|
||||||
X: WINDOW_RIGHT - 650
|
X: WINDOW_RIGHT - 690
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 100
|
Width: 100
|
||||||
Height: 25
|
Height: 25
|
||||||
@@ -536,7 +581,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
TooltipText: Toggle the terrain grid
|
TooltipText: Toggle the terrain grid
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
Label@ZOOM_LABEL:
|
Label@ZOOM_LABEL:
|
||||||
X: WINDOW_RIGHT - 730 - 55
|
X: WINDOW_RIGHT - 770 - 55
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 50
|
Width: 50
|
||||||
Height: 25
|
Height: 25
|
||||||
@@ -545,7 +590,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Font: Bold
|
Font: Bold
|
||||||
Contrast: true
|
Contrast: true
|
||||||
DropDownButton@ZOOM_BUTTON:
|
DropDownButton@ZOOM_BUTTON:
|
||||||
X: WINDOW_RIGHT - 730
|
X: WINDOW_RIGHT - 770
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 70
|
Width: 70
|
||||||
Height: 25
|
Height: 25
|
||||||
@@ -555,7 +600,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
TooltipText: Zoom
|
TooltipText: Zoom
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
Button@COPYPASTE_BUTTON:
|
Button@COPYPASTE_BUTTON:
|
||||||
X: WINDOW_RIGHT - 540
|
X: WINDOW_RIGHT - 580
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 96
|
Width: 96
|
||||||
Height: 25
|
Height: 25
|
||||||
@@ -565,7 +610,7 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
TooltipText: Copy
|
TooltipText: Copy
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
DropDownButton@COPYFILTER_BUTTON:
|
DropDownButton@COPYFILTER_BUTTON:
|
||||||
X: WINDOW_RIGHT - 435
|
X: WINDOW_RIGHT - 475
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 140
|
Width: 140
|
||||||
Height: 25
|
Height: 25
|
||||||
@@ -585,6 +630,26 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Align: Left
|
Align: Left
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Contrast: true
|
Contrast: true
|
||||||
|
Button@UNDO_BUTTON:
|
||||||
|
X: 200
|
||||||
|
Height: 25
|
||||||
|
Width: 100
|
||||||
|
Text: Undo
|
||||||
|
Font: Bold
|
||||||
|
Key: z ctrl
|
||||||
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
|
TooltipText: Undo last step
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Button@REDO_BUTTON:
|
||||||
|
X: 305
|
||||||
|
Height: 25
|
||||||
|
Width: 100
|
||||||
|
Text: Redo
|
||||||
|
Font: Bold
|
||||||
|
Key: y ctrl
|
||||||
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
|
TooltipText: Redo last step
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
|
||||||
ScrollPanel@CATEGORY_FILTER_PANEL:
|
ScrollPanel@CATEGORY_FILTER_PANEL:
|
||||||
Width: 190
|
Width: 190
|
||||||
|
|||||||
@@ -268,3 +268,4 @@ EditorWorld:
|
|||||||
EditorResourceLayer:
|
EditorResourceLayer:
|
||||||
EditorSelectionLayer:
|
EditorSelectionLayer:
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
|
EditorActionManager:
|
||||||
|
|||||||
@@ -287,15 +287,21 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Children:
|
Children:
|
||||||
Button@DELETE_BUTTON:
|
Button@DELETE_BUTTON:
|
||||||
X: 15
|
X: 15
|
||||||
Width: 85
|
Width: 75
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Delete
|
Text: Delete
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Button@CLOSE_BUTTON:
|
Button@CANCEL_BUTTON:
|
||||||
X: 195
|
X: 125
|
||||||
Width: 85
|
Width: 75
|
||||||
Height: 25
|
Height: 25
|
||||||
Text: Close
|
Text: Cancel
|
||||||
|
Font: Bold
|
||||||
|
Button@OK_BUTTON:
|
||||||
|
X: 205
|
||||||
|
Width: 75
|
||||||
|
Height: 25
|
||||||
|
Text: OK
|
||||||
Font: Bold
|
Font: Bold
|
||||||
ViewportController:
|
ViewportController:
|
||||||
Width: WINDOW_RIGHT
|
Width: WINDOW_RIGHT
|
||||||
@@ -313,10 +319,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
BookmarkRestoreKeyPrefix: MapBookmarkRestore
|
BookmarkRestoreKeyPrefix: MapBookmarkRestore
|
||||||
BookmarkKeyCount: 4
|
BookmarkKeyCount: 4
|
||||||
Background@RADAR_BG:
|
Background@RADAR_BG:
|
||||||
X: WINDOW_RIGHT - 255
|
X: WINDOW_RIGHT - 325
|
||||||
Y: 5
|
Y: 5
|
||||||
Width: 250
|
Width: 320
|
||||||
Height: 250
|
Height: 320
|
||||||
Children:
|
Children:
|
||||||
Radar@INGAME_RADAR:
|
Radar@INGAME_RADAR:
|
||||||
X: 10
|
X: 10
|
||||||
@@ -327,10 +333,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Logic: TileSelectorLogic
|
Logic: TileSelectorLogic
|
||||||
Children:
|
Children:
|
||||||
Background@TILES_BG:
|
Background@TILES_BG:
|
||||||
X: WINDOW_RIGHT - 250
|
X: WINDOW_RIGHT - 320
|
||||||
Y: 290
|
Y: 360
|
||||||
Width: 240
|
Width: 310
|
||||||
Height: WINDOW_BOTTOM - 382
|
Height: WINDOW_BOTTOM - 452
|
||||||
Children:
|
Children:
|
||||||
Label@SEARCH_LABEL:
|
Label@SEARCH_LABEL:
|
||||||
Y: 12
|
Y: 12
|
||||||
@@ -378,10 +384,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Logic: LayerSelectorLogic
|
Logic: LayerSelectorLogic
|
||||||
Children:
|
Children:
|
||||||
Background@LAYERS_BG:
|
Background@LAYERS_BG:
|
||||||
X: WINDOW_RIGHT - 250
|
X: WINDOW_RIGHT - 320
|
||||||
Y: 290
|
Y: 360
|
||||||
Width: 240
|
Width: 310
|
||||||
Height: WINDOW_BOTTOM - 382
|
Height: WINDOW_BOTTOM - 452
|
||||||
Children:
|
Children:
|
||||||
ScrollPanel@LAYERTEMPLATE_LIST:
|
ScrollPanel@LAYERTEMPLATE_LIST:
|
||||||
X: 10
|
X: 10
|
||||||
@@ -405,10 +411,10 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Logic: ActorSelectorLogic
|
Logic: ActorSelectorLogic
|
||||||
Children:
|
Children:
|
||||||
Background@ACTORS_BG:
|
Background@ACTORS_BG:
|
||||||
X: WINDOW_RIGHT - 250
|
X: WINDOW_RIGHT - 320
|
||||||
Y: 290
|
Y: 360
|
||||||
Width: 240
|
Width: 310
|
||||||
Height: WINDOW_BOTTOM - 382
|
Height: WINDOW_BOTTOM - 452
|
||||||
Children:
|
Children:
|
||||||
Label@SEARCH_LABEL:
|
Label@SEARCH_LABEL:
|
||||||
Y: 12
|
Y: 12
|
||||||
@@ -467,11 +473,44 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
X: 4
|
X: 4
|
||||||
Y: 4
|
Y: 4
|
||||||
Visible: true
|
Visible: true
|
||||||
|
Container@HISTORY_WIDGETS:
|
||||||
|
Logic: HistoryLogLogic
|
||||||
|
Visible: false
|
||||||
|
Children:
|
||||||
|
Background@HISTORY_BG:
|
||||||
|
X: WINDOW_RIGHT - 320
|
||||||
|
Y: 360
|
||||||
|
Width: 310
|
||||||
|
Height: WINDOW_BOTTOM - 452
|
||||||
|
Children:
|
||||||
|
ScrollPanel@HISTORY_LIST:
|
||||||
|
X: 10
|
||||||
|
Y: 10
|
||||||
|
Width: PARENT_RIGHT - 20
|
||||||
|
Height: PARENT_BOTTOM - 20
|
||||||
|
CollapseHiddenChildren: True
|
||||||
|
TopBottomSpacing: 4
|
||||||
|
ItemSpacing: 4
|
||||||
|
Children:
|
||||||
|
ScrollItem@HISTORY_TEMPLATE:
|
||||||
|
X: 4
|
||||||
|
Visible: false
|
||||||
|
Width: PARENT_RIGHT - 31
|
||||||
|
Height: 25
|
||||||
|
IgnoreChildMouseOver: true
|
||||||
|
TextColor: ffffff
|
||||||
|
TextColorDisabled: 8f8f8f
|
||||||
|
Children:
|
||||||
|
Label@TITLE:
|
||||||
|
X: 5
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: 25
|
||||||
|
Align: Left
|
||||||
Container@MAP_EDITOR_TAB_CONTAINER:
|
Container@MAP_EDITOR_TAB_CONTAINER:
|
||||||
Logic: MapEditorTabsLogic
|
Logic: MapEditorTabsLogic
|
||||||
X: WINDOW_RIGHT - 245
|
X: WINDOW_RIGHT - 315
|
||||||
Y: 260
|
Y: 330
|
||||||
Width: 240
|
Width: 310
|
||||||
Height: 25
|
Height: 25
|
||||||
Children:
|
Children:
|
||||||
Button@TILES_TAB:
|
Button@TILES_TAB:
|
||||||
@@ -492,6 +531,12 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Text: Actors
|
Text: Actors
|
||||||
Font: Bold
|
Font: Bold
|
||||||
|
Button@HISTORY_TAB:
|
||||||
|
X: 230
|
||||||
|
Width: 70
|
||||||
|
Height: 25
|
||||||
|
Text: History
|
||||||
|
Font: Bold
|
||||||
MenuButton@OPTIONS_BUTTON:
|
MenuButton@OPTIONS_BUTTON:
|
||||||
Logic: MenuButtonsChromeLogic
|
Logic: MenuButtonsChromeLogic
|
||||||
MenuContainer: INGAME_MENU
|
MenuContainer: INGAME_MENU
|
||||||
@@ -547,15 +592,35 @@ Container@EDITOR_WORLD_ROOT:
|
|||||||
TooltipTemplate: BUTTON_TOOLTIP
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
TooltipText: Zoom
|
TooltipText: Zoom
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Button@UNDO_BUTTON:
|
||||||
|
X: 630
|
||||||
|
Height: 25
|
||||||
|
Width: 90
|
||||||
|
Text: Undo
|
||||||
|
Font: Bold
|
||||||
|
Key: z ctrl
|
||||||
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
|
TooltipText: Undo last step
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
Button@REDO_BUTTON:
|
||||||
|
X: 730
|
||||||
|
Height: 25
|
||||||
|
Width: 90
|
||||||
|
Text: Redo
|
||||||
|
Font: Bold
|
||||||
|
Key: y ctrl
|
||||||
|
TooltipTemplate: BUTTON_TOOLTIP
|
||||||
|
TooltipText: Redo last step
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
Label@COORDINATE_LABEL:
|
Label@COORDINATE_LABEL:
|
||||||
X: 635
|
X: 835
|
||||||
Width: 50
|
Width: 50
|
||||||
Height: 25
|
Height: 25
|
||||||
Align: Left
|
Align: Left
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Contrast: true
|
Contrast: true
|
||||||
Label@CASH_LABEL:
|
Label@CASH_LABEL:
|
||||||
X: 750
|
X: 950
|
||||||
Width: 50
|
Width: 50
|
||||||
Height: 25
|
Height: 25
|
||||||
Align: Left
|
Align: Left
|
||||||
|
|||||||
@@ -243,3 +243,4 @@ EditorWorld:
|
|||||||
D2kEditorResourceLayer:
|
D2kEditorResourceLayer:
|
||||||
EditorSelectionLayer:
|
EditorSelectionLayer:
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
|
EditorActionManager:
|
||||||
|
|||||||
@@ -284,3 +284,4 @@ EditorWorld:
|
|||||||
EditorResourceLayer:
|
EditorResourceLayer:
|
||||||
EditorSelectionLayer:
|
EditorSelectionLayer:
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
|
EditorActionManager:
|
||||||
|
|||||||
@@ -379,3 +379,4 @@ EditorWorld:
|
|||||||
EditorSelectionLayer:
|
EditorSelectionLayer:
|
||||||
Palette: placefootprint
|
Palette: placefootprint
|
||||||
LoadWidgetAtGameStart:
|
LoadWidgetAtGameStart:
|
||||||
|
EditorActionManager:
|
||||||
|
|||||||
Reference in New Issue
Block a user