mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-14 20:54:16 +01:00
Flesh out material wiring
This commit is contained in:
parent
829016a1c4
commit
a581495c7e
2 changed files with 62 additions and 64 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Files;
|
using Penumbra.GameData.Files;
|
||||||
|
|
||||||
namespace Penumbra.UI.AdvancedWindow;
|
namespace Penumbra.UI.AdvancedWindow;
|
||||||
|
|
@ -10,53 +11,37 @@ public partial class ModEditWindow
|
||||||
{
|
{
|
||||||
public readonly MdlFile Mdl;
|
public readonly MdlFile Mdl;
|
||||||
|
|
||||||
private List<string> _materials;
|
|
||||||
private List<string>[] _attributes;
|
private List<string>[] _attributes;
|
||||||
|
|
||||||
public MdlTab(byte[] bytes)
|
public MdlTab(byte[] bytes)
|
||||||
{
|
{
|
||||||
Mdl = new MdlFile(bytes);
|
Mdl = new MdlFile(bytes);
|
||||||
|
_attributes = PopulateAttributes();
|
||||||
_materials = Mdl.Meshes.Select(mesh => Mdl.Materials[mesh.MaterialIndex]).ToList();
|
|
||||||
_attributes = HydrateAttributes(Mdl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string>[] HydrateAttributes(MdlFile mdl)
|
public void RemoveMaterial(int materialIndex)
|
||||||
{
|
{
|
||||||
return mdl.SubMeshes.Select(submesh =>
|
// Meshes using the removed material are redirected to material 0, and those after the index are corrected.
|
||||||
Enumerable.Range(0,32)
|
for (var meshIndex = 0; meshIndex < Mdl.Meshes.Length; meshIndex++)
|
||||||
.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())
|
|
||||||
{
|
{
|
||||||
var materialIndex = allMaterials.IndexOf(material);
|
var mesh = Mdl.Meshes[meshIndex];
|
||||||
if (materialIndex == -1)
|
if (mesh.MaterialIndex == materialIndex)
|
||||||
{
|
mesh.MaterialIndex = 0;
|
||||||
allMaterials.Add(material);
|
else if (mesh.MaterialIndex > materialIndex)
|
||||||
materialIndex = allMaterials.Count() - 1;
|
mesh.MaterialIndex -= 1;
|
||||||
}
|
|
||||||
|
|
||||||
Mdl.Meshes[meshIndex].MaterialIndex = (ushort)materialIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
public IReadOnlyCollection<string> GetSubmeshAttributes(int submeshIndex) => _attributes[submeshIndex];
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using ImGuiNET;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
|
using Penumbra.GameData;
|
||||||
using Penumbra.GameData.Files;
|
using Penumbra.GameData.Files;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
|
||||||
|
|
@ -14,6 +15,7 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
private readonly FileEditor<MdlTab> _modelTab;
|
private readonly FileEditor<MdlTab> _modelTab;
|
||||||
|
|
||||||
|
private static string _modelNewMaterial = string.Empty;
|
||||||
private static List<TagButtons> _submeshAttributeTagWidgets = new();
|
private static List<TagButtons> _submeshAttributeTagWidgets = new();
|
||||||
|
|
||||||
private static bool DrawModelPanel(MdlTab tab, bool disabled)
|
private static bool DrawModelPanel(MdlTab tab, bool disabled)
|
||||||
|
|
@ -47,12 +49,13 @@ public partial class ModEditWindow
|
||||||
if (!ImGui.CollapsingHeader("Materials"))
|
if (!ImGui.CollapsingHeader("Materials"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var materials = tab.Mdl.Materials;
|
|
||||||
|
|
||||||
using var table = ImRaii.Table(string.Empty, 3, ImGuiTableFlags.SizingFixedFit);
|
using var table = ImRaii.Table(string.Empty, 3, ImGuiTableFlags.SizingFixedFit);
|
||||||
if (!table)
|
if (!table)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
var ret = false;
|
||||||
|
var materials = tab.Mdl.Materials;
|
||||||
|
|
||||||
ImGui.TableSetupColumn("index", ImGuiTableColumnFlags.WidthFixed, 80 * UiHelpers.Scale);
|
ImGui.TableSetupColumn("index", ImGuiTableColumnFlags.WidthFixed, 80 * UiHelpers.Scale);
|
||||||
ImGui.TableSetupColumn("path", ImGuiTableColumnFlags.WidthStretch, 1);
|
ImGui.TableSetupColumn("path", ImGuiTableColumnFlags.WidthStretch, 1);
|
||||||
ImGui.TableSetupColumn("actions", ImGuiTableColumnFlags.WidthFixed, UiHelpers.IconButtonSize.X);
|
ImGui.TableSetupColumn("actions", ImGuiTableColumnFlags.WidthFixed, UiHelpers.IconButtonSize.X);
|
||||||
|
|
@ -63,6 +66,8 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
for (var materialIndex = 0; materialIndex < materials.Length; materialIndex++)
|
for (var materialIndex = 0; materialIndex < materials.Length; materialIndex++)
|
||||||
{
|
{
|
||||||
|
using var id = ImRaii.PushId(materialIndex);
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.AlignTextToFramePadding();
|
ImGui.AlignTextToFramePadding();
|
||||||
ImGui.Text($"Material #{materialIndex + 1}");
|
ImGui.Text($"Material #{materialIndex + 1}");
|
||||||
|
|
@ -70,44 +75,52 @@ public partial class ModEditWindow
|
||||||
var temp = materials[materialIndex];
|
var temp = materials[materialIndex];
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(-1);
|
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();
|
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)
|
if (materials.Length < MdlMaterialMaximum)
|
||||||
{
|
{
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
||||||
// todo: persist
|
|
||||||
var temp = "";
|
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(-1);
|
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 = _modelNewMaterial != "";
|
||||||
var validName = temp != "";
|
|
||||||
ImGui.TableNextColumn();
|
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++)
|
return ret;
|
||||||
// {
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool DrawModelLodDetails(MdlTab tab, int lodIndex, bool disabled)
|
private static bool DrawModelLodDetails(MdlTab tab, int lodIndex, bool disabled)
|
||||||
|
|
@ -160,7 +173,7 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
ImGui.SetNextItemWidth(-1);
|
ImGui.SetNextItemWidth(-1);
|
||||||
using (var materialCombo = ImRaii.Combo("##material", tab.GetMeshMaterial(meshIndex)))
|
using (var materialCombo = ImRaii.Combo("##material", "TODO material"))
|
||||||
{
|
{
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue