Merge pull request #11572 from pchote/building-depth

Add building depth imposters for TS base structures.
This commit is contained in:
Oliver Brakmann
2016-07-14 11:10:13 +02:00
committed by GitHub
10 changed files with 459 additions and 65 deletions

View File

@@ -34,15 +34,22 @@ namespace OpenRA.Mods.Common.Graphics
var nodes = node.Value.ToDictionary();
MiniYaml defaults;
if (nodes.TryGetValue("Defaults", out defaults))
try
{
nodes.Remove("Defaults");
foreach (var n in nodes)
if (nodes.TryGetValue("Defaults", out defaults))
{
n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
n.Value.Value = n.Value.Value ?? defaults.Value;
nodes.Remove("Defaults");
foreach (var n in nodes)
{
n.Value.Nodes = MiniYaml.Merge(new[] { defaults.Nodes, n.Value.Nodes });
n.Value.Value = n.Value.Value ?? defaults.Value;
}
}
}
catch (Exception e)
{
throw new Exception("Error occurred while parsing {0}".F(node.Key), e);
}
foreach (var kvp in nodes)
{
@@ -154,7 +161,7 @@ namespace OpenRA.Mods.Common.Graphics
// Allow per-sprite offset, flipping, start, and length
var subStart = LoadField(sd, "Start", 0);
var subOffset = LoadField(sd, "Offset", float2.Zero);
var subOffset = LoadField(sd, "Offset", float3.Zero);
var subFlipX = LoadField(sd, "FlipX", false);
var subFlipY = LoadField(sd, "FlipY", false);
@@ -162,7 +169,7 @@ namespace OpenRA.Mods.Common.Graphics
var subSprites = cache[subSrc].Select(
s => new Sprite(s.Sheet,
FlipRectangle(s.Bounds, subFlipX, subFlipY), ZRamp,
new float2(subFlipX ? -s.Offset.X : s.Offset.X, subFlipY ? -s.Offset.Y : s.Offset.Y) + subOffset + offset,
new float3(subFlipX ? -s.Offset.X : s.Offset.X, subFlipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + subOffset + offset,
s.Channel, blendMode));
var subLength = 0;
@@ -185,10 +192,47 @@ namespace OpenRA.Mods.Common.Graphics
sprites = cache[src].Select(
s => new Sprite(s.Sheet,
FlipRectangle(s.Bounds, flipX, flipY), ZRamp,
new float2(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y) + offset,
new float3(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + offset,
s.Channel, blendMode)).ToArray();
}
var depthSprite = LoadField<string>(d, "DepthSprite", null);
if (!string.IsNullOrEmpty(depthSprite))
{
var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0);
var depthOffset = LoadField(d, "DepthSpriteOffset", float2.Zero);
var depthSprites = cache.AllCached(depthSprite)
.Select(s => s[depthSpriteFrame]);
sprites = sprites.Select(s =>
{
// The depth sprite must live on the same sheet as the main sprite
var ds = depthSprites.FirstOrDefault(dss => dss.Sheet == s.Sheet);
if (ds == null)
{
// The sequence has probably overflowed onto a new sheet.
// Allocating a new depth sprite on this sheet will almost certainly work
ds = cache.Reload(depthSprite)[depthSpriteFrame];
depthSprites = cache.AllCached(depthSprite)
.Select(ss => ss[depthSpriteFrame]);
// If that doesn't work then we may be referencing a cached sprite from an earlier sheet
// TODO: We could try and reallocate the main sprite, but that requires more complicated code and a perf hit
// We'll only cross that bridge if this becomes a problem in reality
if (ds.Sheet != s.Sheet)
throw new SheetOverflowException("Cross-sheet depth sprite reference: {0}.{1}: {2}");
}
var cw = (ds.Bounds.Left + ds.Bounds.Right) / 2 + (int)(s.Offset.X + depthOffset.X);
var ch = (ds.Bounds.Top + ds.Bounds.Bottom) / 2 + (int)(s.Offset.Y + depthOffset.Y);
var w = s.Bounds.Width / 2;
var h = s.Bounds.Height / 2;
var r = Rectangle.FromLTRB(cw - w, ch - h, cw + w, ch + h);
return new SpriteWithSecondaryData(s, r, ds.Channel);
}).ToArray();
}
MiniYaml length;
if (d.TryGetValue("Length", out length) && length.Value == "*")
Length = sprites.Length - Start;

View File

@@ -26,6 +26,9 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Wall type for connections")]
public readonly string Type = "wall";
[Desc("Override sequence to use when fully open.")]
public readonly string OpenSequence = null;
public override object Create(ActorInitializer init) { return new WithGateSpriteBody(init, this); }
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
@@ -42,10 +45,11 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
class WithGateSpriteBody : WithSpriteBody, INotifyRemovedFromWorld, INotifyBuildComplete, IWallConnector
class WithGateSpriteBody : WithSpriteBody, INotifyRemovedFromWorld, INotifyBuildComplete, IWallConnector, ITick
{
readonly WithGateSpriteBodyInfo gateInfo;
readonly Gate gate;
bool renderOpen;
public WithGateSpriteBody(ActorInitializer init, WithGateSpriteBodyInfo info)
: base(init, info, () => 0)
@@ -54,6 +58,26 @@ namespace OpenRA.Mods.Common.Traits.Render
gate = init.Self.Trait<Gate>();
}
void UpdateState(Actor self)
{
if (renderOpen)
DefaultAnimation.PlayRepeating(NormalizeSequence(self, gateInfo.OpenSequence));
else
DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), GetGateFrame);
}
void ITick.Tick(Actor self)
{
if (gateInfo.OpenSequence == null)
return;
if (gate.Position == gate.OpenPosition ^ renderOpen)
{
renderOpen = gate.Position == gate.OpenPosition;
UpdateState(self);
}
}
int GetGateFrame()
{
return int2.Lerp(0, DefaultAnimation.CurrentSequence.Length - 1, gate.Position, gate.OpenPosition);
@@ -61,12 +85,12 @@ namespace OpenRA.Mods.Common.Traits.Render
public override void DamageStateChanged(Actor self, AttackInfo e)
{
DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), GetGateFrame);
UpdateState(self);
}
public override void BuildingComplete(Actor self)
{
DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), GetGateFrame);
UpdateState(self);
UpdateNeighbours(self);
}