From dc0b395255b1339ac22aca52e8fb2804cdef9518 Mon Sep 17 00:00:00 2001 From: krypto5863 <29824718+krypto5863@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:19:45 -0500 Subject: [PATCH 1/5] Support for creation and reading of PMat files. --- CM3D2.Serialization/Files/PMat.cs | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 CM3D2.Serialization/Files/PMat.cs diff --git a/CM3D2.Serialization/Files/PMat.cs b/CM3D2.Serialization/Files/PMat.cs new file mode 100644 index 0000000..031aec6 --- /dev/null +++ b/CM3D2.Serialization/Files/PMat.cs @@ -0,0 +1,45 @@ +using System; + +namespace CM3D2.Serialization.Files; + +public class PMat : ICM3D2Serializable, ISummarizable +{ + public readonly string signature = "CM3D2_PMATERIAL"; + //Unsure, unused + public int version; + + public int hash; + public string materialName; + public float renderQueue; + //Unused + public string shader; + + public void WriteWith(ICM3D2Writer writer) + { + writer.Write(signature); + + writer.Write(version); + writer.Write(hash); + writer.Write(materialName); + writer.Write(renderQueue); + writer.Write(shader); + } + + public void ReadWith(ICM3D2Reader reader) + { + reader.Read(out string temp_signature); + if (temp_signature != signature) + throw new FormatException($"Expected {nameof(signature)} \"{signature}\" but instead found \"{temp_signature}\""); + + reader.Read(out version); + reader.Read(out hash); + reader.Read(out materialName); + reader.Read(out renderQueue); + reader.Read(out shader); + } + + public string Summarize() + { + return $"{{ {signature} v{version} \"{hash}\" {materialName} {renderQueue} {shader}}}"; + } +} \ No newline at end of file From b608fa190afcce23f657a684288c03c8a66f3ae4 Mon Sep 17 00:00:00 2001 From: krypto5863 <29824718+krypto5863@users.noreply.github.com> Date: Wed, 18 Dec 2024 10:33:24 -0500 Subject: [PATCH 2/5] Added a bit of comments to the PMat fields so they're easier understood. --- CM3D2.Serialization/Files/PMat.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CM3D2.Serialization/Files/PMat.cs b/CM3D2.Serialization/Files/PMat.cs index 031aec6..6e15a63 100644 --- a/CM3D2.Serialization/Files/PMat.cs +++ b/CM3D2.Serialization/Files/PMat.cs @@ -8,7 +8,14 @@ public class PMat : ICM3D2Serializable, ISummarizable //Unsure, unused public int version; + /// + /// This is the hash of the corresponding mate file name . + /// + /// Shouldn't be confused with , which is a copy of the mate file name, not the actual usage. public int hash; + /// + /// The name of the corresponding . + /// public string materialName; public float renderQueue; //Unused From b33155cca696cb3d6b3b2a96dec7a4e13397b9ef Mon Sep 17 00:00:00 2001 From: krypto5863 <29824718+krypto5863@users.noreply.github.com> Date: Tue, 22 Jul 2025 16:59:09 -0400 Subject: [PATCH 3/5] Texture support. --- CM3D2.Serialization/Files/Tex.cs | 105 +++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 CM3D2.Serialization/Files/Tex.cs diff --git a/CM3D2.Serialization/Files/Tex.cs b/CM3D2.Serialization/Files/Tex.cs new file mode 100644 index 0000000..18702fb --- /dev/null +++ b/CM3D2.Serialization/Files/Tex.cs @@ -0,0 +1,105 @@ +using CM3D2.Serialization.Collections; +using CM3D2.Serialization.Types; +using System; + +namespace CM3D2.Serialization.Files; + +public class Tex : ICM3D2Serializable +{ + public readonly string signature = "CM3D2_TEX"; + + public int version; + + public string unknown = string.Empty; + + [FileVersionConstraint(1011)] + public int uvRectCount; + + [FileVersionConstraint(1011)] + [LengthDefinedBy("uvRectCount")] + public LengthDefinedArray uvRects = new(); + + [FileVersionConstraint(1010)] + public int width; + + [FileVersionConstraint(1010)] + public int height; + + [FileVersionConstraint(1010)] + public int format; + + public int imageDataSize; + + [LengthDefinedBy("imageDataSize")] + public LengthDefinedArray imageData = new(); + + public void WriteWith(ICM3D2Writer writer) + { + writer.Write(signature); + writer.Write(version); + writer.Write(unknown); + + if (uvRectCount >= 0) + { + version = 1011; + writer.Write(uvRectCount); + uvRects.ValidateLength(uvRectCount, "uvRects", "uvRectCount"); + writer.Write(uvRects); + } + else + { + version = 1010; + } + + writer.Write(width); + writer.Write(height); + writer.Write(format); + writer.Write(imageDataSize); + imageData.ValidateLength(imageDataSize, "imageData", "imageDataSize"); + writer.Write(imageData); + } + + public void ReadWith(ICM3D2Reader reader) + { + reader.Read(out var text); + if (text != signature) + { + throw new FormatException(string.Concat("Expected signature \"", signature, "\" but instead found \"", text, "\"")); + } + + reader.Read(out version); + reader.Read(out unknown); + + if (version >= 1011) + { + reader.Read(out uvRectCount); + uvRects.SetLength(uvRectCount); + reader.Read(ref uvRects); + } + + if (version >= 1010) + { + reader.Read(out width); + reader.Read(out height); + reader.Read(out format); + } + + reader.Read(out imageDataSize); + imageData.SetLength(imageDataSize); + reader.Read(ref imageData); + + if (version == 1000) + { + if (imageData.Length >= 24) + { + width = (imageData[16] << 24) | (imageData[17] << 16) | (imageData[18] << 8) | imageData[19]; + height = (imageData[20] << 24) | (imageData[21] << 16) | (imageData[22] << 8) | imageData[23]; + format = 5; + } + else + { + throw new FormatException("imageData does not contain enough data to extract width and height for version 1000."); + } + } + } +} \ No newline at end of file From 9b82b863c2a8101844d910e8d3a80f4be546b981 Mon Sep 17 00:00:00 2001 From: krypto5863 <29824718+krypto5863@users.noreply.github.com> Date: Tue, 22 Jul 2025 21:28:59 -0400 Subject: [PATCH 4/5] Fixed tex. Added keywords to mates. --- CM3D2.Serialization/Files/Tex.cs | 52 +++++++++++++++++++++------ CM3D2.Serialization/Types/Material.cs | 45 +++++++++++++++++++++++ 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/CM3D2.Serialization/Files/Tex.cs b/CM3D2.Serialization/Files/Tex.cs index 18702fb..ef054a2 100644 --- a/CM3D2.Serialization/Files/Tex.cs +++ b/CM3D2.Serialization/Files/Tex.cs @@ -1,6 +1,7 @@ using CM3D2.Serialization.Collections; using CM3D2.Serialization.Types; using System; +using System.CodeDom; namespace CM3D2.Serialization.Files; @@ -20,40 +21,71 @@ public class Tex : ICM3D2Serializable public LengthDefinedArray uvRects = new(); [FileVersionConstraint(1010)] - public int width; + public int width = -1; [FileVersionConstraint(1010)] - public int height; + public int height = -1; [FileVersionConstraint(1010)] - public int format; + public int format = -1; public int imageDataSize; [LengthDefinedBy("imageDataSize")] + //Typically you'll want to pass the results of EncodeToPNG here and set format to ARGB32. public LengthDefinedArray imageData = new(); public void WriteWith(ICM3D2Writer writer) { + if (width >= 0 || height >= 0 || format >= 0) + { + version = uvRectCount >= 0 ? 1011 : 1010; + + if (width <= -1) + { + throw new InvalidOperationException("Format or Height is set but width is not"); + } + if (height <= -1) + { + throw new InvalidOperationException("Format or Width is set but height is not"); + } + if (format <= -1) + { + throw new InvalidOperationException("Width or Height is set but format is not"); + } + } + else + { + version = 1000; + + if (uvRectCount >= 0) + { + throw new InvalidOperationException("uvRectCount is set but width, height, and format are not defined."); + } + if (imageDataSize < 24) + { + throw new InvalidOperationException("imageDataSize is less than 24 bytes, which is not valid for version 1000."); + } + } + writer.Write(signature); writer.Write(version); writer.Write(unknown); - if (uvRectCount >= 0) + if (version >= 1011) { - version = 1011; writer.Write(uvRectCount); uvRects.ValidateLength(uvRectCount, "uvRects", "uvRectCount"); writer.Write(uvRects); } - else + + if (version >= 1010) { - version = 1010; + writer.Write(width); + writer.Write(height); + writer.Write(format); } - writer.Write(width); - writer.Write(height); - writer.Write(format); writer.Write(imageDataSize); imageData.ValidateLength(imageDataSize, "imageData", "imageDataSize"); writer.Write(imageData); diff --git a/CM3D2.Serialization/Types/Material.cs b/CM3D2.Serialization/Types/Material.cs index 3d82c8a..f7dd591 100644 --- a/CM3D2.Serialization/Types/Material.cs +++ b/CM3D2.Serialization/Types/Material.cs @@ -154,6 +154,46 @@ protected override void WriteWith(ICM3D2Writer writer) } } + public class KeywordsProperty : Property + { + public static readonly string Type = "keyword"; + public override string type => Type; + + public int count; + public List keywords; + + protected override void ReadWith(ICM3D2Reader reader) + { + keywords.Clear(); + + reader.Read(out count); + for (int i = 0; i < count; i++) + { + var keyword = new KeywordProperty(); + reader.Read(out keyword.keyword); + reader.Read(out keyword.state); + keywords.Add(keyword); + } + } + + protected override void WriteWith(ICM3D2Writer writer) + { + count = keywords.Count; + writer.Write(count); + foreach (var keywordProperty in keywords) + { + writer.Write(keywordProperty.keyword); + writer.Write(keywordProperty.state); + } + } + + public class KeywordProperty + { + public string keyword; + public bool state; + } + } + public readonly string endTag = "end"; void ICM3D2Serializable.ReadWith(ICM3D2Reader reader) @@ -187,6 +227,11 @@ void ICM3D2Serializable.ReadWith(ICM3D2Reader reader) reader.Read(out FProperty newProp); prop = newProp; } + else if (propType == KeywordsProperty.Type) + { + reader.Read(out KeywordsProperty newProp); + prop = newProp; + } #pragma warning restore CM3D2Serialization031 // Field Read / Write out of Order else if (propType == "end") { From 554c6c4689dfb06eca6ea45790cf7ad16589b186 Mon Sep 17 00:00:00 2001 From: krypto5863 <29824718+krypto5863@users.noreply.github.com> Date: Thu, 24 Jul 2025 13:02:39 -0400 Subject: [PATCH 5/5] Minor tweaks, made material keyword section follow what's established. --- CM3D2.Serialization/Files/Tex.cs | 4 +-- CM3D2.Serialization/Types/Material.cs | 48 +++++++++++++++------------ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/CM3D2.Serialization/Files/Tex.cs b/CM3D2.Serialization/Files/Tex.cs index ef054a2..bd13379 100644 --- a/CM3D2.Serialization/Files/Tex.cs +++ b/CM3D2.Serialization/Files/Tex.cs @@ -17,7 +17,7 @@ public class Tex : ICM3D2Serializable public int uvRectCount; [FileVersionConstraint(1011)] - [LengthDefinedBy("uvRectCount")] + [LengthDefinedBy(nameof(uvRectCount))] public LengthDefinedArray uvRects = new(); [FileVersionConstraint(1010)] @@ -31,7 +31,7 @@ public class Tex : ICM3D2Serializable public int imageDataSize; - [LengthDefinedBy("imageDataSize")] + [LengthDefinedBy(nameof(imageDataSize))] //Typically you'll want to pass the results of EncodeToPNG here and set format to ARGB32. public LengthDefinedArray imageData = new(); diff --git a/CM3D2.Serialization/Types/Material.cs b/CM3D2.Serialization/Types/Material.cs index f7dd591..8c63b27 100644 --- a/CM3D2.Serialization/Types/Material.cs +++ b/CM3D2.Serialization/Types/Material.cs @@ -1,4 +1,5 @@ -using System; +using CM3D2.Serialization.Collections; +using System; using System.Collections.Generic; using System.Text; @@ -159,38 +160,41 @@ public class KeywordsProperty : Property public static readonly string Type = "keyword"; public override string type => Type; - public int count; - public List keywords; + public int keywordCount; + + [LengthDefinedBy(nameof(keywordCount))] + public LengthDefinedList keywords; protected override void ReadWith(ICM3D2Reader reader) { - keywords.Clear(); - - reader.Read(out count); - for (int i = 0; i < count; i++) - { - var keyword = new KeywordProperty(); - reader.Read(out keyword.keyword); - reader.Read(out keyword.state); - keywords.Add(keyword); - } + reader.Read(out keywordCount); + keywords.SetLength(keywordCount); + reader.Read(ref keywords); } protected override void WriteWith(ICM3D2Writer writer) { - count = keywords.Count; - writer.Write(count); - foreach (var keywordProperty in keywords) - { - writer.Write(keywordProperty.keyword); - writer.Write(keywordProperty.state); - } + keywordCount = keywords.Count; + writer.Write(keywordCount); + keywords.ValidateLength(keywordCount, nameof(keywords), nameof(keywordCount)); + writer.Write(keywords); } - public class KeywordProperty + public struct KeywordProperty : ICM3D2Serializable { public string keyword; - public bool state; + public bool active; + public void WriteWith(ICM3D2Writer writer) + { + writer.Write(keyword); + writer.Write(active); + } + + public void ReadWith(ICM3D2Reader reader) + { + reader.Read(out keyword); + reader.Read(out active); + } } }