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);
+ }
}
}