From 8c3a493ef36731e23013c1d342a7b45a79956034 Mon Sep 17 00:00:00 2001 From: Passive <20432486+PassiveModding@users.noreply.github.com> Date: Sun, 28 Jul 2024 19:21:08 +1000 Subject: [PATCH] Update Mdl resolution + ui cleanup - fixes mdl deform resolution when file name on disk doesn't contain character code - includes both resolved path and disk path in logs and ui - cleanup UI to use tables instead of columns --- Meddle/Meddle.Plugin/Models/Groups.cs | 6 +- Meddle/Meddle.Plugin/UI/CharacterTab.cs | 501 +++++++++++------------ Meddle/Meddle.Plugin/Utils/ExportUtil.cs | 19 +- Meddle/Meddle.Plugin/Utils/ParseUtil.cs | 11 +- Meddle/Meddle.Plugin/Utils/UIUtil.cs | 65 ++- 5 files changed, 284 insertions(+), 318 deletions(-) diff --git a/Meddle/Meddle.Plugin/Models/Groups.cs b/Meddle/Meddle.Plugin/Models/Groups.cs index 09c4258..5f3524b 100644 --- a/Meddle/Meddle.Plugin/Models/Groups.cs +++ b/Meddle/Meddle.Plugin/Models/Groups.cs @@ -13,8 +13,8 @@ public record CharacterGroup( AttachedModelGroup[] AttachedModelGroups); public record AttachedModelGroup(Attach Attach, MdlFileGroup[] MdlGroups, Skeleton.Skeleton Skeleton); -public record MdlFileGroup(string Path, MdlFile MdlFile, MtrlFileGroup[] MtrlFiles, Model.ShapeAttributeGroup? ShapeAttributeGroup); -public record MtrlFileGroup(string Path, MtrlFile MtrlFile, string ShpkPath, ShpkFile ShpkFile, TexResourceGroup[] TexFiles); -public record TexResourceGroup(string MtrlPath, string ResourcePath, TextureResource Resource); +public record MdlFileGroup(string CharacterPath, string Path, MdlFile MdlFile, MtrlFileGroup[] MtrlFiles, Model.ShapeAttributeGroup? ShapeAttributeGroup); +public record MtrlFileGroup(string MdlPath, string Path, MtrlFile MtrlFile, string ShpkPath, ShpkFile ShpkFile, TexResourceGroup[] TexFiles); +public record TexResourceGroup(string MtrlPath, string Path, TextureResource Resource); public record SklbFileGroup(string Path, SklbFile File); public record Resource(string MdlPath, Vector3 Position, Quaternion Rotation, Vector3 Scale); diff --git a/Meddle/Meddle.Plugin/UI/CharacterTab.cs b/Meddle/Meddle.Plugin/UI/CharacterTab.cs index 8af8b3b..a0cf153 100644 --- a/Meddle/Meddle.Plugin/UI/CharacterTab.cs +++ b/Meddle/Meddle.Plugin/UI/CharacterTab.cs @@ -279,149 +279,40 @@ private void DrawCharacterGroup() DrawSkeleton(characterGroup.Skeleton); } - foreach (var mdlGroup in characterGroup.MdlGroups) + if (ImGui.BeginTable("CharacterTable", 2, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) { - ImGui.PushID(mdlGroup.GetHashCode()); - if (ImGui.CollapsingHeader(mdlGroup.Path)) - { - ImGui.Indent(); - DrawMdlGroup(mdlGroup); - ImGui.Unindent(); - } + ImGui.TableSetupColumn("Options", ImGuiTableColumnFlags.WidthFixed, 100); + // Export button, export toggle checkbox + ImGui.TableSetupColumn("Character Data", ImGuiTableColumnFlags.WidthStretch); + // Character data + ImGui.TableHeadersRow(); - ImGui.PopID(); - } - - if (characterGroup.AttachedModelGroups.Length > 0) - { - ImGui.Separator(); - foreach (var attachedModelGroup in characterGroup.AttachedModelGroups) + foreach (var mdlGroup in characterGroup.MdlGroups) { - foreach (var mdlGroup in attachedModelGroup.MdlGroups) + ImGui.PushID(mdlGroup.GetHashCode()); + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); + if (ImGui.Button("Export")) { - ImGui.PushID(mdlGroup.GetHashCode()); - if (ImGui.CollapsingHeader(mdlGroup.Path)) + exportTask = Task.Run(() => { - ImGui.Indent(); - DrawMdlGroup(mdlGroup); - ImGui.Unindent(); - } - - ImGui.PopID(); - } - } - } - - ImGui.PopID(); - } - - private void DrawExportOptions() - { - if (characterGroup == null) return; - var availWidth = ImGui.GetContentRegionAvail().X; - - ImGui.BeginDisabled(ExportTaskIncomplete); - if (ImGui.Button("Export All")) - { - exportTask = Task.Run(() => - { - try - { - exportUtil.Export(characterGroup); - } - catch (Exception e) - { - log.LogError(e, "Failed to export character"); - throw; - } - }); - } - - if (ImGui.Button("Export Raw Textures")) - { - exportTask = Task.Run(() => - { - try - { - exportUtil.ExportRawTextures(characterGroup); - } - catch (Exception e) - { - log.LogError(e, "Failed to export raw textures"); - throw; - } - }); - } - - ImGui.EndDisabled(); - - if (selectedSetGroup == null) return; - if (ImGui.CollapsingHeader("Export Individual")) - { - ImGui.BeginDisabled(ExportTaskIncomplete); - if (ImGui.Button($"Export Selected Models##{characterGroup.GetHashCode()}")) - { - var group = characterGroup with - { - MdlGroups = selectedSetGroup.MdlGroups, - AttachedModelGroups = selectedSetGroup.AttachedModelGroups - }; - exportTask = Task.Run(() => - { - log.LogInformation("Exporting selected models"); - try - { - exportUtil.Export(group); - } - catch (Exception e) - { - log.LogError(e, "Failed to export selected models"); - throw; - } - }); - } - - ImGui.EndDisabled(); - - ImGui.Columns(2, "ExportIndividual", true); - try - { - // set size - ImGui.SetColumnWidth(0, availWidth * 0.2f); - ImGui.Text("Export"); - ImGui.NextColumn(); - ImGui.Text("Path"); - ImGui.NextColumn(); - foreach (var mdlGroup in characterGroup.MdlGroups) - { - ImGui.PushID(mdlGroup.GetHashCode()); - ImGui.BeginDisabled(ExportTaskIncomplete); - if (ImGui.Button("Export")) - { - var group = characterGroup with + try { - MdlGroups = [mdlGroup], - AttachedModelGroups = [] - }; - exportTask = Task.Run(() => + exportUtil.Export(characterGroup with {MdlGroups = [mdlGroup], AttachedModelGroups = []}); + } + catch (Exception e) { - try - { - exportUtil.Export(group); - } - catch (Exception e) - { - log.LogError(e, "Failed to export mdl group"); - throw; - } - }); - } - - ImGui.EndDisabled(); - - var selected = selectedSetGroup.MdlGroups.Contains(mdlGroup); + log.LogError(e, "Failed to export mdl group"); + throw; + } + }); + } + if (selectedSetGroup != null) + { ImGui.SameLine(); + // checkbox for selecting + var selected = selectedSetGroup.MdlGroups.Contains(mdlGroup); if (ImGui.Checkbox($"##{mdlGroup.GetHashCode()}", ref selected)) { // if selected, make sure mdlgroup is in selectedSetGroup @@ -440,30 +331,45 @@ private void DrawExportOptions() }; } } + } - ImGui.NextColumn(); - ImGui.Text(mdlGroup.Path); - ImGui.NextColumn(); - ImGui.PopID(); + ImGui.TableSetColumnIndex(1); + if (ImGui.CollapsingHeader(mdlGroup.CharacterPath)) + { + ImGui.Indent(); + DrawMdlGroup(mdlGroup); + ImGui.Unindent(); } - ImGui.Separator(); + ImGui.PopID(); + } + + ImGui.EndTable(); + } + + + if (characterGroup.AttachedModelGroups.Length > 0) + { + if (ImGui.BeginTable("AttachedCharacterTable", 2, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) + { + ImGui.TableSetupColumn("Options", ImGuiTableColumnFlags.WidthFixed, 100); + // Export button, export toggle checkbox + ImGui.TableSetupColumn("Attached Character Data", ImGuiTableColumnFlags.WidthStretch); + // Character data + ImGui.TableHeadersRow(); + foreach (var attachedModelGroup in characterGroup.AttachedModelGroups) { ImGui.PushID(attachedModelGroup.GetHashCode()); - ImGui.BeginDisabled(ExportTaskIncomplete); + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); if (ImGui.Button("Export")) { - var group = characterGroup with - { - AttachedModelGroups = [attachedModelGroup], - MdlGroups = [] - }; exportTask = Task.Run(() => { try { - exportUtil.Export(group); + exportUtil.Export(characterGroup with {AttachedModelGroups = [attachedModelGroup], MdlGroups = []}); } catch (Exception e) { @@ -473,45 +379,119 @@ private void DrawExportOptions() }); } - ImGui.EndDisabled(); - - ImGui.SameLine(); - - var selected = selectedSetGroup.AttachedModelGroups.Contains(attachedModelGroup); - if (ImGui.Checkbox($"##{attachedModelGroup.GetHashCode()}", ref selected)) + if (selectedSetGroup != null) { - if (selected) + ImGui.SameLine(); + // checkbox for selecting + var selected = selectedSetGroup.AttachedModelGroups.Contains(attachedModelGroup); + if (ImGui.Checkbox($"##{attachedModelGroup.GetHashCode()}", ref selected)) { - selectedSetGroup = selectedSetGroup with + // if selected, make sure mdlgroup is in selectedSetGroup + if (selected) { - AttachedModelGroups = selectedSetGroup.AttachedModelGroups.Append(attachedModelGroup) - .ToArray() - }; - } - else - { - selectedSetGroup = selectedSetGroup with + selectedSetGroup = selectedSetGroup with + { + AttachedModelGroups = selectedSetGroup.AttachedModelGroups.Append(attachedModelGroup).ToArray() + }; + } + else { - AttachedModelGroups = selectedSetGroup.AttachedModelGroups - .Where(m => m != attachedModelGroup).ToArray() - }; + selectedSetGroup = selectedSetGroup with + { + AttachedModelGroups = selectedSetGroup.AttachedModelGroups.Where(m => m != attachedModelGroup).ToArray() + }; + } } } - ImGui.NextColumn(); - foreach (var attachMdl in attachedModelGroup.MdlGroups) + ImGui.TableSetColumnIndex(1); + foreach (var mdlGroup in attachedModelGroup.MdlGroups) { - ImGui.Text(attachMdl.Path); - } + ImGui.PushID(mdlGroup.GetHashCode()); + if (ImGui.CollapsingHeader(mdlGroup.CharacterPath)) + { + ImGui.Indent(); + DrawMdlGroup(mdlGroup); + ImGui.Unindent(); + } - ImGui.NextColumn(); + ImGui.PopID(); + } + ImGui.PopID(); } - } finally + + ImGui.EndTable(); + } + } + + + ImGui.PopID(); + } + + private void DrawExportOptions() + { + if (characterGroup == null) return; + var availWidth = ImGui.GetContentRegionAvail().X; + + ImGui.BeginDisabled(ExportTaskIncomplete); + if (ImGui.Button("Export All")) + { + exportTask = Task.Run(() => + { + try + { + exportUtil.Export(characterGroup); + } + catch (Exception e) + { + log.LogError(e, "Failed to export character"); + throw; + } + }); + } + + ImGui.SameLine(); + var selectedCount = (selectedSetGroup?.MdlGroups.Length ?? 0) + (selectedSetGroup?.AttachedModelGroups.Length ?? 0); + if (ImGui.Button($"Export {selectedCount} Selected##ExportSelected")) + { + if (selectedSetGroup == null) { - ImGui.Columns(1); + log.LogWarning("No selected set group"); + return; } + exportTask = Task.Run(() => + { + try + { + exportUtil.Export(selectedSetGroup); + } + catch (Exception e) + { + log.LogError(e, "Failed to export selected set group"); + throw; + } + }); + } + + ImGui.SameLine(); + if (ImGui.Button("Export Raw Textures")) + { + exportTask = Task.Run(() => + { + try + { + exportUtil.ExportRawTextures(characterGroup); + } + catch (Exception e) + { + log.LogError(e, "Failed to export raw textures"); + throw; + } + }); } + + ImGui.EndDisabled(); } private Task ParseCharacter(ICharacter character) @@ -635,55 +615,52 @@ private Task ParseCharacter(ICharacter character) private void DrawMdlGroup(MdlFileGroup mdlGroup) { + ImGui.Text($"Character Path: {mdlGroup.CharacterPath}"); ImGui.Text($"Path: {mdlGroup.Path}"); ImGui.Text($"Mtrl Files: {mdlGroup.MtrlFiles.Length}"); - if (mdlGroup.ShapeAttributeGroup != null && ImGui.CollapsingHeader("Shape/Attribute Masks")) + var shouldShowShapeAttributeMenu = + mdlGroup.ShapeAttributeGroup is {ShapeMasks.Length: > 0} or {AttributeMasks.Length: > 0}; + + if (shouldShowShapeAttributeMenu && ImGui.CollapsingHeader("Shape/Attribute Masks")) { - var enabledShapes = Model.GetEnabledValues(mdlGroup.ShapeAttributeGroup.EnabledShapeMask, + var enabledShapes = Model.GetEnabledValues(mdlGroup.ShapeAttributeGroup!.EnabledShapeMask, mdlGroup.ShapeAttributeGroup.ShapeMasks).ToArray(); var enabledAttributes = Model.GetEnabledValues(mdlGroup.ShapeAttributeGroup.EnabledAttributeMask, mdlGroup.ShapeAttributeGroup.AttributeMasks).ToArray(); - ImGui.Text("Shapes"); - ImGui.Columns(2); - ImGui.Text("Name"); - ImGui.NextColumn(); - ImGui.Text("Enabled"); - ImGui.NextColumn(); - - foreach (var shape in mdlGroup.ShapeAttributeGroup.ShapeMasks) - { - ImGui.Text($"[{shape.id}] {shape.name}"); - ImGui.NextColumn(); - ImGui.Text(enabledShapes.Contains(shape.name) ? "Yes" : "No"); - ImGui.NextColumn(); - } - - ImGui.Columns(1); - - ImGui.Text("Attributes"); - ImGui.Columns(2); - ImGui.Text("Name"); - ImGui.NextColumn(); - ImGui.Text("Enabled"); - ImGui.NextColumn(); - - foreach (var attribute in mdlGroup.ShapeAttributeGroup.AttributeMasks) + if (ImGui.BeginTable("ShapeAttributeTable", 2, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) { - ImGui.Text($"[{attribute.id}] {attribute.name}"); - ImGui.NextColumn(); - ImGui.Text(enabledAttributes.Contains(attribute.name) ? "Yes" : "No"); - ImGui.NextColumn(); + ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Enabled", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableHeadersRow(); + + foreach (var shape in mdlGroup.ShapeAttributeGroup.ShapeMasks) + { + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); + ImGui.Text($"[{shape.id}] {shape.name}"); + ImGui.TableSetColumnIndex(1); + ImGui.Text(enabledShapes.Contains(shape.name) ? "Yes" : "No"); + } + + foreach (var attribute in mdlGroup.ShapeAttributeGroup.AttributeMasks) + { + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); + ImGui.Text($"[{attribute.id}] {attribute.name}"); + ImGui.TableSetColumnIndex(1); + ImGui.Text(enabledAttributes.Contains(attribute.name) ? "Yes" : "No"); + } + + ImGui.EndTable(); } - - ImGui.Columns(1); } foreach (var mtrlGroup in mdlGroup.MtrlFiles) { ImGui.PushID(mtrlGroup.GetHashCode()); - if (ImGui.CollapsingHeader($"{mtrlGroup.Path}")) + if (ImGui.CollapsingHeader($"{mtrlGroup.MdlPath}")) { try { @@ -701,23 +678,20 @@ private void DrawMdlGroup(MdlFileGroup mdlGroup) private void DrawMtrlGroup(MtrlFileGroup mtrlGroup) { + ImGui.Text($"Mdl Path: {mtrlGroup.MdlPath}"); ImGui.Text($"Path: {mtrlGroup.Path}"); ImGui.Text($"Shpk Path: {mtrlGroup.ShpkPath}"); ImGui.Text($"Tex Files: {mtrlGroup.TexFiles.Length}"); if (ImGui.CollapsingHeader($"Constants##{mtrlGroup.GetHashCode()}")) { - try + if (ImGui.BeginTable("ConstantsTable", 4, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) { - ImGui.Columns(4); - ImGui.Text("ID"); - ImGui.NextColumn(); - ImGui.Text("Offset"); - ImGui.NextColumn(); - ImGui.Text("Size"); - ImGui.NextColumn(); - ImGui.Text("Values"); - ImGui.NextColumn(); + ImGui.TableSetupColumn("ID", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Offset", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Size", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Values", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableHeadersRow(); foreach (var constant in mtrlGroup.MtrlFile.Constants) { @@ -731,82 +705,73 @@ private void DrawMtrlGroup(MtrlFileGroup mtrlGroup) buf.AddRange(bytes); } - // display as floats + // Display as floats var floats = MemoryMarshal.Cast(buf.ToArray()); + + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); ImGui.Text($"0x{constant.ConstantId:X4}"); - // if has named value in MaterialConstant enum, display + // If has named value in MaterialConstant enum, display if (Enum.IsDefined(typeof(MaterialConstant), constant.ConstantId)) { ImGui.SameLine(); ImGui.Text($"({(MaterialConstant)constant.ConstantId})"); } - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(1); ImGui.Text($"{constant.ValueOffset:X4}"); - ImGui.NextColumn(); + + ImGui.TableSetColumnIndex(2); ImGui.Text($"{count}"); - ImGui.NextColumn(); + + ImGui.TableSetColumnIndex(3); ImGui.Text(string.Join(", ", floats.ToArray())); - ImGui.NextColumn(); } - } finally - { - ImGui.Columns(1); + + ImGui.EndTable(); } } if (ImGui.CollapsingHeader($"Shader Keys##{mtrlGroup.GetHashCode()}")) { var keys = mtrlGroup.MtrlFile.ShaderKeys; - ImGui.Columns(2); - ImGui.Text("Category"); - ImGui.NextColumn(); - ImGui.Text("Value"); - ImGui.NextColumn(); - - foreach (var key in keys) + if (ImGui.BeginTable("ShaderKeysTable", 2, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) { - ImGui.Text($"0x{key.Category:X8}"); - if (Enum.IsDefined(typeof(ShaderCategory), key.Category)) - { - ImGui.SameLine(); - ImGui.Text($"({(ShaderCategory)key.Category})"); - } + ImGui.TableSetupColumn("Category", ImGuiTableColumnFlags.WidthFixed, 150); + ImGui.TableSetupColumn("Value", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableHeadersRow(); - ImGui.NextColumn(); - ImGui.Text($"0x{key.Value:X8}"); - - var shaderCategory = (ShaderCategory)key.Category; - switch (shaderCategory) + foreach (var key in keys) { - case ShaderCategory.CategoryHairType: - ImGui.SameLine(); - ImGui.Text($"({(HairType)key.Value})"); - break; - case ShaderCategory.CategorySkinType: - ImGui.SameLine(); - ImGui.Text($"({(SkinType)key.Value})"); - break; - case ShaderCategory.CategoryFlowMapType: - ImGui.SameLine(); - ImGui.Text($"({(FlowType)key.Value})"); - break; - case ShaderCategory.CategoryTextureType: - ImGui.SameLine(); - ImGui.Text($"({(TextureMode)key.Value})"); - break; - case ShaderCategory.CategorySpecularType: + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); + ImGui.Text($"0x{key.Category:X8}"); + if (Enum.IsDefined(typeof(ShaderCategory), key.Category)) + { ImGui.SameLine(); - ImGui.Text($"({(SpecularMode)key.Value})"); - break; + ImGui.Text($"({(ShaderCategory)key.Category})"); + } + + ImGui.TableSetColumnIndex(1); + var catText = $"0x{key.Value:X8}"; + var catSuffix = (ShaderCategory)key.Category switch + { + ShaderCategory.CategoryHairType => $" ({(HairType)key.Value})", + ShaderCategory.CategorySkinType => $" ({(SkinType)key.Value})", + ShaderCategory.CategoryFlowMapType => $" ({(FlowType)key.Value})", + ShaderCategory.CategoryTextureType => $" ({(TextureMode)key.Value})", + ShaderCategory.CategorySpecularType => $" ({(SpecularMode)key.Value})", + _ => "" + }; + + ImGui.Text($"{catText}{catSuffix}"); } - ImGui.NextColumn(); + ImGui.EndTable(); } - - ImGui.Columns(1); } + if (ImGui.CollapsingHeader($"Color Table##{mtrlGroup.GetHashCode()}")) { UIUtil.DrawColorTable(mtrlGroup.MtrlFile); @@ -823,11 +788,9 @@ private void DrawMtrlGroup(MtrlFileGroup mtrlGroup) private void DrawTexGroup(TexResourceGroup texGroup) { - ImGui.Text($"Path: {texGroup.MtrlPath}"); - if (texGroup.MtrlPath != texGroup.ResourcePath) - { - ImGui.Text($"Resource Path: {texGroup.ResourcePath}"); - } + ImGui.Text($"Mtrl Path: {texGroup.MtrlPath}"); + ImGui.Text($"Path: {texGroup.Path}"); + ImGui.PushID(texGroup.GetHashCode()); try { diff --git a/Meddle/Meddle.Plugin/Utils/ExportUtil.cs b/Meddle/Meddle.Plugin/Utils/ExportUtil.cs index 31e815c..a69f0b3 100644 --- a/Meddle/Meddle.Plugin/Utils/ExportUtil.cs +++ b/Meddle/Meddle.Plugin/Utils/ExportUtil.cs @@ -259,12 +259,12 @@ public static void AddMesh( } } - private MaterialBuilder HandleMaterial(CharacterGroup characterGroup, Material material) + private MaterialBuilder HandleMaterial(CharacterGroup characterGroup, Material material, MtrlFileGroup mtrlGroup) { using var activityMtrl = ActivitySource.StartActivity(); activityMtrl?.SetTag("mtrlPath", material.HandlePath); - logger.LogInformation("Exporting {Path}", material.HandlePath); + logger.LogInformation("Exporting {HandlePath} => {Path}", material.HandlePath, mtrlGroup.Path); activityMtrl?.SetTag("shaderPackageName", material.ShaderPackageName); var name = $"{Path.GetFileNameWithoutExtension(material.HandlePath)}_{Path.GetFileNameWithoutExtension(material.ShaderPackageName)}"; @@ -293,11 +293,12 @@ private MaterialBuilder HandleMaterial(CharacterGroup characterGroup, Material m CharacterGroup characterGroup, MdlFileGroup mdlGroup, ref List bones, BoneNodeBuilder? root, CancellationToken token) { using var activity = ActivitySource.StartActivity(); - activity?.SetTag("mdlPath", mdlGroup.Path); - logger.LogInformation("Exporting {Path}", mdlGroup.Path); - var model = new Model(mdlGroup.Path, mdlGroup.MdlFile, + activity?.SetTag("characterPath", mdlGroup.CharacterPath); + activity?.SetTag("path", mdlGroup.Path); + logger.LogInformation("Exporting {CharacterPath} => {Path}", mdlGroup.CharacterPath, mdlGroup.Path); + var model = new Model(mdlGroup.CharacterPath, mdlGroup.MdlFile, mdlGroup.MtrlFiles.Select(x => ( - x.Path, + x.MdlPath, x.MtrlFile, x.TexFiles.ToDictionary(tf => tf.MtrlPath, tf => tf.Resource), x.ShpkFile)).ToArray(), @@ -334,7 +335,9 @@ private MaterialBuilder HandleMaterial(CharacterGroup characterGroup, Material m { if (token.IsCancellationRequested) return meshOutput; var material = model.Materials[i]; - var builder = HandleMaterial(characterGroup, material); + var materialGroup = mdlGroup.MtrlFiles[i]; + if (material == null) throw new InvalidOperationException("Material is null"); + var builder = HandleMaterial(characterGroup, material, materialGroup); materials.Add(builder); } @@ -401,7 +404,7 @@ public void ExportResource(Resource[] resources, Vector3 rootPosition) texGroups.Add(new TexResourceGroup(texPath, texPath, Texture.GetResource(texFile))); } - mtrlGroups.Add(new MtrlFileGroup(mtrlPath, mtrlFile, shpkPath, shpkFile, texGroups.ToArray())); + mtrlGroups.Add(new MtrlFileGroup(mtrlPath, mtrlPath, mtrlFile, shpkPath, shpkFile, texGroups.ToArray())); } var model = new Model(resource.MdlPath, mdlFile, diff --git a/Meddle/Meddle.Plugin/Utils/ParseUtil.cs b/Meddle/Meddle.Plugin/Utils/ParseUtil.cs index deddfcb..0a8da4c 100644 --- a/Meddle/Meddle.Plugin/Utils/ParseUtil.cs +++ b/Meddle/Meddle.Plugin/Utils/ParseUtil.cs @@ -11,6 +11,7 @@ using Meddle.Utils.Files.SqPack; using Meddle.Utils.Files.Structs.Material; using Meddle.Plugin.Models; +using Meddle.Utils.Models; using Meddle.Utils.Skeletons.Havok; using Meddle.Utils.Skeletons.Havok.Models; using Microsoft.Extensions.Logging; @@ -153,6 +154,7 @@ public unsafe CharacterGroup HandleCharacterGroup( var model = modelPtr.Value; var mdlFileName = model->ModelResourceHandle->ResourceHandle.FileName.ToString(); + var mdlFileActorName = characterBase->ResolveMdlPath((uint)modelIdx); activity?.SetTag("mdl", mdlFileName); var mdlFileResource = pack.GetFileOrReadFromDisk(mdlFileName); if (mdlFileResource == null) @@ -179,6 +181,7 @@ public unsafe CharacterGroup HandleCharacterGroup( new Model.ShapeAttributeGroup(shapesMask, attributeMask, shapes.ToArray(), attributes.ToArray()); var mdlFile = new MdlFile(mdlFileResource); + var mtrlFileNames = mdlFile.GetMaterialNames().Select(x => x.Value).ToArray(); var mtrlGroups = new List(); for (var j = 0; j < model->MaterialsSpan.Length; j++) { @@ -190,14 +193,15 @@ public unsafe CharacterGroup HandleCharacterGroup( continue; } - var mtrlGroup = HandleMtrl(material, modelIdx, j, colorTables); + var mdlMtrlFileName = mtrlFileNames[j]; + var mtrlGroup = HandleMtrl(mdlMtrlFileName, material, modelIdx, j, colorTables); if (mtrlGroup != null) { mtrlGroups.Add(mtrlGroup); } } - return new MdlFileGroup(mdlFileName, mdlFile, mtrlGroups.ToArray(), shapeAttributeGroup); + return new MdlFileGroup(mdlFileActorName, mdlFileName, mdlFile, mtrlGroups.ToArray(), shapeAttributeGroup); } private ShpkFile HandleShpk(string shader) @@ -221,6 +225,7 @@ private ShpkFile HandleShpk(string shader) } private unsafe MtrlFileGroup? HandleMtrl( + string mdlPath, FFXIVClientStructs.FFXIV.Client.Graphics.Render.Material* material, int modelIdx, int j, Dictionary colorTables) { @@ -272,7 +277,7 @@ private ShpkFile HandleShpk(string shader) var texResourceGroup = new TexResourceGroup(texturePath, resourcePath, data.Resource); texGroups.Add(texResourceGroup); } - return new MtrlFileGroup(mtrlFileName, mtrlFile, shader, shpkFile, texGroups.ToArray()); + return new MtrlFileGroup(mdlPath, mtrlFileName, mtrlFile, shader, shpkFile, texGroups.ToArray()); } /*private Meddle.Utils.Export.Texture.TexGroup? HandleTexture(string textureName) diff --git a/Meddle/Meddle.Plugin/Utils/UIUtil.cs b/Meddle/Meddle.Plugin/Utils/UIUtil.cs index 7db5838..bb1a479 100644 --- a/Meddle/Meddle.Plugin/Utils/UIUtil.cs +++ b/Meddle/Meddle.Plugin/Utils/UIUtil.cs @@ -43,32 +43,26 @@ public static void DrawCustomizeData(CustomizeData customize) public static void DrawColorTable(ColorTable table, ColorDyeTable? dyeTable = null) { - ImGui.Columns(9, "ColorTable", true); - ImGui.Text("Row"); - ImGui.NextColumn(); - ImGui.Text("Diffuse"); - ImGui.NextColumn(); - ImGui.Text("Specular"); - ImGui.NextColumn(); - ImGui.Text("Emissive"); - ImGui.NextColumn(); - ImGui.Text("Material Repeat"); - ImGui.NextColumn(); - ImGui.Text("Material Skew"); - ImGui.NextColumn(); - ImGui.Text("Specular"); - ImGui.NextColumn(); - ImGui.Text("Gloss"); - ImGui.NextColumn(); - ImGui.Text("Tile Set"); - ImGui.NextColumn(); - - for (var i = 0; i < table.Rows.Length; i++) + if (ImGui.BeginTable("ColorTable", 9, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) { - DrawRow(i, table, dyeTable); - } + ImGui.TableSetupColumn("Row", ImGuiTableColumnFlags.WidthFixed, 50); + ImGui.TableSetupColumn("Diffuse", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Specular", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Emissive", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Material Repeat", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Material Skew", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Specular Strength", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Gloss", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableSetupColumn("Tile Set", ImGuiTableColumnFlags.WidthFixed, 100); + ImGui.TableHeadersRow(); - ImGui.Columns(1); + for (var i = 0; i < table.Rows.Length; i++) + { + DrawRow(i, table, dyeTable); + } + + ImGui.EndTable(); + } } public static void DrawColorTable(MtrlFile file) @@ -87,8 +81,10 @@ public static void DrawColorTable(MtrlFile file) private static void DrawRow(int i, ColorTable table, ColorDyeTable? dyeTable) { ref var row = ref table.Rows[i]; + ImGui.TableNextRow(); + ImGui.TableSetColumnIndex(0); ImGui.Text($"{i}"); - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(1); ImGui.ColorButton("##rowdiff", new Vector4(row.Diffuse, 1f), ImGuiColorEditFlags.NoAlpha); if (dyeTable != null) { @@ -97,7 +93,7 @@ private static void DrawRow(int i, ColorTable table, ColorDyeTable? dyeTable) ImGui.Checkbox("##rowdiff", ref diff); } - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(2); ImGui.ColorButton("##rowspec", new Vector4(row.Specular, 1f), ImGuiColorEditFlags.NoAlpha); if (dyeTable != null) { @@ -106,7 +102,7 @@ private static void DrawRow(int i, ColorTable table, ColorDyeTable? dyeTable) ImGui.Checkbox("##rowspec", ref spec); } - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(3); ImGui.ColorButton("##rowemm", new Vector4(row.Emissive, 1f), ImGuiColorEditFlags.NoAlpha); if (dyeTable != null) { @@ -115,20 +111,20 @@ private static void DrawRow(int i, ColorTable table, ColorDyeTable? dyeTable) ImGui.Checkbox("##rowemm", ref emm); } - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(4); ImGui.Text($"{row.MaterialRepeat}"); - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(5); ImGui.Text($"{row.MaterialSkew}"); - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(6); if (dyeTable != null) { - var spec = dyeTable.Value[i].SpecularStrength; - ImGui.Checkbox("##rowspecstr", ref spec); + var specStrength = dyeTable.Value[i].SpecularStrength; + ImGui.Checkbox("##rowspecstr", ref specStrength); ImGui.SameLine(); } ImGui.Text($"{row.SpecularStrength}"); - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(7); if (dyeTable != null) { var gloss = dyeTable.Value[i].Gloss; @@ -137,8 +133,7 @@ private static void DrawRow(int i, ColorTable table, ColorDyeTable? dyeTable) } ImGui.Text($"{row.GlossStrength}"); - ImGui.NextColumn(); + ImGui.TableSetColumnIndex(8); ImGui.Text($"{row.TileIndex}"); - ImGui.NextColumn(); } }