diff --git a/Penumbra/Import/Models/Export/MeshExporter.cs b/Penumbra/Import/Models/Export/MeshExporter.cs index 83a0c3cf..928c8670 100644 --- a/Penumbra/Import/Models/Export/MeshExporter.cs +++ b/Penumbra/Import/Models/Export/MeshExporter.cs @@ -38,7 +38,9 @@ public class MeshExporter public string[] Attributes; } - public static Mesh Export(ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) + public static Mesh Export(in ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, + GltfSkeleton? skeleton, + IoNotifier notifier) { var self = new MeshExporter(config, mdl, lod, meshIndex, materials, skeleton, notifier); return new Mesh(self.BuildMeshes(), skeleton); @@ -65,7 +67,8 @@ public class MeshExporter private readonly Type _skinningType; // TODO: This signature is getting out of control. - private MeshExporter(ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) + private MeshExporter(in ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, + GltfSkeleton? skeleton, IoNotifier notifier) { _config = config; _notifier = notifier; @@ -118,9 +121,10 @@ public class MeshExporter Ensure all dependencies are enabled in the current collection, and EST entries (if required) are configured. If this is a known issue with this model and you would like to export anyway, enable the ""Generate missing bones"" option." ); - + (_, gltfBoneIndex) = skeleton.GenerateBone(boneName); - _notifier.Warning($"Generated missing bone \"{boneName}\". Vertices weighted to this bone will not move with the rest of the armature."); + _notifier.Warning( + $"Generated missing bone \"{boneName}\". Vertices weighted to this bone will not move with the rest of the armature."); } indexMap.Add((ushort)tableIndex, gltfBoneIndex); @@ -144,7 +148,7 @@ public class MeshExporter .Take(XivMesh.SubMeshCount) .WithIndex() .Select(subMesh => BuildMesh($"mesh {_meshIndex}.{subMesh.Index}", indices, vertices, - (int)(subMesh.Value.IndexOffset - XivMesh.StartIndex), (int)subMesh.Value.IndexCount, + (int)(subMesh.Value.IndexOffset - XivMesh.StartIndex), (int)subMesh.Value.IndexCount, subMesh.Value.AttributeIndexMask)) .ToArray(); } @@ -233,7 +237,7 @@ public class MeshExporter return new MeshData { - Mesh = meshBuilder, + Mesh = meshBuilder, Attributes = attributes, }; } diff --git a/Penumbra/Import/Models/Export/ModelExporter.cs b/Penumbra/Import/Models/Export/ModelExporter.cs index e0c42d40..55997ef8 100644 --- a/Penumbra/Import/Models/Export/ModelExporter.cs +++ b/Penumbra/Import/Models/Export/ModelExporter.cs @@ -23,7 +23,7 @@ public class ModelExporter } /// Export a model in preparation for usage in a glTF file. If provided, skeleton will be used to skin the resulting meshes where appropriate. - public static Model Export(ExportConfig config, MdlFile mdl, IEnumerable xivSkeletons, Dictionary rawMaterials, IoNotifier notifier) + public static Model Export(in ExportConfig config, MdlFile mdl, IEnumerable xivSkeletons, Dictionary rawMaterials, IoNotifier notifier) { var gltfSkeleton = ConvertSkeleton(xivSkeletons); var materials = ConvertMaterials(mdl, rawMaterials, notifier); @@ -32,7 +32,7 @@ public class ModelExporter } /// Convert a .mdl to a mesh (group) per LoD. - private static List ConvertMeshes(ExportConfig config, MdlFile mdl, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) + private static List ConvertMeshes(in ExportConfig config, MdlFile mdl, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) { var meshes = new List(); diff --git a/Penumbra/Import/Models/ModelManager.cs b/Penumbra/Import/Models/ModelManager.cs index 5340d556..2c341c8b 100644 --- a/Penumbra/Import/Models/ModelManager.cs +++ b/Penumbra/Import/Models/ModelManager.cs @@ -37,7 +37,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect _tasks.Clear(); } - public Task ExportToGltf(ExportConfig config, MdlFile mdl, IEnumerable sklbPaths, Func read, string outputPath) + public Task ExportToGltf(in ExportConfig config, MdlFile mdl, IEnumerable sklbPaths, Func read, string outputPath) => EnqueueWithResult( new ExportToGltfAction(this, config, mdl, sklbPaths, read, outputPath), action => action.Notifier @@ -189,7 +189,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect string outputPath) : IAction { - public IoNotifier Notifier = new IoNotifier(); + public readonly IoNotifier Notifier = new(); public void Execute(CancellationToken cancel) { @@ -224,7 +224,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect // be picked up, if relevant, when the model tries to create mappings // for a bone in the failed sklb. var havokTasks = sklbPaths - .Select(path => read(path)) + .Select(read) .Where(bytes => bytes != null) .Select(bytes => new SklbFile(bytes!)) .WithIndex() @@ -280,7 +280,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect return pngImage ?? throw new Exception("Failed to convert texture to png."); } - private Image CreateDummyImage() + private static Image CreateDummyImage() { var image = new Image(1, 1); image[0, 0] = Color.White; @@ -299,8 +299,8 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect private partial class ImportGltfAction(string inputPath) : IAction { - public MdlFile? Out; - public IoNotifier Notifier = new IoNotifier(); + public MdlFile? Out; + public readonly IoNotifier Notifier = new(); public void Execute(CancellationToken cancel) { diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.MdlTab.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.MdlTab.cs index 8b3a7040..f24464d1 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.MdlTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.MdlTab.cs @@ -15,7 +15,7 @@ public partial class ModEditWindow { private readonly ModEditWindow _edit; - public MdlFile Mdl { get; private set; } + public MdlFile Mdl { get; private set; } private List?[] _attributes; public bool ImportKeepMaterials; @@ -43,7 +43,7 @@ public partial class ModEditWindow [MemberNotNull(nameof(Mdl), nameof(_attributes))] private void Initialize(MdlFile mdl) { - Mdl = mdl; + Mdl = mdl; _attributes = CreateAttributes(Mdl); } @@ -95,14 +95,14 @@ public partial class ModEditWindow task.ContinueWith(t => { RecordIoExceptions(t.Exception); - GamePaths = t.Result; - PendingIo = false; + GamePaths = t.Result; + PendingIo = false; }); } private EstManipulation[] GetCurrentEstManipulations() { - var mod = _edit._editor.Mod; + var mod = _edit._editor.Mod; var option = _edit._editor.Option; if (mod == null || option == null) return []; @@ -140,17 +140,17 @@ public partial class ModEditWindow RecordIoExceptions(task.Exception); if (task is { IsCompletedSuccessfully: true, Result: not null }) IoWarnings = task.Result.GetWarnings().ToList(); - PendingIo = false; + PendingIo = false; }); } - - /// Import a model from an interchange format. + + /// Import a model from an interchange format. /// Disk path to load model data from. public void Import(string inputPath) { PendingIo = true; _edit._models.ImportGltf(inputPath) - .ContinueWith((Task<(MdlFile?, IoNotifier)> task) => + .ContinueWith(task => { RecordIoExceptions(task.Exception); if (task is { IsCompletedSuccessfully: true, Result: (not null, _) }) @@ -158,6 +158,7 @@ public partial class ModEditWindow IoWarnings = task.Result.Item2.GetWarnings().ToList(); FinalizeImport(task.Result.Item1); } + PendingIo = false; }); } @@ -178,11 +179,11 @@ public partial class ModEditWindow // TODO: Add flag editing. newMdl.Flags1 = Mdl.Flags1; newMdl.Flags2 = Mdl.Flags2; - + Initialize(newMdl); _dirty = true; } - + /// Merge material configuration from the source onto the target. /// Model that will be updated. /// Model to copy material configuration from. @@ -218,10 +219,12 @@ public partial class ModEditWindow // to maintain semantic connection between mesh index and sub mesh attributes. if (meshIndex >= source.Meshes.Length) continue; + var sourceMesh = source.Meshes[meshIndex]; if (subMeshOffset >= sourceMesh.SubMeshCount) continue; + var sourceSubMesh = source.SubMeshes[sourceMesh.SubMeshIndex + subMeshOffset]; target.SubMeshes[subMeshIndex].AttributeIndexMask = sourceSubMesh.AttributeIndexMask; @@ -237,11 +240,13 @@ public partial class ModEditWindow foreach (var sourceElement in source.ElementIds) { - var sourceBone = source.Bones[sourceElement.ParentBoneName]; + var sourceBone = source.Bones[sourceElement.ParentBoneName]; var targetIndex = target.Bones.IndexOf(sourceBone); // Given that there's no means of authoring these at the moment, this should probably remain a hard error. if (targetIndex == -1) - throw new Exception($"Failed to merge element IDs. Original model contains element IDs targeting bone {sourceBone}, which is not present on the imported model."); + throw new Exception( + $"Failed to merge element IDs. Original model contains element IDs targeting bone {sourceBone}, which is not present on the imported model."); + elementIds.Add(sourceElement with { ParentBoneName = (uint)targetIndex, @@ -253,13 +258,14 @@ public partial class ModEditWindow private void RecordIoExceptions(Exception? exception) { - IoExceptions = exception switch { + IoExceptions = exception switch + { null => [], AggregateException ae => [.. ae.Flatten().InnerExceptions], _ => [exception], }; } - + /// Read a file from the active collection or game. /// Game path to the file to load. // TODO: Also look up files within the current mod regardless of mod state? @@ -297,7 +303,7 @@ public partial class ModEditWindow /// Create a list of attributes per sub mesh. private static List?[] CreateAttributes(MdlFile mdl) - => mdl.SubMeshes.Select(s => + => mdl.SubMeshes.Select(s => { var maxAttribute = 31 - BitOperations.LeadingZeroCount(s.AttributeIndexMask); // TODO: Research what results in this - it seems to primarily be reproducible on bgparts, is it garbage data, or an alternative usage of the value? diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs index 744e9ea2..561cbed7 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Models.cs @@ -170,8 +170,7 @@ public partial class ModEditWindow using var exceptionNode = ImRaii.TreeNode(message); if (exceptionNode) { - ImGui.Dummy(new Vector2(ImGui.GetStyle().IndentSpacing, 0)); - ImGui.SameLine(); + using var indent = ImRaii.PushIndent(); ImGuiUtil.TextWrapped(exception.ToString()); } } @@ -202,9 +201,8 @@ public partial class ModEditWindow using var warningNode = ImRaii.TreeNode(firstLine); if (warningNode) { - ImGui.Dummy(new Vector2(ImGui.GetStyle().IndentSpacing, 0)); - ImGui.SameLine(); - ImGuiUtil.TextWrapped(warning.ToString()); + using var indent = ImRaii.PushIndent(); + ImGuiUtil.TextWrapped(warning); } } }