Split IPlaceBuildingPreviewGeneratorInfo from PBOG.

This commit is contained in:
Paul Chote
2019-05-18 09:00:12 +00:00
committed by reaperrr
parent e2b27328bd
commit 52fd32c311
13 changed files with 454 additions and 101 deletions

View File

@@ -0,0 +1,109 @@
#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 System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Orders;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Creates a building placement preview based on the map editor actor preview.")]
public class ActorPreviewPlaceBuildingPreviewInfo : FootprintPlaceBuildingPreviewInfo
{
[Desc("Enable the building's idle animation.")]
public readonly bool Animated = true;
[PaletteReference("OverridePaletteIsPlayerPalette")]
[Desc("Custom palette name.")]
public readonly string OverridePalette = null;
[Desc("Custom palette is a player palette BaseName.")]
public readonly bool OverridePaletteIsPlayerPalette = true;
[Desc("Footprint types to draw underneath the actor preview.")]
public readonly PlaceBuildingCellType FootprintUnderPreview = PlaceBuildingCellType.None;
[Desc("Footprint types to draw above the actor preview.")]
public readonly PlaceBuildingCellType FootprintOverPreview = PlaceBuildingCellType.Valid | PlaceBuildingCellType.LineBuild | PlaceBuildingCellType.Invalid;
protected override IPlaceBuildingPreview CreatePreview(WorldRenderer wr, ActorInfo ai, TypeDictionary init)
{
return new ActorPreviewPlaceBuildingPreviewPreview(wr, ai, this, init);
}
public override object Create(ActorInitializer init)
{
return new ActorPreviewPlaceBuildingPreview();
}
}
public class ActorPreviewPlaceBuildingPreview { }
class ActorPreviewPlaceBuildingPreviewPreview : FootprintPlaceBuildingPreviewPreview
{
readonly ActorPreviewPlaceBuildingPreviewInfo info;
readonly PaletteReference palette;
readonly IActorPreview[] preview;
public ActorPreviewPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, ActorPreviewPlaceBuildingPreviewInfo info, TypeDictionary init)
: base(wr, ai, info, init)
{
this.info = info;
var previewInit = new ActorPreviewInitializer(actorInfo, wr, init);
preview = actorInfo.TraitInfos<IRenderActorPreviewInfo>()
.SelectMany(rpi => rpi.RenderPreview(previewInit))
.ToArray();
if (!string.IsNullOrEmpty(info.OverridePalette))
{
var owner = init.Get<OwnerInit>().Value(wr.World);
palette = wr.Palette(info.OverridePaletteIsPlayerPalette ? info.OverridePalette + owner.InternalName : info.OverridePalette);
}
}
protected override void TickInner()
{
if (!info.Animated)
return;
foreach (var p in preview)
p.Tick();
}
protected override IEnumerable<IRenderable> RenderInner(WorldRenderer wr, CPos topLeft, Dictionary<CPos, PlaceBuildingCellType> footprint)
{
var centerPosition = wr.World.Map.CenterOfCell(topLeft) + centerOffset;
var previewRenderables = preview
.SelectMany(p => p.Render(wr, centerPosition));
if (palette != null)
previewRenderables = previewRenderables.Select(a => a.IsDecoration ? a : a.WithPalette(palette));
foreach (var r in RenderDecorations(wr, topLeft))
yield return r;
if (info.FootprintUnderPreview != PlaceBuildingCellType.None)
foreach (var r in RenderFootprint(wr, topLeft, footprint, info.FootprintUnderPreview))
yield return r;
foreach (var r in previewRenderables.OrderBy(WorldRenderer.RenderableScreenZPositionComparisonKey))
yield return r;
if (info.FootprintOverPreview != PlaceBuildingCellType.None)
foreach (var r in RenderFootprint(wr, topLeft, footprint, info.FootprintOverPreview))
yield return r;
}
}
}

View File

