diff --git a/OpenRA.Game/Graphics/SheetBuilder.cs b/OpenRA.Game/Graphics/SheetBuilder.cs index c95fb1909d..ba3702212e 100644 --- a/OpenRA.Game/Graphics/SheetBuilder.cs +++ b/OpenRA.Game/Graphics/SheetBuilder.cs @@ -59,15 +59,15 @@ namespace OpenRA.Graphics this.allocateSheet = allocateSheet; } - public Sprite Add(ISpriteFrame frame) { return Add(frame.Data, frame.Size, frame.Offset); } - public Sprite Add(byte[] src, Size size) { return Add(src, size, float2.Zero); } - public Sprite Add(byte[] src, Size size, float2 spriteOffset) + public Sprite Add(ISpriteFrame frame) { return Add(frame.Data, frame.Size, 0, frame.Offset); } + public Sprite Add(byte[] src, Size size) { return Add(src, size, 0, float3.Zero); } + public Sprite Add(byte[] src, Size size, float zRamp, float3 spriteOffset) { // Don't bother allocating empty sprites if (size.Width == 0 || size.Height == 0) return new Sprite(current, Rectangle.Empty, 0, spriteOffset, channel, BlendMode.Alpha); - var rect = Allocate(size, spriteOffset); + var rect = Allocate(size, zRamp, spriteOffset); Util.FastCopyIntoChannel(rect, src); current.CommitBufferedData(); return rect; @@ -99,8 +99,8 @@ namespace OpenRA.Graphics return (TextureChannel)nextChannel; } - public Sprite Allocate(Size imageSize) { return Allocate(imageSize, float2.Zero); } - public Sprite Allocate(Size imageSize, float2 spriteOffset) + public Sprite Allocate(Size imageSize) { return Allocate(imageSize, 0, float3.Zero); } + public Sprite Allocate(Size imageSize, float zRamp, float3 spriteOffset) { if (imageSize.Width + p.X > current.Size.Width) { @@ -128,7 +128,7 @@ namespace OpenRA.Graphics p = new Point(0, 0); } - var rect = new Sprite(current, new Rectangle(p, imageSize), 0, spriteOffset, channel, BlendMode.Alpha); + var rect = new Sprite(current, new Rectangle(p, imageSize), zRamp, spriteOffset, channel, BlendMode.Alpha); p.X += imageSize.Width; return rect; diff --git a/OpenRA.Game/Graphics/TerrainSpriteLayer.cs b/OpenRA.Game/Graphics/TerrainSpriteLayer.cs index 25fa73d924..7acf569aaf 100644 --- a/OpenRA.Game/Graphics/TerrainSpriteLayer.cs +++ b/OpenRA.Game/Graphics/TerrainSpriteLayer.cs @@ -68,12 +68,10 @@ namespace OpenRA.Graphics public void Update(CPos cell, Sprite sprite) { - var xy = sprite == null ? float2.Zero : - worldRenderer.ScreenPosition(map.CenterOfCell(cell)) + sprite.Offset - 0.5f * sprite.Size; + var xyz = sprite == null ? float3.Zero : + worldRenderer.Screen3DPosition(map.CenterOfCell(cell)) + sprite.Offset - 0.5f * sprite.Size; - // TODO: Deal with sprite z offsets - var z = worldRenderer.ScreenZPosition(map.CenterOfCell(cell), 0); - Update(cell.ToMPos(map.Grid.Type), sprite, new float3(xy.X, xy.Y, z)); + Update(cell.ToMPos(map.Grid.Type), sprite, xyz); } public void Update(MPos uv, Sprite sprite, float3 pos) diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index 543fe7762c..19db585bd9 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -69,12 +69,18 @@ namespace OpenRA.Graphics variants.Add(indices.Select(j => { var f = allFrames[j]; - var s = sheetBuilder.Allocate(f.Size, f.Offset); + var tile = t.Value.Contains(j) ? t.Value[j] : null; + + // The internal z axis is inverted from expectation (negative is closer) + var zOffset = tile != null ? -tile.ZOffset : 0; + var zRamp = tile != null ? tile.ZRamp : 1f; + var offset = new float3(f.Offset, zOffset); + var s = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(s, f.Data); if (tileset.EnableDepth) { - var ss = sheetBuilder.Allocate(f.Size, f.Offset); + var ss = sheetBuilder.Allocate(f.Size, zRamp, offset); Util.FastCopyIntoChannel(ss, allFrames[j + frameCount].Data); // s and ss are guaranteed to use the same sheet @@ -90,7 +96,7 @@ namespace OpenRA.Graphics // Ignore the offsets baked into R8 sprites if (tileset.IgnoreTileSpriteOffsets) - allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, float2.Zero, s.Channel, s.BlendMode)); + allSprites = allSprites.Select(s => new Sprite(s.Sheet, s.Bounds, s.ZRamp, new float3(float2.Zero, s.Offset.Z), s.Channel, s.BlendMode)); templates.Add(t.Value.Id, new TheaterTemplate(allSprites.ToArray(), variants.First().Count(), t.Value.Images.Length)); } diff --git a/OpenRA.Game/Graphics/VoxelRenderer.cs b/OpenRA.Game/Graphics/VoxelRenderer.cs index cda6079646..868a65fbaf 100644 --- a/OpenRA.Game/Graphics/VoxelRenderer.cs +++ b/OpenRA.Game/Graphics/VoxelRenderer.cs @@ -161,8 +161,8 @@ namespace OpenRA.Graphics CalculateSpriteGeometry(tl, br, 1, out spriteSize, out spriteOffset); CalculateSpriteGeometry(stl, sbr, 2, out shadowSpriteSize, out shadowSpriteOffset); - var sprite = sheetBuilder.Allocate(spriteSize, spriteOffset); - var shadowSprite = sheetBuilder.Allocate(shadowSpriteSize, shadowSpriteOffset); + var sprite = sheetBuilder.Allocate(spriteSize, 0, spriteOffset); + var shadowSprite = sheetBuilder.Allocate(shadowSpriteSize, 0, shadowSpriteOffset); var sb = sprite.Bounds; var ssb = shadowSprite.Bounds; var spriteCenter = new float2(sb.Left + sb.Width / 2, sb.Top + sb.Height / 2); diff --git a/OpenRA.Game/Map/TileSet.cs b/OpenRA.Game/Map/TileSet.cs index 5c959849da..b17f1e0513 100644 --- a/OpenRA.Game/Map/TileSet.cs +++ b/OpenRA.Game/Map/TileSet.cs @@ -27,6 +27,9 @@ namespace OpenRA public readonly Color LeftColor; public readonly Color RightColor; + public readonly float ZOffset = 0.0f; + public readonly float ZRamp = 1.0f; + public MiniYaml Save(TileSet tileSet) { var root = new List(); @@ -42,6 +45,12 @@ namespace OpenRA if (RightColor != tileSet.TerrainInfo[TerrainType].Color) root.Add(FieldSaver.SaveField(this, "RightColor")); + if (ZOffset != 0.0f) + root.Add(FieldSaver.SaveField(this, "ZOffset")); + + if (ZRamp != 1.0f) + root.Add(FieldSaver.SaveField(this, "ZRamp")); + return new MiniYaml(tileSet.TerrainInfo[TerrainType].Type, root); } }