Editor actor move

This commit is contained in:
Wojciech Walaszek
2023-12-13 19:10:18 +01:00
committed by Gustas
parent ac610c54eb
commit 7b82d85b27
4 changed files with 160 additions and 41 deletions

View File

@@ -25,10 +25,6 @@ namespace OpenRA.Mods.Common.Traits
{
public readonly string DescriptiveName;
public readonly ActorInfo Info;
public readonly WPos CenterPosition;
public readonly IReadOnlyDictionary<CPos, SubCell> Footprint;
public readonly Rectangle Bounds;
public readonly SelectionBoxAnnotationRenderable SelectionBox;
public string Tooltip =>
(tooltip == null ? " < " + Info.Name + " >" : TranslationProvider.GetString(tooltip.Name)) + "\n" + Owner.Name + " (" + Owner.Faction + ")"
@@ -38,17 +34,22 @@ namespace OpenRA.Mods.Common.Traits
public string ID { get; set; }
public PlayerReference Owner { get; set; }
public SubCell SubCell { get; }
public WPos CenterPosition { get; set; }
public IReadOnlyDictionary<CPos, SubCell> Footprint { get; private set; }
public Rectangle Bounds { get; private set; }
public bool Selected { get; set; }
public Color RadarColor { get; private set; }
readonly RadarColorFromTerrainInfo terrainRadarColorInfo;
public CPos Location { get; private set; }
readonly RadarColorFromTerrainInfo terrainRadarColorInfo;
readonly WorldRenderer worldRenderer;
readonly TooltipInfoBase tooltip;
IActorPreview[] previews;
readonly ActorReference reference;
readonly Action<CPos> onCellEntryChanged;
readonly Dictionary<INotifyEditorPlacementInfo, object> editorData = new();
readonly Action<CPos> onCellEntryChanged;
SelectionBoxAnnotationRenderable selectionBox;
IActorPreview[] previews;
public EditorActorPreview(WorldRenderer worldRenderer, string id, ActorReference reference, PlayerReference owner)
{
@@ -67,41 +68,58 @@ namespace OpenRA.Mods.Common.Traits
if (!world.Map.Rules.Actors.TryGetValue(reference.Type.ToLowerInvariant(), out Info))
throw new InvalidDataException($"Actor {id} of unknown type {reference.Type.ToLowerInvariant()}");
CenterPosition = PreviewPosition(world, reference);
var location = reference.Get<LocationInit>().Value;
var ios = Info.TraitInfoOrDefault<IOccupySpaceInfo>();
var subCellInit = reference.GetOrDefault<SubCellInit>();
var subCell = subCellInit != null ? subCellInit.Value : SubCell.Any;
var occupiedCells = ios?.OccupiedCells(Info, location, subCell);
if (occupiedCells == null || occupiedCells.Count == 0)
Footprint = new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } };
else
Footprint = occupiedCells;
UpdateFromCellChange();
GenerateFootprint();
tooltip = Info.TraitInfos<EditorOnlyTooltipInfo>().FirstOrDefault(info => info.EnabledByDefault) as TooltipInfoBase
?? Info.TraitInfos<TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault);
DescriptiveName = tooltip != null ? tooltip.Name : Info.Name;
GeneratePreviews();
terrainRadarColorInfo = Info.TraitInfoOrDefault<RadarColorFromTerrainInfo>();
UpdateRadarColor();
// Bounds are fixed from the initial render.
// If this is a problem, then we may need to fetch the area from somewhere else
// TODO: updating all actors on the map is not very efficient.
onCellEntryChanged = _ => UpdateFromCellChange();
}
void UpdateFromCellChange()
{
CenterPosition = PreviewPosition(worldRenderer.World, reference);
GeneratePreviews();
GenerateBounds();
}
void GenerateBounds()
{
var r = previews.SelectMany(p => p.ScreenBounds(worldRenderer, CenterPosition));
Bounds = r.Union();
SelectionBox = new SelectionBoxAnnotationRenderable(new WPos(CenterPosition.X, CenterPosition.Y, 8192),
selectionBox = new SelectionBoxAnnotationRenderable(new WPos(CenterPosition.X, CenterPosition.Y, 8192),
new Rectangle(Bounds.X, Bounds.Y, Bounds.Width, Bounds.Height), Color.White);
}
// TODO: updating all actors on the map is not very efficient.
onCellEntryChanged = _ => GeneratePreviews();
void GenerateFootprint()
{
Location = reference.Get<LocationInit>().Value;
var ios = Info.TraitInfoOrDefault<IOccupySpaceInfo>();
var subCellInit = reference.GetOrDefault<SubCellInit>();
var subCell = subCellInit != null ? subCellInit.Value : SubCell.Any;
var occupiedCells = ios?.OccupiedCells(Info, Location, subCell);
if (occupiedCells == null || occupiedCells.Count == 0)
Footprint = new Dictionary<CPos, SubCell>() { { Location, SubCell.FullCell } };
else
Footprint = occupiedCells;
}
void GeneratePreviews()
{
var init = new ActorPreviewInitializer(reference, worldRenderer);
previews = Info.TraitInfos<IRenderActorPreviewInfo>()
.SelectMany(rpi => rpi.RenderPreview(init))
.ToArray();
}
public void Tick()
@@ -131,7 +149,14 @@ namespace OpenRA.Mods.Common.Traits
public IEnumerable<IRenderable> RenderAnnotations()
{
if (Selected)
yield return SelectionBox;
yield return selectionBox;
}
public void UpdateFromMove()
{
CenterPosition = PreviewPosition(worldRenderer.World, reference);
GenerateFootprint();
GenerateBounds();
}
public void AddedToEditor()
@@ -258,14 +283,6 @@ namespace OpenRA.Mods.Common.Traits
throw new InvalidDataException($"Actor {ID} must define Location or CenterPosition");
}
void GeneratePreviews()
{
var init = new ActorPreviewInitializer(reference, worldRenderer);
previews = Info.TraitInfos<IRenderActorPreviewInfo>()
.SelectMany(rpi => rpi.RenderPreview(init))
.ToArray();
}
void UpdateRadarColor()
{
RadarColor = terrainRadarColorInfo == null ? Owner.Color : terrainRadarColorInfo.GetColorFromTerrain(worldRenderer.World);