diff --git a/Penumbra/Import/Models/Export/MeshExporter.cs b/Penumbra/Import/Models/Export/MeshExporter.cs index 219a046e..3a57ab55 100644 --- a/Penumbra/Import/Models/Export/MeshExporter.cs +++ b/Penumbra/Import/Models/Export/MeshExporter.cs @@ -1,4 +1,6 @@ using System.Collections.Immutable; +using System.Text.Json; +using System.Text.Json.Nodes; using Lumina.Extensions; using OtterGui; using Penumbra.GameData.Files; @@ -23,11 +25,11 @@ public class MeshExporter ? scene.AddSkinnedMesh(data.Mesh, Matrix4x4.Identity, [.. skeleton.Value.Joints]) : scene.AddRigidMesh(data.Mesh, Matrix4x4.Identity); - var extras = new Dictionary(data.Attributes.Length); + var node = new JsonObject(); foreach (var attribute in data.Attributes) - extras.Add(attribute, true); + node[attribute] = true; - instance.WithExtras(JsonContent.CreateFrom(extras)); + instance.WithExtras(node); } } } @@ -233,10 +235,7 @@ public class MeshExporter // Named morph targets aren't part of the specification, however `MESH.extras.targetNames` // is a commonly-accepted means of providing the data. - meshBuilder.Extras = JsonContent.CreateFrom(new Dictionary() - { - { "targetNames", shapeNames }, - }); + meshBuilder.Extras = new JsonObject { ["targetNames"] = JsonSerializer.SerializeToNode(shapeNames) }; string[] attributes = []; var maxAttribute = 31 - BitOperations.LeadingZeroCount(attributeMask); diff --git a/Penumbra/Import/Models/Export/VertexFragment.cs b/Penumbra/Import/Models/Export/VertexFragment.cs index 7a82e994..eff34d54 100644 --- a/Penumbra/Import/Models/Export/VertexFragment.cs +++ b/Penumbra/Import/Models/Export/VertexFragment.cs @@ -1,4 +1,6 @@ +using System; using SharpGLTF.Geometry.VertexTypes; +using SharpGLTF.Memory; using SharpGLTF.Schema2; namespace Penumbra.Import.Models.Export; @@ -11,35 +13,40 @@ and there's reason to overhaul the export pipeline. public struct VertexColorFfxiv : IVertexCustom { - // NOTE: We only realistically require UNSIGNED_BYTE for this, however Blender 3.6 errors on that (fixed in 4.0). - [VertexAttribute("_FFXIV_COLOR", EncodingType.UNSIGNED_SHORT, true)] + public IEnumerable> GetEncodingAttributes() + { + // NOTE: We only realistically require UNSIGNED_BYTE for this, however Blender 3.6 errors on that (fixed in 4.0). + yield return new KeyValuePair("_FFXIV_COLOR", + new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); + } + public Vector4 FfxivColor; - public int MaxColors => 0; + public int MaxColors + => 0; - public int MaxTextCoords => 0; + public int MaxTextCoords + => 0; private static readonly string[] CustomNames = ["_FFXIV_COLOR"]; - public IEnumerable CustomAttributes => CustomNames; + + public IEnumerable CustomAttributes + => CustomNames; public VertexColorFfxiv(Vector4 ffxivColor) - { - FfxivColor = ffxivColor; - } + => FfxivColor = ffxivColor; public void Add(in VertexMaterialDelta delta) - { - } + { } public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - => new VertexMaterialDelta(Vector4.Zero, Vector4.Zero, Vector2.Zero, Vector2.Zero); + => new(Vector4.Zero, Vector4.Zero, Vector2.Zero, Vector2.Zero); public Vector2 GetTexCoord(int index) => throw new ArgumentOutOfRangeException(nameof(index)); public void SetTexCoord(int setIndex, Vector2 coord) - { - } + { } public bool TryGetCustomAttribute(string attributeName, out object? value) { @@ -65,12 +72,17 @@ public struct VertexColorFfxiv : IVertexCustom => throw new ArgumentOutOfRangeException(nameof(index)); public void SetColor(int setIndex, Vector4 color) - { - } + { } public void Validate() { - var components = new[] { FfxivColor.X, FfxivColor.Y, FfxivColor.Z, FfxivColor.W }; + var components = new[] + { + FfxivColor.X, + FfxivColor.Y, + FfxivColor.Z, + FfxivColor.W, + }; if (components.Any(component => component < 0 || component > 1)) throw new ArgumentOutOfRangeException(nameof(FfxivColor)); } @@ -78,22 +90,32 @@ public struct VertexColorFfxiv : IVertexCustom public struct VertexTexture1ColorFfxiv : IVertexCustom { - [VertexAttribute("TEXCOORD_0")] + public IEnumerable> GetEncodingAttributes() + { + yield return new KeyValuePair("TEXCOORD_0", + new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); + yield return new KeyValuePair("_FFXIV_COLOR", + new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); + } + public Vector2 TexCoord0; - [VertexAttribute("_FFXIV_COLOR", EncodingType.UNSIGNED_SHORT, true)] public Vector4 FfxivColor; - public int MaxColors => 0; + public int MaxColors + => 0; - public int MaxTextCoords => 1; + public int MaxTextCoords + => 1; private static readonly string[] CustomNames = ["_FFXIV_COLOR"]; - public IEnumerable CustomAttributes => CustomNames; + + public IEnumerable CustomAttributes + => CustomNames; public VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor) { - TexCoord0 = texCoord0; + TexCoord0 = texCoord0; FfxivColor = ffxivColor; } @@ -103,9 +125,7 @@ public struct VertexTexture1ColorFfxiv : IVertexCustom } public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - { - return new VertexMaterialDelta(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), Vector2.Zero); - } + => new(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), Vector2.Zero); public Vector2 GetTexCoord(int index) => index switch @@ -116,8 +136,10 @@ public struct VertexTexture1ColorFfxiv : IVertexCustom public void SetTexCoord(int setIndex, Vector2 coord) { - if (setIndex == 0) TexCoord0 = coord; - if (setIndex >= 1) throw new ArgumentOutOfRangeException(nameof(setIndex)); + if (setIndex == 0) + TexCoord0 = coord; + if (setIndex >= 1) + throw new ArgumentOutOfRangeException(nameof(setIndex)); } public bool TryGetCustomAttribute(string attributeName, out object? value) @@ -144,12 +166,17 @@ public struct VertexTexture1ColorFfxiv : IVertexCustom => throw new ArgumentOutOfRangeException(nameof(index)); public void SetColor(int setIndex, Vector4 color) - { - } + { } public void Validate() { - var components = new[] { FfxivColor.X, FfxivColor.Y, FfxivColor.Z, FfxivColor.W }; + var components = new[] + { + FfxivColor.X, + FfxivColor.Y, + FfxivColor.Z, + FfxivColor.W, + }; if (components.Any(component => component < 0 || component > 1)) throw new ArgumentOutOfRangeException(nameof(FfxivColor)); } @@ -157,26 +184,35 @@ public struct VertexTexture1ColorFfxiv : IVertexCustom public struct VertexTexture2ColorFfxiv : IVertexCustom { - [VertexAttribute("TEXCOORD_0")] + public IEnumerable> GetEncodingAttributes() + { + yield return new KeyValuePair("TEXCOORD_0", + new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); + yield return new KeyValuePair("TEXCOORD_1", + new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false)); + yield return new KeyValuePair("_FFXIV_COLOR", + new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true)); + } + public Vector2 TexCoord0; - - [VertexAttribute("TEXCOORD_1")] public Vector2 TexCoord1; - - [VertexAttribute("_FFXIV_COLOR", EncodingType.UNSIGNED_SHORT, true)] public Vector4 FfxivColor; - public int MaxColors => 0; + public int MaxColors + => 0; - public int MaxTextCoords => 2; + public int MaxTextCoords + => 2; private static readonly string[] CustomNames = ["_FFXIV_COLOR"]; - public IEnumerable CustomAttributes => CustomNames; + + public IEnumerable CustomAttributes + => CustomNames; public VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor) { - TexCoord0 = texCoord0; - TexCoord1 = texCoord1; + TexCoord0 = texCoord0; + TexCoord1 = texCoord1; FfxivColor = ffxivColor; } @@ -187,9 +223,7 @@ public struct VertexTexture2ColorFfxiv : IVertexCustom } public VertexMaterialDelta Subtract(IVertexMaterial baseValue) - { - return new VertexMaterialDelta(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), TexCoord1 - baseValue.GetTexCoord(1)); - } + => new(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), TexCoord1 - baseValue.GetTexCoord(1)); public Vector2 GetTexCoord(int index) => index switch @@ -201,9 +235,12 @@ public struct VertexTexture2ColorFfxiv : IVertexCustom public void SetTexCoord(int setIndex, Vector2 coord) { - if (setIndex == 0) TexCoord0 = coord; - if (setIndex == 1) TexCoord1 = coord; - if (setIndex >= 2) throw new ArgumentOutOfRangeException(nameof(setIndex)); + if (setIndex == 0) + TexCoord0 = coord; + if (setIndex == 1) + TexCoord1 = coord; + if (setIndex >= 2) + throw new ArgumentOutOfRangeException(nameof(setIndex)); } public bool TryGetCustomAttribute(string attributeName, out object? value) @@ -230,12 +267,17 @@ public struct VertexTexture2ColorFfxiv : IVertexCustom => throw new ArgumentOutOfRangeException(nameof(index)); public void SetColor(int setIndex, Vector4 color) - { - } + { } public void Validate() { - var components = new[] { FfxivColor.X, FfxivColor.Y, FfxivColor.Z, FfxivColor.W }; + var components = new[] + { + FfxivColor.X, + FfxivColor.Y, + FfxivColor.Z, + FfxivColor.W, + }; if (components.Any(component => component < 0 || component > 1)) throw new ArgumentOutOfRangeException(nameof(FfxivColor)); } diff --git a/Penumbra/Import/Models/Import/SubMeshImporter.cs b/Penumbra/Import/Models/Import/SubMeshImporter.cs index e81bb622..df08eea3 100644 --- a/Penumbra/Import/Models/Import/SubMeshImporter.cs +++ b/Penumbra/Import/Models/Import/SubMeshImporter.cs @@ -61,7 +61,7 @@ public class SubMeshImporter try { - _morphNames = node.Mesh.Extras.GetNode("targetNames").Deserialize>(); + _morphNames = node.Mesh.Extras["targetNames"].Deserialize>(); } catch { diff --git a/Penumbra/Import/TexToolsImport.cs b/Penumbra/Import/TexToolsImport.cs index ba089662..fed06573 100644 --- a/Penumbra/Import/TexToolsImport.cs +++ b/Penumbra/Import/TexToolsImport.cs @@ -148,7 +148,7 @@ public partial class TexToolsImporter : IDisposable // You can in no way rely on any file paths in TTMPs so we need to just do this, sorry private static ZipArchiveEntry? FindZipEntry(ZipArchive file, string fileName) - => file.Entries.FirstOrDefault(e => !e.IsDirectory && e.Key.Contains(fileName)); + => file.Entries.FirstOrDefault(e => e is { IsDirectory: false, Key: not null } && e.Key.Contains(fileName)); private static string GetStringFromZipEntry(ZipArchiveEntry entry, Encoding encoding) { diff --git a/Penumbra/Import/TexToolsImporter.Archives.cs b/Penumbra/Import/TexToolsImporter.Archives.cs index dea343c6..febbe179 100644 --- a/Penumbra/Import/TexToolsImporter.Archives.cs +++ b/Penumbra/Import/TexToolsImporter.Archives.cs @@ -82,7 +82,7 @@ public partial class TexToolsImporter if (name.Length == 0) throw new Exception("Invalid mod archive: mod meta has no name."); - using var f = File.OpenWrite(Path.Combine(_currentModDirectory.FullName, reader.Entry.Key)); + using var f = File.OpenWrite(Path.Combine(_currentModDirectory.FullName, reader.Entry.Key!)); s.Seek(0, SeekOrigin.Begin); s.WriteTo(f); } @@ -155,13 +155,9 @@ public partial class TexToolsImporter ret = directory; // Check that all other files are also contained in the top-level directory. - if (ret.IndexOfAny(new[] - { - '/', - '\\', - }) - >= 0 - || !archive.Entries.All(e => e.Key.StartsWith(ret) && (e.Key.Length == ret.Length || e.Key[ret.Length] is '/' or '\\'))) + if (ret.IndexOfAny(['/', '\\']) >= 0 + || !archive.Entries.All(e + => e.Key != null && e.Key.StartsWith(ret) && (e.Key.Length == ret.Length || e.Key[ret.Length] is '/' or '\\'))) throw new Exception( "Invalid mod archive: meta.json in wrong location. It needs to be either at root or one directory deep, in which all other files must be nested too."); } diff --git a/Penumbra/Penumbra.csproj b/Penumbra/Penumbra.csproj index 8e143e3c..f42d16ad 100644 --- a/Penumbra/Penumbra.csproj +++ b/Penumbra/Penumbra.csproj @@ -86,11 +86,11 @@ - + - - - + + + diff --git a/Penumbra/Services/MigrationManager.cs b/Penumbra/Services/MigrationManager.cs index 9041fbd0..aa2d445e 100644 --- a/Penumbra/Services/MigrationManager.cs +++ b/Penumbra/Services/MigrationManager.cs @@ -242,7 +242,7 @@ public class MigrationManager(Configuration config) : IService return; } - var path = Path.Combine(directory, reader.Entry.Key); + var path = Path.Combine(directory, reader.Entry.Key!); using var s = new MemoryStream(); using var e = reader.OpenEntryStream(); e.CopyTo(s); diff --git a/Penumbra/packages.lock.json b/Penumbra/packages.lock.json index 8e7106dd..fd3a0a9e 100644 --- a/Penumbra/packages.lock.json +++ b/Penumbra/packages.lock.json @@ -4,11 +4,11 @@ "net8.0-windows7.0": { "EmbedIO": { "type": "Direct", - "requested": "[3.4.3, )", - "resolved": "3.4.3", - "contentHash": "YM6hpZNAfvbbixfG9T4lWDGfF0D/TqutbTROL4ogVcHKwPF1hp+xS3ABwd3cxxTxvDFkj/zZl57QgWuFA8Igxw==", + "requested": "[3.5.2, )", + "resolved": "3.5.2", + "contentHash": "YU4j+3XvuO8/VPkNf7KWOF1TpMhnyVhXnPsG1mvnDhTJ9D5BZOFXVDvCpE/SkQ1AJ0Aa+dXOVSW3ntgmLL7aJg==", "dependencies": { - "Unosquare.Swan.Lite": "3.0.0" + "Unosquare.Swan.Lite": "3.1.0" } }, "PeNet": { @@ -23,23 +23,26 @@ }, "SharpCompress": { "type": "Direct", - "requested": "[0.33.0, )", - "resolved": "0.33.0", - "contentHash": "FlHfpTAADzaSlVCBF33iKJk9UhOr3Xj+r5LXbW2GzqYr0SrhiOf6shLX2LC2fqs7g7d+YlwKbBXqWFtb+e7icw==" + "requested": "[0.37.2, )", + "resolved": "0.37.2", + "contentHash": "cFBpTct57aubLQXkdqMmgP8GGTFRh7fnRWP53lgE/EYUpDZJ27SSvTkdjB4OYQRZ20SJFpzczUquKLbt/9xkhw==", + "dependencies": { + "ZstdSharp.Port": "0.8.0" + } }, "SharpGLTF.Core": { "type": "Direct", - "requested": "[1.0.0-alpha0030, )", - "resolved": "1.0.0-alpha0030", - "contentHash": "HVL6PcrM0H/uEk96nRZfhtPeYvSFGHnni3g1aIckot2IWVp0jLMH5KWgaWfsatEz4Yds3XcdSLUWmJZivDBUPA==" + "requested": "[1.0.1, )", + "resolved": "1.0.1", + "contentHash": "ykeV1oNHcJrEJE7s0pGAsf/nYGYY7wqF9nxCMxJUjp/WdW+UUgR1cGdbAa2lVZPkiXEwLzWenZ5wPz7yS0Gj9w==" }, "SharpGLTF.Toolkit": { "type": "Direct", - "requested": "[1.0.0-alpha0030, )", - "resolved": "1.0.0-alpha0030", - "contentHash": "nsoJWAFhXgEky9bVCY0zLeZVDx+S88u7VjvuebvMb6dJiNyFOGF6FrrMHiJe+x5pcVBxxlc3VoXliBF7r/EqYA==", + "requested": "[1.0.1, )", + "resolved": "1.0.1", + "contentHash": "LYBjHdHW5Z8R1oT1iI04si3559tWdZ3jTdHfDEu0jqhuyU8w3oJRLFUoDfVeCOI5zWXlVQPtlpjhH9XTfFFAcA==", "dependencies": { - "SharpGLTF.Runtime": "1.0.0-alpha0030" + "SharpGLTF.Runtime": "1.0.1" } }, "SixLabors.ImageSharp": { @@ -50,8 +53,8 @@ }, "JetBrains.Annotations": { "type": "Transitive", - "resolved": "2023.3.0", - "contentHash": "PHfnvdBUdGaTVG9bR/GEfxgTwWM0Z97Y6X3710wiljELBISipSfF5okn/vz+C2gfO+ihoEyVPjaJwn8ZalVukA==" + "resolved": "2024.2.0", + "contentHash": "GNnqCFW/163p1fOehKx0CnAqjmpPrUSqrgfHM6qca+P+RN39C9rhlfZHQpJhxmQG/dkOYe/b3Z0P8b6Kv5m1qw==" }, "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", @@ -73,10 +76,10 @@ }, "SharpGLTF.Runtime": { "type": "Transitive", - "resolved": "1.0.0-alpha0030", - "contentHash": "Ysn+fyj9EVXj6mfG0BmzSTBGNi/QvcnTrMd54dBMOlI/TsMRvnOY3JjTn0MpeH2CgHXX4qogzlDt4m+rb3n4Og==", + "resolved": "1.0.1", + "contentHash": "KsgEBKLfsEnu2IPeKaWp4Ih97+kby17IohrAB6Ev8gET18iS80nKMW/APytQWpenMmcWU06utInpANqyrwRlDg==", "dependencies": { - "SharpGLTF.Core": "1.0.0-alpha0030" + "SharpGLTF.Core": "1.0.1" } }, "System.Formats.Asn1": { @@ -99,16 +102,21 @@ }, "Unosquare.Swan.Lite": { "type": "Transitive", - "resolved": "3.0.0", - "contentHash": "noPwJJl1Q9uparXy1ogtkmyAPGNfSGb0BLT1292nFH1jdMKje6o2kvvrQUvF9Xklj+IoiAI0UzF6Aqxlvo10lw==", + "resolved": "3.1.0", + "contentHash": "X3s5QE/KMj3WAPFqFve7St+Ds10BB50u8kW8PmKIn7FVkn7yEXe9Yxr2htt1WV85DRqfFR0MN/BUNHkGHtL4OQ==", "dependencies": { "System.ValueTuple": "4.5.0" } }, + "ZstdSharp.Port": { + "type": "Transitive", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" + }, "ottergui": { "type": "Project", "dependencies": { - "JetBrains.Annotations": "[2023.3.0, )", + "JetBrains.Annotations": "[2024.2.0, )", "Microsoft.Extensions.DependencyInjection": "[8.0.0, )" } }, @@ -122,7 +130,7 @@ "type": "Project", "dependencies": { "OtterGui": "[1.0.0, )", - "Penumbra.Api": "[5.2.0, )", + "Penumbra.Api": "[5.3.0, )", "Penumbra.String": "[1.0.4, )" } },