Flesh out material wiring

This commit is contained in:
ackwell 2023-12-22 23:49:50 +11:00
parent 829016a1c4
commit a581495c7e
2 changed files with 62 additions and 64 deletions

View file

@ -1,5 +1,6 @@
using System.Collections.ObjectModel;
using OtterGui;
using Penumbra.GameData;
using Penumbra.GameData.Files;
namespace Penumbra.UI.AdvancedWindow;
@ -10,53 +11,37 @@ public partial class ModEditWindow
{
public readonly MdlFile Mdl;
private List<string> _materials;
private List<string>[] _attributes;
public MdlTab(byte[] bytes)
{
Mdl = new MdlFile(bytes);
_materials = Mdl.Meshes.Select(mesh => Mdl.Materials[mesh.MaterialIndex]).ToList();
_attributes = HydrateAttributes(Mdl);
_attributes = PopulateAttributes();
}
private List<string>[] HydrateAttributes(MdlFile mdl)
public void RemoveMaterial(int materialIndex)
{
return mdl.SubMeshes.Select(submesh =>
Enumerable.Range(0,32)
.Where(index => ((submesh.AttributeIndexMask >> index) & 1) == 1)
.Select(index => mdl.Attributes[index])
.ToList()
).ToArray();
}
public string GetMeshMaterial(int meshIndex) => _materials[meshIndex];
public void SetMeshMaterial(int meshIndex, string materialPath)
{
_materials[meshIndex] = materialPath;
PersistMaterials();
}
private void PersistMaterials()
{
var allMaterials = new List<string>();
foreach (var (material, meshIndex) in _materials.WithIndex())
// Meshes using the removed material are redirected to material 0, and those after the index are corrected.
for (var meshIndex = 0; meshIndex < Mdl.Meshes.Length; meshIndex++)
{
var materialIndex = allMaterials.IndexOf(material);
if (materialIndex == -1)
{
allMaterials.Add(material);
materialIndex = allMaterials.Count() - 1;
}
Mdl.Meshes[meshIndex].MaterialIndex = (ushort)materialIndex;
var mesh = Mdl.Meshes[meshIndex];
if (mesh.MaterialIndex == materialIndex)
mesh.MaterialIndex = 0;
else if (mesh.MaterialIndex > materialIndex)
mesh.MaterialIndex -= 1;
}
Mdl.Materials = allMaterials.ToArray();
Mdl.Materials = Mdl.Materials.RemoveItems(materialIndex);
}
private List<string>[] PopulateAttributes()
{
return Mdl.SubMeshes.Select(submesh =>
Enumerable.Range(0,32)
.Where(index => ((submesh.AttributeIndexMask >> index) & 1) == 1)
.Select(index => Mdl.Attributes[index])
.ToList()
).ToArray();
}
public IReadOnlyCollection<string> GetSubmeshAttributes(int submeshIndex) => _attributes[submeshIndex];

View file

@ -3,6 +3,7 @@ using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Widgets;
using Penumbra.GameData;
using Penumbra.GameData.Files;
using Penumbra.String.Classes;
@ -14,6 +15,7 @@ public partial class ModEditWindow
private readonly FileEditor<MdlTab> _modelTab;
private static string _modelNewMaterial = string.Empty;
private static List<TagButtons> _submeshAttributeTagWidgets = new();
private static bool DrawModelPanel(MdlTab tab, bool disabled)
@ -47,12 +49,13 @@ public partial class ModEditWindow
if (!ImGui.CollapsingHeader("Materials"))
return false;
var materials = tab.Mdl.Materials;
using var table = ImRaii.Table(string.Empty, 3, ImGuiTableFlags.SizingFixedFit);
if (!table)
return false;
var ret = false;
var materials = tab.Mdl.Materials;
ImGui.TableSetupColumn("index", ImGuiTableColumnFlags.WidthFixed, 80 * UiHelpers.Scale);
ImGui.TableSetupColumn("path", ImGuiTableColumnFlags.WidthStretch, 1);
ImGui.TableSetupColumn("actions", ImGuiTableColumnFlags.WidthFixed, UiHelpers.IconButtonSize.X);
@ -63,6 +66,8 @@ public partial class ModEditWindow
for (var materialIndex = 0; materialIndex < materials.Length; materialIndex++)
{
using var id = ImRaii.PushId(materialIndex);
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.Text($"Material #{materialIndex + 1}");
@ -70,44 +75,52 @@ public partial class ModEditWindow
var temp = materials[materialIndex];
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(-1);
ImGui.InputText($"##material{materialIndex}", ref temp, Utf8GamePath.MaxGamePathLength, inputFlags);
if (
ImGui.InputText($"##material{materialIndex}", ref temp, Utf8GamePath.MaxGamePathLength, inputFlags)
&& temp.Length > 0
&& temp != materials[materialIndex]
) {
materials[materialIndex] = temp;
ret = true;
}
ImGui.TableNextColumn();
var todoDelete = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), UiHelpers.IconButtonSize, "description", disabled || !ImGui.GetIO().KeyCtrl, true);
// Need to have at least one material.
if (materials.Length <= 1)
continue;
if (ImGuiUtil.DrawDisabledButton(
FontAwesomeIcon.Trash.ToIconString(),
UiHelpers.IconButtonSize,
"Delete this material.\nAny meshes targeting this material will be updated to use material #1.\nHold Control while clicking to delete.",
disabled || !ImGui.GetIO().KeyCtrl,
true
)) {
tab.RemoveMaterial(materialIndex);
ret = true;
}
}
if (materials.Length < MdlMaterialMaximum)
{
ImGui.TableNextColumn();
// todo: persist
var temp = "";
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(-1);
ImGui.InputTextWithHint($"##newMaterial", "Add new material...", ref temp, Utf8GamePath.MaxGamePathLength, inputFlags);
ImGui.InputTextWithHint($"##newMaterial", "Add new material...", ref _modelNewMaterial, Utf8GamePath.MaxGamePathLength, inputFlags);
// todo: flesh out this validation
var validName = temp != "";
var validName = _modelNewMaterial != "";
ImGui.TableNextColumn();
var todoAdd = ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), UiHelpers.IconButtonSize, "description", disabled || !validName, true);
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), UiHelpers.IconButtonSize, "description", disabled || !validName, true))
{
tab.Mdl.Materials = materials.AddItem(_modelNewMaterial);
_modelNewMaterial = string.Empty;
ret = true;
}
}
// for (var index = 0; index < MdlMaterialMaximum; index++)
// {
// var temp = "";
// ImGui.InputText($"Material {index}", ref temp, Utf8GamePath.MaxGamePathLength, inputFlags);
// }
// var temp = tab.GetMeshMaterial(meshIndex);
// if (
// ImGui.InputText("Material", ref temp, Utf8GamePath.MaxGamePathLength, disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None)
// && temp.Length > 0
// && temp != tab.GetMeshMaterial(meshIndex)
// ) {
// tab.SetMeshMaterial(meshIndex, temp);
// ret = true;
// }
return false;
return ret;
}
private static bool DrawModelLodDetails(MdlTab tab, int lodIndex, bool disabled)
@ -160,7 +173,7 @@ public partial class ModEditWindow
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(-1);
using (var materialCombo = ImRaii.Combo("##material", tab.GetMeshMaterial(meshIndex)))
using (var materialCombo = ImRaii.Combo("##material", "TODO material"))
{
// todo
}