From 216a2186b3df45b1b16d6d80df0f034ddd153b6c Mon Sep 17 00:00:00 2001 From: lahm86 <33758420+lahm86@users.noreply.github.com> Date: Tue, 16 Apr 2024 22:26:32 +0100 Subject: [PATCH] Refactor mesh, texture and SFX collections (#618) Part of #468. --- Deps/TRGE.Coord.dll | Bin 1613824 -> 1613312 bytes SFXExport/Program.cs | 10 +- .../Model/Types/Mirroring/EMMirrorFunction.cs | 12 +- .../Types/Mirroring/EMMirrorModelFunction.cs | 14 +- .../Types/Mirroring/EMMirrorObjectTexture.cs | 2 +- .../Models/EMConvertSpriteSequenceFunction.cs | 6 +- .../Models/EMCopySpriteSequenceFunction.cs | 15 +- .../EMImportNonGraphicsModelFunction.cs | 12 +- .../Types/Textures/EMCreateTextureFunction.cs | 15 +- TRLevelControl/Control/TR1LevelControl.cs | 146 +++++++----------- TRLevelControl/Control/TR2LevelControl.cs | 136 ++++++---------- TRLevelControl/Control/TR3LevelControl.cs | 136 ++++++---------- TRLevelControl/Control/TR4LevelControl.cs | 20 +-- TRLevelControl/Control/TR5LevelControl.cs | 20 +-- TRLevelControl/Helpers/TRMeshUtilities.cs | 134 ++++------------ TRLevelControl/Model/Base/TR1Level.cs | 112 ++------------ .../Model/Base/TRAnimatedTexture.cs | 6 +- TRLevelControl/Model/TR2/TR2Level.cs | 107 +------------ TRLevelControl/Model/TR3/TR3Level.cs | 107 +------------ TRLevelControl/Model/TR4/TR4Level.cs | 4 +- TRLevelControl/Model/TR4/TR4LevelDataChunk.cs | 95 ++++-------- TRLevelControl/Model/TR5/TR5Level.cs | 4 +- TRLevelControl/Model/TR5/TR5LevelDataChunk.cs | 94 ++++------- TRLevelControl/TR2FileReadUtilities.cs | 9 +- TRLevelControl/TR4FileReadUtilities.cs | 113 ++++++-------- TRLevelControl/TR5FileReadUtilities.cs | 107 +++++-------- .../TR/TRAnimatedTextureControl.cs | 2 +- .../DataControls/TR/TRDemoDataControl.cs | 2 +- .../Controls/DataControls/TR/TRMeshControl.cs | 4 +- .../DataControls/TR/TRSoundControl.cs | 6 +- .../TR/TRSpriteAndObjTextureControl.cs | 6 +- .../Handlers/Animations/AnimationUtilities.cs | 12 +- .../Handlers/ColourTransportHandler.cs | 8 +- .../Handlers/MeshTransportHandler.cs | 6 +- .../Handlers/Sound/SoundUnpacker.cs | 43 ++---- .../Handlers/Sound/SoundUtilities.cs | 37 +++-- .../Textures/AbstractTextureImportHandler.cs | 24 +-- .../Textures/TR1/TR1TextureExportHandler.cs | 2 +- .../Textures/TR1/TR1TextureImportHandler.cs | 30 +--- .../Textures/TR2/TR2TextureExportHandler.cs | 2 +- .../Textures/TR2/TR2TextureImportHandler.cs | 42 ++--- .../Textures/TR3/TR3TextureExportHandler.cs | 2 +- .../Textures/TR3/TR3TextureImportHandler.cs | 28 +--- .../Helpers/TRModelExtensions.cs | 26 ++-- .../Model/Definitions/TR1ModelDefinition.cs | 2 +- .../Model/Definitions/TR2ModelDefinition.cs | 2 +- .../Model/Definitions/TR3ModelDefinition.cs | 2 +- .../Packing/AbstractTexturePacker.cs | 6 +- .../Packing/Types/TR1TexturePacker.cs | 12 +- .../Packing/Types/TR2TexturePacker.cs | 12 +- .../Packing/Types/TR3TexturePacker.cs | 12 +- .../Processors/TR2/TR2ModelAdjuster.cs | 7 +- .../Processors/TR3/TR3SequenceProcessor.cs | 3 +- .../Randomizers/TR1/TR1AudioRandomizer.cs | 40 ++--- .../Randomizers/TR1/TR1EnemyRandomizer.cs | 22 +-- .../Randomizers/TR1/TR1ItemRandomizer.cs | 6 +- .../Randomizers/TR1/TR1OutfitRandomizer.cs | 44 +++--- .../Randomizers/TR1/TR1SecretRandomizer.cs | 4 +- .../Randomizers/TR2/TR2AudioRandomizer.cs | 33 ++-- .../Randomizers/TR2/TR2EnemyRandomizer.cs | 9 +- .../Randomizers/TR2/TR2ItemRandomizer.cs | 7 +- .../Randomizers/TR2/TR2OutfitRandomizer.cs | 19 +-- .../Randomizers/TR2/TR2SecretRandomizer.cs | 6 +- .../Randomizers/TR2R/TR2RAudioRandomizer.cs | 26 ++-- .../Randomizers/TR3/TR3AudioRandomizer.cs | 35 ++--- .../Randomizers/TR3/TR3OutfitRandomizer.cs | 2 +- .../Randomizers/TR3/TR3SecretRandomizer.cs | 10 +- .../Randomizers/TR3R/TR3RAudioRandomizer.cs | 26 ++-- .../Textures/DynamicTextureBuilder.cs | 21 ++- .../Landmarks/AbstractLandmarkImporter.cs | 7 +- .../Textures/Landmarks/TR1LandmarkImporter.cs | 8 +- .../Textures/Landmarks/TR2LandmarkImporter.cs | 8 +- .../Textures/Landmarks/TR3LandmarkImporter.cs | 8 +- .../Wireframing/AbstractTRWireframer.cs | 44 ++---- .../Textures/Wireframing/TR1Wireframer.cs | 34 +--- .../Textures/Wireframing/TR2Wireframer.cs | 36 +---- .../Textures/Wireframing/TR3Wireframer.cs | 36 +---- .../Helpers/TRPalette8Control.cs | 4 +- .../Mapping/AbstractTextureMapping.cs | 16 +- .../Textures/Mapping/TR1TextureMapping.cs | 6 +- .../Textures/Mapping/TR2TextureMapping.cs | 6 +- .../Textures/Mapping/TR3TextureMapping.cs | 6 +- TextureExport/Types/FaceMapper.cs | 47 ++---- TextureExport/Types/HtmlExporter.cs | 2 +- 84 files changed, 725 insertions(+), 1629 deletions(-) diff --git a/Deps/TRGE.Coord.dll b/Deps/TRGE.Coord.dll index 157050b061defa32c1df8be600ad9b5ceca09688..aa1c9b0d785b26d0194da1f4b80c38704859f65f 100644 GIT binary patch delta 21151 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 delta 21238 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 diff --git a/SFXExport/Program.cs b/SFXExport/Program.cs index b890dd5e5..53b7918f0 100644 --- a/SFXExport/Program.cs +++ b/SFXExport/Program.cs @@ -79,19 +79,19 @@ private static void ExtractFromSFX(string file, TRGameVersion version, bool rema private static void ExtractFromPHD(string file, TRGameVersion version) { TR1Level level = new TR1LevelControl().Read(file); - for (int i = 0; i < level.NumSampleIndices; i++) + for (int i = 0; i < level.SampleIndices.Count; i++) { uint sampleStart = level.SampleIndices[i]; - uint sampleEnd = i < level.NumSampleIndices - 1 ? level.SampleIndices[i + 1] : (uint)level.Samples.Length; - if (sampleEnd > level.Samples.Length) + uint sampleEnd = i < level.SampleIndices.Count - 1 ? level.SampleIndices[i + 1] : (uint)level.Samples.Count; + if (sampleEnd > level.Samples.Count) { - sampleEnd = (uint)level.Samples.Length; + sampleEnd = (uint)level.Samples.Count; } using BinaryWriter writer = new(File.Create(Path.Combine(version.ToString(), i + ".wav"))); for (uint j = sampleStart; j < sampleEnd; j++) { - writer.Write(level.Samples[j]); + writer.Write(level.Samples[(int)j]); } } } diff --git a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs index a1570bd72..6564bacff 100644 --- a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs +++ b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs @@ -1080,7 +1080,7 @@ private static void MirrorTextures(TR1Level level) // Include all animated texture references too foreach (TRAnimatedTexture anim in level.AnimatedTextures) { - for (int i = 0; i < anim.Textures.Length; i++) + for (int i = 0; i < anim.Textures.Count; i++) { textureReferences.Add(anim.Textures[i]); } @@ -1161,7 +1161,7 @@ private static void MirrorTextures(TR2Level level) // Include all animated texture references too foreach (TRAnimatedTexture anim in level.AnimatedTextures) { - for (int i = 0; i < anim.Textures.Length; i++) + for (int i = 0; i < anim.Textures.Count; i++) { textureReferences.Add(anim.Textures[i]); } @@ -1232,7 +1232,7 @@ private static void MirrorTextures(TR3Level level) foreach (TRAnimatedTexture anim in level.AnimatedTextures) { - for (int i = 0; i < anim.Textures.Length; i++) + for (int i = 0; i < anim.Textures.Count; i++) { textureReferences.Add(anim.Textures[i]); } @@ -1241,7 +1241,7 @@ private static void MirrorTextures(TR3Level level) MirrorObjectTextures(textureReferences, level.ObjectTextures); } - private static void MirrorObjectTextures(ISet textureReferences, TRObjectTexture[] objectTextures) + private static void MirrorObjectTextures(ISet textureReferences, List objectTextures) { // Flip the object texture vertices in the same way as done for faces foreach (ushort textureRef in textureReferences) @@ -1263,11 +1263,11 @@ private static void MirrorObjectTextures(ISet textureReferences, TRObjec } } - private static void MirrorDependentFaces(IEnumerable models, ISet textureReferences, Func meshAction) + private static void MirrorDependentFaces(IEnumerable models, ISet textureReferences, Func> meshAction) { foreach (TRModel model in models) { - TRMesh[] meshes = meshAction.Invoke(model.ID); + List meshes = meshAction.Invoke(model.ID); if (meshes == null) { continue; diff --git a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorModelFunction.cs b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorModelFunction.cs index ad31ccc36..724cfb44e 100644 --- a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorModelFunction.cs +++ b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorModelFunction.cs @@ -13,8 +13,8 @@ public override void ApplyToLevel(TR1Level level) List meshes = new(); foreach (uint modelID in ModelIDs) { - TRMesh[] modelMeshes = TRMeshUtilities.GetModelMeshes(level, (TR1Type)modelID); - if (modelMeshes == null || modelMeshes.Length > 1) + List modelMeshes = TRMeshUtilities.GetModelMeshes(level, (TR1Type)modelID); + if (modelMeshes == null || modelMeshes.Count > 1) { throw new NotSupportedException("Only models with single meshes can be mirrored."); } @@ -30,8 +30,8 @@ public override void ApplyToLevel(TR2Level level) List meshes = new(); foreach (uint modelID in ModelIDs) { - TRMesh[] modelMeshes = TRMeshUtilities.GetModelMeshes(level, (TR2Type)modelID); - if (modelMeshes == null || modelMeshes.Length > 1) + List modelMeshes = TRMeshUtilities.GetModelMeshes(level, (TR2Type)modelID); + if (modelMeshes == null || modelMeshes.Count > 1) { throw new NotSupportedException("Only models with single meshes can be mirrored."); } @@ -47,8 +47,8 @@ public override void ApplyToLevel(TR3Level level) List meshes = new(); foreach (uint modelID in ModelIDs) { - TRMesh[] modelMeshes = TRMeshUtilities.GetModelMeshes(level, (TR3Type)modelID); - if (modelMeshes == null || modelMeshes.Length > 1) + List modelMeshes = TRMeshUtilities.GetModelMeshes(level, (TR3Type)modelID); + if (modelMeshes == null || modelMeshes.Count> 1) { throw new NotSupportedException("Only models with single meshes can be mirrored."); } @@ -106,7 +106,7 @@ private static ISet MirrorMeshes(List meshes) return textureReferences; } - private static void MirrorObjectTextures(ISet textureReferences, TRObjectTexture[] objectTextures) + private static void MirrorObjectTextures(ISet textureReferences, List objectTextures) { foreach (ushort textureRef in textureReferences) { diff --git a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorObjectTexture.cs b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorObjectTexture.cs index 4e03d5fb1..f7ad371f6 100644 --- a/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorObjectTexture.cs +++ b/TREnvironmentEditor/Model/Types/Mirroring/EMMirrorObjectTexture.cs @@ -22,7 +22,7 @@ public override void ApplyToLevel(TR3Level level) MirrorObjectTextures(level.ObjectTextures); } - private void MirrorObjectTextures(TRObjectTexture[] levelTextures) + private void MirrorObjectTextures(List levelTextures) { foreach (ushort textureRef in Textures) { diff --git a/TREnvironmentEditor/Model/Types/Models/EMConvertSpriteSequenceFunction.cs b/TREnvironmentEditor/Model/Types/Models/EMConvertSpriteSequenceFunction.cs index 43adbd575..38b92ee74 100644 --- a/TREnvironmentEditor/Model/Types/Models/EMConvertSpriteSequenceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Models/EMConvertSpriteSequenceFunction.cs @@ -25,11 +25,11 @@ public override void ApplyToLevel(TR3Level level) UpdateSpriteEntities(level.Entities); } - private void ConvertSpriteSequence(TRSpriteSequence[] sequences) + private void ConvertSpriteSequence(List sequences) { - if (Array.Find(sequences, s => s.SpriteID == NewSpriteID) == null) + if (sequences.Find(s => s.SpriteID == NewSpriteID) == null) { - TRSpriteSequence oldSequence = Array.Find(sequences, s => s.SpriteID == OldSpriteID); + TRSpriteSequence oldSequence = sequences.Find(s => s.SpriteID == OldSpriteID); if (oldSequence != null) { oldSequence.SpriteID = NewSpriteID; diff --git a/TREnvironmentEditor/Model/Types/Models/EMCopySpriteSequenceFunction.cs b/TREnvironmentEditor/Model/Types/Models/EMCopySpriteSequenceFunction.cs index 8afd1cd81..4b20f0ceb 100644 --- a/TREnvironmentEditor/Model/Types/Models/EMCopySpriteSequenceFunction.cs +++ b/TREnvironmentEditor/Model/Types/Models/EMCopySpriteSequenceFunction.cs @@ -9,26 +9,17 @@ public class EMCopySpriteSequenceFunction : BaseEMFunction public override void ApplyToLevel(TR1Level level) { - List sequences = level.SpriteSequences.ToList(); - CopySpriteSequence(sequences); - level.SpriteSequences = sequences.ToArray(); - level.NumSpriteSequences = (uint)sequences.Count; + CopySpriteSequence(level.SpriteSequences); } public override void ApplyToLevel(TR2Level level) { - List sequences = level.SpriteSequences.ToList(); - CopySpriteSequence(sequences); - level.SpriteSequences = sequences.ToArray(); - level.NumSpriteSequences = (uint)sequences.Count; + CopySpriteSequence(level.SpriteSequences); } public override void ApplyToLevel(TR3Level level) { - List sequences = level.SpriteSequences.ToList(); - CopySpriteSequence(sequences); - level.SpriteSequences = sequences.ToArray(); - level.NumSpriteSequences = (uint)sequences.Count; + CopySpriteSequence(level.SpriteSequences); } private void CopySpriteSequence(List sequences) diff --git a/TREnvironmentEditor/Model/Types/Models/EMImportNonGraphicsModelFunction.cs b/TREnvironmentEditor/Model/Types/Models/EMImportNonGraphicsModelFunction.cs index a802ad41a..1cb996955 100644 --- a/TREnvironmentEditor/Model/Types/Models/EMImportNonGraphicsModelFunction.cs +++ b/TREnvironmentEditor/Model/Types/Models/EMImportNonGraphicsModelFunction.cs @@ -27,7 +27,7 @@ public override void ApplyToLevel(TR1Level level) }; importer.Import(); - RemapFaces(data, level.NumObjectTextures - 1, modelID => TRMeshUtilities.GetModelMeshes(level, (TR1Type)modelID)); + RemapFaces(data, level.ObjectTextures.Count - 1, modelID => TRMeshUtilities.GetModelMeshes(level, (TR1Type)modelID)); } public override void ApplyToLevel(TR2Level level) @@ -48,7 +48,7 @@ public override void ApplyToLevel(TR2Level level) }; importer.Import(); - RemapFaces(data, level.NumObjectTextures - 1, modelID => TRMeshUtilities.GetModelMeshes(level, (TR2Type)modelID)); + RemapFaces(data, level.ObjectTextures.Count - 1, modelID => TRMeshUtilities.GetModelMeshes(level, (TR2Type)modelID)); } public override void ApplyToLevel(TR3Level level) @@ -69,7 +69,7 @@ public override void ApplyToLevel(TR3Level level) }; importer.Import(); - RemapFaces(data, level.NumObjectTextures - 1, modelID => TRMeshUtilities.GetModelMeshes(level, (TR3Type)modelID)); + RemapFaces(data, level.ObjectTextures.Count - 1, modelID => TRMeshUtilities.GetModelMeshes(level, (TR3Type)modelID)); } private List PrepareImportData(List existingModels) @@ -85,11 +85,11 @@ private List PrepareImportData(List existingModels) return importData; } - private static void RemapFaces(List data, uint maximumTexture, Func meshAction) + private static void RemapFaces(List data, int maximumTexture, Func> meshAction) { foreach (EMMeshTextureData textureData in data) { - TRMesh[] meshes = meshAction.Invoke(textureData.ModelID); + List meshes = meshAction.Invoke(textureData.ModelID); foreach (TRMesh mesh in meshes) { foreach (TRFace3 face in mesh.ColouredTriangles) @@ -112,7 +112,7 @@ private static void RemapFaces(List data, uint maximumTexture } } - private static ushort SelectReplacementTexture(EMMeshTextureData data, ushort currentTexture, int defaultTexture, uint maximumTexture) + private static ushort SelectReplacementTexture(EMMeshTextureData data, ushort currentTexture, int defaultTexture, int maximumTexture) { if (data.TextureMap != null && data.TextureMap.ContainsKey(currentTexture)) { diff --git a/TREnvironmentEditor/Model/Types/Textures/EMCreateTextureFunction.cs b/TREnvironmentEditor/Model/Types/Textures/EMCreateTextureFunction.cs index 802e5da5b..ba3d54440 100644 --- a/TREnvironmentEditor/Model/Types/Textures/EMCreateTextureFunction.cs +++ b/TREnvironmentEditor/Model/Types/Textures/EMCreateTextureFunction.cs @@ -16,10 +16,7 @@ public override void ApplyToLevel(TR1Level level) TR1TexturePacker packer = new(level); List textures = new(level.ObjectTextures); - List mapping = BuildAndPackTextures(packer, textures); - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)textures.Count; - + List mapping = BuildAndPackTextures(packer, level.ObjectTextures); mapping.ForEach(m => new EMRefaceFunction { TextureMap = m @@ -31,10 +28,7 @@ public override void ApplyToLevel(TR2Level level) TR2TexturePacker packer = new(level); List textures = new(level.ObjectTextures); - List mapping = BuildAndPackTextures(packer, textures); - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)textures.Count; - + List mapping = BuildAndPackTextures(packer, level.ObjectTextures); mapping.ForEach(m => new EMRefaceFunction { TextureMap = m @@ -46,10 +40,7 @@ public override void ApplyToLevel(TR3Level level) TR3TexturePacker packer = new(level); List textures = new(level.ObjectTextures); - List mapping = BuildAndPackTextures(packer, textures); - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)textures.Count; - + List mapping = BuildAndPackTextures(packer, level.ObjectTextures); mapping.ForEach(m => new EMRefaceFunction { TextureMap = m diff --git a/TRLevelControl/Control/TR1LevelControl.cs b/TRLevelControl/Control/TR1LevelControl.cs index e7e265a0e..23df8684f 100644 --- a/TRLevelControl/Control/TR1LevelControl.cs +++ b/TRLevelControl/Control/TR1LevelControl.cs @@ -99,29 +99,14 @@ protected override void Read(TRLevelReader reader) uint numFloorData = reader.ReadUInt32(); _level.FloorData = reader.ReadUInt16s(numFloorData).ToList(); - //Mesh Data - //This tells us how much mesh data (# of words/uint16s) coming up - //just like the rooms previously. - _level.NumMeshData = reader.ReadUInt32(); - _level.RawMeshData = new ushort[_level.NumMeshData]; - - for (int i = 0; i < _level.NumMeshData; i++) - { - _level.RawMeshData[i] = reader.ReadUInt16(); - } + uint numMeshData = reader.ReadUInt32(); + ushort[] rawMeshData = reader.ReadUInt16s(numMeshData); //Mesh Pointers - _level.NumMeshPointers = reader.ReadUInt32(); - _level.MeshPointers = new uint[_level.NumMeshPointers]; + uint numMeshPointers = reader.ReadUInt32(); + _level.MeshPointers = reader.ReadUInt32s(numMeshPointers).ToList(); - for (int i = 0; i < _level.NumMeshPointers; i++) - { - _level.MeshPointers[i] = reader.ReadUInt32(); - } - - //Mesh Construction - //level.Meshes = ConstructMeshData(level.NumMeshData, level.NumMeshPointers, level.RawMeshData); - _level.Meshes = ConstructMeshData(_level.MeshPointers, _level.RawMeshData); + _level.Meshes = ConstructMeshData(_level.MeshPointers, rawMeshData); //Animations uint numAnimations = reader.ReadUInt32(); @@ -187,31 +172,25 @@ protected override void Read(TRLevelReader reader) _level.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } - //Object Textures - _level.NumObjectTextures = reader.ReadUInt32(); - _level.ObjectTextures = new TRObjectTexture[_level.NumObjectTextures]; - - for (int i = 0; i < _level.NumObjectTextures; i++) + uint numObjectTextures = reader.ReadUInt32(); + _level.ObjectTextures = new(); + for (int i = 0; i < numObjectTextures; i++) { - _level.ObjectTextures[i] = TR2FileReadUtilities.ReadObjectTexture(reader); + _level.ObjectTextures.Add(TR2FileReadUtilities.ReadObjectTexture(reader)); } - //Sprite Textures - _level.NumSpriteTextures = reader.ReadUInt32(); - _level.SpriteTextures = new TRSpriteTexture[_level.NumSpriteTextures]; - - for (int i = 0; i < _level.NumSpriteTextures; i++) + uint numSpriteTextures = reader.ReadUInt32(); + _level.SpriteTextures = new(); + for (int i = 0; i < numSpriteTextures; i++) { - _level.SpriteTextures[i] = TR2FileReadUtilities.ReadSpriteTexture(reader); + _level.SpriteTextures.Add(TR2FileReadUtilities.ReadSpriteTexture(reader)); } - //Sprite Sequences - _level.NumSpriteSequences = reader.ReadUInt32(); - _level.SpriteSequences = new TRSpriteSequence[_level.NumSpriteSequences]; - - for (int i = 0; i < _level.NumSpriteSequences; i++) + uint numSpriteSequences = reader.ReadUInt32(); + _level.SpriteSequences = new(); + for (int i = 0; i < numSpriteSequences; i++) { - _level.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); + _level.SpriteSequences.Add(TR2FileReadUtilities.ReadSpriteSequence(reader)); } //Cameras @@ -244,13 +223,12 @@ protected override void Read(TRLevelReader reader) ushort[] zoneData = reader.ReadUInt16s(numBoxes * 6); _level.Zones = TR1BoxUtilities.ReadZones(numBoxes, zoneData); - //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) - //followed by a ushort to describe the number of actual texture group objects. - _level.NumAnimatedTextures = reader.ReadUInt32(); - _level.AnimatedTextures = new TRAnimatedTexture[reader.ReadUInt16()]; - for (int i = 0; i < _level.AnimatedTextures.Length; i++) + reader.ReadUInt32(); // Total count of ushorts + ushort numGroups = reader.ReadUInt16(); + _level.AnimatedTextures = new(); + for (int i = 0; i < numGroups; i++) { - _level.AnimatedTextures[i] = TR2FileReadUtilities.ReadAnimatedTexture(reader); + _level.AnimatedTextures.Add(TR2FileReadUtilities.ReadAnimatedTexture(reader)); } //Entities @@ -268,14 +246,8 @@ protected override void Read(TRLevelReader reader) _level.CinematicFrames.Add(TR2FileReadUtilities.ReadCinematicFrame(reader)); } - //Demo Data - _level.NumDemoData = reader.ReadUInt16(); - _level.DemoData = new byte[_level.NumDemoData]; - - for (int i = 0; i < _level.NumDemoData; i++) - { - _level.DemoData[i] = reader.ReadByte(); - } + ushort numDemoData = reader.ReadUInt16(); + _level.DemoData = reader.ReadBytes(numDemoData); //Sound Map & Sound Details _level.SoundMap = new short[256]; @@ -285,30 +257,22 @@ protected override void Read(TRLevelReader reader) _level.SoundMap[i] = reader.ReadInt16(); } - _level.NumSoundDetails = reader.ReadUInt32(); - _level.SoundDetails = new TRSoundDetails[_level.NumSoundDetails]; - - for (int i = 0; i < _level.NumSoundDetails; i++) + uint numSoundDetails = reader.ReadUInt32(); + _level.SoundDetails = new(); + for (int i = 0; i < numSoundDetails; i++) { - _level.SoundDetails[i] = TR2FileReadUtilities.ReadSoundDetails(reader); + _level.SoundDetails.Add(TR2FileReadUtilities.ReadSoundDetails(reader)); } - //Samples - _level.NumSamples = reader.ReadUInt32(); - _level.Samples = new byte[_level.NumSamples]; - - for (int i = 0; i < _level.NumSamples; i++) + uint numSamples = reader.ReadUInt32(); + _level.Samples = new(); + for (int i = 0; i < numSamples; i++) { - _level.Samples[i] = reader.ReadByte(); + _level.Samples.Add(reader.ReadByte()); } - _level.NumSampleIndices = reader.ReadUInt32(); - _level.SampleIndices = new uint[_level.NumSampleIndices]; - - for (int i = 0; i < _level.NumSampleIndices; i++) - { - _level.SampleIndices[i] = reader.ReadUInt32(); - } + uint numSampleIndices = reader.ReadUInt32(); + _level.SampleIndices = reader.ReadUInt32s(numSampleIndices).ToList(); } protected override void Write(TRLevelWriter writer) @@ -324,10 +288,11 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.FloorData.Count); writer.Write(_level.FloorData); - writer.Write(_level.NumMeshData); - foreach (TRMesh mesh in _level.Meshes) { writer.Write(mesh.Serialize()); } - writer.Write(_level.NumMeshPointers); - foreach (uint ptr in _level.MeshPointers) { writer.Write(ptr); } + List meshData = _level.Meshes.SelectMany(m => m.Serialize()).ToList(); + writer.Write((uint)meshData.Count / 2); + writer.Write(meshData.ToArray()); + writer.Write((uint)_level.MeshPointers.Count); + writer.Write(_level.MeshPointers); writer.Write((uint)_level.Animations.Count); foreach (TRAnimation anim in _level.Animations) { writer.Write(anim.Serialize()); } @@ -347,11 +312,11 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.StaticMeshes.Count); foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); } - writer.Write(_level.NumObjectTextures); + writer.Write((uint)_level.ObjectTextures.Count); foreach (TRObjectTexture tex in _level.ObjectTextures) { writer.Write(tex.Serialize()); } - writer.Write(_level.NumSpriteTextures); + writer.Write((uint)_level.SpriteTextures.Count); foreach (TRSpriteTexture tex in _level.SpriteTextures) { writer.Write(tex.Serialize()); } - writer.Write(_level.NumSpriteSequences); + writer.Write((uint)_level.SpriteSequences.Count); foreach (TRSpriteSequence sequence in _level.SpriteSequences) { writer.Write(sequence.Serialize()); } writer.Write((uint)_level.Cameras.Count); @@ -366,9 +331,10 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.Overlaps); writer.Write(TR1BoxUtilities.FlattenZones(_level.Zones)); - writer.Write(_level.NumAnimatedTextures); - writer.Write((ushort)_level.AnimatedTextures.Length); - foreach (TRAnimatedTexture texture in _level.AnimatedTextures) { writer.Write(texture.Serialize()); } + byte[] animTextureData = _level.AnimatedTextures.SelectMany(a => a.Serialize()).ToArray(); + writer.Write((uint)(animTextureData.Length / sizeof(ushort)) + 1); + writer.Write((ushort)_level.AnimatedTextures.Count); + writer.Write(animTextureData); writer.Write((uint)_level.Entities.Count); writer.Write(_level.Entities); @@ -381,16 +347,16 @@ protected override void Write(TRLevelWriter writer) writer.Write((ushort)_level.CinematicFrames.Count); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } - writer.Write(_level.NumDemoData); + writer.Write((ushort)_level.DemoData.Length); writer.Write(_level.DemoData); foreach (short sound in _level.SoundMap) { writer.Write(sound); } - writer.Write(_level.NumSoundDetails); + writer.Write((uint)_level.SoundDetails.Count); foreach (TRSoundDetails snddetail in _level.SoundDetails) { writer.Write(snddetail.Serialize()); } - writer.Write(_level.NumSamples); - foreach (byte sample in _level.Samples) { writer.Write(sample); } - writer.Write(_level.NumSampleIndices); - foreach (uint index in _level.SampleIndices) { writer.Write(index); } + writer.Write((uint)_level.Samples.Count); + writer.Write(_level.Samples.ToArray()); + writer.Write((uint)_level.SampleIndices.Count); + writer.Write(_level.SampleIndices); } private static TRRoomData ConvertToRoomData(TRRoom room) @@ -500,21 +466,21 @@ private static TRRoomData ConvertToRoomData(TRRoom room) return RoomData; } - private static TRMesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshData) + private static List ConstructMeshData(List meshPointers, ushort[] rawMeshData) { byte[] target = new byte[rawMeshData.Length * 2]; Buffer.BlockCopy(rawMeshData, 0, target, 0, target.Length); // The mesh pointer list can contain duplicates so we must make // sure to iterate over distinct values only - meshPointers = meshPointers.Distinct().ToArray(); + meshPointers = new(meshPointers.Distinct()); List meshes = new(); using (MemoryStream ms = new(target)) using (BinaryReader br = new(ms)) { - for (int i = 0; i < meshPointers.Length; i++) + for (int i = 0; i < meshPointers.Count; i++) { TRMesh mesh = new(); meshes.Add(mesh); @@ -599,6 +565,6 @@ private static TRMesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshD } } - return meshes.ToArray(); + return meshes; } } diff --git a/TRLevelControl/Control/TR2LevelControl.cs b/TRLevelControl/Control/TR2LevelControl.cs index 8914a241b..05e656657 100644 --- a/TRLevelControl/Control/TR2LevelControl.cs +++ b/TRLevelControl/Control/TR2LevelControl.cs @@ -107,29 +107,13 @@ protected override void Read(TRLevelReader reader) uint numFloorData = reader.ReadUInt32(); _level.FloorData = reader.ReadUInt16s(numFloorData).ToList(); - //Mesh Data - //This tells us how much mesh data (# of words/uint16s) coming up - //just like the rooms previously. - _level.NumMeshData = reader.ReadUInt32(); - _level.RawMeshData = new ushort[_level.NumMeshData]; + uint numMeshData = reader.ReadUInt32(); + ushort[] rawMeshData = reader.ReadUInt16s(numMeshData); - for (int i = 0; i < _level.NumMeshData; i++) - { - _level.RawMeshData[i] = reader.ReadUInt16(); - } - - //Mesh Pointers - _level.NumMeshPointers = reader.ReadUInt32(); - _level.MeshPointers = new uint[_level.NumMeshPointers]; + uint numMeshPointers = reader.ReadUInt32(); + _level.MeshPointers = reader.ReadUInt32s(numMeshPointers).ToList(); - for (int i = 0; i < _level.NumMeshPointers; i++) - { - _level.MeshPointers[i] = reader.ReadUInt32(); - } - - //Mesh Construction - //level.Meshes = ConstructMeshData(level.NumMeshData, level.NumMeshPointers, level.RawMeshData); - _level.Meshes = ConstructMeshData(_level.MeshPointers, _level.RawMeshData); + _level.Meshes = ConstructMeshData(_level.MeshPointers, rawMeshData); //Animations uint numAnimations = reader.ReadUInt32(); @@ -194,31 +178,25 @@ protected override void Read(TRLevelReader reader) _level.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } - //Object Textures - _level.NumObjectTextures = reader.ReadUInt32(); - _level.ObjectTextures = new TRObjectTexture[_level.NumObjectTextures]; - - for (int i = 0; i < _level.NumObjectTextures; i++) + uint numObjectTextures = reader.ReadUInt32(); + _level.ObjectTextures = new(); + for (int i = 0; i < numObjectTextures; i++) { - _level.ObjectTextures[i] = TR2FileReadUtilities.ReadObjectTexture(reader); + _level.ObjectTextures.Add(TR2FileReadUtilities.ReadObjectTexture(reader)); } - //Sprite Textures - _level.NumSpriteTextures = reader.ReadUInt32(); - _level.SpriteTextures = new TRSpriteTexture[_level.NumSpriteTextures]; - - for (int i = 0; i < _level.NumSpriteTextures; i++) + uint numSpriteTextures = reader.ReadUInt32(); + _level.SpriteTextures = new(); + for (int i = 0; i < numSpriteTextures; i++) { - _level.SpriteTextures[i] = TR2FileReadUtilities.ReadSpriteTexture(reader); + _level.SpriteTextures.Add(TR2FileReadUtilities.ReadSpriteTexture(reader)); } - //Sprite Sequences - _level.NumSpriteSequences = reader.ReadUInt32(); - _level.SpriteSequences = new TRSpriteSequence[_level.NumSpriteSequences]; - - for (int i = 0; i < _level.NumSpriteSequences; i++) + uint numSpriteSequences = reader.ReadUInt32(); + _level.SpriteSequences = new(); + for (int i = 0; i < numSpriteSequences; i++) { - _level.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); + _level.SpriteSequences.Add(TR2FileReadUtilities.ReadSpriteSequence(reader)); } uint numCameras = reader.ReadUInt32(); @@ -250,13 +228,12 @@ protected override void Read(TRLevelReader reader) ushort[] zoneData = reader.ReadUInt16s(numBoxes * 10); _level.Zones = TR2BoxUtilities.ReadZones(numBoxes, zoneData); - //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) - //followed by a ushort to describe the number of actual texture group objects. - _level.NumAnimatedTextures = reader.ReadUInt32(); - _level.AnimatedTextures = new TRAnimatedTexture[reader.ReadUInt16()]; - for (int i = 0; i < _level.AnimatedTextures.Length; i++) + reader.ReadUInt32(); // Total count of ushorts + ushort numGroups = reader.ReadUInt16(); + _level.AnimatedTextures = new(); + for (int i = 0; i < numGroups; i++) { - _level.AnimatedTextures[i] = TR2FileReadUtilities.ReadAnimatedTexture(reader); + _level.AnimatedTextures.Add(TR2FileReadUtilities.ReadAnimatedTexture(reader)); } //Entities @@ -273,14 +250,8 @@ protected override void Read(TRLevelReader reader) _level.CinematicFrames.Add(TR2FileReadUtilities.ReadCinematicFrame(reader)); } - //Demo Data - _level.NumDemoData = reader.ReadUInt16(); - _level.DemoData = new byte[_level.NumDemoData]; - - for (int i = 0; i < _level.NumDemoData; i++) - { - _level.DemoData[i] = reader.ReadByte(); - } + ushort numDemoData = reader.ReadUInt16(); + _level.DemoData = reader.ReadBytes(numDemoData); //Sound Map (370 shorts = 740 bytes) & Sound Details _level.SoundMap = new short[370]; @@ -290,22 +261,15 @@ protected override void Read(TRLevelReader reader) _level.SoundMap[i] = reader.ReadInt16(); } - _level.NumSoundDetails = reader.ReadUInt32(); - _level.SoundDetails = new TRSoundDetails[_level.NumSoundDetails]; - - for (int i = 0; i < _level.NumSoundDetails; i++) + uint numSoundDetails = reader.ReadUInt32(); + _level.SoundDetails = new(); + for (int i = 0; i < numSoundDetails; i++) { - _level.SoundDetails[i] = TR2FileReadUtilities.ReadSoundDetails(reader); + _level.SoundDetails.Add(TR2FileReadUtilities.ReadSoundDetails(reader)); } - //Samples - _level.NumSampleIndices = reader.ReadUInt32(); - _level.SampleIndices = new uint[_level.NumSampleIndices]; - - for (int i = 0; i < _level.NumSampleIndices; i++) - { - _level.SampleIndices[i] = reader.ReadUInt32(); - } + uint numSampleIndices = reader.ReadUInt32(); + _level.SampleIndices = reader.ReadUInt32s(numSampleIndices).ToList(); } protected override void Write(TRLevelWriter writer) @@ -328,10 +292,11 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.FloorData.Count); writer.Write(_level.FloorData); - writer.Write(_level.NumMeshData); - foreach (TRMesh mesh in _level.Meshes) { writer.Write(mesh.Serialize()); } - writer.Write(_level.NumMeshPointers); - foreach (uint ptr in _level.MeshPointers) { writer.Write(ptr); } + List meshData = _level.Meshes.SelectMany(m => m.Serialize()).ToList(); + writer.Write((uint)meshData.Count / 2); + writer.Write(meshData.ToArray()); + writer.Write((uint)_level.MeshPointers.Count); + writer.Write(_level.MeshPointers); writer.Write((uint)_level.Animations.Count); foreach (TRAnimation anim in _level.Animations) { writer.Write(anim.Serialize()); } @@ -351,11 +316,11 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.StaticMeshes.Count); foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); } - writer.Write(_level.NumObjectTextures); + writer.Write((uint)_level.ObjectTextures.Count); foreach (TRObjectTexture tex in _level.ObjectTextures) { writer.Write(tex.Serialize()); } - writer.Write(_level.NumSpriteTextures); + writer.Write((uint)_level.SpriteTextures.Count); foreach (TRSpriteTexture tex in _level.SpriteTextures) { writer.Write(tex.Serialize()); } - writer.Write(_level.NumSpriteSequences); + writer.Write((uint)_level.SpriteSequences.Count); foreach (TRSpriteSequence sequence in _level.SpriteSequences) { writer.Write(sequence.Serialize()); } writer.Write((uint)_level.Cameras.Count); @@ -370,10 +335,11 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.Overlaps); writer.Write(TR2BoxUtilities.FlattenZones(_level.Zones)); - writer.Write(_level.NumAnimatedTextures); - writer.Write((ushort)_level.AnimatedTextures.Length); - foreach (TRAnimatedTexture texture in _level.AnimatedTextures) { writer.Write(texture.Serialize()); } - + byte[] animTextureData = _level.AnimatedTextures.SelectMany(a => a.Serialize()).ToArray(); + writer.Write((uint)(animTextureData.Length / sizeof(ushort)) + 1); + writer.Write((ushort)_level.AnimatedTextures.Count); + writer.Write(animTextureData); + writer.Write((uint)_level.Entities.Count); writer.Write(_level.Entities); @@ -383,14 +349,14 @@ protected override void Write(TRLevelWriter writer) writer.Write((ushort)_level.CinematicFrames.Count); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } - writer.Write(_level.NumDemoData); + writer.Write((ushort)_level.DemoData.Length); writer.Write(_level.DemoData); foreach (short sound in _level.SoundMap) { writer.Write(sound); } - writer.Write(_level.NumSoundDetails); + writer.Write((uint)_level.SoundDetails.Count); foreach (TRSoundDetails snddetail in _level.SoundDetails) { writer.Write(snddetail.Serialize()); } - writer.Write(_level.NumSampleIndices); - foreach (uint index in _level.SampleIndices) { writer.Write(index); } + writer.Write((uint)_level.SampleIndices.Count); + writer.Write(_level.SampleIndices); } private static TR2RoomData ConvertToRoomData(TR2Room room) @@ -504,21 +470,21 @@ private static TR2RoomData ConvertToRoomData(TR2Room room) return RoomData; } - private static TRMesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshData) + private static List ConstructMeshData(List meshPointers, ushort[] rawMeshData) { byte[] target = new byte[rawMeshData.Length * 2]; Buffer.BlockCopy(rawMeshData, 0, target, 0, target.Length); // The mesh pointer list can contain duplicates so we must make // sure to iterate over distinct values only - meshPointers = meshPointers.Distinct().ToArray(); + meshPointers = new(meshPointers.Distinct()); List meshes = new(); using (MemoryStream ms = new(target)) using (BinaryReader br = new(ms)) { - for (int i = 0; i < meshPointers.Length; i++) + for (int i = 0; i < meshPointers.Count; i++) { TRMesh mesh = new(); meshes.Add(mesh); @@ -603,6 +569,6 @@ private static TRMesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshD } } - return meshes.ToArray(); + return meshes; } } diff --git a/TRLevelControl/Control/TR3LevelControl.cs b/TRLevelControl/Control/TR3LevelControl.cs index 2c4d363cd..d041c1f6a 100644 --- a/TRLevelControl/Control/TR3LevelControl.cs +++ b/TRLevelControl/Control/TR3LevelControl.cs @@ -111,29 +111,13 @@ protected override void Read(TRLevelReader reader) uint numFloorData = reader.ReadUInt32(); _level.FloorData = reader.ReadUInt16s(numFloorData).ToList(); - //Mesh Data - //This tells us how much mesh data (# of words/uint16s) coming up - //just like the rooms previously. - _level.NumMeshData = reader.ReadUInt32(); - _level.RawMeshData = new ushort[_level.NumMeshData]; + uint numMeshData = reader.ReadUInt32(); + ushort[] rawMeshData = reader.ReadUInt16s(numMeshData); - for (int i = 0; i < _level.NumMeshData; i++) - { - _level.RawMeshData[i] = reader.ReadUInt16(); - } - - //Mesh Pointers - _level.NumMeshPointers = reader.ReadUInt32(); - _level.MeshPointers = new uint[_level.NumMeshPointers]; - - for (int i = 0; i < _level.NumMeshPointers; i++) - { - _level.MeshPointers[i] = reader.ReadUInt32(); - } + uint numMeshPointers = reader.ReadUInt32(); + _level.MeshPointers = reader.ReadUInt32s(numMeshPointers).ToList(); - //Mesh Construction - //level.Meshes = ConstructMeshData(level.NumMeshData, level.NumMeshPointers, level.RawMeshData); - _level.Meshes = ConstructMeshData(_level.MeshPointers, _level.RawMeshData); + _level.Meshes = ConstructMeshData(_level.MeshPointers, rawMeshData); //Animations uint numAnimations = reader.ReadUInt32(); @@ -199,24 +183,18 @@ protected override void Read(TRLevelReader reader) _level.StaticMeshes.Add(TR2FileReadUtilities.ReadStaticMesh(reader)); } - //Object Textures - in TR3 this is now after animated textures - - //Sprite Textures - _level.NumSpriteTextures = reader.ReadUInt32(); - _level.SpriteTextures = new TRSpriteTexture[_level.NumSpriteTextures]; - - for (int i = 0; i < _level.NumSpriteTextures; i++) + uint numSpriteTextures = reader.ReadUInt32(); + _level.SpriteTextures = new(); + for (int i = 0; i < numSpriteTextures; i++) { - _level.SpriteTextures[i] = TR2FileReadUtilities.ReadSpriteTexture(reader); + _level.SpriteTextures.Add(TR2FileReadUtilities.ReadSpriteTexture(reader)); } - //Sprite Sequences - _level.NumSpriteSequences = reader.ReadUInt32(); - _level.SpriteSequences = new TRSpriteSequence[_level.NumSpriteSequences]; - - for (int i = 0; i < _level.NumSpriteSequences; i++) + uint numSpriteSequences = reader.ReadUInt32(); + _level.SpriteSequences = new(); + for (int i = 0; i < numSpriteSequences; i++) { - _level.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); + _level.SpriteSequences.Add(TR2FileReadUtilities.ReadSpriteSequence(reader)); } uint numCameras = reader.ReadUInt32(); @@ -248,22 +226,20 @@ protected override void Read(TRLevelReader reader) ushort[] zoneData = reader.ReadUInt16s(numBoxes * 10); _level.Zones = TR2BoxUtilities.ReadZones(numBoxes, zoneData); - //Animated Textures - the data stores the total number of ushorts to read (NumAnimatedTextures) - //followed by a ushort to describe the number of actual texture group objects. - _level.NumAnimatedTextures = reader.ReadUInt32(); - _level.AnimatedTextures = new TRAnimatedTexture[reader.ReadUInt16()]; - for (int i = 0; i < _level.AnimatedTextures.Length; i++) + reader.ReadUInt32(); // Total count of ushorts + ushort numGroups = reader.ReadUInt16(); + _level.AnimatedTextures = new(); + for (int i = 0; i < numGroups; i++) { - _level.AnimatedTextures[i] = TR2FileReadUtilities.ReadAnimatedTexture(reader); + _level.AnimatedTextures.Add(TR2FileReadUtilities.ReadAnimatedTexture(reader)); } //Object Textures - in TR3 this is now after animated textures - _level.NumObjectTextures = reader.ReadUInt32(); - _level.ObjectTextures = new TRObjectTexture[_level.NumObjectTextures]; - - for (int i = 0; i < _level.NumObjectTextures; i++) + uint numObjectTextures = reader.ReadUInt32(); + _level.ObjectTextures = new(); + for (int i = 0; i < numObjectTextures; i++) { - _level.ObjectTextures[i] = TR2FileReadUtilities.ReadObjectTexture(reader); + _level.ObjectTextures.Add(TR2FileReadUtilities.ReadObjectTexture(reader)); } //Entities @@ -280,14 +256,8 @@ protected override void Read(TRLevelReader reader) _level.CinematicFrames.Add(TR2FileReadUtilities.ReadCinematicFrame(reader)); } - //Demo Data - _level.NumDemoData = reader.ReadUInt16(); - _level.DemoData = new byte[_level.NumDemoData]; - - for (int i = 0; i < _level.NumDemoData; i++) - { - _level.DemoData[i] = reader.ReadByte(); - } + ushort numDemoData = reader.ReadUInt16(); + _level.DemoData = reader.ReadBytes(numDemoData); //Sound Map (370 shorts = 740 bytes) & Sound Details _level.SoundMap = new short[370]; @@ -297,22 +267,15 @@ protected override void Read(TRLevelReader reader) _level.SoundMap[i] = reader.ReadInt16(); } - _level.NumSoundDetails = reader.ReadUInt32(); - _level.SoundDetails = new TR3SoundDetails[_level.NumSoundDetails]; - - for (int i = 0; i < _level.NumSoundDetails; i++) + uint numSoundDetails = reader.ReadUInt32(); + _level.SoundDetails = new(); + for (int i = 0; i < numSoundDetails; i++) { - _level.SoundDetails[i] = TR3FileReadUtilities.ReadSoundDetails(reader); + _level.SoundDetails.Add(TR3FileReadUtilities.ReadSoundDetails(reader)); } - //Samples - _level.NumSampleIndices = reader.ReadUInt32(); - _level.SampleIndices = new uint[_level.NumSampleIndices]; - - for (int i = 0; i < _level.NumSampleIndices; i++) - { - _level.SampleIndices[i] = reader.ReadUInt32(); - } + uint numSampleIndices = reader.ReadUInt32(); + _level.SampleIndices = reader.ReadUInt32s(numSampleIndices).ToList(); } protected override void Write(TRLevelWriter writer) @@ -335,10 +298,11 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.FloorData.Count); writer.Write(_level.FloorData); - writer.Write(_level.NumMeshData); - foreach (TRMesh mesh in _level.Meshes) { writer.Write(mesh.Serialize()); } - writer.Write(_level.NumMeshPointers); - foreach (uint ptr in _level.MeshPointers) { writer.Write(ptr); } + List meshData = _level.Meshes.SelectMany(m => m.Serialize()).ToList(); + writer.Write((uint)meshData.Count / 2); + writer.Write(meshData.ToArray()); + writer.Write((uint)_level.MeshPointers.Count); + writer.Write(_level.MeshPointers); writer.Write((uint)_level.Animations.Count); foreach (TRAnimation anim in _level.Animations) { writer.Write(anim.Serialize()); } @@ -358,9 +322,9 @@ protected override void Write(TRLevelWriter writer) writer.Write((uint)_level.StaticMeshes.Count); foreach (TRStaticMesh mesh in _level.StaticMeshes) { writer.Write(mesh.Serialize()); } - writer.Write(_level.NumSpriteTextures); + writer.Write((uint)_level.SpriteTextures.Count); foreach (TRSpriteTexture tex in _level.SpriteTextures) { writer.Write(tex.Serialize()); } - writer.Write(_level.NumSpriteSequences); + writer.Write((uint)_level.SpriteSequences.Count); foreach (TRSpriteSequence sequence in _level.SpriteSequences) { writer.Write(sequence.Serialize()); } writer.Write((uint)_level.Cameras.Count); @@ -375,10 +339,12 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.Overlaps); writer.Write(TR2BoxUtilities.FlattenZones(_level.Zones)); - writer.Write(_level.NumAnimatedTextures); - writer.Write((ushort)_level.AnimatedTextures.Length); - foreach (TRAnimatedTexture texture in _level.AnimatedTextures) { writer.Write(texture.Serialize()); } - writer.Write(_level.NumObjectTextures); + byte[] animTextureData = _level.AnimatedTextures.SelectMany(a => a.Serialize()).ToArray(); + writer.Write((uint)(animTextureData.Length / sizeof(ushort)) + 1); + writer.Write((ushort)_level.AnimatedTextures.Count); + writer.Write(animTextureData); + + writer.Write((uint)_level.ObjectTextures.Count); foreach (TRObjectTexture tex in _level.ObjectTextures) { writer.Write(tex.Serialize()); } writer.Write((uint)_level.Entities.Count); @@ -390,14 +356,14 @@ protected override void Write(TRLevelWriter writer) writer.Write((ushort)_level.CinematicFrames.Count); foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); } - writer.Write(_level.NumDemoData); + writer.Write((ushort)_level.DemoData.Length); writer.Write(_level.DemoData); foreach (short sound in _level.SoundMap) { writer.Write(sound); } - writer.Write(_level.NumSoundDetails); + writer.Write((uint)_level.SoundDetails.Count); foreach (TR3SoundDetails snddetail in _level.SoundDetails) { writer.Write(snddetail.Serialize()); } - writer.Write(_level.NumSampleIndices); - foreach (uint index in _level.SampleIndices) { writer.Write(index); } + writer.Write((uint)_level.SampleIndices.Count); + writer.Write(_level.SampleIndices); } private static TR3RoomData ConvertToRoomData(TR3Room room) @@ -511,21 +477,21 @@ private static TR3RoomData ConvertToRoomData(TR3Room room) return RoomData; } - private static TRMesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshData) + private static List ConstructMeshData(List meshPointers, ushort[] rawMeshData) { byte[] target = new byte[rawMeshData.Length * 2]; Buffer.BlockCopy(rawMeshData, 0, target, 0, target.Length); // The mesh pointer list can contain duplicates so we must make // sure to iterate over distinct values only - meshPointers = meshPointers.Distinct().ToArray(); + meshPointers = new(meshPointers.Distinct()); List meshes = new(); using (MemoryStream ms = new(target)) using (BinaryReader br = new(ms)) { - for (int i = 0; i < meshPointers.Length; i++) + for (int i = 0; i < meshPointers.Count; i++) { TRMesh mesh = new(); meshes.Add(mesh); @@ -610,6 +576,6 @@ private static TRMesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshD } } - return meshes.ToArray(); + return meshes; } } diff --git a/TRLevelControl/Control/TR4LevelControl.cs b/TRLevelControl/Control/TR4LevelControl.cs index 78eb53309..266cf8928 100644 --- a/TRLevelControl/Control/TR4LevelControl.cs +++ b/TRLevelControl/Control/TR4LevelControl.cs @@ -56,19 +56,16 @@ protected override void Read(TRLevelReader reader) //Decompress DecompressLevelDataChunk(_level); - //Samples - _level.NumSamples = reader.ReadUInt32(); - _level.Samples = new TR4Sample[_level.NumSamples]; + uint numSamples = reader.ReadUInt32(); + _level.Samples = new(); - for(int i = 0; i < _level.NumSamples; i++) + for (int i = 0; i < numSamples; i++) { - TR4Sample sample = new() + _level.Samples.Add(new() { UncompSize = reader.ReadUInt32(), CompSize = reader.ReadUInt32(), - }; - - _level.Samples[i] = sample; + }); //Compressed chunk is actually NOT zlib compressed - it is simply a WAV file. _level.Samples[i].CompressedChunk = reader.ReadBytes((int)_level.Samples[i].CompSize); @@ -109,8 +106,7 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.LevelDataChunk.CompressedSize); writer.Write(chunk); - writer.Write(_level.NumSamples); - + writer.Write((uint)_level.Samples.Count); foreach (TR4Sample sample in _level.Samples) { writer.Write(sample.UncompSize); @@ -134,13 +130,13 @@ private static void DecompressLevelDataChunk(TR4Level lvl) TR4FileReadUtilities.PopulateAnimations(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateMeshTreesFramesModels(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateStaticMeshes(lvlChunkReader, lvl); - TR4FileReadUtilities.VerifySPRMarker(lvlChunkReader, lvl); + TR4FileReadUtilities.VerifySPRMarker(lvlChunkReader); TR4FileReadUtilities.PopulateSprites(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateCameras(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateSoundSources(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateBoxesOverlapsZones(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateAnimatedTextures(lvlChunkReader, lvl); - TR4FileReadUtilities.VerifyTEXMarker(lvlChunkReader, lvl); + TR4FileReadUtilities.VerifyTEXMarker(lvlChunkReader); TR4FileReadUtilities.PopulateObjectTextures(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateEntitiesAndAI(lvlChunkReader, lvl); TR4FileReadUtilities.PopulateDemoSoundSampleIndices(lvlChunkReader, lvl); diff --git a/TRLevelControl/Control/TR5LevelControl.cs b/TRLevelControl/Control/TR5LevelControl.cs index f7178594d..a1f393daa 100644 --- a/TRLevelControl/Control/TR5LevelControl.cs +++ b/TRLevelControl/Control/TR5LevelControl.cs @@ -58,19 +58,16 @@ protected override void Read(TRLevelReader reader) //Decompress DecompressLevelDataChunk(_level); - //Samples - _level.NumSamples = reader.ReadUInt32(); - _level.Samples = new TR4Sample[_level.NumSamples]; + uint numSamples = reader.ReadUInt32(); + _level.Samples = new(); - for (int i = 0; i < _level.NumSamples; i++) + for (int i = 0; i < numSamples; i++) { - TR4Sample sample = new() + _level.Samples.Add(new() { UncompSize = reader.ReadUInt32(), CompSize = reader.ReadUInt32(), - }; - - _level.Samples[i] = sample; + }); //Compressed chunk is actually NOT zlib compressed - it is simply a WAV file. _level.Samples[i].CompressedChunk = reader.ReadBytes((int)_level.Samples[i].CompSize); @@ -112,8 +109,7 @@ protected override void Write(TRLevelWriter writer) writer.Write(_level.LevelDataChunk.CompressedSize); writer.Write(chunk); - writer.Write(_level.NumSamples); - + writer.Write((uint)_level.Samples.Count); foreach (TR4Sample sample in _level.Samples) { writer.Write(sample.UncompSize); @@ -138,13 +134,13 @@ private static void DecompressLevelDataChunk(TR5Level lvl) TR5FileReadUtilities.PopulateAnimations(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateMeshTreesFramesModels(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateStaticMeshes(lvlChunkReader, lvl); - TR5FileReadUtilities.VerifySPRMarker(lvlChunkReader, lvl); + TR5FileReadUtilities.VerifySPRMarker(lvlChunkReader); TR5FileReadUtilities.PopulateSprites(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateCameras(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateSoundSources(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateBoxesOverlapsZones(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateAnimatedTextures(lvlChunkReader, lvl); - TR5FileReadUtilities.VerifyTEXMarker(lvlChunkReader, lvl); + TR5FileReadUtilities.VerifyTEXMarker(lvlChunkReader); TR5FileReadUtilities.PopulateObjectTextures(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateEntitiesAndAI(lvlChunkReader, lvl); TR5FileReadUtilities.PopulateDemoSoundSampleIndices(lvlChunkReader, lvl); diff --git a/TRLevelControl/Helpers/TRMeshUtilities.cs b/TRLevelControl/Helpers/TRMeshUtilities.cs index 3c24a6a9b..e9a240795 100644 --- a/TRLevelControl/Helpers/TRMeshUtilities.cs +++ b/TRLevelControl/Helpers/TRMeshUtilities.cs @@ -49,9 +49,9 @@ public static TRMesh GetModelFirstMesh(TR3Level level, TRModel model) return GetMesh(level, model.StartingMesh); } - public static TRMesh[] GetModelMeshes(TR1Level level, TR1Type entity) + public static List GetModelMeshes(TR1Level level, TR1Type entity) { - TRModel model = level.Models.ToList().Find(e => e.ID == (uint)entity); + TRModel model = level.Models.Find(e => e.ID == (uint)entity); if (model != null) { return GetModelMeshes(level, model); @@ -59,9 +59,9 @@ public static TRMesh[] GetModelMeshes(TR1Level level, TR1Type entity) return null; } - public static TRMesh[] GetModelMeshes(TR2Level level, TR2Type entity) + public static List GetModelMeshes(TR2Level level, TR2Type entity) { - TRModel model = level.Models.ToList().Find(e => e.ID == (uint)entity); + TRModel model = level.Models.Find(e => e.ID == (uint)entity); if (model != null) { return GetModelMeshes(level, model); @@ -69,9 +69,9 @@ public static TRMesh[] GetModelMeshes(TR2Level level, TR2Type entity) return null; } - public static TRMesh[] GetModelMeshes(TR3Level level, TR3Type entity) + public static List GetModelMeshes(TR3Level level, TR3Type entity) { - TRModel model = level.Models.ToList().Find(e => e.ID == (uint)entity); + TRModel model = level.Models.Find(e => e.ID == (uint)entity); if (model != null) { return GetModelMeshes(level, model); @@ -79,45 +79,45 @@ public static TRMesh[] GetModelMeshes(TR3Level level, TR3Type entity) return null; } - public static TRMesh[] GetModelMeshes(TR1Level level, TRModel model) + public static List GetModelMeshes(TR1Level level, TRModel model) { return GetModelMeshes(level.Meshes, level.MeshPointers, model); } - public static TRMesh[] GetModelMeshes(TR2Level level, TRModel model) + public static List GetModelMeshes(TR2Level level, TRModel model) { return GetModelMeshes(level.Meshes, level.MeshPointers, model); } - public static TRMesh[] GetModelMeshes(TR3Level level, TRModel model) + public static List GetModelMeshes(TR3Level level, TRModel model) { return GetModelMeshes(level.Meshes, level.MeshPointers, model); } - public static TRMesh[] GetModelMeshes(IEnumerable meshes, uint[] meshPointers, TRModel model) + public static List GetModelMeshes(IEnumerable meshes, List meshPointers, TRModel model) { List modelMeshes = new(); - uint meshPointer = model.StartingMesh; - for (uint j = 0; j < model.NumMeshes; j++) + int meshPointer = model.StartingMesh; + for (int j = 0; j < model.NumMeshes; j++) { modelMeshes.Add(GetMesh(meshes, meshPointers[meshPointer + j])); } - return modelMeshes.ToArray(); + return modelMeshes; } public static TRMesh GetMesh(TR1Level level, uint meshPointer) { - return GetMesh(level.Meshes, level.MeshPointers[meshPointer]); + return GetMesh(level.Meshes, level.MeshPointers[(int)meshPointer]); } public static TRMesh GetMesh(TR2Level level, uint meshPointer) { - return GetMesh(level.Meshes, level.MeshPointers[meshPointer]); + return GetMesh(level.Meshes, level.MeshPointers[(int)meshPointer]); } public static TRMesh GetMesh(TR3Level level, uint meshPointer) { - return GetMesh(level.Meshes, level.MeshPointers[meshPointer]); + return GetMesh(level.Meshes, level.MeshPointers[(int)meshPointer]); } public static TRMesh GetMesh(IEnumerable meshes, uint offset) @@ -164,76 +164,20 @@ public static TRMeshTreeNode[] GetModelMeshTrees(List meshTrees, return nodes.ToArray(); } - /// - /// Inserts a new mesh and returns its index in MeshPointers. - /// public static int InsertMesh(TR1Level level, TRMesh newMesh) - { - //get the final mesh we currently have - if(level.Meshes.Length > 0) - { - TRMesh lastMesh = level.Meshes[^1]; - //new mesh pointer will be the current final mesh's pointer plus its length - newMesh.Pointer = lastMesh.Pointer + (uint)lastMesh.Serialize().Length; - } - else - { - newMesh.Pointer = 0; - } - - List meshes = level.Meshes.ToList(); - meshes.Add(newMesh); - level.Meshes = meshes.ToArray(); - - List pointers = level.MeshPointers.ToList(); - pointers.Add(newMesh.Pointer); - level.MeshPointers = pointers.ToArray(); - level.NumMeshPointers++; - - //NumMeshData needs the additional mesh size added - level.NumMeshData += (uint)newMesh.Serialize().Length / 2; - - //the pointer index will be the final index in the array - return level.MeshPointers.Length - 1; - } + => InsertMesh(newMesh, level.Meshes, level.MeshPointers); public static int InsertMesh(TR2Level level, TRMesh newMesh) - { - //get the final mesh we currently have - if (level.Meshes.Length > 0) - { - TRMesh lastMesh = level.Meshes[^1]; - //new mesh pointer will be the current final mesh's pointer plus its length - newMesh.Pointer = lastMesh.Pointer + (uint)lastMesh.Serialize().Length; - } - else - { - newMesh.Pointer = 0; - } - - List meshes = level.Meshes.ToList(); - meshes.Add(newMesh); - level.Meshes = meshes.ToArray(); - - List pointers = level.MeshPointers.ToList(); - pointers.Add(newMesh.Pointer); - level.MeshPointers = pointers.ToArray(); - level.NumMeshPointers++; - - //NumMeshData needs the additional mesh size added - level.NumMeshData += (uint)newMesh.Serialize().Length / 2; - - //the pointer index will be the final index in the array - return level.MeshPointers.Length - 1; - } + => InsertMesh(newMesh, level.Meshes, level.MeshPointers); public static int InsertMesh(TR3Level level, TRMesh newMesh) + => InsertMesh(newMesh, level.Meshes, level.MeshPointers); + + private static int InsertMesh(TRMesh newMesh, List meshes, List meshPointers) { - //get the final mesh we currently have - if (level.Meshes.Length > 0) + if (meshes.Count > 0) { - TRMesh lastMesh = level.Meshes[^1]; - //new mesh pointer will be the current final mesh's pointer plus its length + TRMesh lastMesh = meshes[^1]; newMesh.Pointer = lastMesh.Pointer + (uint)lastMesh.Serialize().Length; } else @@ -241,20 +185,10 @@ public static int InsertMesh(TR3Level level, TRMesh newMesh) newMesh.Pointer = 0; } - List meshes = level.Meshes.ToList(); meshes.Add(newMesh); - level.Meshes = meshes.ToArray(); - - List pointers = level.MeshPointers.ToList(); - pointers.Add(newMesh.Pointer); - level.MeshPointers = pointers.ToArray(); - level.NumMeshPointers++; - - //NumMeshData needs the additional mesh size added - level.NumMeshData += (uint)newMesh.Serialize().Length / 2; + meshPointers.Add(newMesh.Pointer); - //the pointer index will be the final index in the array - return level.MeshPointers.Length - 1; + return meshPointers.Count - 1; } /// @@ -326,10 +260,8 @@ public static void UpdateMeshPointers(TR1Level level, TRMesh modifiedMesh, int p } } - level.MeshPointers = pointers.ToArray(); - - int numMeshData = (int)level.NumMeshData + lengthDiff / 2; - level.NumMeshData = (uint)numMeshData; + level.MeshPointers.Clear(); + level.MeshPointers.AddRange(pointers); // While the Pointer property on meshes is only for convenience and not // written to the level, we need to update them regardless in case of @@ -358,10 +290,8 @@ public static void UpdateMeshPointers(TR2Level level, TRMesh modifiedMesh, int p } } - level.MeshPointers = pointers.ToArray(); - - int numMeshData = (int)level.NumMeshData + lengthDiff / 2; - level.NumMeshData = (uint)numMeshData; + level.MeshPointers.Clear(); + level.MeshPointers.AddRange(pointers); // While the Pointer property on meshes is only for convenience and not // written to the level, we need to update them regardless in case of @@ -390,10 +320,8 @@ public static void UpdateMeshPointers(TR3Level level, TRMesh modifiedMesh, int p } } - level.MeshPointers = pointers.ToArray(); - - int numMeshData = (int)level.NumMeshData + lengthDiff / 2; - level.NumMeshData = (uint)numMeshData; + level.MeshPointers.Clear(); + level.MeshPointers.AddRange(pointers); // While the Pointer property on meshes is only for convenience and not // written to the level, we need to update them regardless in case of diff --git a/TRLevelControl/Model/Base/TR1Level.cs b/TRLevelControl/Model/Base/TR1Level.cs index 32619ab19..b43b24225 100644 --- a/TRLevelControl/Model/Base/TR1Level.cs +++ b/TRLevelControl/Model/Base/TR1Level.cs @@ -5,32 +5,8 @@ public class TR1Level : TRLevelBase public List Images8 { get; set; } public List Rooms { get; set; } public List FloorData { get; set; } - - /// - /// 4 bytes - /// - public uint NumMeshData { get; set; } - - /// - /// 2 * NumMeshData, holds the raw data stored in Meshes - /// - public ushort[] RawMeshData { get; set; } - - /// - /// Variable - /// - public TRMesh[] Meshes { get; set; } - - /// - /// 4 bytes - /// - public uint NumMeshPointers { get; set; } - - /// - /// NumMeshPointers * 4 bytes - /// - public uint[] MeshPointers { get; set; } - + public List Meshes { get; set; } + public List MeshPointers { get; set; } public List Animations { get; set; } public List StateChanges { get; set; } public List AnimDispatches { get; set; } @@ -39,92 +15,22 @@ public class TR1Level : TRLevelBase public List Frames { get; set; } public List Models { get; set; } public List StaticMeshes { get; set; } - - /// - /// 4 bytes - /// - public uint NumObjectTextures { get; set; } - - /// - /// NumObjectTextures * 20 bytes - /// - public TRObjectTexture[] ObjectTextures { get; set; } - - /// - /// 4 bytes - /// - public uint NumSpriteTextures { get; set; } - - /// - /// NumSpriteTextures * 16 bytes - /// - public TRSpriteTexture[] SpriteTextures { get; set; } - - /// - /// 4 bytes - /// - public uint NumSpriteSequences { get; set; } - - /// - /// NumSpriteSequences * 8 bytes - /// - public TRSpriteSequence[] SpriteSequences { get; set; } + public List ObjectTextures { get; set; } + public List SpriteTextures { get; set; } + public List SpriteSequences { get; set; } public List Cameras { get; set; } public List SoundSources { get; set; } public List Boxes { get; set; } public List Overlaps { get; set; } public List Zones { get; set; } - - /// - /// 4 bytes - /// - public uint NumAnimatedTextures { get; set; } - - /// - /// NumAnimatesTextures * 2 bytes - /// - public TRAnimatedTexture[] AnimatedTextures { get; set; } + public List AnimatedTextures { get; set; } public List Entities { get; set; } public List LightMap { get; set; } public List Palette { get; set; } public List CinematicFrames { get; set; } - - /// - /// 2 bytes - /// - public ushort NumDemoData { get; set; } - - /// - /// NumDemoData bytes - /// public byte[] DemoData { get; set; } - - /// - /// 370 entries of 2 bytes each = 740 bytes - /// public short[] SoundMap { get; set; } - - /// - /// 4 bytes - /// - public uint NumSoundDetails { get; set; } - - /// - /// NumSoundDetails * 8 bytes - /// - public TRSoundDetails[] SoundDetails { get; set; } - - public uint NumSamples { get; set; } - - public byte[] Samples { get; set; } - - /// - /// 4 bytes - /// - public uint NumSampleIndices { get; set; } - - /// - /// NumSampleIndices * 4 bytes - /// - public uint[] SampleIndices { get; set; } + public List SoundDetails { get; set; } + public List Samples { get; set; } + public List SampleIndices { get; set; } } diff --git a/TRLevelControl/Model/Base/TRAnimatedTexture.cs b/TRLevelControl/Model/Base/TRAnimatedTexture.cs index 0e6c4c3b2..74374cda7 100644 --- a/TRLevelControl/Model/Base/TRAnimatedTexture.cs +++ b/TRLevelControl/Model/Base/TRAnimatedTexture.cs @@ -4,15 +4,13 @@ namespace TRLevelControl.Model; public class TRAnimatedTexture : ISerializableCompact { - //https://opentomb.github.io/TRosettaStone3/trosettastone.html#_animated_textures_2 - public ushort NumTextures => (ushort)(Textures.Length - 1); - public ushort[] Textures { get; set; } + public List Textures { get; set; } public byte[] Serialize() { using MemoryStream stream = new(); using BinaryWriter writer = new(stream); - writer.Write(NumTextures); + writer.Write((ushort)(Textures.Count - 1)); foreach (ushort texture in Textures) { writer.Write(texture); diff --git a/TRLevelControl/Model/TR2/TR2Level.cs b/TRLevelControl/Model/TR2/TR2Level.cs index 6169c78a4..c3cb8b2c3 100644 --- a/TRLevelControl/Model/TR2/TR2Level.cs +++ b/TRLevelControl/Model/TR2/TR2Level.cs @@ -8,32 +8,8 @@ public class TR2Level : TRLevelBase public List Images16 { get; set; } public List Rooms { get; set; } public List FloorData { get; set; } - - /// - /// 4 bytes - /// - public uint NumMeshData { get; set; } - - /// - /// 2 * NumMeshData, holds the raw data stored in Meshes - /// - public ushort[] RawMeshData { get; set; } - - /// - /// Variable - /// - public TRMesh[] Meshes { get; set; } - - /// - /// 4 bytes - /// - public uint NumMeshPointers { get; set; } - - /// - /// NumMeshPointers * 4 bytes - /// - public uint[] MeshPointers { get; set; } - + public List Meshes { get; set; } + public List MeshPointers { get; set; } public List Animations { get; set; } public List StateChanges { get; set; } public List AnimDispatches { get; set; } @@ -42,87 +18,20 @@ public class TR2Level : TRLevelBase public List Frames { get; set; } public List Models { get; set; } public List StaticMeshes { get; set; } - - /// - /// 4 bytes - /// - public uint NumObjectTextures { get; set; } - - /// - /// NumObjectTextures * 20 bytes - /// - public TRObjectTexture[] ObjectTextures { get; set; } - - /// - /// 4 bytes - /// - public uint NumSpriteTextures { get; set; } - - /// - /// NumSpriteTextures * 16 bytes - /// - public TRSpriteTexture[] SpriteTextures { get; set; } - - /// - /// 4 bytes - /// - public uint NumSpriteSequences { get; set; } - - /// - /// NumSpriteSequences * 8 bytes - /// - public TRSpriteSequence[] SpriteSequences { get; set; } + public List ObjectTextures { get; set; } + public List SpriteTextures { get; set; } + public List SpriteSequences { get; set; } public List Cameras { get; set; } public List SoundSources { get; set; } public List Boxes { get; set; } public List Overlaps { get; set; } public List Zones { get; set; } - - /// - /// 4 bytes - /// - public uint NumAnimatedTextures { get; set; } - - /// - /// NumAnimatesTextures * 2 bytes - /// - public TRAnimatedTexture[] AnimatedTextures { get; set; } + public List AnimatedTextures { get; set; } public List Entities { get; set; } public List LightMap { get; set; } public List CinematicFrames { get; set; } - - /// - /// 2 bytes - /// - public ushort NumDemoData { get; set; } - - /// - /// NumDemoData bytes - /// public byte[] DemoData { get; set; } - - /// - /// 370 entries of 2 bytes each = 740 bytes - /// public short[] SoundMap { get; set; } - - /// - /// 4 bytes - /// - public uint NumSoundDetails { get; set; } - - /// - /// NumSoundDetails * 8 bytes - /// - public TRSoundDetails[] SoundDetails { get; set; } - - /// - /// 4 bytes - /// - public uint NumSampleIndices { get; set; } - - /// - /// NumSampleIndices * 4 bytes - /// - public uint[] SampleIndices { get; set; } + public List SoundDetails { get; set; } + public List SampleIndices { get; set; } } diff --git a/TRLevelControl/Model/TR3/TR3Level.cs b/TRLevelControl/Model/TR3/TR3Level.cs index 36319ad06..3c97a6de9 100644 --- a/TRLevelControl/Model/TR3/TR3Level.cs +++ b/TRLevelControl/Model/TR3/TR3Level.cs @@ -8,32 +8,8 @@ public class TR3Level : TRLevelBase public List Images16 { get; set; } public List Rooms { get; set; } public List FloorData { get; set; } - - /// - /// 4 bytes - /// - public uint NumMeshData { get; set; } - - /// - /// 2 * NumMeshData, holds the raw data stored in Meshes - /// - public ushort[] RawMeshData { get; set; } - - /// - /// Variable - /// - public TRMesh[] Meshes { get; set; } - - /// - /// 4 bytes - /// - public uint NumMeshPointers { get; set; } - - /// - /// NumMeshPointers * 4 bytes - /// - public uint[] MeshPointers { get; set; } - + public List Meshes { get; set; } + public List MeshPointers { get; set; } public List Animations { get; set; } public List StateChanges { get; set; } public List AnimDispatches { get; set; } @@ -42,87 +18,20 @@ public class TR3Level : TRLevelBase public List Frames { get; set; } public List Models { get; set; } public List StaticMeshes { get; set; } - - /// - /// 4 bytes - /// - public uint NumSpriteTextures { get; set; } - - /// - /// NumSpriteTextures * 16 bytes - /// - public TRSpriteTexture[] SpriteTextures { get; set; } - - /// - /// 4 bytes - /// - public uint NumSpriteSequences { get; set; } - - /// - /// NumSpriteSequences * 8 bytes - /// - public TRSpriteSequence[] SpriteSequences { get; set; } + public List SpriteTextures { get; set; } + public List SpriteSequences { get; set; } public List Cameras { get; set; } public List SoundSources { get; set; } public List Boxes { get; set; } public List Overlaps { get; set; } public List Zones { get; set; } - - /// - /// 4 bytes - /// - public uint NumAnimatedTextures { get; set; } - - /// - /// NumAnimatesTextures * 2 bytes - /// - public TRAnimatedTexture[] AnimatedTextures { get; set; } - - /// - /// 4 bytes - /// - public uint NumObjectTextures { get; set; } - - /// - /// NumObjectTextures * 20 bytes - /// - public TRObjectTexture[] ObjectTextures { get; set; } + public List AnimatedTextures { get; set; } + public List ObjectTextures { get; set; } public List Entities { get; set; } public List LightMap { get; set; } public List CinematicFrames { get; set; } - - /// - /// 2 bytes - /// - public ushort NumDemoData { get; set; } - - /// - /// NumDemoData bytes - /// public byte[] DemoData { get; set; } - - /// - /// 370 entries of 2 bytes each = 740 bytes - /// public short[] SoundMap { get; set; } - - /// - /// 4 bytes - /// - public uint NumSoundDetails { get; set; } - - /// - /// NumSoundDetails * 8 bytes - /// - public TR3SoundDetails[] SoundDetails { get; set; } - - /// - /// 4 bytes - /// - public uint NumSampleIndices { get; set; } - - /// - /// NumSampleIndices * 4 bytes - /// - public uint[] SampleIndices { get; set; } + public List SoundDetails { get; set; } + public List SampleIndices { get; set; } } diff --git a/TRLevelControl/Model/TR4/TR4Level.cs b/TRLevelControl/Model/TR4/TR4Level.cs index fad4a53e6..cb414b56e 100644 --- a/TRLevelControl/Model/TR4/TR4Level.cs +++ b/TRLevelControl/Model/TR4/TR4Level.cs @@ -10,7 +10,5 @@ public class TR4Level : TRLevelBase public TR4LevelDataChunk LevelDataChunk { get; set; } - public uint NumSamples { get; set; } - - public TR4Sample[] Samples { get; set; } + public List Samples { get; set; } } diff --git a/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs b/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs index 2a1715327..b938e670b 100644 --- a/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs +++ b/TRLevelControl/Model/TR4/TR4LevelDataChunk.cs @@ -5,6 +5,9 @@ namespace TRLevelControl.Model; public class TR4LevelDataChunk : ISerializableCompact { + public static readonly string SPRMarker = "SPR"; + public static readonly string TEXMarker = "TEX"; + public uint UncompressedSize { get; set; } public uint CompressedSize { get; set; } @@ -12,17 +15,8 @@ public class TR4LevelDataChunk : ISerializableCompact public uint Unused { get; set; } public List Rooms { get; set; } public List FloorData { get; set; } - - public uint NumMeshData { get; set; } - - public ushort[] RawMeshData { get; set; } - - public TR4Mesh[] Meshes { get; set; } - - public uint NumMeshPointers { get; set; } - - public uint[] MeshPointers { get; set; } - + public List Meshes { get; set; } + public List MeshPointers { get; set; } public List Animations { get; set; } public List StateChanges { get; set; } public List AnimDispatches { get; set; } @@ -31,50 +25,23 @@ public class TR4LevelDataChunk : ISerializableCompact public List Frames { get; set; } public List Models { get; set; } public List StaticMeshes { get; set; } - - public byte[] SPRMarker { get; set; } - - public uint NumSpriteTextures { get; set; } - - public TRSpriteTexture[] SpriteTextures { get; set; } - - public uint NumSpriteSequences { get; set; } - - public TRSpriteSequence[] SpriteSequences { get; set; } + public List SpriteTextures { get; set; } + public List SpriteSequences { get; set; } public List Cameras { get; set; } public List FlybyCameras { get; set; } public List SoundSources { get; set; } public List Boxes { get; set; } public List Overlaps { get; set; } public List Zones { get; set; } - - public uint NumAnimatedTextures { get; set; } - - public TRAnimatedTexture[] AnimatedTextures { get; set; } - + public List AnimatedTextures { get; set; } public byte AnimatedTexturesUVCount { get; set; } - - public byte[] TEXMarker { get; set; } - - public uint NumObjectTextures { get; set; } - - public TR4ObjectTexture[] ObjectTextures { get; set; } + public List ObjectTextures { get; set; } public List Entities { get; set; } public List AIEntities { get; set; } - - public ushort NumDemoData { get; set; } - public byte[] DemoData { get; set; } - public short[] SoundMap { get; set; } - - public uint NumSoundDetails { get; set; } - - public TR3SoundDetails[] SoundDetails { get; set; } - - public uint NumSampleIndices { get; set; } - - public uint[] SampleIndices { get; set; } + public List SoundDetails { get; set; } + public List SampleIndices { get; set; } public byte[] Seperator { get; set; } @@ -97,15 +64,11 @@ public byte[] Serialize() writer.Write((uint)FloorData.Count); writer.Write(FloorData); - writer.Write(NumMeshData); - - foreach (TR4Mesh mesh in Meshes) - { - writer.Write(mesh.Serialize()); - } - - writer.Write(NumMeshPointers); + List meshData = Meshes.SelectMany(m => m.Serialize()).ToList(); + writer.Write((uint)meshData.Count / 2); + writer.Write(meshData.ToArray()); + writer.Write((uint)MeshPointers.Count); foreach (uint data in MeshPointers) { writer.Write(data); @@ -159,17 +122,15 @@ public byte[] Serialize() writer.Write(sm.Serialize()); } - writer.Write(SPRMarker); - - writer.Write(NumSpriteTextures); + writer.Write(SPRMarker.ToCharArray()); + writer.Write((uint)SpriteTextures.Count); foreach (TRSpriteTexture st in SpriteTextures) { writer.Write(st.Serialize()); } - writer.Write(NumSpriteSequences); - + writer.Write((uint)SpriteSequences.Count); foreach (TRSpriteSequence seq in SpriteSequences) { writer.Write(seq.Serialize()); @@ -210,15 +171,15 @@ public byte[] Serialize() writer.Write(zone); } - writer.Write(NumAnimatedTextures); - writer.Write((ushort)AnimatedTextures.Length); - foreach (TRAnimatedTexture texture in AnimatedTextures) { writer.Write(texture.Serialize()); } + byte[] animTextureData = AnimatedTextures.SelectMany(a => a.Serialize()).ToArray(); + writer.Write((uint)(animTextureData.Length / sizeof(ushort)) + 1); + writer.Write((ushort)AnimatedTextures.Count); + writer.Write(animTextureData); writer.Write(AnimatedTexturesUVCount); - writer.Write(TEXMarker); - - writer.Write(NumObjectTextures); + writer.Write(TEXMarker.ToCharArray()); + writer.Write((uint)ObjectTextures.Count); foreach (TR4ObjectTexture otex in ObjectTextures) { writer.Write(otex.Serialize()); @@ -230,7 +191,7 @@ public byte[] Serialize() writer.Write((uint)AIEntities.Count); writer.Write(AIEntities); - writer.Write(NumDemoData); + writer.Write((ushort)DemoData.Length); writer.Write(DemoData); foreach (short sound in SoundMap) @@ -238,15 +199,13 @@ public byte[] Serialize() writer.Write(sound); } - writer.Write(NumSoundDetails); - + writer.Write((uint)SoundDetails.Count); foreach (TR3SoundDetails snd in SoundDetails) { writer.Write(snd.Serialize()); } - writer.Write(NumSampleIndices); - + writer.Write((uint)SampleIndices.Count); foreach (uint sampleindex in SampleIndices) { writer.Write(sampleindex); diff --git a/TRLevelControl/Model/TR5/TR5Level.cs b/TRLevelControl/Model/TR5/TR5Level.cs index ffff05716..324c570c5 100644 --- a/TRLevelControl/Model/TR5/TR5Level.cs +++ b/TRLevelControl/Model/TR5/TR5Level.cs @@ -16,7 +16,5 @@ public class TR5Level : TRLevelBase public TR5LevelDataChunk LevelDataChunk { get; set; } - public uint NumSamples { get; set; } - - public TR4Sample[] Samples { get; set; } + public List Samples { get; set; } } diff --git a/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs b/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs index 619694d06..2a0f96bf8 100644 --- a/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs +++ b/TRLevelControl/Model/TR5/TR5LevelDataChunk.cs @@ -2,6 +2,9 @@ public class TR5LevelDataChunk { + public static readonly string SPRMarker = "SPR\0"; + public static readonly string TEXMarker = "TEX\0"; + public uint UncompressedSize { get; set; } public uint CompressedSize { get; set; } @@ -9,17 +12,8 @@ public class TR5LevelDataChunk public uint Unused { get; set; } public List Rooms { get; set; } public List FloorData { get; set; } - - public uint NumMeshData { get; set; } - - public ushort[] RawMeshData { get; set; } - - public TR4Mesh[] Meshes { get; set; } - - public uint NumMeshPointers { get; set; } - - public uint[] MeshPointers { get; set; } - + public List Meshes { get; set; } + public List MeshPointers { get; set; } public List Animations { get; set; } public List StateChanges { get; set; } public List AnimDispatches { get; set; } @@ -28,50 +22,24 @@ public class TR5LevelDataChunk public List Frames { get; set; } public List Models { get; set; } public List StaticMeshes { get; set; } - - public byte[] SPRMarker { get; set; } - - public uint NumSpriteTextures { get; set; } - - public TRSpriteTexture[] SpriteTextures { get; set; } - - public uint NumSpriteSequences { get; set; } - - public TRSpriteSequence[] SpriteSequences { get; set; } + public List SpriteTextures { get; set; } + public List SpriteSequences { get; set; } public List Cameras { get; set; } public List FlybyCameras { get; set; } public List SoundSources { get; set; } public List Boxes { get; set; } public List Overlaps { get; set; } public List Zones { get; set; } - - public uint NumAnimatedTextures { get; set; } - - public TRAnimatedTexture[] AnimatedTextures { get; set; } - + public List AnimatedTextures { get; set; } public byte AnimatedTexturesUVCount { get; set; } - - public byte[] TEXMarker { get; set; } - - public uint NumObjectTextures { get; set; } - - public TR5ObjectTexture[] ObjectTextures { get; set; } + public List ObjectTextures { get; set; } public List Entities { get; set; } public List AIEntities { get; set; } - - public ushort NumDemoData { get; set; } - public byte[] DemoData { get; set; } public short[] SoundMap { get; set; } - - public uint NumSoundDetails { get; set; } - - public TR3SoundDetails[] SoundDetails { get; set; } - - public uint NumSampleIndices { get; set; } - - public uint[] SampleIndices { get; set; } + public List SoundDetails { get; set; } + public List SampleIndices { get; set; } public byte[] Seperator { get; set; } @@ -94,15 +62,11 @@ public byte[] Serialize() writer.Write((uint)FloorData.Count); writer.Write(FloorData); - writer.Write(NumMeshData); - - foreach (TR4Mesh mesh in Meshes) - { - writer.Write(mesh.Serialize()); - } - - writer.Write(NumMeshPointers); + List meshData = Meshes.SelectMany(m => m.Serialize()).ToList(); + writer.Write((uint)meshData.Count / 2); + writer.Write(meshData.ToArray()); + writer.Write((uint)MeshPointers.Count); foreach (uint data in MeshPointers) { writer.Write(data); @@ -156,17 +120,15 @@ public byte[] Serialize() writer.Write(sm.Serialize()); } - writer.Write(SPRMarker); - - writer.Write(NumSpriteTextures); + writer.Write(SPRMarker.ToCharArray()); + writer.Write((uint)SpriteTextures.Count); foreach (TRSpriteTexture st in SpriteTextures) { writer.Write(st.Serialize()); } - writer.Write(NumSpriteSequences); - + writer.Write((uint)SpriteSequences.Count); foreach (TRSpriteSequence seq in SpriteSequences) { writer.Write(seq.Serialize()); @@ -207,15 +169,15 @@ public byte[] Serialize() writer.Write(zone); } - writer.Write(NumAnimatedTextures); - writer.Write((ushort)AnimatedTextures.Length); - foreach (TRAnimatedTexture texture in AnimatedTextures) { writer.Write(texture.Serialize()); } + byte[] animTextureData = AnimatedTextures.SelectMany(a => a.Serialize()).ToArray(); + writer.Write((uint)(animTextureData.Length / sizeof(ushort)) + 1); + writer.Write((ushort)AnimatedTextures.Count); + writer.Write(animTextureData); writer.Write(AnimatedTexturesUVCount); - writer.Write(TEXMarker); - - writer.Write(NumObjectTextures); + writer.Write(TEXMarker.ToCharArray()); + writer.Write((uint)ObjectTextures.Count); foreach (TR5ObjectTexture otex in ObjectTextures) { writer.Write(otex.Serialize()); @@ -227,7 +189,7 @@ public byte[] Serialize() writer.Write((uint)AIEntities.Count); writer.Write(AIEntities); - writer.Write(NumDemoData); + writer.Write((ushort)DemoData.Length); writer.Write(DemoData); foreach (short sound in SoundMap) @@ -235,15 +197,13 @@ public byte[] Serialize() writer.Write(sound); } - writer.Write(NumSoundDetails); - + writer.Write((uint)SoundDetails.Count); foreach (TR3SoundDetails snd in SoundDetails) { writer.Write(snd.Serialize()); } - writer.Write(NumSampleIndices); - + writer.Write((uint)SampleIndices.Count); foreach (uint sampleindex in SampleIndices) { writer.Write(sampleindex); diff --git a/TRLevelControl/TR2FileReadUtilities.cs b/TRLevelControl/TR2FileReadUtilities.cs index b60b8d287..eee10c444 100644 --- a/TRLevelControl/TR2FileReadUtilities.cs +++ b/TRLevelControl/TR2FileReadUtilities.cs @@ -312,11 +312,12 @@ public static TR2Box ReadBox(BinaryReader reader) public static TRAnimatedTexture ReadAnimatedTexture(BinaryReader reader) { - ushort numTextures = reader.ReadUInt16(); // Actually num textures - 1, see https://opentomb.github.io/TRosettaStone3/trosettastone.html#_animated_textures_2 - ushort[] textures = new ushort[numTextures + 1]; - for (int i = 0; i < textures.Length; i++) + // See https://opentomb.github.io/TRosettaStone3/trosettastone.html#_animated_textures_2 + int numTextures = reader.ReadUInt16() + 1; + List textures = new(); + for (int i = 0; i < numTextures; i++) { - textures[i] = reader.ReadUInt16(); + textures.Add(reader.ReadUInt16()); } return new TRAnimatedTexture diff --git a/TRLevelControl/TR4FileReadUtilities.cs b/TRLevelControl/TR4FileReadUtilities.cs index 57ba58092..11edb98ce 100644 --- a/TRLevelControl/TR4FileReadUtilities.cs +++ b/TRLevelControl/TR4FileReadUtilities.cs @@ -95,29 +95,23 @@ public static void PopulateFloordata(BinaryReader reader, TR4Level lvl) public static void PopulateMeshes(BinaryReader reader, TR4Level lvl) { - //Mesh Data - //This tells us how much mesh data (# of words/uint16s) coming up - //just like the rooms previously. - lvl.LevelDataChunk.NumMeshData = reader.ReadUInt32(); - lvl.LevelDataChunk.RawMeshData = new ushort[lvl.LevelDataChunk.NumMeshData]; + uint numMeshData = reader.ReadUInt32(); + ushort[] rawMeshData = new ushort[numMeshData]; - for (int i = 0; i < lvl.LevelDataChunk.NumMeshData; i++) + for (int i = 0; i < numMeshData; i++) { - lvl.LevelDataChunk.RawMeshData[i] = reader.ReadUInt16(); + rawMeshData[i] = reader.ReadUInt16(); } - //Mesh Pointers - lvl.LevelDataChunk.NumMeshPointers = reader.ReadUInt32(); - lvl.LevelDataChunk.MeshPointers = new uint[lvl.LevelDataChunk.NumMeshPointers]; + uint numMeshPointers = reader.ReadUInt32(); + lvl.LevelDataChunk.MeshPointers = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumMeshPointers; i++) + for (int i = 0; i < numMeshPointers; i++) { - lvl.LevelDataChunk.MeshPointers[i] = reader.ReadUInt32(); + lvl.LevelDataChunk.MeshPointers.Add(reader.ReadUInt32()); } - //Mesh Construction - //level.Meshes = ConstructMeshData(level.NumMeshData, level.NumMeshPointers, level.RawMeshData); - lvl.LevelDataChunk.Meshes = ConstructMeshData(lvl.LevelDataChunk.MeshPointers, lvl.LevelDataChunk.RawMeshData); + lvl.LevelDataChunk.Meshes = ConstructMeshData(lvl.LevelDataChunk.MeshPointers, rawMeshData); } public static void PopulateAnimations(BinaryReader reader, TR4Level lvl) @@ -193,33 +187,28 @@ public static void PopulateStaticMeshes(BinaryReader reader, TR4Level lvl) } } - public static void VerifySPRMarker(BinaryReader reader, TR4Level lvl) + public static void VerifySPRMarker(BinaryReader reader) { - lvl.LevelDataChunk.SPRMarker = reader.ReadBytes(3); - - Debug.Assert(lvl.LevelDataChunk.SPRMarker[0] == 0x53); - Debug.Assert(lvl.LevelDataChunk.SPRMarker[1] == 0x50); - Debug.Assert(lvl.LevelDataChunk.SPRMarker[2] == 0x52); + string sprMarker = new(reader.ReadChars(TR4LevelDataChunk.SPRMarker.Length)); + Debug.Assert(sprMarker == TR4LevelDataChunk.SPRMarker); } public static void PopulateSprites(BinaryReader reader, TR4Level lvl) { - //Sprite Textures - lvl.LevelDataChunk.NumSpriteTextures = reader.ReadUInt32(); - lvl.LevelDataChunk.SpriteTextures = new TRSpriteTexture[lvl.LevelDataChunk.NumSpriteTextures]; + uint numSpriteTextures = reader.ReadUInt32(); + lvl.LevelDataChunk.SpriteTextures = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSpriteTextures; i++) + for (int i = 0; i < numSpriteTextures; i++) { - lvl.LevelDataChunk.SpriteTextures[i] = TR2FileReadUtilities.ReadSpriteTexture(reader); + lvl.LevelDataChunk.SpriteTextures.Add(TR2FileReadUtilities.ReadSpriteTexture(reader)); } - //Sprite Sequences - lvl.LevelDataChunk.NumSpriteSequences = reader.ReadUInt32(); - lvl.LevelDataChunk.SpriteSequences = new TRSpriteSequence[lvl.LevelDataChunk.NumSpriteSequences]; + uint numSpriteSequences = reader.ReadUInt32(); + lvl.LevelDataChunk.SpriteSequences = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSpriteSequences; i++) + for (int i = 0; i < numSpriteSequences; i++) { - lvl.LevelDataChunk.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); + lvl.LevelDataChunk.SpriteSequences.Add(TR2FileReadUtilities.ReadSpriteSequence(reader)); } } @@ -286,35 +275,32 @@ public static void PopulateBoxesOverlapsZones(BinaryReader reader, TR4Level lvl) public static void PopulateAnimatedTextures(BinaryReader reader, TR4Level lvl) { - lvl.LevelDataChunk.NumAnimatedTextures = reader.ReadUInt32(); - lvl.LevelDataChunk.AnimatedTextures = new TRAnimatedTexture[reader.ReadUInt16()]; - for (int i = 0; i < lvl.LevelDataChunk.AnimatedTextures.Length; i++) + reader.ReadUInt32(); // Total count of ushorts + ushort numGroups = reader.ReadUInt16(); + lvl.LevelDataChunk.AnimatedTextures = new(); + for (int i = 0; i < numGroups; i++) { - lvl.LevelDataChunk.AnimatedTextures[i] = TR2FileReadUtilities.ReadAnimatedTexture(reader); + lvl.LevelDataChunk.AnimatedTextures.Add(TR2FileReadUtilities.ReadAnimatedTexture(reader)); } //TR4+ Specific lvl.LevelDataChunk.AnimatedTexturesUVCount = reader.ReadByte(); } - public static void VerifyTEXMarker(BinaryReader reader, TR4Level lvl) + public static void VerifyTEXMarker(BinaryReader reader) { - lvl.LevelDataChunk.TEXMarker = reader.ReadBytes(3); - - Debug.Assert(lvl.LevelDataChunk.TEXMarker[0] == 0x54); - Debug.Assert(lvl.LevelDataChunk.TEXMarker[1] == 0x45); - Debug.Assert(lvl.LevelDataChunk.TEXMarker[2] == 0x58); + string texMarker = new(reader.ReadChars(TR4LevelDataChunk.TEXMarker.Length)); + Debug.Assert(texMarker == TR4LevelDataChunk.TEXMarker); } public static void PopulateObjectTextures(BinaryReader reader, TR4Level lvl) { - //Object Textures - lvl.LevelDataChunk.NumObjectTextures = reader.ReadUInt32(); - lvl.LevelDataChunk.ObjectTextures = new TR4ObjectTexture[lvl.LevelDataChunk.NumObjectTextures]; + uint numObjectTextures = reader.ReadUInt32(); + lvl.LevelDataChunk.ObjectTextures = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumObjectTextures; i++) + for (int i = 0; i < numObjectTextures; i++) { - lvl.LevelDataChunk.ObjectTextures[i] = TR4FileReadUtilities.ReadObjectTexture(reader); + lvl.LevelDataChunk.ObjectTextures.Add(ReadObjectTexture(reader)); } } @@ -331,14 +317,8 @@ public static void PopulateEntitiesAndAI(TRLevelReader reader, TR4Level lvl) public static void PopulateDemoSoundSampleIndices(BinaryReader reader, TR4Level lvl) { - //Demo Data - lvl.LevelDataChunk.NumDemoData = reader.ReadUInt16(); - lvl.LevelDataChunk.DemoData = new byte[lvl.LevelDataChunk.NumDemoData]; - - for (int i = 0; i < lvl.LevelDataChunk.NumDemoData; i++) - { - lvl.LevelDataChunk.DemoData[i] = reader.ReadByte(); - } + ushort numDemoData = reader.ReadUInt16(); + lvl.LevelDataChunk.DemoData = reader.ReadBytes(numDemoData); //Sound Map (370 shorts) & Sound Details lvl.LevelDataChunk.SoundMap = new short[370]; @@ -348,21 +328,20 @@ public static void PopulateDemoSoundSampleIndices(BinaryReader reader, TR4Level lvl.LevelDataChunk.SoundMap[i] = reader.ReadInt16(); } - lvl.LevelDataChunk.NumSoundDetails = reader.ReadUInt32(); - lvl.LevelDataChunk.SoundDetails = new TR3SoundDetails[lvl.LevelDataChunk.NumSoundDetails]; + uint numSoundDetails = reader.ReadUInt32(); + lvl.LevelDataChunk.SoundDetails = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSoundDetails; i++) + for (int i = 0; i < numSoundDetails; i++) { - lvl.LevelDataChunk.SoundDetails[i] = TR3FileReadUtilities.ReadSoundDetails(reader); + lvl.LevelDataChunk.SoundDetails.Add(TR3FileReadUtilities.ReadSoundDetails(reader)); } - //Samples - lvl.LevelDataChunk.NumSampleIndices = reader.ReadUInt32(); - lvl.LevelDataChunk.SampleIndices = new uint[lvl.LevelDataChunk.NumSampleIndices]; + uint numSampleIndices = reader.ReadUInt32(); + lvl.LevelDataChunk.SampleIndices = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSampleIndices; i++) + for (int i = 0; i < numSampleIndices; i++) { - lvl.LevelDataChunk.SampleIndices[i] = reader.ReadUInt32(); + lvl.LevelDataChunk.SampleIndices.Add(reader.ReadUInt32()); } } @@ -515,21 +494,21 @@ private static TR4RoomLight ReadRoomLight(BinaryReader reader) }; } - public static TR4Mesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshData) + public static List ConstructMeshData(List meshPointers, ushort[] rawMeshData) { byte[] target = new byte[rawMeshData.Length * 2]; Buffer.BlockCopy(rawMeshData, 0, target, 0, target.Length); // The mesh pointer list can contain duplicates so we must make // sure to iterate over distinct values only - meshPointers = meshPointers.Distinct().ToArray(); + meshPointers = new(meshPointers.Distinct()); List meshes = new(); using (MemoryStream ms = new(target)) using (BinaryReader br = new(ms)) { - for (int i = 0; i < meshPointers.Length; i++) + for (int i = 0; i < meshPointers.Count; i++) { TR4Mesh mesh = new(); meshes.Add(mesh); @@ -598,7 +577,7 @@ public static TR4Mesh[] ConstructMeshData(uint[] meshPointers, ushort[] rawMeshD } } - return meshes.ToArray(); + return meshes; } public static TR4MeshFace4 ReadTR4MeshFace4(BinaryReader reader) diff --git a/TRLevelControl/TR5FileReadUtilities.cs b/TRLevelControl/TR5FileReadUtilities.cs index 3bffba328..b93e8794f 100644 --- a/TRLevelControl/TR5FileReadUtilities.cs +++ b/TRLevelControl/TR5FileReadUtilities.cs @@ -212,29 +212,23 @@ public static void PopulateFloordata(BinaryReader reader, TR5Level lvl) public static void PopulateMeshes(BinaryReader reader, TR5Level lvl) { - //Mesh Data - //This tells us how much mesh data (# of words/uint16s) coming up - //just like the rooms previously. - lvl.LevelDataChunk.NumMeshData = reader.ReadUInt32(); - lvl.LevelDataChunk.RawMeshData = new ushort[lvl.LevelDataChunk.NumMeshData]; + uint numMeshData = reader.ReadUInt32(); + ushort[] rawMeshData = new ushort[numMeshData]; - for (int i = 0; i < lvl.LevelDataChunk.NumMeshData; i++) + for (int i = 0; i < numMeshData; i++) { - lvl.LevelDataChunk.RawMeshData[i] = reader.ReadUInt16(); + rawMeshData[i] = reader.ReadUInt16(); } - //Mesh Pointers - lvl.LevelDataChunk.NumMeshPointers = reader.ReadUInt32(); - lvl.LevelDataChunk.MeshPointers = new uint[lvl.LevelDataChunk.NumMeshPointers]; + uint numMeshPointers = reader.ReadUInt32(); + lvl.LevelDataChunk.MeshPointers = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumMeshPointers; i++) + for (int i = 0; i < numMeshPointers; i++) { - lvl.LevelDataChunk.MeshPointers[i] = reader.ReadUInt32(); + lvl.LevelDataChunk.MeshPointers.Add(reader.ReadUInt32()); } - //Mesh Construction - //level.Meshes = ConstructMeshData(level.NumMeshData, level.NumMeshPointers, level.RawMeshData); - lvl.LevelDataChunk.Meshes = TR4FileReadUtilities.ConstructMeshData(lvl.LevelDataChunk.MeshPointers, lvl.LevelDataChunk.RawMeshData); + lvl.LevelDataChunk.Meshes = TR4FileReadUtilities.ConstructMeshData(lvl.LevelDataChunk.MeshPointers, rawMeshData); } public static void PopulateAnimations(BinaryReader reader, TR5Level lvl) @@ -324,34 +318,28 @@ public static void PopulateStaticMeshes(BinaryReader reader, TR5Level lvl) } } - public static void VerifySPRMarker(BinaryReader reader, TR5Level lvl) + public static void VerifySPRMarker(BinaryReader reader) { - lvl.LevelDataChunk.SPRMarker = reader.ReadBytes(4); - - Debug.Assert(lvl.LevelDataChunk.SPRMarker[0] == 0x53); - Debug.Assert(lvl.LevelDataChunk.SPRMarker[1] == 0x50); - Debug.Assert(lvl.LevelDataChunk.SPRMarker[2] == 0x52); - Debug.Assert(lvl.LevelDataChunk.SPRMarker[3] == 0x00); + string sprMarker = new(reader.ReadChars(TR5LevelDataChunk.SPRMarker.Length)); + Debug.Assert(sprMarker == TR5LevelDataChunk.SPRMarker); } public static void PopulateSprites(BinaryReader reader, TR5Level lvl) { - //Sprite Textures - lvl.LevelDataChunk.NumSpriteTextures = reader.ReadUInt32(); - lvl.LevelDataChunk.SpriteTextures = new TRSpriteTexture[lvl.LevelDataChunk.NumSpriteTextures]; + uint numSpriteTextures = reader.ReadUInt32(); + lvl.LevelDataChunk.SpriteTextures = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSpriteTextures; i++) + for (int i = 0; i < numSpriteTextures; i++) { - lvl.LevelDataChunk.SpriteTextures[i] = TR2FileReadUtilities.ReadSpriteTexture(reader); + lvl.LevelDataChunk.SpriteTextures.Add(TR2FileReadUtilities.ReadSpriteTexture(reader)); } - //Sprite Sequences - lvl.LevelDataChunk.NumSpriteSequences = reader.ReadUInt32(); - lvl.LevelDataChunk.SpriteSequences = new TRSpriteSequence[lvl.LevelDataChunk.NumSpriteSequences]; + uint numSpriteSequences = reader.ReadUInt32(); + lvl.LevelDataChunk.SpriteSequences = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSpriteSequences; i++) + for (int i = 0; i < numSpriteSequences; i++) { - lvl.LevelDataChunk.SpriteSequences[i] = TR2FileReadUtilities.ReadSpriteSequence(reader); + lvl.LevelDataChunk.SpriteSequences.Add(TR2FileReadUtilities.ReadSpriteSequence(reader)); } } @@ -418,36 +406,32 @@ public static void PopulateBoxesOverlapsZones(BinaryReader reader, TR5Level lvl) public static void PopulateAnimatedTextures(BinaryReader reader, TR5Level lvl) { - lvl.LevelDataChunk.NumAnimatedTextures = reader.ReadUInt32(); - lvl.LevelDataChunk.AnimatedTextures = new TRAnimatedTexture[reader.ReadUInt16()]; - for (int i = 0; i < lvl.LevelDataChunk.AnimatedTextures.Length; i++) + reader.ReadUInt32(); // Total count of ushorts + ushort numGroups = reader.ReadUInt16(); + lvl.LevelDataChunk.AnimatedTextures = new(); + for (int i = 0; i < numGroups; i++) { - lvl.LevelDataChunk.AnimatedTextures[i] = TR2FileReadUtilities.ReadAnimatedTexture(reader); + lvl.LevelDataChunk.AnimatedTextures.Add(TR2FileReadUtilities.ReadAnimatedTexture(reader)); } //TR4+ Specific lvl.LevelDataChunk.AnimatedTexturesUVCount = reader.ReadByte(); } - public static void VerifyTEXMarker(BinaryReader reader, TR5Level lvl) + public static void VerifyTEXMarker(BinaryReader reader) { - lvl.LevelDataChunk.TEXMarker = reader.ReadBytes(4); - - Debug.Assert(lvl.LevelDataChunk.TEXMarker[0] == 0x54); - Debug.Assert(lvl.LevelDataChunk.TEXMarker[1] == 0x45); - Debug.Assert(lvl.LevelDataChunk.TEXMarker[2] == 0x58); - Debug.Assert(lvl.LevelDataChunk.TEXMarker[3] == 0x00); + string texMarker = new(reader.ReadChars(TR5LevelDataChunk.TEXMarker.Length)); + Debug.Assert(texMarker == TR5LevelDataChunk.TEXMarker); } public static void PopulateObjectTextures(BinaryReader reader, TR5Level lvl) { - //Object Textures - lvl.LevelDataChunk.NumObjectTextures = reader.ReadUInt32(); - lvl.LevelDataChunk.ObjectTextures = new TR5ObjectTexture[lvl.LevelDataChunk.NumObjectTextures]; + uint numObjectTextures = reader.ReadUInt32(); + lvl.LevelDataChunk.ObjectTextures = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumObjectTextures; i++) + for (int i = 0; i < numObjectTextures; i++) { - lvl.LevelDataChunk.ObjectTextures[i] = ReadTR5ObjectTexture(reader); + lvl.LevelDataChunk.ObjectTextures.Add(ReadTR5ObjectTexture(reader)); } } @@ -501,14 +485,8 @@ public static void PopulateEntitiesAndAI(TRLevelReader reader, TR5Level lvl) public static void PopulateDemoSoundSampleIndices(BinaryReader reader, TR5Level lvl) { - //Demo Data - lvl.LevelDataChunk.NumDemoData = reader.ReadUInt16(); - lvl.LevelDataChunk.DemoData = new byte[lvl.LevelDataChunk.NumDemoData]; - - for (int i = 0; i < lvl.LevelDataChunk.NumDemoData; i++) - { - lvl.LevelDataChunk.DemoData[i] = reader.ReadByte(); - } + ushort numDemoData = reader.ReadUInt16(); + lvl.LevelDataChunk.DemoData = reader.ReadBytes(numDemoData); //Sound Map (370 shorts) & Sound Details lvl.LevelDataChunk.SoundMap = new short[450]; @@ -518,21 +496,20 @@ public static void PopulateDemoSoundSampleIndices(BinaryReader reader, TR5Level lvl.LevelDataChunk.SoundMap[i] = reader.ReadInt16(); } - lvl.LevelDataChunk.NumSoundDetails = reader.ReadUInt32(); - lvl.LevelDataChunk.SoundDetails = new TR3SoundDetails[lvl.LevelDataChunk.NumSoundDetails]; + uint numSoundDetails = reader.ReadUInt32(); + lvl.LevelDataChunk.SoundDetails = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSoundDetails; i++) + for (int i = 0; i < numSoundDetails; i++) { - lvl.LevelDataChunk.SoundDetails[i] = TR3FileReadUtilities.ReadSoundDetails(reader); + lvl.LevelDataChunk.SoundDetails.Add(TR3FileReadUtilities.ReadSoundDetails(reader)); } - //Samples - lvl.LevelDataChunk.NumSampleIndices = reader.ReadUInt32(); - lvl.LevelDataChunk.SampleIndices = new uint[lvl.LevelDataChunk.NumSampleIndices]; + uint numSampleIndices = reader.ReadUInt32(); + lvl.LevelDataChunk.SampleIndices = new(); - for (int i = 0; i < lvl.LevelDataChunk.NumSampleIndices; i++) + for (int i = 0; i < numSampleIndices; i++) { - lvl.LevelDataChunk.SampleIndices[i] = reader.ReadUInt32(); + lvl.LevelDataChunk.SampleIndices.Add(reader.ReadUInt32()); } } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRAnimatedTextureControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRAnimatedTextureControl.cs index 5e885f76f..2d451cc84 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRAnimatedTextureControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRAnimatedTextureControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Animated Textures", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Animated Texture Count: " + IOManager.CurrentLevelAsTR1?.NumAnimatedTextures); + ImGui.Text("Animated Texture Count: " + IOManager.CurrentLevelAsTR1?.AnimatedTextures.Count); ImGui.TreePop(); } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRDemoDataControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRDemoDataControl.cs index e8c2fc13f..8be2b5479 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRDemoDataControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRDemoDataControl.cs @@ -10,7 +10,7 @@ public void Draw() { if (ImGui.TreeNodeEx("Demo Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Demo Data Size: " + IOManager.CurrentLevelAsTR1?.NumDemoData); + ImGui.Text("Demo Data Size: " + IOManager.CurrentLevelAsTR1?.DemoData.Length); ImGui.TreePop(); } } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRMeshControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRMeshControl.cs index 5bcf42329..d0ef8d7c0 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRMeshControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRMeshControl.cs @@ -10,8 +10,8 @@ public void Draw() { if (ImGui.TreeNodeEx("Mesh Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Mesh data count: " + IOManager.CurrentLevelAsTR1?.NumMeshData); - ImGui.Text("Mesh pointer count: " + IOManager.CurrentLevelAsTR1?.NumMeshPointers); + ImGui.Text("Mesh count: " + IOManager.CurrentLevelAsTR1?.Meshes.Count); + ImGui.Text("Mesh pointer count: " + IOManager.CurrentLevelAsTR1?.MeshPointers.Count); ImGui.TreePop(); } diff --git a/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs index 15446cd12..4017806f9 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRSoundControl.cs @@ -11,9 +11,9 @@ public void Draw() if (ImGui.TreeNodeEx("Sound Data", ImGuiTreeNodeFlags.OpenOnArrow)) { ImGui.Text("Sound sources count: " + IOManager.CurrentLevelAsTR1?.SoundSources.Count); - ImGui.Text("Sound details count: " + IOManager.CurrentLevelAsTR1?.NumSoundDetails); - ImGui.Text("Sound samples count: " + IOManager.CurrentLevelAsTR1?.NumSamples); - ImGui.Text("Sound sample indices count: " + IOManager.CurrentLevelAsTR1?.NumSampleIndices); + ImGui.Text("Sound details count: " + IOManager.CurrentLevelAsTR1?.SoundDetails.Count); + ImGui.Text("Sound samples count: " + IOManager.CurrentLevelAsTR1?.Samples.Count); + ImGui.Text("Sound sample indices count: " + IOManager.CurrentLevelAsTR1?.SampleIndices.Count); ImGui.Text("Sound map size: " + IOManager.CurrentLevelAsTR1?.SoundMap.Length); ImGui.TreePop(); diff --git a/TRLevelToolset/Controls/DataControls/TR/TRSpriteAndObjTextureControl.cs b/TRLevelToolset/Controls/DataControls/TR/TRSpriteAndObjTextureControl.cs index 6d3df3907..6843ecd41 100644 --- a/TRLevelToolset/Controls/DataControls/TR/TRSpriteAndObjTextureControl.cs +++ b/TRLevelToolset/Controls/DataControls/TR/TRSpriteAndObjTextureControl.cs @@ -10,9 +10,9 @@ public void Draw() { if (ImGui.TreeNodeEx("Sprite and Object Texture Data", ImGuiTreeNodeFlags.OpenOnArrow)) { - ImGui.Text("Object texture count: " + IOManager.CurrentLevelAsTR1?.NumObjectTextures); - ImGui.Text("Sprite texture count: " + IOManager.CurrentLevelAsTR1?.NumSpriteTextures); - ImGui.Text("Sprite sequence count: " + IOManager.CurrentLevelAsTR1?.NumSpriteSequences); + ImGui.Text("Object texture count: " + IOManager.CurrentLevelAsTR1?.ObjectTextures.Count); + ImGui.Text("Sprite texture count: " + IOManager.CurrentLevelAsTR1?.SpriteTextures.Count); + ImGui.Text("Sprite sequence count: " + IOManager.CurrentLevelAsTR1?.SpriteSequences.Count); ImGui.TreePop(); } diff --git a/TRModelTransporter/Handlers/Animations/AnimationUtilities.cs b/TRModelTransporter/Handlers/Animations/AnimationUtilities.cs index 50645367f..91695e8b5 100644 --- a/TRModelTransporter/Handlers/Animations/AnimationUtilities.cs +++ b/TRModelTransporter/Handlers/Animations/AnimationUtilities.cs @@ -165,7 +165,7 @@ public static void PackAnimSounds(TR3Level level, TR3PackedAnimation packedAnima } // Covers TR1 - private static void PackAnimSounds(short[] soundMap, TRSoundDetails[] soundDetails, uint[] sampleIndices, byte[] wavSamples, TR1PackedAnimation packedAnimation) + private static void PackAnimSounds(short[] soundMap, List soundDetails, List sampleIndices, List wavSamples, TR1PackedAnimation packedAnimation) { foreach (TR1PackedAnimationCommand cmd in packedAnimation.Commands.Values) { @@ -185,7 +185,7 @@ private static void PackAnimSounds(short[] soundMap, TRSoundDetails[] soundDetai ushort sampleIndex = (ushort)(details.Sample + i); samples[i] = sampleIndices[sampleIndex]; - uint nextIndex = sampleIndex == sampleIndices.Length - 1 ? (uint)sampleIndices.Length : sampleIndices[sampleIndex + 1]; + uint nextIndex = sampleIndex == sampleIndices.Count - 1 ? (uint)sampleIndices.Count : sampleIndices[sampleIndex + 1]; packedAnimation.Sound.Samples[samples[i]] = GetSample(samples[i], nextIndex, wavSamples); } @@ -195,18 +195,18 @@ private static void PackAnimSounds(short[] soundMap, TRSoundDetails[] soundDetai } } - public static byte[] GetSample(uint offset, uint endOffset, byte[] wavSamples) + public static byte[] GetSample(uint offset, uint endOffset, List wavSamples) { List data = new(); for (uint i = offset; i < endOffset; i++) { - data.Add(wavSamples[i]); + data.Add(wavSamples[(int)i]); } return data.ToArray(); } // Covers TR2 - private static void PackAnimSounds(short[] soundMap, TRSoundDetails[] soundDetails, uint[] sampleIndices, TR2PackedAnimation packedAnimation) + private static void PackAnimSounds(short[] soundMap, List soundDetails, List sampleIndices, TR2PackedAnimation packedAnimation) { foreach (TR1PackedAnimationCommand cmd in packedAnimation.Commands.Values) { @@ -233,7 +233,7 @@ private static void PackAnimSounds(short[] soundMap, TRSoundDetails[] soundDetai } // Covers TR3-5 - private static void PackAnimSounds(short[] soundMap, TR3SoundDetails[] soundDetails, uint[] sampleIndices, TR3PackedAnimation packedAnimation) + private static void PackAnimSounds(short[] soundMap, List soundDetails, List sampleIndices, TR3PackedAnimation packedAnimation) { foreach (TR1PackedAnimationCommand cmd in packedAnimation.Commands.Values) { diff --git a/TRModelTransporter/Handlers/ColourTransportHandler.cs b/TRModelTransporter/Handlers/ColourTransportHandler.cs index 002ebac27..785458bc9 100644 --- a/TRModelTransporter/Handlers/ColourTransportHandler.cs +++ b/TRModelTransporter/Handlers/ColourTransportHandler.cs @@ -21,7 +21,7 @@ public static void Export(TR3Level level, TR3ModelDefinition definition) definition.Colours = GetUsedMeshColours(definition.Meshes, level.Palette16); } - private static Dictionary GetUsedMeshColours(TRMesh[] meshes, List colours) + private static Dictionary GetUsedMeshColours(List meshes, List colours) { ISet colourIndices = GetAllColourIndices(meshes, false); @@ -34,7 +34,7 @@ private static Dictionary GetUsedMeshColours(TRMesh[] meshes, Lis return usedColours; } - private static Dictionary GetUsedMeshColours(TRMesh[] meshes, List colours) + private static Dictionary GetUsedMeshColours(List meshes, List colours) { ISet colourIndices = GetAllColourIndices(meshes, true); @@ -47,7 +47,7 @@ private static Dictionary GetUsedMeshColours(TRMesh[] meshes, Li return usedColours; } - private static ISet GetAllColourIndices(TRMesh[] meshes, bool has16Bit) + private static ISet GetAllColourIndices(List meshes, bool has16Bit) { ISet colourIndices = new SortedSet(); foreach (TRMesh mesh in meshes) @@ -107,7 +107,7 @@ public static void Import(TR3Level level, TR3ModelDefinition definition) ReindexMeshTextures(definition.Meshes, indexMap, true); } - private static void ReindexMeshTextures(TRMesh[] meshes, Dictionary indexMap, bool has16Bit) + private static void ReindexMeshTextures(List meshes, Dictionary indexMap, bool has16Bit) { foreach (TRMesh mesh in meshes) { diff --git a/TRModelTransporter/Handlers/MeshTransportHandler.cs b/TRModelTransporter/Handlers/MeshTransportHandler.cs index d1fb18363..312d254e2 100644 --- a/TRModelTransporter/Handlers/MeshTransportHandler.cs +++ b/TRModelTransporter/Handlers/MeshTransportHandler.cs @@ -38,7 +38,7 @@ public static void Import(TR1Level level, TR1ModelDefinition definition) } } - for (int i = 0; i < definition.Meshes.Length; i++) + for (int i = 0; i < definition.Meshes.Count; i++) { int insertedIndex = TRMeshUtilities.InsertMesh(level, definition.Meshes[i]); if (i == 0) @@ -59,7 +59,7 @@ public static void Import(TR2Level level, TR2ModelDefinition definition) } } - for (int i = 0; i < definition.Meshes.Length; i++) + for (int i = 0; i < definition.Meshes.Count; i++) { int insertedIndex = TRMeshUtilities.InsertMesh(level, definition.Meshes[i]); if (i == 0) @@ -80,7 +80,7 @@ public static void Import(TR3Level level, TR3ModelDefinition definition) } } - for (int i = 0; i < definition.Meshes.Length; i++) + for (int i = 0; i < definition.Meshes.Count; i++) { int insertedIndex = TRMeshUtilities.InsertMesh(level, definition.Meshes[i]); if (i == 0) diff --git a/TRModelTransporter/Handlers/Sound/SoundUnpacker.cs b/TRModelTransporter/Handlers/Sound/SoundUnpacker.cs index 1b73355f0..a66ca0ef8 100644 --- a/TRModelTransporter/Handlers/Sound/SoundUnpacker.cs +++ b/TRModelTransporter/Handlers/Sound/SoundUnpacker.cs @@ -23,43 +23,34 @@ public void Unpack(TR1PackedSound sound, TR1Level level, bool retainInternalIndi { Dictionary sampleDataMap = ImportSamples(level, sound.Samples); GenerateSampleMap(level.SampleIndices, sound.SampleIndices, sampleDataMap); - List soundDetails = GenerateSoundDetailsMap(level.SoundDetails, sound.SoundDetails); + GenerateSoundDetailsMap(level.SoundDetails, sound.SoundDetails); GenerateSoundIndexMap(level, retainInternalIndices, sound.SoundMapIndices); - level.Samples = _samples.ToArray(); - level.NumSamples = (uint)_samples.Count; + level.Samples.Clear(); + level.Samples.AddRange(_samples); - level.SampleIndices = _sampleIndices.ToArray(); - level.NumSampleIndices = (uint)_sampleIndices.Count; - - level.SoundDetails = soundDetails.ToArray(); - level.NumSoundDetails = (uint)soundDetails.Count; + level.SampleIndices.Clear(); + level.SampleIndices.AddRange(_sampleIndices); } public void Unpack(TR2PackedSound sound, TR2Level level, bool retainInternalIndices = false) { GenerateSampleMap(level.SampleIndices, sound.SampleIndices); - List soundDetails = GenerateSoundDetailsMap(level.SoundDetails, sound.SoundDetails); + GenerateSoundDetailsMap(level.SoundDetails, sound.SoundDetails); GenerateSoundIndexMap(level, retainInternalIndices, sound.SoundMapIndices); - level.SampleIndices = _sampleIndices.ToArray(); - level.NumSampleIndices = (uint)_sampleIndices.Count; - - level.SoundDetails = soundDetails.ToArray(); - level.NumSoundDetails = (uint)soundDetails.Count; + level.SampleIndices.Clear(); + level.SampleIndices.AddRange(_sampleIndices); } public void Unpack(TR3PackedSound sound, TR3Level level, bool retainInternalIndices = false) { GenerateSampleMap(level.SampleIndices, sound.SampleIndices); - List soundDetails = GenerateSoundDetailsMap(level.SoundDetails, sound.SoundDetails); + GenerateSoundDetailsMap(level.SoundDetails, sound.SoundDetails); GenerateSoundIndexMap(level, retainInternalIndices, sound.SoundMapIndices); - level.SampleIndices = _sampleIndices.ToArray(); - level.NumSampleIndices = (uint)_sampleIndices.Count; - - level.SoundDetails = soundDetails.ToArray(); - level.NumSoundDetails = (uint)soundDetails.Count; + level.SampleIndices.Clear(); + level.SampleIndices.AddRange(_sampleIndices); } private Dictionary ImportSamples(TR1Level level, Dictionary sampleData) @@ -78,7 +69,7 @@ private Dictionary ImportSamples(TR1Level level, Dictionary packedIndices, Dictionary sampleKeyMap = null) + private void GenerateSampleMap(List sampleIndices, Dictionary packedIndices, Dictionary sampleKeyMap = null) { // Insert each required SampleIndex value, which are the values that point into // MAIN.SFX (or Samples[] in TR1). Note the first inserted index for updating @@ -121,11 +112,10 @@ private void GenerateSampleMap(uint[] sampleIndices, Dictionary } // TR1-2 - private List GenerateSoundDetailsMap(TRSoundDetails[] currentSoundDetails, Dictionary packedSoundDetails) + private void GenerateSoundDetailsMap(List soundDetails, Dictionary packedSoundDetails) { // Update each SoundDetails.Sample with the new SampleIndex values. Store // a map of old SoundsDetails indices to new. - List soundDetails = currentSoundDetails.ToList(); _soundDetailsMap = new Dictionary(); foreach (int soundDetailsIndex in packedSoundDetails.Keys) @@ -144,14 +134,11 @@ private List GenerateSoundDetailsMap(TRSoundDetails[] currentSou _soundDetailsMap[soundDetailsIndex] = currentIndex; } } - - return soundDetails; } // TR3+ - private List GenerateSoundDetailsMap(TR3SoundDetails[] currentSoundDetails, Dictionary packedSoundDetails) + private void GenerateSoundDetailsMap(List soundDetails, Dictionary packedSoundDetails) { - List soundDetails = currentSoundDetails.ToList(); _soundDetailsMap = new Dictionary(); foreach (int soundDetailsIndex in packedSoundDetails.Keys) @@ -170,8 +157,6 @@ private List GenerateSoundDetailsMap(TR3SoundDetails[] currentS _soundDetailsMap[soundDetailsIndex] = currentIndex; } } - - return soundDetails; } private static int FindSoundDetailsIndex(TRSoundDetails details, List allDetails) diff --git a/TRModelTransporter/Handlers/Sound/SoundUtilities.cs b/TRModelTransporter/Handlers/Sound/SoundUtilities.cs index b8d6dd9a9..634d65ecb 100644 --- a/TRModelTransporter/Handlers/Sound/SoundUtilities.cs +++ b/TRModelTransporter/Handlers/Sound/SoundUtilities.cs @@ -12,7 +12,7 @@ public static void ImportLevelSound(TR1Level baseLevel, TR1Level sourceLevel, sh SoundUtilities.ResortSoundIndices(baseLevel); } - public static TR1PackedSound BuildPackedSound(short[] soundMap, TRSoundDetails[] soundDetails, uint[] sampleIndices, byte[] wavSamples, short[] hardcodedSounds) + public static TR1PackedSound BuildPackedSound(short[] soundMap, List soundDetails, List sampleIndices, List wavSamples, short[] hardcodedSounds) { if (hardcodedSounds == null || hardcodedSounds.Length == 0) { @@ -39,7 +39,7 @@ public static TR1PackedSound BuildPackedSound(short[] soundMap, TRSoundDetails[] ushort sampleIndex = (ushort)(details.Sample + i); samples[i] = sampleIndices[sampleIndex]; - uint nextIndex = sampleIndex == sampleIndices.Length - 1 ? (uint)wavSamples.Length : sampleIndices[sampleIndex + 1]; + uint nextIndex = sampleIndex == sampleIndices.Count - 1 ? (uint)wavSamples.Count : sampleIndices[sampleIndex + 1]; packedSound.Samples[samples[i]] = AnimationUtilities.GetSample(samples[i], nextIndex, wavSamples); } @@ -58,7 +58,7 @@ public static TR1PackedSound BuildPackedSound(short[] soundMap, TRSoundDetails[] return packedSound; } - public static TR2PackedSound BuildPackedSound(short[] soundMap, TRSoundDetails[] soundDetails, uint[] sampleIndices, short[] hardcodedSounds) + public static TR2PackedSound BuildPackedSound(short[] soundMap, List soundDetails, List sampleIndices, short[] hardcodedSounds) { if (hardcodedSounds == null || hardcodedSounds.Length == 0) { @@ -100,7 +100,7 @@ public static TR2PackedSound BuildPackedSound(short[] soundMap, TRSoundDetails[] return packedSound; } - public static TR3PackedSound BuildPackedSound(short[] soundMap, TR3SoundDetails[] soundDetails, uint[] sampleIndices, short[] hardcodedSounds) + public static TR3PackedSound BuildPackedSound(short[] soundMap, List soundDetails, List sampleIndices, short[] hardcodedSounds) { if (hardcodedSounds == null || hardcodedSounds.Length == 0) { @@ -169,7 +169,7 @@ public static void ResortSoundIndices(TR1Level level) ushort samplePointerIndex = (ushort)(oldSample + i); uint oldSampleIndex = level.SampleIndices[oldSample + i]; - uint nextSampleIndex = samplePointerIndex == level.SampleIndices.Length - 1 ? (uint)level.Samples.Length : level.SampleIndices[samplePointerIndex + 1]; + uint nextSampleIndex = samplePointerIndex == level.SampleIndices.Count - 1 ? (uint)level.Samples.Count : level.SampleIndices[samplePointerIndex + 1]; newSampleIndices.Add((uint)newSamples.Count); newSamples.AddRange(AnimationUtilities.GetSample(oldSampleIndex, nextSampleIndex, level.Samples)); @@ -178,38 +178,37 @@ public static void ResortSoundIndices(TR1Level level) } level.SoundMap = newSoundMap.ToArray(); - level.SoundDetails = newSoundDetails.ToArray(); - level.SampleIndices = newSampleIndices.ToArray(); - level.Samples = newSamples.ToArray(); - level.NumSoundDetails = (uint)newSoundDetails.Count; - level.NumSampleIndices = (uint)newSampleIndices.Count; - level.NumSamples = (uint)newSamples.Count; + level.SoundDetails.Clear(); + level.SampleIndices.Clear(); + level.Samples.Clear(); + + level.SoundDetails.AddRange(newSoundDetails); + level.SampleIndices.AddRange(newSampleIndices); + level.Samples.AddRange(newSamples); } public static void ResortSoundIndices(TR2Level level) { - List sampleIndices = level.SampleIndices.ToList(); List soundDetails = level.SoundDetails.ToList(); List soundMap = level.SoundMap.ToList(); - ResortSoundIndices(sampleIndices, soundDetails, soundMap); + ResortSoundIndices(level.SampleIndices, soundDetails, soundMap); - level.SampleIndices = sampleIndices.ToArray(); - level.SoundDetails = soundDetails.ToArray(); + level.SoundDetails.Clear(); + level.SoundDetails.AddRange(soundDetails); level.SoundMap = soundMap.ToArray(); } public static void ResortSoundIndices(TR3Level level) { - List sampleIndices = level.SampleIndices.ToList(); List soundDetails = level.SoundDetails.ToList(); List soundMap = level.SoundMap.ToList(); - ResortSoundIndices(sampleIndices, soundDetails, soundMap); + ResortSoundIndices(level.SampleIndices, soundDetails, soundMap); - level.SampleIndices = sampleIndices.ToArray(); - level.SoundDetails = soundDetails.ToArray(); + level.SoundDetails.Clear(); + level.SoundDetails.AddRange(soundDetails); level.SoundMap = soundMap.ToArray(); } diff --git a/TRModelTransporter/Handlers/Textures/AbstractTextureImportHandler.cs b/TRModelTransporter/Handlers/Textures/AbstractTextureImportHandler.cs index 4dc764071..72c4a12c0 100644 --- a/TRModelTransporter/Handlers/Textures/AbstractTextureImportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/AbstractTextureImportHandler.cs @@ -183,7 +183,7 @@ protected virtual void MergeObjectTextures() { // Add each ObjectTexture to the level and store a map of old index to new index. // Make use of any invalid texture first because we are limited to 2048 entries - List levelObjectTextures = GetExistingObjectTextures().ToList(); + List levelObjectTextures = GetExistingObjectTextures(); Queue reusableIndices = new(GetInvalidObjectTextureIndices()); Dictionary> indexMap = new(); @@ -225,9 +225,6 @@ protected virtual void MergeObjectTextures() } } - // Save the new textures in the level - WriteObjectTextures(levelObjectTextures); - // Change the definition's meshes so that the textured rectangles and triangles point // to the correct object texture. RemapMeshTextures(indexMap); @@ -235,8 +232,8 @@ protected virtual void MergeObjectTextures() protected virtual void MergeSpriteTextures() { - List levelSpriteTextures = GetExistingSpriteTextures().ToList(); - List levelSpriteSequences = GetExistingSpriteSequences().ToList(); + List levelSpriteTextures = GetExistingSpriteTextures(); + List levelSpriteSequences = GetExistingSpriteSequences(); foreach (D definition in _definitions) { @@ -267,29 +264,20 @@ protected virtual void MergeSpriteTextures() } } } - - WriteSpriteTextures(levelSpriteTextures); - WriteSpriteSequences(levelSpriteSequences); } - protected abstract IEnumerable GetExistingSpriteSequences(); + protected abstract List GetExistingSpriteSequences(); - protected abstract IEnumerable GetExistingSpriteTextures(); + protected abstract List GetExistingSpriteTextures(); protected abstract AbstractTexturePacker CreatePacker(); protected abstract void ProcessRemovals(AbstractTexturePacker packer); - protected abstract IEnumerable GetExistingObjectTextures(); + protected abstract List GetExistingObjectTextures(); protected abstract IEnumerable GetInvalidObjectTextureIndices(); - protected abstract void WriteObjectTextures(IEnumerable objectTextures); - - protected abstract void WriteSpriteTextures(IEnumerable spriteTextures); - - protected abstract void WriteSpriteSequences(IEnumerable spriteSequences); - protected abstract void RemapMeshTextures(Dictionary> indexMap); public abstract void ResetUnusedTextures(); diff --git a/TRModelTransporter/Handlers/Textures/TR1/TR1TextureExportHandler.cs b/TRModelTransporter/Handlers/Textures/TR1/TR1TextureExportHandler.cs index 33a00cbfc..19b0210d2 100644 --- a/TRModelTransporter/Handlers/Textures/TR1/TR1TextureExportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR1/TR1TextureExportHandler.cs @@ -13,6 +13,6 @@ protected override AbstractTexturePacker CreatePacker() protected override TRSpriteSequence GetSprite(TR1Type entity) { - return _level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)entity); + return _level.SpriteSequences.Find(s => s.SpriteID == (int)entity); } } diff --git a/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs b/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs index 626fc7608..73442d32e 100644 --- a/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR1/TR1TextureImportHandler.cs @@ -10,10 +10,10 @@ public class TR1TextureImportHandler : AbstractTextureImportHandler GetExistingSpriteSequences() + protected override List GetExistingSpriteSequences() { // Allow replacing the Explosion sequence in Vilcabamba (it's there but empty) - List sequences = _level.SpriteSequences.ToList(); + List sequences = _level.SpriteSequences; TRSpriteSequence explosion = sequences.Find(s => s.SpriteID == (int)TR1Type.Explosion1_S_H); if (explosion != null && explosion.NegativeLength == -1) { @@ -22,21 +22,9 @@ protected override IEnumerable GetExistingSpriteSequences() return sequences; } - protected override void WriteSpriteSequences(IEnumerable spriteSequences) + protected override List GetExistingSpriteTextures() { - _level.SpriteSequences = spriteSequences.ToArray(); - _level.NumSpriteSequences = (uint)_level.SpriteSequences.Length; - } - - protected override IEnumerable GetExistingSpriteTextures() - { - return _level.SpriteTextures.ToList(); - } - - protected override void WriteSpriteTextures(IEnumerable spriteTextures) - { - _level.SpriteTextures = spriteTextures.ToArray(); - _level.NumSpriteTextures = (uint)_level.SpriteTextures.Length; + return _level.SpriteTextures; } protected override AbstractTexturePacker CreatePacker() @@ -92,9 +80,9 @@ private void RemoveUnusedSprites(AbstractTexturePacker packer packer.RemoveSpriteSegments(unusedItems); } - protected override IEnumerable GetExistingObjectTextures() + protected override List GetExistingObjectTextures() { - return _level.ObjectTextures.ToList(); + return _level.ObjectTextures; } protected override IEnumerable GetInvalidObjectTextureIndices() @@ -102,12 +90,6 @@ protected override IEnumerable GetInvalidObjectTextureIndices() return _level.GetInvalidObjectTextureIndices(); } - protected override void WriteObjectTextures(IEnumerable objectTextures) - { - _level.ObjectTextures = objectTextures.ToArray(); - _level.NumObjectTextures = (uint)_level.ObjectTextures.Length; - } - protected override void RemapMeshTextures(Dictionary> indexMap) { foreach (TR1ModelDefinition definition in indexMap.Keys) diff --git a/TRModelTransporter/Handlers/Textures/TR2/TR2TextureExportHandler.cs b/TRModelTransporter/Handlers/Textures/TR2/TR2TextureExportHandler.cs index e17941a0f..5a3d0493a 100644 --- a/TRModelTransporter/Handlers/Textures/TR2/TR2TextureExportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR2/TR2TextureExportHandler.cs @@ -13,6 +13,6 @@ protected override AbstractTexturePacker CreatePacker() protected override TRSpriteSequence GetSprite(TR2Type entity) { - return _level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)entity); + return _level.SpriteSequences.Find(s => s.SpriteID == (int)entity); } } diff --git a/TRModelTransporter/Handlers/Textures/TR2/TR2TextureImportHandler.cs b/TRModelTransporter/Handlers/Textures/TR2/TR2TextureImportHandler.cs index d71dcbd3a..f6b86da58 100644 --- a/TRModelTransporter/Handlers/Textures/TR2/TR2TextureImportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR2/TR2TextureImportHandler.cs @@ -7,26 +7,14 @@ namespace TRModelTransporter.Handlers; public class TR2TextureImportHandler : AbstractTextureImportHandler { - protected override IEnumerable GetExistingSpriteSequences() + protected override List GetExistingSpriteSequences() { return _level.SpriteSequences; } - protected override void WriteSpriteSequences(IEnumerable spriteSequences) + protected override List GetExistingSpriteTextures() { - _level.SpriteSequences = spriteSequences.ToArray(); - _level.NumSpriteSequences = (uint)_level.SpriteSequences.Length; - } - - protected override IEnumerable GetExistingSpriteTextures() - { - return _level.SpriteTextures.ToList(); - } - - protected override void WriteSpriteTextures(IEnumerable spriteTextures) - { - _level.SpriteTextures = spriteTextures.ToArray(); - _level.NumSpriteTextures = (uint)_level.SpriteTextures.Length; + return _level.SpriteTextures; } protected override AbstractTexturePacker CreatePacker() @@ -81,30 +69,26 @@ private void ApplyFlamePatch() _level.Models.FindIndex(m => flameEnemies.Contains((TR2Type)m.ID)) != -1 ) { - List sequences = _level.SpriteSequences.ToList(); - int blastSequence = sequences.FindIndex(s => s.SpriteID == (int)TR2Type.FireBlast_S_H); - int grenadeSequence = sequences.FindIndex(s => s.SpriteID == (int)TR2Type.Explosion_S_H); + int blastSequence = _level.SpriteSequences.FindIndex(s => s.SpriteID == (int)TR2Type.FireBlast_S_H); + int grenadeSequence = _level.SpriteSequences.FindIndex(s => s.SpriteID == (int)TR2Type.Explosion_S_H); if (grenadeSequence != -1) { if (blastSequence == -1) { - TRSpriteSequence grenadeBlast = sequences[grenadeSequence]; - sequences.Add(new TRSpriteSequence + TRSpriteSequence grenadeBlast = _level.SpriteSequences[grenadeSequence]; + _level.SpriteSequences.Add(new TRSpriteSequence { SpriteID = (int)TR2Type.FireBlast_S_H, NegativeLength = grenadeBlast.NegativeLength, Offset = grenadeBlast.Offset }); - - _level.SpriteSequences = sequences.ToArray(); - _level.NumSpriteSequences++; } else { // #275 Rather than just pointing the blast sequence offset to the grenade sequence offset, // retain the original sprite texture objects but just remap where they point in the tiles. - for (int i = 0; i < sequences[grenadeSequence].NegativeLength * -1; i++) + for (int i = 0; i < _level.SpriteSequences[grenadeSequence].NegativeLength * -1; i++) { _level.SpriteTextures[_level.SpriteSequences[blastSequence].Offset + i] = _level.SpriteTextures[_level.SpriteSequences[grenadeSequence].Offset + i]; } @@ -139,9 +123,9 @@ private void RemoveUnusedSprites(AbstractTexturePacker packer packer.RemoveSpriteSegments(unusedItems); } - protected override IEnumerable GetExistingObjectTextures() + protected override List GetExistingObjectTextures() { - return _level.ObjectTextures.ToList(); + return _level.ObjectTextures; } protected override IEnumerable GetInvalidObjectTextureIndices() @@ -149,12 +133,6 @@ protected override IEnumerable GetInvalidObjectTextureIndices() return _level.GetInvalidObjectTextureIndices(); } - protected override void WriteObjectTextures(IEnumerable objectTextures) - { - _level.ObjectTextures = objectTextures.ToArray(); - _level.NumObjectTextures = (uint)_level.ObjectTextures.Length; - } - protected override void RemapMeshTextures(Dictionary> indexMap) { foreach (TR2ModelDefinition definition in indexMap.Keys) diff --git a/TRModelTransporter/Handlers/Textures/TR3/TR3TextureExportHandler.cs b/TRModelTransporter/Handlers/Textures/TR3/TR3TextureExportHandler.cs index 96dfe6092..910d0e651 100644 --- a/TRModelTransporter/Handlers/Textures/TR3/TR3TextureExportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR3/TR3TextureExportHandler.cs @@ -12,6 +12,6 @@ protected override AbstractTexturePacker CreatePacker() } protected override TRSpriteSequence GetSprite(TR3Type entity) { - return _level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)entity); + return _level.SpriteSequences.Find(s => s.SpriteID == (int)entity); } } diff --git a/TRModelTransporter/Handlers/Textures/TR3/TR3TextureImportHandler.cs b/TRModelTransporter/Handlers/Textures/TR3/TR3TextureImportHandler.cs index 1254296a3..c2dba0386 100644 --- a/TRModelTransporter/Handlers/Textures/TR3/TR3TextureImportHandler.cs +++ b/TRModelTransporter/Handlers/Textures/TR3/TR3TextureImportHandler.cs @@ -7,26 +7,14 @@ namespace TRModelTransporter.Handlers; public class TR3TextureImportHandler : AbstractTextureImportHandler { - protected override IEnumerable GetExistingSpriteSequences() + protected override List GetExistingSpriteSequences() { return _level.SpriteSequences; } - protected override void WriteSpriteSequences(IEnumerable spriteSequences) + protected override List GetExistingSpriteTextures() { - _level.SpriteSequences = spriteSequences.ToArray(); - _level.NumSpriteSequences = (uint)_level.SpriteSequences.Length; - } - - protected override IEnumerable GetExistingSpriteTextures() - { - return _level.SpriteTextures.ToList(); - } - - protected override void WriteSpriteTextures(IEnumerable spriteTextures) - { - _level.SpriteTextures = spriteTextures.ToArray(); - _level.NumSpriteTextures = (uint)_level.SpriteTextures.Length; + return _level.SpriteTextures; } protected override AbstractTexturePacker CreatePacker() @@ -80,9 +68,9 @@ private void RemoveUnusedSprites(AbstractTexturePacker packer packer.RemoveSpriteSegments(unusedItems); } - protected override IEnumerable GetExistingObjectTextures() + protected override List GetExistingObjectTextures() { - return _level.ObjectTextures.ToList(); + return _level.ObjectTextures; } protected override IEnumerable GetInvalidObjectTextureIndices() @@ -90,12 +78,6 @@ protected override IEnumerable GetInvalidObjectTextureIndices() return _level.GetInvalidObjectTextureIndices(); } - protected override void WriteObjectTextures(IEnumerable objectTextures) - { - _level.ObjectTextures = objectTextures.ToArray(); - _level.NumObjectTextures = (uint)_level.ObjectTextures.Length; - } - protected override void RemapMeshTextures(Dictionary> indexMap) { foreach (TR3ModelDefinition definition in indexMap.Keys) diff --git a/TRModelTransporter/Helpers/TRModelExtensions.cs b/TRModelTransporter/Helpers/TRModelExtensions.cs index d4920a990..427f3e13a 100644 --- a/TRModelTransporter/Helpers/TRModelExtensions.cs +++ b/TRModelTransporter/Helpers/TRModelExtensions.cs @@ -109,10 +109,10 @@ public static List GetInvalidObjectTextureIndices(this TR3Level level) return GetInvalidObjectTextureIndices(level.ObjectTextures); } - private static List GetInvalidObjectTextureIndices(TRObjectTexture[] objectTextures) + private static List GetInvalidObjectTextureIndices(List objectTextures) { List reusableIndices = new(); - for (int i = 0; i < objectTextures.Length; i++) + for (int i = 0; i < objectTextures.Count; i++) { if (!objectTextures[i].IsValid()) { @@ -162,13 +162,13 @@ public static void ReindexTextures(this TR2Level level, Dictionary ind List textures = level.ObjectTextures.ToList(); foreach (TRAnimatedTexture anim in level.AnimatedTextures) { - for (int i = 0; i < anim.Textures.Length; i++) + for (int i = 0; i < anim.Textures.Count; i++) { anim.Textures[i] = ConvertTextureReference(anim.Textures[i], indexMap, defaultToOriginal); } ushort previousIndex = anim.Textures[0]; - for (int i = 1; i < anim.Textures.Length; i++) + for (int i = 1; i < anim.Textures.Count; i++) { if (anim.Textures[i] == previousIndex && textures.Count < 2048) { @@ -179,10 +179,10 @@ public static void ReindexTextures(this TR2Level level, Dictionary ind } } - if (textures.Count > level.NumObjectTextures) + if (textures.Count > level.ObjectTextures.Count) { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)textures.Count; + level.ObjectTextures.Clear(); + level.ObjectTextures.AddRange(textures); } } @@ -220,13 +220,13 @@ public static void ReindexTextures(this TR3Level level, Dictionary ind List textures = level.ObjectTextures.ToList(); foreach (TRAnimatedTexture anim in level.AnimatedTextures) { - for (int i = 0; i < anim.Textures.Length; i++) + for (int i = 0; i < anim.Textures.Count; i++) { anim.Textures[i] = ConvertTextureReference(anim.Textures[i], indexMap, defaultToOriginal); } ushort previousIndex = anim.Textures[0]; - for (int i = 1; i < anim.Textures.Length; i++) + for (int i = 1; i < anim.Textures.Count; i++) { if (anim.Textures[i] == previousIndex && textures.Count < 2048) { @@ -237,10 +237,10 @@ public static void ReindexTextures(this TR3Level level, Dictionary ind } } - if (textures.Count > level.NumObjectTextures) + if (textures.Count > level.ObjectTextures.Count) { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)textures.Count; + level.ObjectTextures.Clear(); + level.ObjectTextures.AddRange(textures); } } @@ -254,7 +254,7 @@ private static ushort ConvertTextureReference(ushort textureReference, Dictionar return defaultToOriginal ? textureReference : (ushort)0; } - public static string ComputeSkeletonHash(this TRMesh[] meshes) + public static string ComputeSkeletonHash(this IEnumerable meshes) { using MemoryStream ms = new(); using BinaryWriter writer = new(ms); diff --git a/TRModelTransporter/Model/Definitions/TR1ModelDefinition.cs b/TRModelTransporter/Model/Definitions/TR1ModelDefinition.cs index dfad5876e..6fbe389ae 100644 --- a/TRModelTransporter/Model/Definitions/TR1ModelDefinition.cs +++ b/TRModelTransporter/Model/Definitions/TR1ModelDefinition.cs @@ -12,7 +12,7 @@ public class TR1ModelDefinition : AbstractTRModelDefinition public TRCinematicFrame[] CinematicFrames { get; set; } public Dictionary Colours { get; set; } public TR1PackedSound HardcodedSound { get; set; } - public TRMesh[] Meshes { get; set; } + public List Meshes { get; set; } public TRMeshTreeNode[] MeshTrees { get; set; } public TRModel Model { get; set; } diff --git a/TRModelTransporter/Model/Definitions/TR2ModelDefinition.cs b/TRModelTransporter/Model/Definitions/TR2ModelDefinition.cs index e639a1a57..5a3c4a7c9 100644 --- a/TRModelTransporter/Model/Definitions/TR2ModelDefinition.cs +++ b/TRModelTransporter/Model/Definitions/TR2ModelDefinition.cs @@ -12,7 +12,7 @@ public class TR2ModelDefinition : AbstractTRModelDefinition public TRCinematicFrame[] CinematicFrames { get; set; } public Dictionary Colours { get; set; } public TR2PackedSound HardcodedSound { get; set; } - public TRMesh[] Meshes { get; set; } + public List Meshes { get; set; } public TRMeshTreeNode[] MeshTrees { get; set; } public TRModel Model { get; set; } diff --git a/TRModelTransporter/Model/Definitions/TR3ModelDefinition.cs b/TRModelTransporter/Model/Definitions/TR3ModelDefinition.cs index 73ac3ec4c..893d0ecae 100644 --- a/TRModelTransporter/Model/Definitions/TR3ModelDefinition.cs +++ b/TRModelTransporter/Model/Definitions/TR3ModelDefinition.cs @@ -12,7 +12,7 @@ public class TR3ModelDefinition : AbstractTRModelDefinition public TRCinematicFrame[] CinematicFrames { get; set; } public Dictionary Colours { get; set; } public TR3PackedSound HardcodedSound { get; set; } - public TRMesh[] Meshes { get; set; } + public List Meshes { get; set; } public TRMeshTreeNode[] MeshTrees { get; set; } public TRModel Model { get; set; } diff --git a/TRModelTransporter/Packing/AbstractTexturePacker.cs b/TRModelTransporter/Packing/AbstractTexturePacker.cs index cda765904..76ac0fc6f 100644 --- a/TRModelTransporter/Packing/AbstractTexturePacker.cs +++ b/TRModelTransporter/Packing/AbstractTexturePacker.cs @@ -93,7 +93,7 @@ public PackingResult Pack(bool commitToLevel) public Dictionary> GetModelSegments(E modelEntity) { Dictionary> segmentMap = new(); - TRMesh[] meshes = GetModelMeshes(modelEntity); + List meshes = GetModelMeshes(modelEntity); if (meshes != null) { IEnumerable indices = GetMeshTextureIndices(meshes); @@ -125,7 +125,7 @@ public Dictionary> GetObjectTextureSegme return segmentMap; } - protected abstract TRMesh[] GetModelMeshes(E modelEntity); + protected abstract List GetModelMeshes(E modelEntity); public Dictionary> GetSpriteSegments(E entity) { @@ -169,7 +169,7 @@ public Dictionary> GetSpriteTextureSegme protected abstract TRSpriteSequence GetSpriteSequence(E entity); - protected IEnumerable GetMeshTextureIndices(TRMesh[] meshes) + protected IEnumerable GetMeshTextureIndices(List meshes) { ISet textureIndices = new SortedSet(); foreach (TRMesh mesh in meshes) diff --git a/TRModelTransporter/Packing/Types/TR1TexturePacker.cs b/TRModelTransporter/Packing/Types/TR1TexturePacker.cs index 3b5c163c1..adda6c0ec 100644 --- a/TRModelTransporter/Packing/Types/TR1TexturePacker.cs +++ b/TRModelTransporter/Packing/Types/TR1TexturePacker.cs @@ -22,8 +22,8 @@ public TR1TexturePacker(TR1Level level, ITextureClassifier classifier = null) protected override List LoadObjectTextures() { - List textures = new((int)Level.NumObjectTextures); - for (int i = 0; i < Level.NumObjectTextures; i++) + List textures = new(Level.ObjectTextures.Count); + for (int i = 0; i < Level.ObjectTextures.Count; i++) { TRObjectTexture texture = Level.ObjectTextures[i]; if (texture.IsValid()) @@ -41,8 +41,8 @@ protected override List LoadObjectTextures() protected override List LoadSpriteTextures() { - List textures = new((int)Level.NumSpriteTextures); - for (int i = 0; i < Level.NumSpriteTextures; i++) + List textures = new(Level.SpriteTextures.Count); + for (int i = 0; i < Level.SpriteTextures.Count; i++) { TRSpriteTexture texture = Level.SpriteTextures[i]; if (texture.IsValid()) @@ -58,14 +58,14 @@ protected override List LoadSpriteTextures() return textures; } - protected override TRMesh[] GetModelMeshes(TR1Type modelEntity) + protected override List GetModelMeshes(TR1Type modelEntity) { return TRMeshUtilities.GetModelMeshes(Level, modelEntity); } protected override TRSpriteSequence GetSpriteSequence(TR1Type entity) { - return Level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)entity); + return Level.SpriteSequences.Find(s => s.SpriteID == (int)entity); } protected override IEnumerable GetAllModelTypes() diff --git a/TRModelTransporter/Packing/Types/TR2TexturePacker.cs b/TRModelTransporter/Packing/Types/TR2TexturePacker.cs index 36ddebd8f..8d639866e 100644 --- a/TRModelTransporter/Packing/Types/TR2TexturePacker.cs +++ b/TRModelTransporter/Packing/Types/TR2TexturePacker.cs @@ -19,8 +19,8 @@ public TR2TexturePacker(TR2Level level, ITextureClassifier classifier = null) protected override List LoadObjectTextures() { - List textures = new((int)Level.NumObjectTextures); - for (int i = 0; i < Level.NumObjectTextures; i++) + List textures = new(Level.ObjectTextures.Count); + for (int i = 0; i < Level.ObjectTextures.Count; i++) { TRObjectTexture texture = Level.ObjectTextures[i]; if (texture.IsValid()) @@ -38,8 +38,8 @@ protected override List LoadObjectTextures() protected override List LoadSpriteTextures() { - List textures = new((int)Level.NumSpriteTextures); - for (int i = 0; i < Level.NumSpriteTextures; i++) + List textures = new(Level.SpriteTextures.Count); + for (int i = 0; i < Level.SpriteTextures.Count; i++) { TRSpriteTexture texture = Level.SpriteTextures[i]; if (texture.IsValid()) @@ -55,14 +55,14 @@ protected override List LoadSpriteTextures() return textures; } - protected override TRMesh[] GetModelMeshes(TR2Type modelEntity) + protected override List GetModelMeshes(TR2Type modelEntity) { return TRMeshUtilities.GetModelMeshes(Level, modelEntity); } protected override TRSpriteSequence GetSpriteSequence(TR2Type entity) { - return Level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)entity); + return Level.SpriteSequences.Find(s => s.SpriteID == (int)entity); } protected override IEnumerable GetAllModelTypes() diff --git a/TRModelTransporter/Packing/Types/TR3TexturePacker.cs b/TRModelTransporter/Packing/Types/TR3TexturePacker.cs index bd69910b6..e03ef19a4 100644 --- a/TRModelTransporter/Packing/Types/TR3TexturePacker.cs +++ b/TRModelTransporter/Packing/Types/TR3TexturePacker.cs @@ -19,8 +19,8 @@ public TR3TexturePacker(TR3Level level, ITextureClassifier classifier = null) protected override List LoadObjectTextures() { - List textures = new((int)Level.NumObjectTextures); - for (int i = 0; i < Level.NumObjectTextures; i++) + List textures = new(Level.ObjectTextures.Count); + for (int i = 0; i < Level.ObjectTextures.Count; i++) { TRObjectTexture texture = Level.ObjectTextures[i]; if (texture.IsValid()) @@ -38,8 +38,8 @@ protected override List LoadObjectTextures() protected override List LoadSpriteTextures() { - List textures = new((int)Level.NumSpriteTextures); - for (int i = 0; i < Level.NumSpriteTextures; i++) + List textures = new(Level.SpriteTextures.Count); + for (int i = 0; i < Level.SpriteTextures.Count; i++) { TRSpriteTexture texture = Level.SpriteTextures[i]; if (texture.IsValid()) @@ -55,14 +55,14 @@ protected override List LoadSpriteTextures() return textures; } - protected override TRMesh[] GetModelMeshes(TR3Type modelEntity) + protected override List GetModelMeshes(TR3Type modelEntity) { return TRMeshUtilities.GetModelMeshes(Level, modelEntity); } protected override TRSpriteSequence GetSpriteSequence(TR3Type entity) { - return Level.SpriteSequences.ToList().Find(s => s.SpriteID == (int)entity); + return Level.SpriteSequences.Find(s => s.SpriteID == (int)entity); } protected override IEnumerable GetAllModelTypes() diff --git a/TRRandomizerCore/Processors/TR2/TR2ModelAdjuster.cs b/TRRandomizerCore/Processors/TR2/TR2ModelAdjuster.cs index 98965a120..4143a12f0 100644 --- a/TRRandomizerCore/Processors/TR2/TR2ModelAdjuster.cs +++ b/TRRandomizerCore/Processors/TR2/TR2ModelAdjuster.cs @@ -42,14 +42,11 @@ private void AdjustInstanceModels() return; } - List models = _levelInstance.Data.Models.ToList(); - List sprites = _levelInstance.Data.SpriteSequences.ToList(); - // Point the old models to the new ones, and any matching entities that are instances // of the old model, should also point to the new model type. foreach (TR2Type oldEntity in _modelRemap.Keys) { - TRModel model = models.Find(m => m.ID == (short)oldEntity); + TRModel model = _levelInstance.Data.Models.Find(m => m.ID == (short)oldEntity); if (model != null) { model.ID = (uint)_modelRemap[oldEntity]; @@ -65,7 +62,7 @@ private void AdjustInstanceModels() // Repeat for sprites foreach (TR2Type oldEntity in _spriteRemap.Keys) { - TRSpriteSequence sprite = sprites.Find(s => s.SpriteID == (short)oldEntity); + TRSpriteSequence sprite = _levelInstance.Data.SpriteSequences.Find(s => s.SpriteID == (short)oldEntity); if (sprite != null) { sprite.SpriteID = (short)_spriteRemap[oldEntity]; diff --git a/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs b/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs index f4d855f77..35b17f9a3 100644 --- a/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs +++ b/TRRandomizerCore/Processors/TR3/TR3SequenceProcessor.cs @@ -246,11 +246,10 @@ private static void AmendAntarctica(TR3CombinedLevel level) private void ImportArtefactMenuModels(TR3CombinedLevel level) { - List models = level.Data.Models.ToList(); List imports = new(); foreach (TR3Type artefactMenuModel in TR3TypeUtilities.GetArtefactMenuModels()) { - if (models.Find(m => m.ID == (uint)artefactMenuModel) == null) + if (level.Data.Models.Find(m => m.ID == (uint)artefactMenuModel) == null) { imports.Add(artefactMenuModel); } diff --git a/TRRandomizerCore/Randomizers/TR1/TR1AudioRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1AudioRandomizer.cs index b0e680fa9..44fef9726 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1AudioRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1AudioRandomizer.cs @@ -158,7 +158,7 @@ private void RandomizeSoundEffects(TR1CombinedLevel level) ISet usedSamples = new HashSet(); // Replace each sample but be sure to avoid duplicates - for (int i = 0; i < level.Data.NumSampleIndices; i++) + for (int i = 0; i < level.Data.SampleIndices.Count; i++) { byte[] sample; string id; @@ -177,9 +177,10 @@ private void RandomizeSoundEffects(TR1CombinedLevel level) newSamples.AddRange(sample); } - level.Data.SampleIndices = newSampleIndices.ToArray(); - level.Data.Samples = newSamples.ToArray(); - level.Data.NumSamples = (uint)newSamples.Count; + level.Data.SampleIndices.Clear(); + level.Data.SampleIndices.AddRange(newSampleIndices); + level.Data.Samples.Clear(); + level.Data.Samples.AddRange(newSamples); } else { @@ -259,41 +260,28 @@ private static short ImportSoundEffect(TR1Level level, TR1SFXDefinition definiti // This may result in duplicate WAV data if a sound definition is imported more than // once, but ResortSoundIndices will tidy the data such that only the required WAV // file is retained in the end. - List levelSamples = level.Samples.ToList(); - List levelSampleIndices = level.SampleIndices.ToList(); - - foreach (byte[] sample in definition.SoundData.Samples.Values) - { - levelSampleIndices.Add((uint)levelSamples.Count); - levelSamples.AddRange(sample); - } - newDetails = new TRSoundDetails { Chance = defDetails.Chance, Characteristics = defDetails.Characteristics, - Sample = (ushort)level.SampleIndices.Length, + Sample = (ushort)level.SampleIndices.Count, Volume = defDetails.Volume }; + foreach (byte[] sample in definition.SoundData.Samples.Values) + { + level.SampleIndices.Add((uint)level.Samples.Count); + level.Samples.AddRange(sample); + } + if (category == TRSFXGeneralCategory.StandardWeaponFiring || category == TRSFXGeneralCategory.FastWeaponFiring) { newDetails.LoopingMode = 1; // OneShotRewound } - level.Samples = levelSamples.ToArray(); - level.NumSamples = (uint)levelSamples.Count; - - level.SampleIndices = levelSampleIndices.ToArray(); - level.NumSampleIndices = (uint)levelSampleIndices.Count; - - List levelSoundDetails = level.SoundDetails.ToList(); - levelSoundDetails.Add(newDetails); - level.SoundDetails = levelSoundDetails.ToArray(); - level.NumSoundDetails++; - - return (short)(level.NumSoundDetails - 1); + level.SoundDetails.Add(newDetails); + return (short)(level.SoundDetails.Count - 1); } private void ImportSpeechSFX(TR1CombinedLevel level) diff --git a/TRRandomizerCore/Randomizers/TR1/TR1EnemyRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1EnemyRandomizer.cs index 22fb9fa7f..b4d1c340f 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1EnemyRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1EnemyRandomizer.cs @@ -879,7 +879,7 @@ private static void AmendToQLarson(TR1CombinedLevel level) .ForEach(e => e.TypeID = TR1Type.Raptor); // Make the scion invisible. - TRMesh[] larsonMeshes = TRMeshUtilities.GetModelMeshes(level.Data, larsonModel); + List larsonMeshes = TRMeshUtilities.GetModelMeshes(level.Data, larsonModel); MeshEditor editor = new(); foreach (TRMesh mesh in larsonMeshes) { @@ -961,7 +961,7 @@ private void AmendAtlanteanModels(TR1CombinedLevel level, EnemyRandomizationColl // If we're using flying mummies, add a chance that they'll have proper wings if (enemies.Available.Contains(TR1Type.BandagedFlyer) && _generator.NextDouble() < 0.5) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.FlyingAtlantean); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.FlyingAtlantean); ushort bandageTexture = meshes[1].TexturedRectangles[3].Texture; for (int i = 15; i < 21; i++) { @@ -1141,19 +1141,19 @@ private void RandomizeMeshes(TR1CombinedLevel level, List availableEnem [TR1Type.CassettePlayer_M_H] = 1 }; - TRMesh[] scion = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.ScionPiece4_S_P); + List scion = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.ScionPiece4_S_P); List replacementKeys = scionSwaps.Keys.ToList(); TR1Type replacement = replacementKeys[_generator.Next(0, replacementKeys.Count)]; - TRMesh[] replacementMeshes = TRMeshUtilities.GetModelMeshes(level.Data, replacement); + List replacementMeshes = TRMeshUtilities.GetModelMeshes(level.Data, replacement); int colRadius = scion[0].CollRadius; TRMeshUtilities.DuplicateMesh(level.Data, scion[0], replacementMeshes[scionSwaps[replacement]]); scion[0].CollRadius = colRadius; // Retain original as Lara may need to shoot it // Cutscene head swaps - TRMesh[] lara = TRMeshUtilities.GetModelMeshes(level.CutSceneLevel.Data, TR1Type.CutsceneActor1); - TRMesh[] natla = TRMeshUtilities.GetModelMeshes(level.CutSceneLevel.Data, TR1Type.CutsceneActor3); - TRMesh[] pierre = TRMeshUtilities.GetModelMeshes(level.CutSceneLevel.Data, TR1Type.Pierre); + List lara = TRMeshUtilities.GetModelMeshes(level.CutSceneLevel.Data, TR1Type.CutsceneActor1); + List natla = TRMeshUtilities.GetModelMeshes(level.CutSceneLevel.Data, TR1Type.CutsceneActor3); + List pierre = TRMeshUtilities.GetModelMeshes(level.CutSceneLevel.Data, TR1Type.Pierre); switch (_generator.Next(0, 6)) { @@ -1191,7 +1191,7 @@ private void RandomizeMeshes(TR1CombinedLevel level, List availableEnem if (availableEnemies.Contains(TR1Type.Adam) && _generator.NextDouble() < 0.4) { // Replace Adam's head with a much larger version of Natla's, Larson's or normal/angry Lara's. - TRMesh[] adam = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.Adam); + List adam = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.Adam); TRMesh replacement; if (availableEnemies.Contains(TR1Type.Natla) && _generator.NextDouble() < 0.5) { @@ -1239,9 +1239,9 @@ private void RandomizeMeshes(TR1CombinedLevel level, List availableEnem if (availableEnemies.Contains(TR1Type.Pierre) && _generator.NextDouble() < 0.25) { // Replace Pierre's head with a slightly bigger version of Lara's (either angry Lara or normal Lara) - TRMesh[] pierre = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.Pierre); - TRMesh[] lara = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.Lara); - TRMesh[] laraUziAnim = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraUziAnimation_H); + List pierre = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.Pierre); + List lara = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.Lara); + List laraUziAnim = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraUziAnimation_H); TRMeshUtilities.DuplicateMesh(level.Data, pierre[8], MeshEditor.CloneMesh(_generator.NextDouble() < 0.5 ? laraUziAnim[14] : lara[14])); foreach (TRVertex vertex in pierre[8].Vertices) diff --git a/TRRandomizerCore/Randomizers/TR1/TR1ItemRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1ItemRandomizer.cs index cd02b5125..c425d3068 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1ItemRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1ItemRandomizer.cs @@ -523,12 +523,10 @@ private void RandomizeSprites() } } - _spriteRandomizer.Sequences = _levelInstance.Data.SpriteSequences.ToList(); - _spriteRandomizer.Textures = _levelInstance.Data.SpriteTextures.ToList(); + _spriteRandomizer.Sequences = _levelInstance.Data.SpriteSequences; + _spriteRandomizer.Textures = _levelInstance.Data.SpriteTextures; _spriteRandomizer.Randomize(_generator); - - _levelInstance.Data.SpriteTextures = _spriteRandomizer.Textures.ToArray(); } private static bool IsSecretItem(TR1Entity entity, int entityIndex, TR1Level level, FDControl floorData) diff --git a/TRRandomizerCore/Randomizers/TR1/TR1OutfitRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1OutfitRandomizer.cs index dd4db415f..4db2d5686 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1OutfitRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1OutfitRandomizer.cs @@ -327,7 +327,7 @@ private void ImportBraid(TR1CombinedLevel level) } // Find the texture references for the plain parts of imported hair - TRMesh[] ponytailMeshes = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraPonytail_H_U); + List ponytailMeshes = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraPonytail_H_U); ushort plainHairQuad = ponytailMeshes[0].TexturedRectangles[0].Texture; ushort plainHairTri = ponytailMeshes[5].TexturedTriangles[0].Texture; @@ -343,8 +343,8 @@ private void ImportBraid(TR1CombinedLevel level) foreach (TR1Type laraType in headAmendments.Keys) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, laraType); - if (meshes == null || meshes.Length < 15) + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, laraType); + if (meshes == null || meshes.Count < 15) { continue; } @@ -380,7 +380,7 @@ private static void CreateGoldenBraid(TR1CombinedLevel level) ushort goldPalette = goldenHips.ColouredRectangles[0].Texture; TRModel ponytail = level.Data.Models.Find(m => m.ID == (uint)TR1Type.LaraPonytail_H_U); - TRMesh[] ponytailMeshes = TRMeshUtilities.GetModelMeshes(level.Data, ponytail); + List ponytailMeshes = TRMeshUtilities.GetModelMeshes(level.Data, ponytail); MeshEditor editor = new(); foreach (TRMesh mesh in ponytailMeshes) { @@ -397,7 +397,7 @@ private static void HideEntities(TR1CombinedLevel level, IEnumerable en MeshEditor editor = new(); foreach (TR1Type ent in entities) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, ent); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, ent); if (meshes != null) { foreach (TRMesh mesh in meshes) @@ -494,12 +494,12 @@ private void ConvertToGymOutfit(TR1CombinedLevel level) return; } - TRMesh[] lara = TRMeshUtilities.GetModelMeshes(level.Data, level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara); - TRMesh[] laraPistol = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraPistolAnim_H); - TRMesh[] laraShotgun = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraShotgunAnim_H); - TRMesh[] laraMagnums = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMagnumAnim_H); - TRMesh[] laraUzis = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraUziAnimation_H); - TRMesh[] laraMisc = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMiscAnim_H); + List lara = TRMeshUtilities.GetModelMeshes(level.Data, level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara); + List laraPistol = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraPistolAnim_H); + List laraShotgun = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraShotgunAnim_H); + List laraMagnums = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMagnumAnim_H); + List laraUzis = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraUziAnimation_H); + List laraMisc = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMiscAnim_H); // Basic meshes to take from LaraMiscAnim. We don't replace Lara's gloves // or thighs (at this stage - handled below with gun swaps). @@ -592,7 +592,7 @@ private void ConvertToGymOutfit(TR1CombinedLevel level) byte[] replacementSfx = _outer._barefootSfx[soundID][i]; for (int j = 0; j < replacementSfx.Length; j++) { - level.Data.Samples[samplePointer + j] = replacementSfx[j]; + level.Data.Samples[(int)samplePointer + j] = replacementSfx[j]; } } } @@ -616,9 +616,9 @@ private void ConvertToPartialGymOutfit(TR1CombinedLevel level) return; } - TRMesh[] lara = TRMeshUtilities.GetModelMeshes(level.Data, level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara); - TRMesh[] laraShotgun = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraShotgunAnim_H); - TRMesh[] laraMisc = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMiscAnim_H); + List lara = TRMeshUtilities.GetModelMeshes(level.Data, level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara); + List laraShotgun = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraShotgunAnim_H); + List laraMisc = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMiscAnim_H); // Just the torso TRMeshUtilities.DuplicateMesh(level.Data, lara[7], laraMisc[7]); @@ -675,7 +675,7 @@ private void ConvertToPartialGymOutfit(TR1CombinedLevel level) } } - private static void CreateGoldGymOutfit(TR1CombinedLevel level, TRMesh[] laraMisc, Func cloneBaseFunc) + private static void CreateGoldGymOutfit(TR1CombinedLevel level, List laraMisc, Func cloneBaseFunc) { if (!level.Data.Entities.Any(e => e.TypeID == TR1Type.MidasHand_N)) { @@ -686,7 +686,7 @@ private static void CreateGoldGymOutfit(TR1CombinedLevel level, TRMesh[] laraMis .FindClosest(_midasGoldColour, 1); MeshEditor editor = new(); - for (int i = 0; i < laraMisc.Length; i++) + for (int i = 0; i < laraMisc.Count; i++) { TRMesh mesh = laraMisc[i]; TRMeshUtilities.DuplicateMesh(level.Data, mesh, MeshEditor.CloneMesh(cloneBaseFunc(i))); @@ -721,7 +721,7 @@ private bool ImportGymOutfit(TR1CombinedLevel level) if (existingModel != null) { // If we already have the gym outfit available, we're done. - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, existingModel); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, existingModel); if (meshes.ComputeSkeletonHash() == _gymOutfitHash) { return true; @@ -854,9 +854,9 @@ private static void CopyMeshParts(TR1Level level, MeshCopyData data) private void ConvertToMauledOutfit(TR1CombinedLevel level) { - TRMesh[] lara = TRMeshUtilities.GetModelMeshes(level.Data, level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara); - TRMesh[] laraShotgun = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraShotgunAnim_H); - TRMesh[] laraMisc = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMiscAnim_H); + List lara = TRMeshUtilities.GetModelMeshes(level.Data, level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara); + List laraShotgun = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraShotgunAnim_H); + List laraMisc = TRMeshUtilities.GetModelMeshes(level.Data, TR1Type.LaraMiscAnim_H); if (level.Is(TR1LevelNames.QUALOPEC_CUT)) { @@ -912,7 +912,7 @@ private void ConvertToMauledOutfit(TR1CombinedLevel level) }; foreach (TR1Type gunAnimType in gunAnims) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, gunAnimType); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, gunAnimType); if (meshes == null) continue; diff --git a/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs b/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs index b188251d8..e99871786 100644 --- a/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR1/TR1SecretRandomizer.cs @@ -867,8 +867,6 @@ protected override void ProcessImpl() importer.Import(); - List sequences = level.Data.SpriteSequences.ToList(); - // Redefine the artefacts as puzzle models foreach (TR1Type secretModelType in allocation.ImportModels) { @@ -878,7 +876,7 @@ protected override void ProcessImpl() TR1Type puzzlePickupType = _modelReplacements[puzzleModelType]; level.Data.Models.Find(m => m.ID == (uint)secretModelType).ID = (uint)puzzleModelType; - sequences.Find(s => s.SpriteID == (int)secretPickupType).SpriteID = (int)puzzlePickupType; + level.Data.SpriteSequences.Find(s => s.SpriteID == (int)secretPickupType).SpriteID = (int)puzzlePickupType; if (secretModelType == TR1Type.SecretScion_M_H && _outer.Are3DPickupsEnabled()) { diff --git a/TRRandomizerCore/Randomizers/TR2/TR2AudioRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/TR2AudioRandomizer.cs index 6c17b3515..37ce02f4f 100644 --- a/TRRandomizerCore/Randomizers/TR2/TR2AudioRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/TR2AudioRandomizer.cs @@ -211,12 +211,13 @@ private void RandomizeSoundEffects(TR2CombinedLevel level) if (IsUncontrolledLevel(level.Script)) { // Choose a random sample for each current entry and replace the entire index list. - ISet indices = new HashSet(); - while (indices.Count < level.Data.NumSampleIndices) + HashSet indices = new(); + while (indices.Count < level.Data.SampleIndices.Count) { indices.Add((uint)_generator.Next(0, _maxSample + 1)); } - level.Data.SampleIndices = indices.ToArray(); + level.Data.SampleIndices.Clear(); + level.Data.SampleIndices.AddRange(indices); } else { @@ -280,29 +281,18 @@ private static short ImportSoundEffect(TR2Level level, TRSFXDefinition levelSamples = level.SampleIndices.ToList(); List levelSoundDetails = level.SoundDetails.ToList(); uint minSample = definition.SampleIndices.Min(); - if (levelSamples.Contains(minSample)) + if (level.SampleIndices.Contains(minSample)) { - // This index is already defined, so locate the TRSoundDetails that references it - // and return its index. - return (short)levelSoundDetails.FindIndex(d => levelSamples[d.Sample] == minSample); + return (short)levelSoundDetails.FindIndex(d => level.SampleIndices[d.Sample] == minSample); } - // Otherwise, we need to import the samples, create a sound details object to - // point to the first sample, and then return the new index. Make sure the - // samples are sorted first. - ushort newSampleIndex = (ushort)levelSamples.Count; - List sortedSamples = new(definition.SampleIndices); - sortedSamples.Sort(); - levelSamples.AddRange(sortedSamples); + ushort newSampleIndex = (ushort)level.SampleIndices.Count; + level.SampleIndices.AddRange(definition.SampleIndices); - level.SampleIndices = levelSamples.ToArray(); - level.NumSampleIndices = (uint)levelSamples.Count; - - levelSoundDetails.Add(new TRSoundDetails + level.SoundDetails.Add(new TRSoundDetails { Chance = definition.Details.Chance, Characteristics = definition.Details.Characteristics, @@ -310,10 +300,7 @@ private static short ImportSoundEffect(TR2Level level, TRSFXDefinition levelModels = level.Data.Models.ToList(); if (laraClones.Count > 0) { - TRModel laraModel = levelModels.Find(m => m.ID == (uint)TR2Type.Lara); + TRModel laraModel = level.Data.Models.Find(m => m.ID == (uint)TR2Type.Lara); foreach (TR2Type enemyType in laraClones) { - TRModel enemyModel = levelModels.Find(m => m.ID == (uint)enemyType); + TRModel enemyModel = level.Data.Models.Find(m => m.ID == (uint)enemyType); enemyModel.MeshTree = laraModel.MeshTree; enemyModel.StartingMesh = laraModel.StartingMesh; enemyModel.NumMeshes = laraModel.NumMeshes; @@ -951,8 +950,8 @@ private void RandomizeEnemyMeshes(TR2CombinedLevel level, EnemyRandomizationColl && _generator.Next(0, chance) == 0) { // Make Marco look and behave like Winston, until Lara gets too close - TRModel marcoModel = levelModels.Find(m => m.ID == (uint)TR2Type.MarcoBartoli); - TRModel winnieModel = levelModels.Find(m => m.ID == (uint)TR2Type.Winston); + TRModel marcoModel = level.Data.Models.Find(m => m.ID == (uint)TR2Type.MarcoBartoli); + TRModel winnieModel = level.Data.Models.Find(m => m.ID == (uint)TR2Type.Winston); marcoModel.Animation = winnieModel.Animation; marcoModel.FrameOffset = winnieModel.FrameOffset; marcoModel.MeshTree = winnieModel.MeshTree; diff --git a/TRRandomizerCore/Randomizers/TR2/TR2ItemRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/TR2ItemRandomizer.cs index 7f9aadb43..d5abc385d 100644 --- a/TRRandomizerCore/Randomizers/TR2/TR2ItemRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/TR2ItemRandomizer.cs @@ -185,14 +185,11 @@ private void RandomizeSprites() // The _spriteRandomizer exists so it gets all the SpriteSquence and SpriteTexture from the level // We cannot pass the level itself as ItemSpriteRandomizer is a shared class - _spriteRandomizer.Sequences = _levelInstance.Data.SpriteSequences.ToList(); - _spriteRandomizer.Textures = _levelInstance.Data.SpriteTextures.ToList(); + _spriteRandomizer.Sequences = _levelInstance.Data.SpriteSequences; + _spriteRandomizer.Textures = _levelInstance.Data.SpriteTextures; //Calling the actual randomization _spriteRandomizer.Randomize(_generator); - - // Only the SpriteTexture needs to be rewritten - _levelInstance.Data.SpriteTextures = _spriteRandomizer.Textures.ToArray(); } public void RandomizeItemLocations(TR2CombinedLevel level) diff --git a/TRRandomizerCore/Randomizers/TR2/TR2OutfitRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/TR2OutfitRandomizer.cs index 3edb9545f..af84f0bc5 100644 --- a/TRRandomizerCore/Randomizers/TR2/TR2OutfitRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/TR2OutfitRandomizer.cs @@ -229,9 +229,8 @@ protected override void ProcessImpl() private bool Import(TR2CombinedLevel level, TR2Type lara) { - List models = level.Data.Models.ToList(); - TRModel laraModel = models.Find(m => m.ID == (uint)TR2Type.Lara); - List laraClones = models.FindAll(m => m.MeshTree == laraModel.MeshTree && m != laraModel); + TRModel laraModel = level.Data.Models.Find(m => m.ID == (uint)TR2Type.Lara); + List laraClones = level.Data.Models.FindAll(m => m.MeshTree == laraModel.MeshTree && m != laraModel); if (lara == TR2Type.LaraInvisible) { @@ -276,8 +275,7 @@ private bool Import(TR2CombinedLevel level, TR2Type lara) // #314 Any clones of Lara should copy her new style if (laraClones.Count > 0) { - models = level.Data.Models.ToList(); - laraModel = models.Find(m => m.ID == (uint)TR2Type.Lara); + laraModel = level.Data.Models.Find(m => m.ID == (uint)TR2Type.Lara); foreach (TRModel model in laraClones) { model.MeshTree = laraModel.MeshTree; @@ -311,9 +309,9 @@ private static void CloneLaraMeshes(TR2CombinedLevel level, List clones { if (clones.Count > 0) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, laraModel); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, laraModel); int firstMeshIndex = -1; - for (int i = 0; i < meshes.Length; i++) + for (int i = 0; i < meshes.Count; i++) { int insertedIndex = TRMeshUtilities.InsertMesh(level.Data, MeshEditor.CloneMesh(meshes[i])); if (firstMeshIndex == -1) @@ -334,7 +332,7 @@ private static void HideEntities(TR2CombinedLevel level, IEnumerable en MeshEditor editor = new(); foreach (TR2Type ent in entities) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, ent); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, ent); if (meshes != null) { foreach (TRMesh mesh in meshes) @@ -420,9 +418,8 @@ private void AdjustOutfit(TR2CombinedLevel level, TR2Type lara) // into the diving suit, but model ID 99 is the one before. We always want the cutscene actor to // match DA, but this unfortunately means she'll leave the cutscene in the same outfit. She just // didn't like the look of any of the alternatives... - List models = level.Data.Models.ToList(); - TRModel actorLara = models.Find(m => m.ID == (short)TR2Type.CutsceneActor3); - TRModel realLara = models.Find(m => m.ID == (short)TR2Type.Lara); + TRModel actorLara = level.Data.Models.Find(m => m.ID == (short)TR2Type.CutsceneActor3); + TRModel realLara = level.Data.Models.Find(m => m.ID == (short)TR2Type.Lara); actorLara.MeshTree = realLara.MeshTree; actorLara.NumMeshes = realLara.NumMeshes; diff --git a/TRRandomizerCore/Randomizers/TR2/TR2SecretRandomizer.cs b/TRRandomizerCore/Randomizers/TR2/TR2SecretRandomizer.cs index 3a1b20eb7..5caf958ed 100644 --- a/TRRandomizerCore/Randomizers/TR2/TR2SecretRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2/TR2SecretRandomizer.cs @@ -185,10 +185,10 @@ private static void FixSecretTextures(TR2CombinedLevel level) // Swap Stone and Jade textures - OG has them the wrong way around. // SpriteSequence offsets have to remain in order, so swap the texture targets instead. - TRSpriteSequence stoneSequence = Array.Find(level.Data.SpriteSequences, s => s.SpriteID == (int)TR2Type.StoneSecret_S_P); - TRSpriteSequence jadeSequence = Array.Find(level.Data.SpriteSequences, s => s.SpriteID == (int)TR2Type.JadeSecret_S_P); + TRSpriteSequence stoneSequence = level.Data.SpriteSequences.Find(s => s.SpriteID == (int)TR2Type.StoneSecret_S_P); + TRSpriteSequence jadeSequence = level.Data.SpriteSequences.Find(s => s.SpriteID == (int)TR2Type.JadeSecret_S_P); - TRSpriteTexture[] textures = level.Data.SpriteTextures; + List textures = level.Data.SpriteTextures; (textures[jadeSequence.Offset], textures[stoneSequence.Offset]) = (textures[stoneSequence.Offset], textures[jadeSequence.Offset]); } diff --git a/TRRandomizerCore/Randomizers/TR2R/TR2RAudioRandomizer.cs b/TRRandomizerCore/Randomizers/TR2R/TR2RAudioRandomizer.cs index ae13be06b..6bfbc82f8 100644 --- a/TRRandomizerCore/Randomizers/TR2R/TR2RAudioRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR2R/TR2RAudioRandomizer.cs @@ -189,11 +189,12 @@ private void RandomizeSoundEffects(TR2RCombinedLevel level) if (IsUncontrolledLevel(level.Script)) { HashSet indices = new(); - while (indices.Count < level.Data.NumSampleIndices) + while (indices.Count < level.Data.SampleIndices.Count) { indices.Add((uint)_generator.Next(0, _maxSample + 1)); } - level.Data.SampleIndices = indices.ToArray(); + level.Data.SampleIndices.Clear(); + level.Data.SampleIndices.AddRange(indices); } else { @@ -246,24 +247,18 @@ private static short ImportSoundEffect(TR2Level level, TRSFXDefinition levelSamples = level.SampleIndices.ToList(); List levelSoundDetails = level.SoundDetails.ToList(); uint minSample = definition.SampleIndices.Min(); - if (levelSamples.Contains(minSample)) + if (level.SampleIndices.Contains(minSample)) { - return (short)levelSoundDetails.FindIndex(d => levelSamples[d.Sample] == minSample); + return (short)levelSoundDetails.FindIndex(d => level.SampleIndices[d.Sample] == minSample); } - ushort newSampleIndex = (ushort)levelSamples.Count; - List sortedSamples = new(definition.SampleIndices); - sortedSamples.Sort(); - levelSamples.AddRange(sortedSamples); + ushort newSampleIndex = (ushort)level.SampleIndices.Count; + level.SampleIndices.AddRange(definition.SampleIndices); - level.SampleIndices = levelSamples.ToArray(); - level.NumSampleIndices = (uint)levelSamples.Count; - - levelSoundDetails.Add(new TRSoundDetails + level.SoundDetails.Add(new TRSoundDetails { Chance = definition.Details.Chance, Characteristics = definition.Details.Characteristics, @@ -271,10 +266,7 @@ private static short ImportSoundEffect(TR2Level level, TRSFXDefinition indices = new HashSet(); - while (indices.Count < level.Data.NumSampleIndices) + HashSet indices = new(); + while (indices.Count < level.Data.SampleIndices.Count) { indices.Add((uint)_generator.Next(0, _maxSample + 1)); } - level.Data.SampleIndices = indices.ToArray(); + level.Data.SampleIndices.Clear(); + level.Data.SampleIndices.AddRange(indices); } else { @@ -243,31 +244,18 @@ private static short ImportSoundEffect(TR3Level level, TRSFXDefinition levelSamples = level.SampleIndices.ToList(); List levelSoundDetails = level.SoundDetails.ToList(); uint minSample = newDefinition.SampleIndices.Min(); - if (levelSamples.Contains(minSample)) + if (level.SampleIndices.Contains(minSample)) { - // This index is already defined, so locate the TRSoundDetails that references it - // and return its index. - return (short)levelSoundDetails.FindIndex(d => levelSamples[d.Sample] == minSample); + return (short)levelSoundDetails.FindIndex(d => level.SampleIndices[d.Sample] == minSample); } - // Otherwise, we need to import the samples, create a sound details object to - // point to the first sample, and then return the new index. Make sure the - // samples are sorted first. - ushort newSampleIndex = (ushort)levelSamples.Count; - List sortedSamples = new(newDefinition.SampleIndices); - sortedSamples.Sort(); - levelSamples.AddRange(sortedSamples); + ushort newSampleIndex = (ushort)level.SampleIndices.Count; + level.SampleIndices.AddRange(newDefinition.SampleIndices); - level.SampleIndices = levelSamples.ToArray(); - level.NumSampleIndices = (uint)levelSamples.Count; - - // Make a new details object, but make sure to use the same chance as the current definition otherwise the - // likes of the Coastal Village "Sheila" guy will say "Hey" continuously. - levelSoundDetails.Add(new TR3SoundDetails + level.SoundDetails.Add(new TR3SoundDetails { Chance = currentDefinition.Details.Chance, Characteristics = newDefinition.Details.Characteristics, @@ -277,10 +265,7 @@ private static short ImportSoundEffect(TR3Level level, TRSFXDefinition en MeshEditor editor = new(); foreach (TR3Type ent in entities) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level.Data, ent); + List meshes = TRMeshUtilities.GetModelMeshes(level.Data, ent); if (meshes != null) { foreach (TRMesh mesh in meshes) diff --git a/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs b/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs index 1b0f402e7..2f3b99705 100644 --- a/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3/TR3SecretRandomizer.cs @@ -762,15 +762,13 @@ protected override void StartImpl() // We exclude artefacts from import if this level already has an // actual artefact model, and we exclude current puzzle/key items // from the available switching pool. - List models = level.Data.Models.ToList(); - if (level.Is(TR3LevelNames.CRASH)) { // Special case for Crash Site, which is the only level that uses Quest1 (the swamp map). // We want to reallocate this as a key to allow us to reuse Quest1 on import. Amend the // models to become Key3 and update the script to match. - models.Find(m => m.ID == (uint)TR3Type.Quest1_P).ID = (uint)TR3Type.Key3_P; - models.Find(m => m.ID == (uint)TR3Type.Quest1_M_H).ID = (uint)TR3Type.Key3_M_H; + level.Data.Models.Find(m => m.ID == (uint)TR3Type.Quest1_P).ID = (uint)TR3Type.Key3_P; + level.Data.Models.Find(m => m.ID == (uint)TR3Type.Quest1_M_H).ID = (uint)TR3Type.Key3_M_H; level.Script.Keys[2] = level.Script.Pickups[0]; level.Script.SetStartInventoryItems(new Dictionary { @@ -780,7 +778,7 @@ protected override void StartImpl() foreach (TR3Type puzzleType in _artefactReplacements.Keys) { - if (models.Find(m => m.ID == (uint)puzzleType) == null) + if (level.Data.Models.Find(m => m.ID == (uint)puzzleType) == null) { allocation.AvailablePickupModels.Add(puzzleType); } @@ -790,7 +788,7 @@ protected override void StartImpl() for (int i = artefactTypes.Count - 1; i >= 0; i--) { TR3Type artefactType = artefactTypes[i]; - if (models.Find(m => m.ID == (uint)artefactType) != null) + if (level.Data.Models.Find(m => m.ID == (uint)artefactType) != null) { artefactTypes.RemoveAt(i); } diff --git a/TRRandomizerCore/Randomizers/TR3R/TR3RAudioRandomizer.cs b/TRRandomizerCore/Randomizers/TR3R/TR3RAudioRandomizer.cs index 475fc2951..9351490b7 100644 --- a/TRRandomizerCore/Randomizers/TR3R/TR3RAudioRandomizer.cs +++ b/TRRandomizerCore/Randomizers/TR3R/TR3RAudioRandomizer.cs @@ -149,11 +149,12 @@ private void RandomizeSoundEffects(TR3RCombinedLevel level) if (IsUncontrolledLevel(level.Script)) { HashSet indices = new(); - while (indices.Count < level.Data.NumSampleIndices) + while (indices.Count < level.Data.SampleIndices.Count) { indices.Add((uint)_generator.Next(0, _maxSample + 1)); } - level.Data.SampleIndices = indices.ToArray(); + level.Data.SampleIndices.Clear(); + level.Data.SampleIndices.AddRange(indices); } else { @@ -206,24 +207,18 @@ private static short ImportSoundEffect(TR3Level level, TRSFXDefinition levelSamples = level.SampleIndices.ToList(); List levelSoundDetails = level.SoundDetails.ToList(); uint minSample = newDefinition.SampleIndices.Min(); - if (levelSamples.Contains(minSample)) + if (level.SampleIndices.Contains(minSample)) { - return (short)levelSoundDetails.FindIndex(d => levelSamples[d.Sample] == minSample); + return (short)levelSoundDetails.FindIndex(d => level.SampleIndices[d.Sample] == minSample); } - ushort newSampleIndex = (ushort)levelSamples.Count; - List sortedSamples = new(newDefinition.SampleIndices); - sortedSamples.Sort(); - levelSamples.AddRange(sortedSamples); + ushort newSampleIndex = (ushort)level.SampleIndices.Count; + level.SampleIndices.AddRange(newDefinition.SampleIndices); - level.SampleIndices = levelSamples.ToArray(); - level.NumSampleIndices = (uint)levelSamples.Count; - - levelSoundDetails.Add(new TR3SoundDetails + level.SoundDetails.Add(new TR3SoundDetails { Chance = currentDefinition.Details.Chance, Characteristics = newDefinition.Details.Characteristics, @@ -233,10 +228,7 @@ private static short ImportSoundEffect(TR3Level level, TRSFXDefinition s.Offset == sprite.Texture + if (level.Data.SpriteSequences.Find(s => s.Offset == sprite.Texture && level.Data.Entities.Find(e => e.TypeID == (TR1Type)s.SpriteID) != null) == null) { defaultSpriteTextures.Add(sprite.Texture); @@ -156,7 +156,7 @@ public DynamicTextureTarget Build(TR1CombinedLevel level) // textures from the same animation list. foreach (int texture in defaultObjectTextures.ToList()) { - TRAnimatedTexture anim = Array.Find(level.Data.AnimatedTextures, a => a.Textures.Contains((ushort)texture)); + TRAnimatedTexture anim = level.Data.AnimatedTextures.Find(a => a.Textures.Contains((ushort)texture)); if (anim != null) { foreach (ushort animTexture in anim.Textures) @@ -245,7 +245,7 @@ private void AddModelTextures(TR1Level level, TRModel model, TRMesh dummyMesh, I return; } - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(level, model); + List meshes = TRMeshUtilities.GetModelMeshes(level, model); List excludedMeshes = new() { dummyMesh }; if (modelID == TR1Type.Adam) @@ -272,7 +272,7 @@ private void AddModelTextures(TR1Level level, TRModel model, TRMesh dummyMesh, I } } else if ((modelID == TR1Type.ScionPiece3_S_P || modelID == TR1Type.ScionPiece4_S_P) - && meshes.Length == 1 && meshes[0].NumNormals != 123) + && meshes.Count == 1 && meshes[0].NumNormals != 123) { try { @@ -329,7 +329,6 @@ private void DuplicateMeshTextures(TR1Level level, TRMesh mesh) packer.Pack(true); // Map the packed segments to object textures. - List levelObjectTextures = level.ObjectTextures.ToList(); Queue reusableIndices = new(level.GetInvalidObjectTextureIndices()); Dictionary reindex = new(); foreach (TexturedTileSegment segment in duplicates) @@ -345,12 +344,12 @@ private void DuplicateMeshTextures(TR1Level level, TRMesh mesh) if (reusableIndices.Count > 0) { newIndex = reusableIndices.Dequeue(); - levelObjectTextures[newIndex] = objTexture.Texture; + level.ObjectTextures[newIndex] = objTexture.Texture; } - else if (levelObjectTextures.Count < maximumObjects) + else if (level.ObjectTextures.Count < maximumObjects) { - levelObjectTextures.Add(objTexture.Texture); - newIndex = levelObjectTextures.Count - 1; + level.ObjectTextures.Add(objTexture.Texture); + newIndex = level.ObjectTextures.Count - 1; } else { @@ -371,8 +370,6 @@ private void DuplicateMeshTextures(TR1Level level, TRMesh mesh) f.Texture = (ushort)reindex[f.Texture]; } - level.ObjectTextures = levelObjectTextures.ToArray(); - level.NumObjectTextures = (uint)levelObjectTextures.Count; level.ResetUnusedTextures(); } @@ -386,7 +383,7 @@ private static void AddMeshTextures(TRMesh mesh, ISet textures) private static void AddSpriteTextures(TR1Level level, TR1Type spriteID, ISet textures) { - TRSpriteSequence sequence = Array.Find(level.SpriteSequences, s => s.SpriteID == (int)spriteID); + TRSpriteSequence sequence = level.SpriteSequences.Find(s => s.SpriteID == (int)spriteID); if (sequence != null) { for (int i = 0; i < sequence.NegativeLength * -1; i++) diff --git a/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs b/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs index e393a3ec0..55d3ce26c 100644 --- a/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs +++ b/TRRandomizerCore/Textures/Landmarks/AbstractLandmarkImporter.cs @@ -20,8 +20,7 @@ public abstract class AbstractLandmarkImporter protected abstract int MaxTextures { get; } protected abstract AbstractTexturePacker CreatePacker(L level); - protected abstract TRObjectTexture[] GetObjectTextures(L level); - protected abstract void SetObjectTextures(L level, IEnumerable textures); + protected abstract List GetObjectTextures(L level); protected abstract void SetRoomTexture(L level, int roomIndex, int rectangleIndex, ushort textureIndex); protected abstract short? GetRoomFromPortal(L level, PortalSector portalSector, bool isLevelMirrored); @@ -31,7 +30,7 @@ public bool Import(L level, AbstractTextureMapping mapping, bool isLevelMi mapping.CommitGraphics(); // If we are already at the maximum number of textures, bail out. - List textures = GetObjectTextures(level).ToList(); + List textures = GetObjectTextures(level); if (textures.Count == MaxTextures) { return false; @@ -164,8 +163,6 @@ public bool Import(L level, AbstractTextureMapping mapping, bool isLevelMi } } - SetObjectTextures(level, textures); - return true; } catch (PackingException) diff --git a/TRRandomizerCore/Textures/Landmarks/TR1LandmarkImporter.cs b/TRRandomizerCore/Textures/Landmarks/TR1LandmarkImporter.cs index d85f97343..9bfb42e14 100644 --- a/TRRandomizerCore/Textures/Landmarks/TR1LandmarkImporter.cs +++ b/TRRandomizerCore/Textures/Landmarks/TR1LandmarkImporter.cs @@ -14,17 +14,11 @@ protected override AbstractTexturePacker CreatePacker(TR1Leve return new TR1TexturePacker(level); } - protected override TRObjectTexture[] GetObjectTextures(TR1Level level) + protected override List GetObjectTextures(TR1Level level) { return level.ObjectTextures; } - protected override void SetObjectTextures(TR1Level level, IEnumerable textures) - { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)level.ObjectTextures.Length; - } - protected override void SetRoomTexture(TR1Level level, int roomIndex, int rectangleIndex, ushort textureIndex) { level.Rooms[roomIndex].RoomData.Rectangles[rectangleIndex].Texture = textureIndex; diff --git a/TRRandomizerCore/Textures/Landmarks/TR2LandmarkImporter.cs b/TRRandomizerCore/Textures/Landmarks/TR2LandmarkImporter.cs index ad60c168b..b801930ea 100644 --- a/TRRandomizerCore/Textures/Landmarks/TR2LandmarkImporter.cs +++ b/TRRandomizerCore/Textures/Landmarks/TR2LandmarkImporter.cs @@ -14,17 +14,11 @@ protected override AbstractTexturePacker CreatePacker(TR2Leve return new TR2TexturePacker(level); } - protected override TRObjectTexture[] GetObjectTextures(TR2Level level) + protected override List GetObjectTextures(TR2Level level) { return level.ObjectTextures; } - protected override void SetObjectTextures(TR2Level level, IEnumerable textures) - { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)level.ObjectTextures.Length; - } - protected override void SetRoomTexture(TR2Level level, int roomIndex, int rectangleIndex, ushort textureIndex) { level.Rooms[roomIndex].RoomData.Rectangles[rectangleIndex].Texture = textureIndex; diff --git a/TRRandomizerCore/Textures/Landmarks/TR3LandmarkImporter.cs b/TRRandomizerCore/Textures/Landmarks/TR3LandmarkImporter.cs index c9a1bdb34..b62fc588e 100644 --- a/TRRandomizerCore/Textures/Landmarks/TR3LandmarkImporter.cs +++ b/TRRandomizerCore/Textures/Landmarks/TR3LandmarkImporter.cs @@ -14,17 +14,11 @@ protected override AbstractTexturePacker CreatePacker(TR3Leve return new TR3TexturePacker(level); } - protected override TRObjectTexture[] GetObjectTextures(TR3Level level) + protected override List GetObjectTextures(TR3Level level) { return level.ObjectTextures; } - protected override void SetObjectTextures(TR3Level level, IEnumerable textures) - { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)level.ObjectTextures.Length; - } - protected override void SetRoomTexture(TR3Level level, int roomIndex, int rectangleIndex, ushort textureIndex) { level.Rooms[roomIndex].RoomData.Rectangles[rectangleIndex].Texture = textureIndex; diff --git a/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs b/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs index cab1f5cea..39f296489 100644 --- a/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/AbstractTRWireframer.cs @@ -102,7 +102,7 @@ public void Apply(L level, WireframeData data) packer.Pack(true); Queue reusableTextures = new(GetInvalidObjectTextureIndices(level)); - List levelObjectTextures = GetObjectTextures(level).ToList(); + List levelObjectTextures = GetObjectTextures(level); ushort roomTextureIndex = (ushort)reusableTextures.Dequeue(); levelObjectTextures[roomTextureIndex] = roomTexture.Texture; @@ -134,8 +134,6 @@ public void Apply(L level, WireframeData data) } } - SetObjectTextures(level, levelObjectTextures); - ResetRoomTextures(roomTextureIndex, ladderTextureIndex, triggerTextureIndex, deathTextureIndex, specialTextureRemap); ResetMeshTextures(modelRemap, specialTextureRemap); TidyModels(level); @@ -145,8 +143,8 @@ public void Apply(L level, WireframeData data) private void RetainCustomTextures(L level) { - TRObjectTexture[] textures = GetObjectTextures(level); - for (ushort i = 0; i < textures.Length; i++) + List textures = GetObjectTextures(level); + for (ushort i = 0; i < textures.Count; i++) { if (textures[i].Attribute == (ushort)TRBlendingMode.Unused01) { @@ -355,7 +353,7 @@ private void ProcessClips(AbstractTexturePacker packer, L level, Pen pen, { // Some animated textures are shared in segments e.g. 4 32x32 segments within a 64x64 container, // so in instances where we only want to wireframe a section of these, we use manual clipping. - TRObjectTexture[] textures = GetObjectTextures(level); + List textures = GetObjectTextures(level); foreach (WireframeClip clip in _data.ManualClips) { BitmapGraphics frame = CreateFrame(clip.Clip.Width, clip.Clip.Height, pen, mode, true); @@ -681,37 +679,24 @@ private void SetFace3Colours(IEnumerable faces, int colourIndex) private void DeleteAnimatedTextures(L level) { - List animatedTextures = GetAnimatedTextures(level).ToList(); + List animatedTextures = GetAnimatedTextures(level); for (int i = animatedTextures.Count - 1; i >= 0; i--) { TRAnimatedTexture animatedTexture = animatedTextures[i]; - List textures = animatedTexture.Textures.ToList(); - for (int j = textures.Count - 1; j >= 0; j--) + for (int j = animatedTexture.Textures.Count - 1; j >= 0; j--) { - if (!IsTextureExcluded(textures[j])) + if (!IsTextureExcluded(animatedTexture.Textures[j])) { - textures.RemoveAt(j); + animatedTexture.Textures.RemoveAt(j); } } - if (textures.Count < 2) + if (animatedTexture.Textures.Count < 2) { animatedTextures.RemoveAt(i); } - else - { - animatedTexture.Textures = textures.ToArray(); - } } - - int length = 1; - foreach (TRAnimatedTexture animatedTexture in animatedTextures) - { - length += animatedTexture.NumTextures + 2; - } - - SetAnimatedTextures(level, animatedTextures.ToArray(), (ushort)length); } protected abstract Dictionary> CollectLadders(L level); @@ -722,14 +707,12 @@ private void DeleteAnimatedTextures(L level) protected abstract IEnumerable> GetRoomFace3s(L level); protected abstract void ResetUnusedTextures(L level); protected abstract IEnumerable GetInvalidObjectTextureIndices(L level); - protected abstract TRObjectTexture[] GetObjectTextures(L level); - protected abstract void SetObjectTextures(L level, IEnumerable textures); - protected abstract Dictionary GetModelMeshes(L level); + protected abstract List GetObjectTextures(L level); protected abstract int GetBlackPaletteIndex(L level); protected abstract int ImportColour(L level, Color c); protected abstract List GetModels(L level); - protected abstract TRMesh[] GetModelMeshes(L level, TRModel model); - protected abstract TRMesh[] GetLevelMeshes(L level); + protected abstract List GetModelMeshes(L level, TRModel model); + protected abstract List GetLevelMeshes(L level); protected abstract List GetStaticMeshes(L level); protected abstract TRMesh GetStaticMesh(L level, TRStaticMesh staticMesh); protected abstract bool IsSkybox(TRModel model); @@ -739,8 +722,7 @@ private void DeleteAnimatedTextures(L level) protected abstract bool IsInteractableModel(TRModel model); protected virtual bool ShouldSolidifyModel(TRModel model) => false; protected abstract void SetSkyboxVisible(L level); - protected abstract TRAnimatedTexture[] GetAnimatedTextures(L level); - protected abstract void SetAnimatedTextures(L level, TRAnimatedTexture[] animatedTextures, ushort length); + protected abstract List GetAnimatedTextures(L level); public virtual bool Is8BitPalette { get; } protected virtual void ResetPaletteTracking(L level) { } diff --git a/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs index f638798a7..52567f0b5 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR1Wireframer.cs @@ -86,26 +86,12 @@ protected override IEnumerable GetInvalidObjectTextureIndices(TR1Level leve return level.GetInvalidObjectTextureIndices(); } - protected override TRMesh[] GetLevelMeshes(TR1Level level) + protected override List GetLevelMeshes(TR1Level level) { return level.Meshes; } - protected override Dictionary GetModelMeshes(TR1Level level) - { - Dictionary modelMeshes = new(); - foreach (TRModel model in level.Models) - { - TRMesh[] meshes = GetModelMeshes(level, model); - if (meshes != null) - { - modelMeshes[(TR1Type)model.ID] = meshes; - } - } - return modelMeshes; - } - - protected override TRMesh[] GetModelMeshes(TR1Level level, TRModel model) + protected override List GetModelMeshes(TR1Level level, TRModel model) { return TRMeshUtilities.GetModelMeshes(level, model); } @@ -115,7 +101,7 @@ protected override List GetModels(TR1Level level) return level.Models; } - protected override TRObjectTexture[] GetObjectTextures(TR1Level level) + protected override List GetObjectTextures(TR1Level level) { return level.ObjectTextures; } @@ -183,12 +169,6 @@ protected override void ResetUnusedTextures(TR1Level level) level.ResetUnusedTextures(); } - protected override void SetObjectTextures(TR1Level level, IEnumerable textures) - { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)level.ObjectTextures.Length; - } - protected override void SetSkyboxVisible(TR1Level level) { } protected override Dictionary> CollectLadders(TR1Level level) @@ -206,17 +186,11 @@ protected override List CollectDeathFaces(TR1Level level) return FaceUtilities.GetTriggerFaces(level, new List(), true); } - protected override TRAnimatedTexture[] GetAnimatedTextures(TR1Level level) + protected override List GetAnimatedTextures(TR1Level level) { return level.AnimatedTextures; } - protected override void SetAnimatedTextures(TR1Level level, TRAnimatedTexture[] animatedTextures, ushort length) - { - level.AnimatedTextures = animatedTextures; - level.NumAnimatedTextures = length; - } - protected override Dictionary CreateSpecialSegments(TR1Level level, Pen pen) { Dictionary segments = new(); diff --git a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs index 3f350729a..b7f50609d 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR2Wireframer.cs @@ -58,36 +58,22 @@ protected override IEnumerable GetInvalidObjectTextureIndices(TR2Level leve return level.GetInvalidObjectTextureIndices(); } - protected override TRMesh[] GetLevelMeshes(TR2Level level) + protected override List GetLevelMeshes(TR2Level level) { return level.Meshes; } - protected override Dictionary GetModelMeshes(TR2Level level) - { - Dictionary modelMeshes = new(); - foreach (TRModel model in level.Models) - { - TRMesh[] meshes = GetModelMeshes(level, model); - if (meshes != null) - { - modelMeshes[(TR2Type)model.ID] = meshes; - } - } - return modelMeshes; - } - - protected override TRMesh[] GetModelMeshes(TR2Level level, TRModel model) + protected override List GetModelMeshes(TR2Level level, TRModel model) { return TRMeshUtilities.GetModelMeshes(level, model); } protected override List GetModels(TR2Level level) { - return level.Models.ToList(); + return level.Models; } - protected override TRObjectTexture[] GetObjectTextures(TR2Level level) + protected override List GetObjectTextures(TR2Level level) { return level.ObjectTextures; } @@ -144,12 +130,6 @@ protected override void ResetUnusedTextures(TR2Level level) level.ResetUnusedTextures(); } - protected override void SetObjectTextures(TR2Level level, IEnumerable textures) - { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)level.ObjectTextures.Length; - } - protected override void SetSkyboxVisible(TR2Level level) { foreach (TR2Room room in level.Rooms) @@ -173,14 +153,8 @@ protected override List CollectDeathFaces(TR2Level level) return FaceUtilities.GetTriggerFaces(level, new List(), true); } - protected override TRAnimatedTexture[] GetAnimatedTextures(TR2Level level) + protected override List GetAnimatedTextures(TR2Level level) { return level.AnimatedTextures; } - - protected override void SetAnimatedTextures(TR2Level level, TRAnimatedTexture[] animatedTextures, ushort length) - { - level.AnimatedTextures = animatedTextures; - level.NumAnimatedTextures = length; - } } diff --git a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs index 3af3d2e49..4a8300d81 100644 --- a/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs +++ b/TRRandomizerCore/Textures/Wireframing/TR3Wireframer.cs @@ -53,36 +53,22 @@ protected override IEnumerable GetInvalidObjectTextureIndices(TR3Level leve return level.GetInvalidObjectTextureIndices(); } - protected override TRMesh[] GetLevelMeshes(TR3Level level) + protected override List GetLevelMeshes(TR3Level level) { return level.Meshes; } - protected override Dictionary GetModelMeshes(TR3Level level) - { - Dictionary modelMeshes = new(); - foreach (TRModel model in level.Models) - { - TRMesh[] meshes = GetModelMeshes(level, model); - if (meshes != null) - { - modelMeshes[(TR3Type)model.ID] = meshes; - } - } - return modelMeshes; - } - - protected override TRMesh[] GetModelMeshes(TR3Level level, TRModel model) + protected override List GetModelMeshes(TR3Level level, TRModel model) { return TRMeshUtilities.GetModelMeshes(level, model); } protected override List GetModels(TR3Level level) { - return level.Models.ToList(); + return level.Models; } - protected override TRObjectTexture[] GetObjectTextures(TR3Level level) + protected override List GetObjectTextures(TR3Level level) { return level.ObjectTextures; } @@ -150,12 +136,6 @@ protected override void ResetUnusedTextures(TR3Level level) level.ResetUnusedTextures(); } - protected override void SetObjectTextures(TR3Level level, IEnumerable textures) - { - level.ObjectTextures = textures.ToArray(); - level.NumObjectTextures = (uint)level.ObjectTextures.Length; - } - protected override void SetSkyboxVisible(TR3Level level) { foreach (TR3Room room in level.Rooms) @@ -179,17 +159,11 @@ protected override List CollectDeathFaces(TR3Level level) return FaceUtilities.GetTriggerFaces(level, new List(), true); } - protected override TRAnimatedTexture[] GetAnimatedTextures(TR3Level level) + protected override List GetAnimatedTextures(TR3Level level) { return level.AnimatedTextures; } - protected override void SetAnimatedTextures(TR3Level level, TRAnimatedTexture[] animatedTextures, ushort length) - { - level.AnimatedTextures = animatedTextures; - level.NumAnimatedTextures = length; - } - protected override Dictionary CreateSpecialSegments(TR3Level level, Pen pen) { Dictionary segments = new(); diff --git a/TRTexture16Importer/Helpers/TRPalette8Control.cs b/TRTexture16Importer/Helpers/TRPalette8Control.cs index 81b182437..bef4c5689 100644 --- a/TRTexture16Importer/Helpers/TRPalette8Control.cs +++ b/TRTexture16Importer/Helpers/TRPalette8Control.cs @@ -64,10 +64,10 @@ public void MergeTiles() // Grab meshes we aren't interested in - but don't remove Lara's hips e.g. Atlantean spawns List ignoredMeshes = new(); - TRMesh[] laraMeshes = TRMeshUtilities.GetModelMeshes(Level, TR1Type.Lara); + List laraMeshes = TRMeshUtilities.GetModelMeshes(Level, TR1Type.Lara); foreach (TR1Type entity in ObsoleteModels) { - TRMesh[] meshes = TRMeshUtilities.GetModelMeshes(Level, entity); + List meshes = TRMeshUtilities.GetModelMeshes(Level, entity); if (meshes != null) { foreach (TRMesh mesh in meshes) diff --git a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs index 0557863f1..4e8d90a41 100644 --- a/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/AbstractTextureMapping.cs @@ -30,12 +30,12 @@ protected AbstractTextureMapping(L level) _committed = false; } - protected abstract TRMesh[] GetModelMeshes(E entity); + protected abstract List GetModelMeshes(E entity); protected abstract List GetPalette8(); protected abstract List GetPalette16(); protected abstract int ImportColour(Color colour); - protected abstract TRSpriteSequence[] GetSpriteSequences(); - protected abstract TRSpriteTexture[] GetSpriteTextures(); + protected abstract List GetSpriteSequences(); + protected abstract List GetSpriteTextures(); protected abstract Bitmap GetTile(int tileIndex); protected abstract void SetTile(int tileIndex, Bitmap bitmap); @@ -302,7 +302,7 @@ public void RedrawStaticTargets(StaticTextureSource source, string variant, D { translatedEntity = EntityMap[entity]; } - TRMesh[] meshes = GetModelMeshes(translatedEntity); + List meshes = GetModelMeshes(translatedEntity); ISet colourIndices = new HashSet(); foreach (TRMesh mesh in meshes) { @@ -364,8 +364,8 @@ public void RedrawStaticTargets(StaticTextureSource source, string variant, D { translatedEntity = EntityMap[entity]; } - TRMesh[] meshes = GetModelMeshes(translatedEntity); - if (meshes == null || meshes.Length == 0) + List meshes = GetModelMeshes(translatedEntity); + if (meshes == null || meshes.Count == 0) { continue; } @@ -433,8 +433,8 @@ private void GenerateSpriteSequenceTargets(StaticTextureSource source) throw new ArgumentException(string.Format("SpriteSequence {0} cannot be dynamically mapped without at least one source rectangle.", source.SpriteSequence)); } - List spriteSequences = GetSpriteSequences().ToList(); - TRSpriteTexture[] spriteTextures = GetSpriteTextures(); + List spriteSequences = GetSpriteSequences(); + List spriteTextures = GetSpriteTextures(); int spriteID = Convert.ToInt32(source.SpriteSequence); TRSpriteSequence sequence = spriteSequences.Find(s => s.SpriteID == spriteID); diff --git a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs index 05539483b..919342a54 100644 --- a/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR1TextureMapping.cs @@ -45,17 +45,17 @@ protected override int ImportColour(Color colour) return PaletteManager.AddPredefinedColour(colour); } - protected override TRMesh[] GetModelMeshes(TR1Type entity) + protected override List GetModelMeshes(TR1Type entity) { return TRMeshUtilities.GetModelMeshes(_level, entity); } - protected override TRSpriteSequence[] GetSpriteSequences() + protected override List GetSpriteSequences() { return _level.SpriteSequences; } - protected override TRSpriteTexture[] GetSpriteTextures() + protected override List GetSpriteTextures() { return _level.SpriteTextures; } diff --git a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs index a56fa3796..716d21095 100644 --- a/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR2TextureMapping.cs @@ -41,17 +41,17 @@ protected override int ImportColour(Color colour) return _paletteTracker.Import(colour); } - protected override TRMesh[] GetModelMeshes(TR2Type entity) + protected override List GetModelMeshes(TR2Type entity) { return TRMeshUtilities.GetModelMeshes(_level, entity); } - protected override TRSpriteSequence[] GetSpriteSequences() + protected override List GetSpriteSequences() { return _level.SpriteSequences; } - protected override TRSpriteTexture[] GetSpriteTextures() + protected override List GetSpriteTextures() { return _level.SpriteTextures; } diff --git a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs index 62e3e4866..0e5bc5006 100644 --- a/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs +++ b/TRTexture16Importer/Textures/Mapping/TR3TextureMapping.cs @@ -42,17 +42,17 @@ protected override int ImportColour(Color colour) return _paletteTracker.Import(colour); } - protected override TRMesh[] GetModelMeshes(TR3Type entity) + protected override List GetModelMeshes(TR3Type entity) { return TRMeshUtilities.GetModelMeshes(_level, entity); } - protected override TRSpriteSequence[] GetSpriteSequences() + protected override List GetSpriteSequences() { return _level.SpriteSequences; } - protected override TRSpriteTexture[] GetSpriteTextures() + protected override List GetSpriteTextures() { return _level.SpriteTextures; } diff --git a/TextureExport/Types/FaceMapper.cs b/TextureExport/Types/FaceMapper.cs index 60cab44ee..406b00b17 100644 --- a/TextureExport/Types/FaceMapper.cs +++ b/TextureExport/Types/FaceMapper.cs @@ -18,8 +18,6 @@ public static void DrawFaces(TR1Level level, string lvl, int[] roomNumbers) using TR1TexturePacker packer = new(level); packer.MaximumTiles = 255; - List objectTextures = level.ObjectTextures.ToList(); - Dictionary> rectFaces = new(); Dictionary> triFaces = new(); @@ -50,8 +48,8 @@ public static void DrawFaces(TR1Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, "Q" + rectIndex, true); packer.AddRectangle(newSegment); - newRectFaces[roomNumber][rectIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newRectFaces[roomNumber][rectIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } @@ -63,8 +61,8 @@ public static void DrawFaces(TR1Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, "T" + triIndex, true); packer.AddRectangle(newSegment); - newTriFaces[roomNumber][triIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newTriFaces[roomNumber][triIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } } @@ -83,9 +81,6 @@ public static void DrawFaces(TR1Level level, string lvl, int[] roomNumbers) } } - level.ObjectTextures = objectTextures.ToArray(); - level.NumObjectTextures = (uint)objectTextures.Count; - Directory.CreateDirectory(@"TR1\Faces"); new TR1LevelControl().Write(level, @"TR1\Faces\" + lvl); } @@ -95,8 +90,6 @@ public static void DrawFaces(TR2Level level, string lvl, int[] roomNumbers) using TR2TexturePacker packer = new(level); packer.MaximumTiles = 255; - List objectTextures = level.ObjectTextures.ToList(); - Dictionary> rectFaces = new(); Dictionary> triFaces = new(); @@ -127,8 +120,8 @@ public static void DrawFaces(TR2Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, "Q" + rectIndex); packer.AddRectangle(newSegment); - newRectFaces[roomNumber][rectIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newRectFaces[roomNumber][rectIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } @@ -140,8 +133,8 @@ public static void DrawFaces(TR2Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, "T" + triIndex); packer.AddRectangle(newSegment); - newTriFaces[roomNumber][triIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newTriFaces[roomNumber][triIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } } @@ -160,9 +153,6 @@ public static void DrawFaces(TR2Level level, string lvl, int[] roomNumbers) } } - level.ObjectTextures = objectTextures.ToArray(); - level.NumObjectTextures = (uint)objectTextures.Count; - Directory.CreateDirectory(@"TR2\Faces"); new TR2LevelControl().Write(level, @"TR2\Faces\" + lvl); } @@ -172,8 +162,6 @@ public static void DrawFaces(TR3Level level, string lvl, int[] roomNumbers) using TR3TexturePacker packer = new(level); packer.MaximumTiles = 255; - List objectTextures = level.ObjectTextures.ToList(); - Dictionary> rectFaces = new(); Dictionary> triFaces = new(); @@ -204,8 +192,8 @@ public static void DrawFaces(TR3Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, "Q" + rectIndex); packer.AddRectangle(newSegment); - newRectFaces[roomNumber][rectIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newRectFaces[roomNumber][rectIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } @@ -217,8 +205,8 @@ public static void DrawFaces(TR3Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, "T" + triIndex); packer.AddRectangle(newSegment); - newTriFaces[roomNumber][triIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newTriFaces[roomNumber][triIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } } @@ -237,9 +225,6 @@ public static void DrawFaces(TR3Level level, string lvl, int[] roomNumbers) } } - level.ObjectTextures = objectTextures.ToArray(); - level.NumObjectTextures = (uint)objectTextures.Count; - Directory.CreateDirectory(@"TR3\Faces"); new TR3LevelControl().Write(level, @"TR3\Faces\" + lvl); } @@ -252,7 +237,6 @@ public static void DrawBoxes(TR2Level level, string lvl, int[] roomNumbers) Dictionary> rectFaces = new(); Dictionary> newRectFaces = new(); - List objectTextures = level.ObjectTextures.ToList(); FDControl control = new(); control.ParseFromLevel(level); @@ -276,8 +260,8 @@ public static void DrawBoxes(TR2Level level, string lvl, int[] roomNumbers) TexturedTileSegment newSegment = DrawNewFace(segment, GetBoxDescription(level, control, roomNumber, rectIndex)); packer.AddRectangle(newSegment); - newRectFaces[roomNumber][rectIndex] = objectTextures.Count; - objectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); + newRectFaces[roomNumber][rectIndex] = level.ObjectTextures.Count; + level.ObjectTextures.Add((newSegment.FirstTexture as IndexedTRObjectTexture).Texture); } } @@ -291,9 +275,6 @@ public static void DrawBoxes(TR2Level level, string lvl, int[] roomNumbers) } } - level.ObjectTextures = objectTextures.ToArray(); - level.NumObjectTextures = (uint)objectTextures.Count; - Directory.CreateDirectory(@"TR2\Boxes"); new TR2LevelControl().Write(level, @"TR2\Boxes\" + lvl); } diff --git a/TextureExport/Types/HtmlExporter.cs b/TextureExport/Types/HtmlExporter.cs index 528e29e24..562dbcb87 100644 --- a/TextureExport/Types/HtmlExporter.cs +++ b/TextureExport/Types/HtmlExporter.cs @@ -183,7 +183,7 @@ private static void BuildLevelSelect(StringBuilder html, string currentLevel, IE } } - private static Dictionary GetSkyBoxColours(TRMesh[] meshes, List palette16) + private static Dictionary GetSkyBoxColours(List meshes, List palette16) { Dictionary colours = new(); if (meshes != null)