Skip to content

Commit

Permalink
Add support for TR1X 4 (LostArtefacts#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahm86 authored May 15, 2024
1 parent ac65dc7 commit d9615fe
Show file tree
Hide file tree
Showing 27 changed files with 328 additions and 277 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## [Unreleased](https://github.com/LostArtefacts/TR-Rando/compare/V1.8.4...master) - xxxx-xx-xx
- added support for TR1X V4 (#626)
- fixed a key item softlock in Crash Site (#662)

## [V1.8.4](https://github.com/LostArtefacts/TR-Rando/compare/V1.8.3...V1.8.4) - 2024-02-12
Expand Down
Binary file modified Deps/TRGE.Coord.dll
Binary file not shown.
Binary file modified Deps/TRGE.Core.dll
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class EMImportNonGraphicsModelFunction : BaseEMFunction

public override void ApplyToLevel(TR1Level level)
{
IEnumerable<EMMeshTextureData> data = PrepareImportData(level.Models);
List<EMMeshTextureData> data = PrepareImportData(level.Models);
if (!data.Any())
{
return;
Expand All @@ -29,7 +29,7 @@ public override void ApplyToLevel(TR1Level level)

public override void ApplyToLevel(TR2Level level)
{
IEnumerable<EMMeshTextureData> data = PrepareImportData(level.Models);
List<EMMeshTextureData> data = PrepareImportData(level.Models);
if (!data.Any())
{
return;
Expand All @@ -50,7 +50,7 @@ public override void ApplyToLevel(TR2Level level)

public override void ApplyToLevel(TR3Level level)
{
IEnumerable<EMMeshTextureData> data = PrepareImportData(level.Models);
List<EMMeshTextureData> data = PrepareImportData(level.Models);
if (!data.Any())
{
return;
Expand All @@ -69,10 +69,10 @@ public override void ApplyToLevel(TR3Level level)
RemapFaces(data, level.ObjectTextures.Count - 1, level.Models);
}

private IEnumerable<EMMeshTextureData> PrepareImportData<T>(SortedDictionary<T, TRModel> existingModels)
private List<EMMeshTextureData> PrepareImportData<T>(SortedDictionary<T, TRModel> existingModels)
where T : Enum
{
return Data.Where(d => !existingModels.ContainsKey((T)(object)(uint)d.ModelID));
return Data.Where(d => !existingModels.ContainsKey((T)(object)(uint)d.ModelID)).ToList();
}

private static void RemapFaces<T>(IEnumerable<EMMeshTextureData> data, int maximumTexture, SortedDictionary<T, TRModel> models)
Expand Down
5 changes: 4 additions & 1 deletion TRDataControl/Transport/TRDataImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,13 @@ private void CleanRemovalList()
{
entityClean = false;
}
}

if (entityClean)
{
// And similarly for cyclic dependencies
IEnumerable<T> cyclics = Data.GetCyclicDependencies(type);
entityClean = cyclics.All(TypesToRemove.Contains);
entityClean = cyclics.All(TypesToRemove.Contains) && !cyclics.Any(TypesToImport.Contains);
}

if (entityClean)
Expand Down
33 changes: 27 additions & 6 deletions TRImageControl/TRImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,10 @@ public Bitmap ToBitmap()
for (int i = 0; i < Pixels.Length; i++)
{
uint pixel = Pixels[i];
byte a = (byte)((pixel & 0xFF000000) >> 24);
byte r = (byte)((pixel & 0xFF0000) >> 16);
byte g = (byte)((pixel & 0xFF00) >> 8);
byte b = (byte)(pixel & 0xFF);
byte a = (byte)((pixel & 0xFF000000) > 0 ? 0xFF : 0);

pixels.Add(b);
pixels.Add(g);
Expand Down Expand Up @@ -232,7 +232,7 @@ public void Read(Rectangle bounds, Action<Color, int, int> callback)
{
for (int x = bounds.Left; x < bounds.Right; x++)
{
callback.Invoke(Color.FromArgb((int)this[x, y]), x, y);
callback.Invoke(GetPixel(x, y), x, y);
}
}
}
Expand All @@ -248,7 +248,7 @@ public void Write(Rectangle bounds, Func<Color, int, int, Color> callback)
{
for (int x = bounds.Left; x < bounds.Right; x++)
{
this[x, y] = (uint)callback.Invoke(Color.FromArgb((int)this[x, y]), x, y).ToArgb();
this[x, y] = (uint)callback.Invoke(GetPixel(x, y), x, y).ToArgb();
}
}

Expand All @@ -266,18 +266,39 @@ public void Import(TRImage image, Point point, bool retainBackground = false)
{
for (int x = 0; x < image.Size.Width; x++)
{
Color c = image.GetPixel(x, y);
if (!retainBackground || c.A != 0)
Color inColour = image.GetPixel(x, y);
if (!retainBackground || inColour.A == 0xFF)
{
this[x + point.X, y + point.Y] = image[x, y];
}
else if (inColour.A > 0)
{
Color curColour = GetPixel(x + point.X, y + point.Y);

float a0 = inColour.A / 255.0f;
float r0 = (inColour.R / 255.0f) * a0;
float g0 = (inColour.G / 255.0f) * a0;
float b0 = (inColour.B / 255.0f) * a0;

float a1 = curColour.A / 255.0f;
float r1 = (curColour.R / 255.0f) * a1;
float g1 = (curColour.G / 255.0f) * a1;
float b1 = (curColour.B / 255.0f) * a1;

float aOut = a0 + a1 * (1 - a0);
float rOut = (r0 + r1 * (1 - a0)) / aOut;
float gOut = (g0 + g1 * (1 - a0)) / aOut;
float bOut = (b0 + b1 * (1 - a0)) / aOut;

Color blend = Color.FromArgb((int)(aOut * 255), (int)(rOut * 255), (int)(gOut * 255), (int)(bOut * 255));
this[x + point.X, y + point.Y] = (uint)blend.ToArgb();
}
}
}

DataChanged?.Invoke(this, EventArgs.Empty);
}


public TRImage Export(Rectangle bounds)
{
TRImage image = new(bounds.Size);
Expand Down
28 changes: 20 additions & 8 deletions TRImageControlTests/ImageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
namespace TRImageControlTests;

[TestClass]
[TestCategory("Textures")]
public class ImageTests : TestBase
{
[TestMethod]
[TestCategory("Textures")]
[Description("Test that an 8-bit image is identical after conversion into TRImage type.")]
public void Test8Bit()
{
Expand All @@ -35,7 +35,6 @@ public void Test8Bit()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test that a 16-bit image is identical after conversion into TRImage type.")]
public void Test16Bit()
{
Expand All @@ -49,7 +48,6 @@ public void Test16Bit()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test that a 32-bit image is identical after conversion into TRImage type.")]
public void Test32Bit()
{
Expand All @@ -63,7 +61,6 @@ public void Test32Bit()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test that the correct portion of an image is deleted.")]
public void TestDelete()
{
Expand Down Expand Up @@ -99,7 +96,6 @@ public void TestDelete()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test that a portion of an image exported matches the source.")]
public void TestCopy()
{
Expand All @@ -121,7 +117,6 @@ public void TestCopy()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test importing an image into another.")]
[DataRow(true)]
[DataRow(false)]
Expand Down Expand Up @@ -172,7 +167,6 @@ bool TestMatch()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test reading and writing to an image.")]
public void TestReadWrite()
{
Expand Down Expand Up @@ -203,7 +197,6 @@ public void TestReadWrite()
}

[TestMethod]
[TestCategory("Textures")]
[Description("Test bitmap interpretation.")]
public void TestBitmap()
{
Expand All @@ -225,4 +218,23 @@ public void TestBitmap()

CollectionAssert.AreEqual(ms1.ToArray(), ms2.ToArray());
}

[TestMethod]
[Description("Test alpha blending")]
public void TestBlending()
{
TRImage baseImage = new(128, 128);
baseImage.Fill(Color.FromArgb(153, 0, 100, 255)); // 60%

TRImage overlay = new(64, 64);
overlay.Fill(Color.FromArgb(102, Color.Red)); // 40%

baseImage.Import(overlay, new(32, 32), true);

Color blend = baseImage.GetPixel(32, 32);
Assert.AreEqual(134, blend.R);
Assert.AreEqual(47, blend.G);
Assert.AreEqual(120, blend.B);
Assert.AreEqual(193, blend.A);
}
}
2 changes: 1 addition & 1 deletion TRLevelControl/Build/TRModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ private void DeconstructModel(T type, TRModel model)
{
ID = (uint)(object)type,
Animation = model.Animations.Count == 0 ? TRConsts.NoAnimation : (ushort)_placeholderAnimations.Count,
FrameOffset = (uint)_frames.Count * sizeof(short),
FrameOffset = _observer == null && model.Animations.Count == 0 ? 0 : (uint)_frames.Count * sizeof(short),
NumMeshes = (ushort)model.Meshes.Count,
};
_placeholderModels.Add(placeholderModel);
Expand Down
9 changes: 6 additions & 3 deletions TRRandomizerCore/Editors/TR1ClassicEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,10 @@ private void AmendTitleAndCredits(AbstractTRScriptEditor scriptEditor, TRSaveMon
string backupTitle = Path.Combine(GetReadBasePath(), mainMenuPic);
if (File.Exists(backupTitle))
{
string editedTitle = Path.Combine(GetWriteBasePath(), mainMenuPic);
string editedTitle = Path.Combine(GetWriteBasePath(), "title.png");
TRImage bg = new(backupTitle);
TRImage badge = new(@"Resources\Shared\Graphics\goldbadge-small.png");
bg.Import(badge, scriptEditor.GameMode == GameMode.Gold ? _goldBadgePos : _regularBadgePos, true);
Color c = bg.GetPixel(706, 537);

if (scriptEditor.GameMode == GameMode.Combined)
{
Expand All @@ -369,6 +368,10 @@ private void AmendTitleAndCredits(AbstractTRScriptEditor scriptEditor, TRSaveMon
}

bg.Save(editedTitle);

string titlePath = @"data\title.png";
script.MainMenuPicture = titlePath;
script.AddAdditionalBackupFile(titlePath);
}

{
Expand All @@ -395,9 +398,9 @@ private void AmendTitleAndCredits(AbstractTRScriptEditor scriptEditor, TRSaveMon
});

script.AddAdditionalBackupFile(creditPath);
scriptEditor.SaveScript();
}

scriptEditor.SaveScript();
monitor.FireSaveStateChanged(1);
}
}
13 changes: 8 additions & 5 deletions TRRandomizerCore/Randomizers/TR1/TR1OutfitRandomizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,10 @@ private static void CreateGoldenBraid(TR1CombinedLevel level)
TRModel ponytail = level.Data.Models[TR1Type.LaraPonytail_H_U];
List<TRMesh> goldMeshes = new(ponytail.Meshes.Select(m => MeshEditor.CloneMeshAsColoured(m, goldPalette)));
ponytail.Meshes.AddRange(goldMeshes);
ponytail.MeshTrees.AddRange(ponytail.MeshTrees);

List<TRMeshTreeNode> treeClones = new(ponytail.MeshTrees.Select(t => t.Clone()));
ponytail.MeshTrees.Add(new()); // Additional dummy tree required
ponytail.MeshTrees.AddRange(treeClones);
}

private static void HideEntities(TR1CombinedLevel level, IEnumerable<TR1Type> entities)
Expand Down Expand Up @@ -588,8 +591,8 @@ private void ConvertToPartialGymOutfit(TR1CombinedLevel level)
}

List<TRMesh> lara = level.Data.Models[(level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara)].Meshes;
List<TRMesh> laraShotgun = level.Data.Models[TR1Type.LaraShotgunAnim_H].Meshes;
List<TRMesh> laraMisc = level.Data.Models[TR1Type.LaraMiscAnim_H].Meshes;
List<TRMesh> laraShotgun = level.Data.Models[TR1Type.LaraShotgunAnim_H]?.Meshes;
List<TRMesh> laraMisc = level.Data.Models[TR1Type.LaraMiscAnim_H]?.Meshes;

// Just the torso
laraMisc[7].CopyInto(lara[7]);
Expand Down Expand Up @@ -803,8 +806,8 @@ private static void CopyMeshParts(MeshCopyData data)
private void ConvertToMauledOutfit(TR1CombinedLevel level)
{
List<TRMesh> lara = level.Data.Models[(level.IsCutScene ? TR1Type.CutsceneActor1 : TR1Type.Lara)].Meshes;
List<TRMesh> laraShotgun = level.Data.Models[TR1Type.LaraShotgunAnim_H].Meshes;
List<TRMesh> laraMisc = level.Data.Models[TR1Type.LaraMiscAnim_H].Meshes;
List<TRMesh> laraShotgun = level.Data.Models[TR1Type.LaraShotgunAnim_H]?.Meshes;
List<TRMesh> laraMisc = level.Data.Models[TR1Type.LaraMiscAnim_H]?.Meshes;

if (level.Is(TR1LevelNames.QUALOPEC_CUT))
{
Expand Down
56 changes: 28 additions & 28 deletions TRRandomizerCore/Resources/TR1/Environment/CAT.PHD-Environment.json
Original file line number Diff line number Diff line change
Expand Up @@ -922,11 +922,11 @@
{
"ModelID": 43,
"TextureMap": {
"744": 955,
"745": 955,
"746": 955,
"747": 952,
"748": 955,
"749": 206
"746": 952,
"747": 955,
"748": 206
}
}
]
Expand Down Expand Up @@ -1079,18 +1079,18 @@
{
"ModelID": 36,
"TextureMap": {
"666": 176,
"667": 176,
"668": 176,
"669": 953,
"670": 176,
"671": 773,
"672": 773,
"673": 773,
"674": 773,
"675": 773,
"676": 773,
"677": 773
"659": 176,
"660": 176,
"661": 176,
"662": 953,
"663": 176,
"664": 773,
"665": 773,
"666": 773,
"667": 773,
"668": 773,
"669": 773,
"670": 773
}
}
]
Expand Down Expand Up @@ -1139,18 +1139,18 @@
{
"ModelID": 36,
"TextureMap": {
"666": 176,
"667": 176,
"668": 176,
"669": 953,
"670": 176,
"671": 773,
"672": 773,
"673": 773,
"674": 773,
"675": 773,
"676": 773,
"677": 773
"659": 176,
"660": 176,
"661": 176,
"662": 953,
"663": 176,
"664": 773,
"665": 773,
"666": 773,
"667": 773,
"668": 773,
"669": 773,
"670": 773
}
}
]
Expand Down
Loading

0 comments on commit d9615fe

Please sign in to comment.