mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +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 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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue