Make ActorPreview and EditorActorPreview wrap ActorReference.

This commit is contained in:
Paul Chote
2020-06-12 13:21:09 +01:00
committed by reaperrr
parent ae7cfa56b7
commit c6c3a8c60d
22 changed files with 265 additions and 162 deletions

View File

@@ -184,7 +184,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorSlider("Facing", EditorFacingDisplayOrder, 0, 255, 8,
actor =>
{
var init = actor.Init<FacingInit>();
var init = actor.GetInitOrDefault<FacingInit>(this);
return init != null ? init.Value : InitialFacing;
},
(actor, value) => actor.ReplaceInit(new FacingInit((int)value)));

View File

@@ -42,14 +42,14 @@ namespace OpenRA.Mods.Common.Traits
}
else
{
var owner = map.PlayerDefinitions.Single(p => s.InitDict.Get<OwnerInit>().InternalName == p.Value.Nodes.Last(k => k.Key == "Name").Value.Value);
var owner = map.PlayerDefinitions.Single(p => s.Get<OwnerInit>().InternalName == p.Value.Nodes.Last(k => k.Key == "Name").Value.Value);
var colorValue = owner.Value.Nodes.Where(n => n.Key == "Color");
var ownerColor = colorValue.Any() ? colorValue.First().Value.Value : "FFFFFF";
Color.TryParse(ownerColor, out color);
}
var ios = ai.TraitInfo<IOccupySpaceInfo>();
var cells = ios.OccupiedCells(ai, s.InitDict.Get<LocationInit>().Value);
var cells = ios.OccupiedCells(ai, s.Get<LocationInit>().Value);
foreach (var cell in cells)
destinationBuffer.Add(new Pair<MPos, Color>(cell.Key.ToMPos(map), color));
}

View File

@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorDropdown("Stance", EditorStanceDisplayOrder, labels,
actor =>
{
var init = actor.Init<StanceInit>();
var init = actor.GetInitOrDefault<StanceInit>(this);
var stance = init != null ? init.Value : InitialStance;
return stances[(int)stance];
},

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorCheckbox("Spawn Child Actor", EditorFreeActorDisplayOrder,
actor =>
{
var init = actor.Init<FreeActorInit>();
var init = actor.GetInitOrDefault<FreeActorInit>(this);
if (init != null)
return init.Value;
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits
},
(actor, value) =>
{
actor.ReplaceInit(new FreeActorInit(this, value));
actor.ReplaceInit(new FreeActorInit(this, value), this);
});
}

View File

