diff --git a/OpenRA.Game/Graphics/SpriteRenderable.cs b/OpenRA.Game/Graphics/SpriteRenderable.cs index 12a235fba5..b6074cd14f 100644 --- a/OpenRA.Game/Graphics/SpriteRenderable.cs +++ b/OpenRA.Game/Graphics/SpriteRenderable.cs @@ -52,7 +52,9 @@ namespace OpenRA.Graphics float3 ScreenPosition(WorldRenderer wr) { var xy = wr.ScreenPxPosition(pos) + wr.ScreenPxOffset(offset) - (0.5f * scale * sprite.Size.XY).ToInt2(); - return new float3(xy, wr.ScreenZPosition(pos, 0) - 0.5f * scale * sprite.Size.Z); + + // HACK: The z offset needs to be applied somewhere, but this probably is the wrong place. + return new float3(xy, sprite.Offset.Z + wr.ScreenZPosition(pos, 0) - 0.5f * scale * sprite.Size.Z); } public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; } diff --git a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs index 021efda8dd..c77b77f6db 100644 --- a/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs +++ b/OpenRA.Mods.Common/Graphics/DefaultSpriteSequence.cs @@ -161,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); @@ -169,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; @@ -192,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(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; diff --git a/mods/ts/bits/isodepth.shp b/mods/ts/bits/isodepth.shp new file mode 100644 index 0000000000..d531a5a422 Binary files /dev/null and b/mods/ts/bits/isodepth.shp differ