Skip to content

Commit

Permalink
Fix room sprite offset handling (#771)
Browse files Browse the repository at this point in the history
Resolves #770.
  • Loading branch information
lahm86 authored Sep 29, 2024
1 parent 60708fb commit d7bd796
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 15 deletions.
11 changes: 8 additions & 3 deletions TRLevelControl/Build/TRRoomBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,15 @@ protected List<TRRoomSprite<T>> 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)),
});
}

Expand Down Expand Up @@ -127,7 +132,7 @@ protected void WriteSprites(List<TRRoomSprite<T>> sprites, ISpriteProvider<T> sp
foreach (TRRoomSprite<T> sprite in sprites)
{
writer.Write(sprite.Vertex);
writer.Write(spriteProvider.GetSpriteOffset(sprite.ID));
writer.Write((short)(spriteProvider.GetSpriteOffset(sprite.ID) + sprite.Frame));
}
}

Expand Down
32 changes: 20 additions & 12 deletions TRLevelControl/Build/TRSpriteBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class TRSpriteBuilder<T> : ISpriteProvider<T>
private static readonly string _sprMarker = "SPR";

private readonly TRGameVersion _version;
private Dictionary<T, short> _spriteOffsets;
private TRDictionary<T, TRSpriteSequence> _sprites;

public TRSpriteBuilder(TRGameVersion version)
{
Expand Down Expand Up @@ -86,30 +86,38 @@ public void WriteSprites(TRLevelWriter writer, TRDictionary<T, TRSpriteSequence>

public void CacheSpriteOffsets(TRDictionary<T, TRSpriteSequence> 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<T>.Default.Equals(type, spriteType))
{
break;
}

offset += sprite.Textures.Count;
}

return (short)offset;
}
}
1 change: 1 addition & 0 deletions TRLevelControl/Model/Common/TRRoomSprite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public class TRRoomSprite<T> : ICloneable
where T : Enum
{
public T ID { get; set; }
public short Frame { get; set; }
public short Vertex { get; set; }

public TRRoomSprite<T> Clone()
Expand Down
Binary file modified TRLevelControlTests/Levels/TR1/TEST2.PHD
Binary file not shown.
29 changes: 29 additions & 0 deletions TRLevelControlTests/TR1/SpriteTests.cs
Original file line number Diff line number Diff line change
@@ -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<TR1Type> 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);
}
}

0 comments on commit d7bd796

Please sign in to comment.