Skip to content

Commit

Permalink
Convert model storage to dictionaries (LostArtefacts#632)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahm86 authored Apr 29, 2024
1 parent 3835b01 commit c025659
Show file tree
Hide file tree
Showing 73 changed files with 430 additions and 544 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@ public class EMModelExistsCondition : BaseEMCondition

protected override bool Evaluate(TR1Level level)
{
TRModel model = level.Models.Find(m => m.ID == ModelID);
return model != null;
return level.Models.ContainsKey((TR1Type)ModelID);
}

protected override bool Evaluate(TR2Level level)
{
TRModel model = level.Models.Find(m => m.ID == ModelID);
return model != null;
return level.Models.ContainsKey((TR2Type)ModelID);
}

protected override bool Evaluate(TR3Level level)
{
TRModel model = level.Models.Find(m => m.ID == ModelID);
return model != null;
return level.Models.ContainsKey((TR3Type)ModelID);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,8 @@ protected override bool Evaluate(TR1Level level)

protected override bool Evaluate(TR2Level level)
{
TRModel model = level.Models.Find(m => m.ID == (uint)TR2Type.BirdMonster);
if (model != null)
{
return model.Animations[20].FrameEnd == model.Animations[19].FrameEnd;
}
return false;
TRModel model = level.Models[TR2Type.BirdMonster];
return model != null && model.Animations[20].FrameEnd == model.Animations[19].FrameEnd;
}

protected override bool Evaluate(TR3Level level)
Expand Down
21 changes: 8 additions & 13 deletions TREnvironmentEditor/Model/Types/Mirroring/EMMirrorFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ private static void MirrorTextures(TR1Level level)
// Models such as doors may use textures also used on walls, but
// these models aren't mirrored so the texture will end up being
// upside down. Rotate the relevant mesh faces.
MirrorDependentFaces(level.Models, textureReferences);
MirrorDependentFaces(level.Models.Values, textureReferences);
}

private static void MirrorTextures(TR2Level level)
Expand Down Expand Up @@ -1247,19 +1247,14 @@ private static void MirrorObjectTextures(ISet<ushort> textureReferences, List<TR

private static void MirrorDependentFaces(IEnumerable<TRModel> models, ISet<ushort> textureReferences)
{
foreach (TRModel model in models)
IEnumerable<TRMeshFace> faces = models.SelectMany(m => m.Meshes)
.SelectMany(m => m.TexturedRectangles)
.Where(f => textureReferences.Contains(f.Texture))
.Distinct();
foreach (TRMeshFace face in faces)
{
foreach (TRMesh mesh in model.Meshes)
{
foreach (TRMeshFace face in mesh.TexturedRectangles)
{
if (textureReferences.Contains(face.Texture))
{
face.SwapVertices(0, 2);
face.SwapVertices(1, 3);
}
}
}
face.SwapVertices(0, 2);
face.SwapVertices(1, 3);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,24 @@ public class EMMirrorModelFunction : BaseEMFunction
public override void ApplyToLevel(TR1Level level)
{
IEnumerable<TRModel> models = level.Models
.Where(m => ModelIDs.Contains(m.ID) && m.Meshes.Count == 1);
.Where(kvp => ModelIDs.Contains((uint)kvp.Key) && kvp.Value.Meshes.Count == 1)
.Select(kvp => kvp.Value);
MirrorObjectTextures(MirrorMeshes(models), level.ObjectTextures);
}

public override void ApplyToLevel(TR2Level level)
{
IEnumerable<TRModel> models = level.Models
.Where(m => ModelIDs.Contains(m.ID) && m.Meshes.Count == 1);
.Where(kvp => ModelIDs.Contains((uint)kvp.Key) && kvp.Value.Meshes.Count == 1)
.Select(kvp => kvp.Value);
MirrorObjectTextures(MirrorMeshes(models), level.ObjectTextures);
}

public override void ApplyToLevel(TR3Level level)
{
IEnumerable<TRModel> models = level.Models
.Where(m => ModelIDs.Contains(m.ID) && m.Meshes.Count == 1);
.Where(kvp => ModelIDs.Contains((uint)kvp.Key) && kvp.Value.Meshes.Count == 1)
.Select(kvp => kvp.Value);
MirrorObjectTextures(MirrorMeshes(models), level.ObjectTextures);
}

Expand Down
54 changes: 13 additions & 41 deletions TREnvironmentEditor/Model/Types/Models/EMConvertModelFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,63 +9,35 @@ public class EMConvertModelFunction : BaseEMFunction

public override void ApplyToLevel(TR1Level level)
{
ConvertModel(level.Models);
UpdateModelEntities(level.Entities);
ConvertModel(level.Models, level.Entities);
}

public override void ApplyToLevel(TR2Level level)
{
ConvertModel(level.Models);
UpdateModelEntities(level.Entities);
ConvertModel(level.Models, level.Entities);
}

public override void ApplyToLevel(TR3Level level)
{
ConvertModel(level.Models);
UpdateModelEntities(level.Entities);
ConvertModel(level.Models, level.Entities);
}

private void ConvertModel(List<TRModel> models)
private void ConvertModel<T, E>(TRDictionary<T, TRModel> models, List<E> entities)
where T : Enum
where E : TREntity<T>
{
if (models.Find(m => m.ID == NewModelID) == null)
T oldID = (T)(object)OldModelID;
T newID = (T)(object)NewModelID;
if (!models.ChangeKey(oldID, newID))
{
TRModel oldModel = models.Find(m => m.ID == OldModelID);
if (oldModel != null)
{
oldModel.ID = NewModelID;
}
}
}

private void UpdateModelEntities(List<TR1Entity> entities)
{
foreach (TR1Entity entity in entities)
{
if (entity.TypeID == (TR1Type)OldModelID)
{
entity.TypeID = (TR1Type)NewModelID;
}
return;
}
}

private void UpdateModelEntities(IEnumerable<TR2Entity> entities)
{
foreach (TR2Entity entity in entities)
{
if (entity.TypeID == (TR2Type)OldModelID)
{
entity.TypeID = (TR2Type)NewModelID;
}
}
}

private void UpdateModelEntities(IEnumerable<TR3Entity> entities)
{
foreach (TR3Entity entity in entities)
foreach (E entity in entities)
{
if (entity.TypeID == (TR3Type)OldModelID)
if (EqualityComparer<T>.Default.Equals(entity.TypeID, oldID))
{
entity.TypeID = (TR3Type)NewModelID;
entity.TypeID = newID;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class EMImportNonGraphicsModelFunction : BaseEMFunction

public override void ApplyToLevel(TR1Level level)
{
List<EMMeshTextureData> data = PrepareImportData(level.Models);
if (data.Count == 0)
IEnumerable<EMMeshTextureData> data = PrepareImportData(level.Models);
if (!data.Any())
{
return;
}
Expand All @@ -26,13 +26,13 @@ public override void ApplyToLevel(TR1Level level)
};
importer.Import();

RemapFaces(data, level.ObjectTextures.Count - 1, modelID => level.Models.Find(m => m.ID == modelID));
RemapFaces(data, level.ObjectTextures.Count - 1, level.Models);
}

public override void ApplyToLevel(TR2Level level)
{
List<EMMeshTextureData> data = PrepareImportData(level.Models);
if (data.Count == 0)
IEnumerable<EMMeshTextureData> data = PrepareImportData(level.Models);
if (!data.Any())
{
return;
}
Expand All @@ -47,13 +47,13 @@ public override void ApplyToLevel(TR2Level level)
};
importer.Import();

RemapFaces(data, level.ObjectTextures.Count - 1, modelID => level.Models.Find(m => m.ID == modelID));
RemapFaces(data, level.ObjectTextures.Count - 1, level.Models);
}

public override void ApplyToLevel(TR3Level level)
{
List<EMMeshTextureData> data = PrepareImportData(level.Models);
if (data.Count == 0)
IEnumerable<EMMeshTextureData> data = PrepareImportData(level.Models);
if (!data.Any())
{
return;
}
Expand All @@ -68,27 +68,21 @@ public override void ApplyToLevel(TR3Level level)
};
importer.Import();

RemapFaces(data, level.ObjectTextures.Count - 1, modelID => level.Models.Find(m => m.ID == modelID));
RemapFaces(data, level.ObjectTextures.Count - 1, level.Models);
}

private List<EMMeshTextureData> PrepareImportData(List<TRModel> existingModels)
private IEnumerable<EMMeshTextureData> PrepareImportData<T>(SortedDictionary<T, TRModel> existingModels)
where T : Enum
{
List<EMMeshTextureData> importData = new();
foreach (EMMeshTextureData data in Data)
{
if (existingModels.Find(m => m.ID == data.ModelID) == null)
{
importData.Add(data);
}
}
return importData;
return Data.Where(d => !existingModels.ContainsKey((T)(object)d.ModelID));
}

private static void RemapFaces(List<EMMeshTextureData> data, int maximumTexture, Func<short, TRModel> modelAction)
private static void RemapFaces<T>(IEnumerable<EMMeshTextureData> data, int maximumTexture, SortedDictionary<T, TRModel> models)
where T : Enum
{
foreach (EMMeshTextureData textureData in data)
{
TRModel model= modelAction.Invoke(textureData.ModelID);
TRModel model = models[(T)(object)textureData.ModelID];
foreach (TRMesh mesh in model.Meshes)
{
foreach (TRMeshFace face in mesh.ColouredTriangles)
Expand Down
41 changes: 19 additions & 22 deletions TRLevelControl/Build/TRModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

namespace TRLevelControl.Build;

public class TRModelBuilder
public class TRModelBuilder<T>
where T : Enum
{
private static readonly ushort _tr5ModelPadding = 0xFFEF;

Expand All @@ -29,7 +30,7 @@ public TRModelBuilder(TRGameVersion version, ITRLevelObserver observer = null)
_observer = observer;
}

public List<TRModel> ReadModelData(TRLevelReader reader, IMeshProvider meshProvider)
public TRDictionary<T, TRModel> ReadModelData(TRLevelReader reader, IMeshProvider meshProvider)
{
ReadAnimations(reader);
ReadStateChanges(reader);
Expand All @@ -39,18 +40,18 @@ public List<TRModel> ReadModelData(TRLevelReader reader, IMeshProvider meshProvi
ReadFrames(reader);
ReadModels(reader);

List<TRModel> models = new();
TRDictionary<T, TRModel> models = new();
foreach (PlaceholderModel placeholder in _placeholderModels)
{
models.Add(BuildModel(placeholder, meshProvider));
models[(T)(object)placeholder.ID] = BuildModel(placeholder, meshProvider);
}

TestTR5Changes(models);
TestTR5Changes(models.Values);

return models;
}

public void WriteModelData(TRLevelWriter writer, List<TRModel> models)
public void WriteModelData(TRLevelWriter writer, TRDictionary<T, TRModel> models)
{
_placeholderAnimations = new();
_placeholderChanges = new();
Expand All @@ -62,9 +63,9 @@ public void WriteModelData(TRLevelWriter writer, List<TRModel> models)
_dispatchToAnimMap = new();
_dispatchFrameBase = new();

foreach (TRModel model in models)
foreach (var (type, model) in models)
{
DeconstructModel(model);
DeconstructModel(type, model);
}

RestoreTR5Extras();
Expand Down Expand Up @@ -214,11 +215,7 @@ private void ReadModels(TRLevelReader reader)

private TRModel BuildModel(PlaceholderModel placeholder, IMeshProvider meshProvider)
{
TRModel model = new()
{
// To be eliminated
ID = placeholder.ID,
};
TRModel model = new();

// Everything has a dummy mesh tree, so load one less than the mesh count
int treePointer = (int)placeholder.MeshTree / sizeof(int);
Expand Down Expand Up @@ -517,7 +514,7 @@ private TRAnimFrame BuildFrame(ref int frameIndex, int numRotations)
return frame;
}

private void TestTR5Changes(List<TRModel> models)
private void TestTR5Changes(IEnumerable<TRModel> models)
{
if (_observer == null || _version != TRGameVersion.TR5)
{
Expand All @@ -534,11 +531,11 @@ private void TestTR5Changes(List<TRModel> models)
}
}

private void DeconstructModel(TRModel model)
private void DeconstructModel(T type, TRModel model)
{
PlaceholderModel placeholderModel = new()
{
ID = model.ID,
ID = (uint)(object)type,
Animation = model.Animations.Count == 0 ? TRConsts.NoAnimation : (ushort)_placeholderAnimations.Count,
FrameOffset = (uint)_frames.Count * sizeof(short),
NumMeshes = (ushort)model.Meshes.Count,
Expand Down Expand Up @@ -755,12 +752,12 @@ private void RestoreTR5Extras()
}
}

private void WriteAnimations(TRLevelWriter writer, List<TRModel> models)
private void WriteAnimations(TRLevelWriter writer, TRDictionary<T, TRModel> models)
{
writer.Write((uint)_placeholderAnimations.Count);
foreach (TRModel model in models)
foreach (var (type, model) in models)
{
PlaceholderModel placeholderModel = _placeholderModels.Find(m => m.ID == model.ID);
PlaceholderModel placeholderModel = _placeholderModels.Find(m => m.ID == (uint)(object)type);

for (int i = 0; i < model.Animations.Count; i++)
{
Expand Down Expand Up @@ -857,15 +854,15 @@ private void WriteFrames(TRLevelWriter writer)
writer.Write(_frames);
}

private void WriteModels(TRLevelWriter writer, List<TRModel> models)
private void WriteModels(TRLevelWriter writer, TRDictionary<T, TRModel> models)
{
writer.Write((uint)models.Count);

uint treePointer = 0;
ushort startingMesh = 0;
foreach (TRModel model in models)
foreach (var (type, model) in models)
{
PlaceholderModel placeholderModel = _placeholderModels.Find(m => m.ID == model.ID);
PlaceholderModel placeholderModel = _placeholderModels.Find(m => m.ID == (uint)(object)type);

writer.Write(placeholderModel.ID);
writer.Write(placeholderModel.NumMeshes);
Expand Down
Loading

0 comments on commit c025659

Please sign in to comment.