diff --git a/TRLevelControl/Build/TRRoomBuilder.cs b/TRLevelControl/Build/TRRoomBuilder.cs index 14bc7784..0cdc8ac2 100644 --- a/TRLevelControl/Build/TRRoomBuilder.cs +++ b/TRLevelControl/Build/TRRoomBuilder.cs @@ -73,10 +73,15 @@ protected List> ReadSprites(TRLevelReader reader, ISpriteProvide for (int i = 0; i < numSprites; i++) { + short vertex = reader.ReadInt16(); + short offset = reader.ReadInt16(); + + T type = spriteProvider.FindSpriteType(offset); sprites.Add(new() { - Vertex = reader.ReadInt16(), - ID = spriteProvider.FindSpriteType(reader.ReadInt16()) + ID = type, + Vertex = vertex, + Frame = (short)(offset - spriteProvider.GetSpriteOffset(type)), }); } @@ -127,7 +132,7 @@ protected void WriteSprites(List> sprites, ISpriteProvider sp foreach (TRRoomSprite sprite in sprites) { writer.Write(sprite.Vertex); - writer.Write(spriteProvider.GetSpriteOffset(sprite.ID)); + writer.Write((short)(spriteProvider.GetSpriteOffset(sprite.ID) + sprite.Frame)); } } diff --git a/TRLevelControl/Build/TRSpriteBuilder.cs b/TRLevelControl/Build/TRSpriteBuilder.cs index f5cba3bf..cb427137 100644 --- a/TRLevelControl/Build/TRSpriteBuilder.cs +++ b/TRLevelControl/Build/TRSpriteBuilder.cs @@ -9,7 +9,7 @@ public class TRSpriteBuilder : ISpriteProvider private static readonly string _sprMarker = "SPR"; private readonly TRGameVersion _version; - private Dictionary _spriteOffsets; + private TRDictionary _sprites; public TRSpriteBuilder(TRGameVersion version) { @@ -86,30 +86,38 @@ public void WriteSprites(TRLevelWriter writer, TRDictionary public void CacheSpriteOffsets(TRDictionary spriteSequences) { - _spriteOffsets = new(); - short offset = 0; - foreach (var (type, sequence) in spriteSequences) - { - _spriteOffsets[type] = offset; - offset += (short)sequence.Textures.Count; - } + _sprites = spriteSequences; } public T FindSpriteType(short textureOffset) { - foreach (var (type, offset) in _spriteOffsets) + int offset = 0; + foreach (var (type, sprite) in _sprites) { - if (offset == textureOffset) + if (textureOffset >= offset && textureOffset < offset + sprite.Textures.Count) { return type; } + + offset += sprite.Textures.Count; } throw new IndexOutOfRangeException(); } - public short GetSpriteOffset(T type) + public short GetSpriteOffset(T spriteType) { - return _spriteOffsets[type]; + int offset = 0; + foreach (var (type, sprite) in _sprites) + { + if (EqualityComparer.Default.Equals(type, spriteType)) + { + break; + } + + offset += sprite.Textures.Count; + } + + return (short)offset; } } diff --git a/TRLevelControl/Model/Common/TRRoomSprite.cs b/TRLevelControl/Model/Common/TRRoomSprite.cs index fa837d6b..74ee6f41 100644 --- a/TRLevelControl/Model/Common/TRRoomSprite.cs +++ b/TRLevelControl/Model/Common/TRRoomSprite.cs @@ -4,6 +4,7 @@ public class TRRoomSprite : ICloneable where T : Enum { public T ID { get; set; } + public short Frame { get; set; } public short Vertex { get; set; } public TRRoomSprite Clone() diff --git a/TRLevelControlTests/Levels/TR1/TEST2.PHD b/TRLevelControlTests/Levels/TR1/TEST2.PHD index ff9f4b11..245830b9 100644 Binary files a/TRLevelControlTests/Levels/TR1/TEST2.PHD and b/TRLevelControlTests/Levels/TR1/TEST2.PHD differ diff --git a/TRLevelControlTests/TR1/SpriteTests.cs b/TRLevelControlTests/TR1/SpriteTests.cs new file mode 100644 index 00000000..392efcfe --- /dev/null +++ b/TRLevelControlTests/TR1/SpriteTests.cs @@ -0,0 +1,29 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using TRLevelControl.Model; + +namespace TRLevelControlTests.TR1; + +[TestClass] +[TestCategory("Sprites")] +public class SpriteTests : TestBase +{ + [TestMethod] + public void TestRoomSprites() + { + TR1Level level = GetTR1AltTestLevel(); + Assert.IsTrue(level.Rooms[0].Mesh.Sprites.Count == 1); + TRRoomSprite sprite = level.Rooms[0].Mesh.Sprites[0]; + + Assert.AreEqual(TR1Type.Plant2, sprite.ID); + Assert.AreEqual(0, sprite.Frame); + + Assert.IsTrue(level.Sprites[TR1Type.Plant2].Textures.Count > 1); + sprite.Frame = (short)(level.Sprites[TR1Type.Plant2].Textures.Count - 1); + + level = WriteReadTempLevel(level); + sprite = level.Rooms[0].Mesh.Sprites[0]; + + Assert.AreEqual(TR1Type.Plant2, sprite.ID); + Assert.AreEqual((short)(level.Sprites[TR1Type.Plant2].Textures.Count - 1), sprite.Frame); + } +}