@@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorCheckbox("Deployed", EditorDeployedDisplayOrder,
actor =>
{
var init = actor.Init<DeployStateInit>();
var init = actor.GetInitOrDefault<DeployStateInit>();
if (init != null)
return init.Value == DeployState.Deployed;

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorSlider("Health", EditorHealthDisplayOrder, 0, 100, 5,
actor =>
{
var init = actor.Init<HealthInit>();
var init = actor.GetInitOrDefault<HealthInit>();
return init != null ? init.Value : 100;
},
(actor, value) => actor.ReplaceInit(new HealthInit((int)value)));

View File

@@ -130,23 +130,24 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorSlider("Facing", EditorFacingDisplayOrder, 0, 255, 8,
actor =>
{
var init = actor.Init<FacingInit>();
var init = actor.GetInitOrDefault<FacingInit>(this);
return init != null ? init.Value : InitialFacing;
},
(actor, value) =>
{
// TODO: This can all go away once turrets are properly defined as a relative facing
var turretInit = actor.Init<TurretFacingInit>();
var turretsInit = actor.Init<TurretFacingsInit>();
var facingInit = actor.Init<FacingInit>();
var turretsInit = actor.GetInitOrDefault<TurretFacingsInit>();
var facingInit = actor.GetInitOrDefault<FacingInit>();
var oldFacing = facingInit != null ? facingInit.Value : InitialFacing;
var newFacing = (int)value;
if (turretInit != null)
var turretInits = actor.GetInits<TurretFacingInit>().ToList();
actor.RemoveInits<TurretFacingInit>();
foreach (var turretInit in turretInits)
{
var newTurretFacing = (turretInit.Value + newFacing - oldFacing + 255) % 255;
actor.ReplaceInit(new TurretFacingInit(this, newTurretFacing));
actor.AddInit(new TurretFacingInit(turretInit.InstanceName, newTurretFacing));
}
if (turretsInit != null)

View File

@@ -53,11 +53,11 @@ namespace OpenRA.Mods.Common.Traits
yield return new EditorActorSlider("Turret", EditorTurretFacingDisplayOrder, 0, 255, 8,
actor =>
{
var init = actor.Init<TurretFacingInit>();
var init = actor.GetInitOrDefault<TurretFacingInit>(this);
if (init != null)
return init.Value;
var facingInit = actor.Init<FacingInit>();
var facingInit = actor.GetInitOrDefault<FacingInit>(this);
if (facingInit != null)
return facingInit.Value;
@@ -67,8 +67,9 @@ namespace OpenRA.Mods.Common.Traits
{
actor.RemoveInit<TurretFacingsInit>();
// Force a single global turret facing for multi-turret actors by not passing this TraitInfo instance
actor.ReplaceInit(new TurretFacingInit((int)value));
// Force a single global turret facing for multi-turret actors
actor.RemoveInits<TurretFacingInit>();
actor.AddInit(new TurretFacingInit((int)value));
});
}
@@ -274,6 +275,9 @@ namespace OpenRA.Mods.Common.Traits
public TurretFacingInit(TraitInfo info, int value)
: base(info, value) { }
public TurretFacingInit(string instanceName, int value)
: base(instanceName, value) { }
public TurretFacingInit(int value)
: base(value) { }
}

View File

@@ -118,7 +118,7 @@ namespace OpenRA.Mods.Common.Traits
public EditorActorPreview Add(string id, ActorReference reference, bool initialSetup = false)
{
var owner = Players.Players[reference.InitDict.Get<OwnerInit>().InternalName];
var owner = Players.Players[reference.Get<OwnerInit>().InternalName];
var preview = new EditorActorPreview(worldRenderer, id, reference, owner);
Add(preview, initialSetup);
@@ -144,7 +144,7 @@ namespace OpenRA.Mods.Common.Traits
{
UpdateNeighbours(preview.Footprint);
if (preview.Actor.Type == "mpspawn")
if (preview.Type == "mpspawn")
SyncMultiplayerCount();
}
}

View File

@@ -28,7 +28,6 @@ namespace OpenRA.Mods.Common.Traits
public readonly IReadOnlyDictionary<CPos, SubCell> Footprint;
public readonly Rectangle Bounds;
public readonly SelectionBoxAnnotationRenderable SelectionBox;
public readonly ActorReference Actor;
public string Tooltip
{
@@ -39,6 +38,8 @@ namespace OpenRA.Mods.Common.Traits
}
}
public string Type { get { return reference.Type; } }
public string ID { get; set; }
public PlayerReference Owner { get; set; }
public SubCell SubCell { get; private set; }
@@ -47,30 +48,31 @@ namespace OpenRA.Mods.Common.Traits
readonly WorldRenderer worldRenderer;
readonly TooltipInfoBase tooltip;
IActorPreview[] previews;
readonly ActorReference reference;
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference actor, PlayerReference owner)
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference reference, PlayerReference owner)
{
ID = id;
Actor = actor;
this.reference = reference;
Owner = owner;
this.worldRenderer = worldRenderer;
if (!actor.InitDict.Contains<FactionInit>())
actor.InitDict.Add(new FactionInit(owner.Faction));
if (!reference.Contains<FactionInit>())
reference.Add(new FactionInit(owner.Faction));
if (!actor.InitDict.Contains<OwnerInit>())
actor.InitDict.Add(new OwnerInit(owner.Name));
if (!reference.Contains<OwnerInit>())
reference.Add(new OwnerInit(owner.Name));
var world = worldRenderer.World;
if (!world.Map.Rules.Actors.TryGetValue(actor.Type.ToLowerInvariant(), out Info))
throw new InvalidDataException("Actor {0} of unknown type {1}".F(id, actor.Type.ToLowerInvariant()));
if (!world.Map.Rules.Actors.TryGetValue(reference.Type.ToLowerInvariant(), out Info))
throw new InvalidDataException("Actor {0} of unknown type {1}".F(id, reference.Type.ToLowerInvariant()));
CenterPosition = PreviewPosition(world, actor.InitDict);
CenterPosition = PreviewPosition(world, reference);
var location = actor.InitDict.Get<LocationInit>().Value;
var location = reference.Get<LocationInit>().Value;
var ios = Info.TraitInfoOrDefault<IOccupySpaceInfo>();
var subCellInit = actor.InitDict.GetOrDefault<SubCellInit>();
var subCellInit = reference.GetOrDefault<SubCellInit>();
var subCell = subCellInit != null ? subCellInit.Value : SubCell.Any;
if (ios != null)
@@ -124,27 +126,66 @@ namespace OpenRA.Mods.Common.Traits
yield return SelectionBox;
}
public void ReplaceInit<T>(T init)
public void AddInit<T>(T init) where T : ActorInit
{
var original = Actor.InitDict.GetOrDefault<T>();
if (original != null)
Actor.InitDict.Remove(original);
Actor.InitDict.Add(init);
reference.Add(init);
GeneratePreviews();
}
public void RemoveInit<T>()
public void ReplaceInit<T>(T init, TraitInfo info) where T : ActorInit
{
var original = Actor.InitDict.GetOrDefault<T>();
var original = GetInitOrDefault<T>(info);
if (original != null)
Actor.InitDict.Remove(original);
reference.Remove(original);
reference.Add(init);
GeneratePreviews();
}
public T Init<T>()
public void RemoveInit<T>(TraitInfo info) where T : ActorInit
{
return Actor.InitDict.GetOrDefault<T>();
var original = GetInitOrDefault<T>(info);
if (original != null)
reference.Remove(original);
GeneratePreviews();
}
public int RemoveInits<T>() where T : ActorInit
{
var removed = reference.RemoveAll<T>();
GeneratePreviews();
return removed;
}
public T GetInitOrDefault<T>(TraitInfo info) where T : ActorInit
{
return reference.GetOrDefault<T>(info);
}
public IEnumerable<T> GetInits<T>() where T : ActorInit
{
return reference.GetAll<T>();
}
public T GetInitOrDefault<T>() where T : ActorInit, ISingleInstanceInit
{
return reference.GetOrDefault<T>();
}
public void ReplaceInit<T>(T init) where T : ActorInit, ISingleInstanceInit
{
var original = reference.GetOrDefault<T>();
if (original != null)
reference.Remove(original);
reference.Add(init);
GeneratePreviews();
}
public void RemoveInit<T>() where T : ActorInit, ISingleInstanceInit
{
reference.RemoveAll<T>();
GeneratePreviews();
}
public MiniYaml Save()
@@ -160,20 +201,23 @@ namespace OpenRA.Mods.Common.Traits
return true;
};
return Actor.Save(saveInit);
return reference.Save(saveInit);
}
WPos PreviewPosition(World world, TypeDictionary init)
WPos PreviewPosition(World world, ActorReference actor)
{
if (init.Contains<CenterPositionInit>())
return init.Get<CenterPositionInit>().Value;
var centerPositionInit = actor.GetOrDefault<CenterPositionInit>();
if (centerPositionInit != null)
return centerPositionInit.Value;
if (init.Contains<LocationInit>())
var locationInit = actor.GetOrDefault<LocationInit>();
if (locationInit != null)
{
var cell = init.Get<LocationInit>().Value;
var cell = locationInit.Value;
var offset = WVec.Zero;
var subCellInit = Actor.InitDict.GetOrDefault<SubCellInit>();
var subCellInit = reference.GetOrDefault<SubCellInit>();
var subCell = subCellInit != null ? subCellInit.Value : SubCell.Any;
var buildingInfo = Info.TraitInfoOrDefault<BuildingInfo>();
@@ -188,7 +232,7 @@ namespace OpenRA.Mods.Common.Traits
void GeneratePreviews()
{
var init = new ActorPreviewInitializer(Info, worldRenderer, Actor.InitDict);
var init = new ActorPreviewInitializer(reference, worldRenderer);
previews = Info.TraitInfos<IRenderActorPreviewInfo>()
.SelectMany(rpi => rpi.RenderPreview(init))
.ToArray();
@@ -196,7 +240,7 @@ namespace OpenRA.Mods.Common.Traits
public ActorReference Export()
{
return new ActorReference(Actor.Type, Actor.Save().ToDictionary());
return reference.Clone();
}
public override string ToString()

View File

@@ -113,8 +113,7 @@ namespace OpenRA.Mods.Common.Traits
if (actorLocation != cell)
{
actorLocation = cell;
Actor.Actor.InitDict.Remove(Actor.Actor.InitDict.Get<LocationInit>());
Actor.Actor.InitDict.Add(new LocationInit(cell));
Actor.ReplaceInit(new LocationInit(cell));
updated = true;
}
@@ -122,23 +121,19 @@ namespace OpenRA.Mods.Common.Traits
{
actorSubCell = subCell;
var subcellInit = Actor.Actor.InitDict.GetOrDefault<SubCellInit>();
if (subcellInit != null)
{
Actor.Actor.InitDict.Remove(subcellInit);
if (Actor.RemoveInits<SubCellInit>() > 0)
updated = true;
}
var subcell = world.Map.Tiles.Contains(cell) ? editorLayer.FreeSubCellAt(cell) : SubCell.Invalid;
if (subcell != SubCell.Invalid)
{
Actor.Actor.InitDict.Add(new SubCellInit(subcell));
Actor.AddInit(new SubCellInit(subcell));
updated = true;
}
}
if (updated)
Actor = new EditorActorPreview(wr, null, Actor.Actor, Actor.Owner);
Actor = new EditorActorPreview(wr, null, Actor.Export(), Actor.Owner);
}
}
@@ -184,25 +179,25 @@ namespace OpenRA.Mods.Common.Traits
ownerName = specificOwnerInfo.ValidOwnerNames.First();
var reference = new ActorReference(actor.Name);
reference.InitDict.Add(new OwnerInit(ownerName));
reference.InitDict.Add(new FactionInit(owner.Faction));
reference.Add(new OwnerInit(ownerName));
reference.Add(new FactionInit(owner.Faction));
var worldPx = wr.Viewport.ViewToWorldPx(Viewport.LastMousePos) - wr.ScreenPxOffset(actorCenterOffset);
var cell = wr.Viewport.ViewToWorld(wr.Viewport.WorldToViewPx(worldPx));
reference.InitDict.Add(new LocationInit(cell));
reference.Add(new LocationInit(cell));
if (ios != null && ios.SharesCell)
{
actorSubCell = editorLayer.FreeSubCellAt(cell);
if (actorSubCell != SubCell.Invalid)
reference.InitDict.Add(new SubCellInit(actorSubCell));
reference.Add(new SubCellInit(actorSubCell));
}
if (actor.HasTraitInfo<IFacingInfo>())
reference.InitDict.Add(new FacingInit(info.PreviewFacing));
reference.Add(new FacingInit(info.PreviewFacing));
if (actor.HasTraitInfo<TurretedInfo>())
reference.InitDict.Add(new TurretFacingInit(info.PreviewFacing));
reference.Add(new TurretFacingInit(info.PreviewFacing));
Type = EditorCursorType.Actor;
Actor = new EditorActorPreview(wr, null, reference, owner);

View File

@@ -35,18 +35,17 @@ namespace OpenRA.Mods.Common.Traits
var actorReference = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
// If there is no real player associated, don't spawn it.
var ownerName = actorReference.InitDict.Get<OwnerInit>().InternalName;
var ownerName = actorReference.Get<OwnerInit>().InternalName;
if (!world.Players.Any(p => p.InternalName == ownerName))
continue;
var initDict = actorReference.InitDict;
initDict.Add(new SkipMakeAnimsInit());
initDict.Add(new SpawnedByMapInit(kv.Key));
actorReference.Add(new SkipMakeAnimsInit());
actorReference.Add(new SpawnedByMapInit(kv.Key));
if (PreventMapSpawn(world, actorReference, preventMapSpawns))
continue;
var actor = world.CreateActor(actorReference.Type, initDict);
var actor = world.CreateActor(true, actorReference);
Actors[kv.Key] = actor;
LastMapActorID = actor.ActorID;
}