@@ -0,0 +1,120 @@
#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 System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Orders;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Creates a building placement preview showing only the building footprint.")]
public class FootprintPlaceBuildingPreviewInfo : TraitInfo<FootprintPlaceBuildingPreview>, IPlaceBuildingPreviewGeneratorInfo
{
[PaletteReference]
[Desc("Palette to use for rendering the placement sprite.")]
public readonly string Palette = TileSet.TerrainPaletteInternalName;
[PaletteReference]
[Desc("Palette to use for rendering the placement sprite for line build segments.")]
public readonly string LineBuildSegmentPalette = TileSet.TerrainPaletteInternalName;
protected virtual IPlaceBuildingPreview CreatePreview(WorldRenderer wr, ActorInfo ai, TypeDictionary init)
{
return new FootprintPlaceBuildingPreviewPreview(wr, ai, this, init);
}
IPlaceBuildingPreview IPlaceBuildingPreviewGeneratorInfo.CreatePreview(WorldRenderer wr, ActorInfo ai, TypeDictionary init)
{
return CreatePreview(wr, ai, init);
}
}
public class FootprintPlaceBuildingPreview { }
class FootprintPlaceBuildingPreviewPreview : IPlaceBuildingPreview
{
protected readonly ActorInfo actorInfo;
protected readonly WVec centerOffset;
readonly FootprintPlaceBuildingPreviewInfo info;
readonly IPlaceBuildingDecorationInfo[] decorations;
readonly int2 topLeftScreenOffset;
readonly Sprite buildOk;
readonly Sprite buildBlocked;
public FootprintPlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, FootprintPlaceBuildingPreviewInfo info, TypeDictionary init)
{
actorInfo = ai;
this.info = info;
decorations = actorInfo.TraitInfos<IPlaceBuildingDecorationInfo>().ToArray();
var world = wr.World;
centerOffset = actorInfo.TraitInfo<BuildingInfo>().CenterOffset(world);
topLeftScreenOffset = -wr.ScreenPxOffset(centerOffset);
var tileset = world.Map.Tileset.ToLowerInvariant();
if (world.Map.Rules.Sequences.HasSequence("overlay", "build-valid-{0}".F(tileset)))
buildOk = world.Map.Rules.Sequences.GetSequence("overlay", "build-valid-{0}".F(tileset)).GetSprite(0);
else
buildOk = world.Map.Rules.Sequences.GetSequence("overlay", "build-valid").GetSprite(0);
buildBlocked = world.Map.Rules.Sequences.GetSequence("overlay", "build-invalid").GetSprite(0);
}
protected virtual void TickInner() { }
protected IEnumerable<IRenderable> RenderFootprint(WorldRenderer wr, CPos topLeft, Dictionary<CPos, PlaceBuildingCellType> footprint,
PlaceBuildingCellType filter = PlaceBuildingCellType.Invalid | PlaceBuildingCellType.Valid | PlaceBuildingCellType.LineBuild)
{
var cellPalette = wr.Palette(info.Palette);
var linePalette = wr.Palette(info.LineBuildSegmentPalette);
var topLeftPos = wr.World.Map.CenterOfCell(topLeft);
foreach (var c in footprint)
{
if ((c.Value & filter) == 0)
continue;
var tile = !c.Value.HasFlag(PlaceBuildingCellType.Invalid) ? buildOk : buildBlocked;
var pal = c.Value.HasFlag(PlaceBuildingCellType.LineBuild) ? linePalette : cellPalette;
var pos = wr.World.Map.CenterOfCell(c.Key);
var offset = new WVec(0, 0, topLeftPos.Z - pos.Z);
yield return new SpriteRenderable(tile, pos, offset, -511, pal, 1f, true);
}
}
protected IEnumerable<IRenderable> RenderDecorations(WorldRenderer wr, CPos topLeft)
{
var centerPosition = wr.World.Map.CenterOfCell(topLeft) + centerOffset;
foreach (var d in decorations)
foreach (var r in d.Render(wr, wr.World, actorInfo, centerPosition))
yield return r;
}
protected virtual IEnumerable<IRenderable> RenderInner(WorldRenderer wr, CPos topLeft, Dictionary<CPos, PlaceBuildingCellType> footprint)
{
foreach (var r in RenderDecorations(wr, topLeft))
yield return r;
foreach (var r in RenderFootprint(wr, topLeft, footprint))
yield return r;
}
IEnumerable<IRenderable> IPlaceBuildingPreview.Render(WorldRenderer wr, CPos topLeft, Dictionary<CPos, PlaceBuildingCellType> footprint)
{
return RenderInner(wr, topLeft, footprint);
}
void IPlaceBuildingPreview.Tick() { TickInner(); }
int2 IPlaceBuildingPreview.TopLeftScreenOffset { get { return topLeftScreenOffset; } }
}
}

View File

@@ -0,0 +1,101 @@
#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.Orders;
using OpenRA.Mods.Common.Traits.Render;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Creates a building placement preview based on a defined sequence.")]
public class SequencePlaceBuildingPreviewInfo : FootprintPlaceBuildingPreviewInfo, Requires<RenderSpritesInfo>
{
[SequenceReference]
[Desc("Sequence name to use.")]
public readonly string Sequence = "idle";
[PaletteReference("SequencePaletteIsPlayerPalette")]
[Desc("Custom palette name.")]
public readonly string SequencePalette = null;
[Desc("Custom palette is a player palette BaseName.")]
public readonly bool SequencePaletteIsPlayerPalette = true;
[Desc("Footprint types to draw underneath the actor preview.")]
public readonly PlaceBuildingCellType FootprintUnderPreview = PlaceBuildingCellType.None;
[Desc("Footprint types to draw above the actor preview.")]
public readonly PlaceBuildingCellType FootprintOverPreview = PlaceBuildingCellType.Valid | PlaceBuildingCellType.LineBuild | PlaceBuildingCellType.Invalid;
protected override IPlaceBuildingPreview CreatePreview(WorldRenderer wr, ActorInfo ai, TypeDictionary init)
{
return new SequencePlaceBuildingPreviewPreview(wr, ai, this, init);
}
public override object Create(ActorInitializer init)
{
return new SequencePlaceBuildingPreview();
}
}
public class SequencePlaceBuildingPreview { }
class SequencePlaceBuildingPreviewPreview : FootprintPlaceBuildingPreviewPreview
{
readonly SequencePlaceBuildingPreviewInfo info;
readonly Animation preview;
readonly PaletteReference palette;
public SequencePlaceBuildingPreviewPreview(WorldRenderer wr, ActorInfo ai, SequencePlaceBuildingPreviewInfo info, TypeDictionary init)
: base(wr, ai, info, init)
{
this.info = info;
var owner = init.Get<OwnerInit>().Value(wr.World);
var faction = init.Get<FactionInit>().Value(wr.World);
var rsi = ai.TraitInfo<RenderSpritesInfo>();
if (!string.IsNullOrEmpty(info.SequencePalette))
palette = wr.Palette(info.SequencePaletteIsPlayerPalette ? info.SequencePalette + owner.InternalName : info.SequencePalette);
else
palette = wr.Palette(rsi.Palette ?? rsi.PlayerPalette + owner.InternalName);
preview = new Animation(wr.World, rsi.GetImage(ai, wr.World.Map.Rules.Sequences, faction));
preview.PlayRepeating(info.Sequence);
}
protected override void TickInner()
{
preview.Tick();
}
protected override IEnumerable<IRenderable> RenderInner(WorldRenderer wr, CPos topLeft, Dictionary<CPos, PlaceBuildingCellType> footprint)
{
foreach (var r in RenderDecorations(wr, topLeft))
yield return r;
if (info.FootprintUnderPreview != PlaceBuildingCellType.None)
foreach (var r in RenderFootprint(wr, topLeft, footprint, info.FootprintUnderPreview))
yield return r;
var centerPosition = wr.World.Map.CenterOfCell(topLeft) + centerOffset;
foreach (var r in preview.Render(centerPosition, WVec.Zero, 0, palette, 1.0f))
yield return r;
if (info.FootprintOverPreview != PlaceBuildingCellType.None)
foreach (var r in RenderFootprint(wr, topLeft, footprint, info.FootprintOverPreview))
yield return r;
}
}
}

View File

@@ -21,14 +21,6 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Allows the player to execute build orders.", " Attach this to the player actor.")]
public class PlaceBuildingInfo : ITraitInfo
{
[PaletteReference]
[Desc("Palette to use for rendering the placement sprite.")]
public readonly string Palette = TileSet.TerrainPaletteInternalName;
[PaletteReference]
[Desc("Palette to use for rendering the placement sprite for line build segments.")]
public readonly string LineBuildSegmentPalette = TileSet.TerrainPaletteInternalName;
[Desc("Play NewOptionsNotification this many ticks after building placement.")]
public readonly int NewOptionsNotificationDelay = 10;