mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Move persitence logic to tab file
This commit is contained in:
parent
f04b295989
commit
28246244cd
2 changed files with 96 additions and 60 deletions
|
|
@ -1,3 +1,5 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.Files;
|
||||
|
||||
namespace Penumbra.UI.AdvancedWindow;
|
||||
|
|
@ -8,9 +10,94 @@ 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);
|
||||
}
|
||||
|
||||
private List<string>[] HydrateAttributes(MdlFile mdl)
|
||||
{
|
||||
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())
|
||||
{
|
||||
var materialIndex = allMaterials.IndexOf(material);
|
||||
if (materialIndex == -1)
|
||||
{
|
||||
allMaterials.Add(material);
|
||||
materialIndex = allMaterials.Count() - 1;
|
||||
}
|
||||
|
||||
Mdl.Meshes[meshIndex].MaterialIndex = (ushort)materialIndex;
|
||||
}
|
||||
|
||||
Mdl.Materials = allMaterials.ToArray();
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<string> GetSubmeshAttributes(int submeshIndex) => _attributes[submeshIndex];
|
||||
|
||||
public void UpdateSubmeshAttribute(int submeshIndex, string? old, string? new_)
|
||||
{
|
||||
var attributes = _attributes[submeshIndex];
|
||||
|
||||
if (old != null)
|
||||
attributes.Remove(old);
|
||||
|
||||
if (new_ != null)
|
||||
attributes.Add(new_);
|
||||
|
||||
PersistAttributes();
|
||||
}
|
||||
|
||||
private void PersistAttributes()
|
||||
{
|
||||
var allAttributes = new List<string>();
|
||||
|
||||
foreach (var (attributes, submeshIndex) in _attributes.WithIndex())
|
||||
{
|
||||
var mask = 0u;
|
||||
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
var attributeIndex = allAttributes.IndexOf(attribute);
|
||||
if (attributeIndex == -1)
|
||||
{
|
||||
allAttributes.Add(attribute);
|
||||
attributeIndex = allAttributes.Count() - 1;
|
||||
}
|
||||
|
||||
mask |= 1u << attributeIndex;
|
||||
}
|
||||
|
||||
Mdl.SubMeshes[submeshIndex].AttributeIndexMask = mask;
|
||||
}
|
||||
|
||||
Mdl.Attributes = allAttributes.ToArray();
|
||||
}
|
||||
|
||||
public bool Valid => Mdl.Valid;
|
||||
|
|
|
|||
|
|
@ -29,32 +29,33 @@ public partial class ModEditWindow
|
|||
var ret = false;
|
||||
|
||||
for (var i = 0; i < file.Meshes.Length; ++i)
|
||||
ret |= DrawMeshDetails(file, i, disabled);
|
||||
ret |= DrawMeshDetails(tab, i, disabled);
|
||||
|
||||
ret |= DrawOtherModelDetails(file, disabled);
|
||||
|
||||
return !disabled && ret;
|
||||
}
|
||||
|
||||
private static bool DrawMeshDetails(MdlFile file, int meshIndex, bool disabled)
|
||||
private static bool DrawMeshDetails(MdlTab tab, int meshIndex, bool disabled)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader($"Mesh {meshIndex}"))
|
||||
return false;
|
||||
|
||||
using var id = ImRaii.PushId(meshIndex);
|
||||
|
||||
var file = tab.Mdl;
|
||||
var mesh = file.Meshes[meshIndex];
|
||||
|
||||
var ret = false;
|
||||
|
||||
// Mesh material.
|
||||
var temp = file.Materials[mesh.MaterialIndex];
|
||||
var temp = tab.GetMeshMaterial(meshIndex);
|
||||
if (
|
||||
ImGui.InputText("Material", ref temp, Utf8GamePath.MaxGamePathLength, disabled ? ImGuiInputTextFlags.ReadOnly : ImGuiInputTextFlags.None)
|
||||
&& temp.Length > 0
|
||||
&& temp != file.Materials[mesh.MaterialIndex]
|
||||
&& temp != tab.GetMeshMaterial(meshIndex)
|
||||
) {
|
||||
file.Materials[mesh.MaterialIndex] = temp;
|
||||
tab.SetMeshMaterial(meshIndex, temp);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
|
@ -64,20 +65,16 @@ public partial class ModEditWindow
|
|||
using var submeshId = ImRaii.PushId(submeshOffset);
|
||||
|
||||
var submeshIndex = mesh.SubMeshIndex + submeshOffset;
|
||||
|
||||
var submesh = file.SubMeshes[submeshIndex];
|
||||
var widget = _submeshAttributeTagWidgets[submeshIndex];
|
||||
|
||||
var attributes = HydrateAttributes(file, submesh.AttributeIndexMask).ToArray();
|
||||
var attributes = tab.GetSubmeshAttributes(submeshIndex);
|
||||
|
||||
UiHelpers.DefaultLineSpace();
|
||||
var tagIndex = widget.Draw($"Submesh {submeshOffset} Attributes", "", attributes, out var editedAttribute, !disabled);
|
||||
if (tagIndex >= 0)
|
||||
{
|
||||
EditSubmeshAttribute(
|
||||
file,
|
||||
tab.UpdateSubmeshAttribute(
|
||||
submeshIndex,
|
||||
tagIndex < attributes.Length ? attributes[tagIndex] : null,
|
||||
tagIndex < attributes.Count() ? attributes.ElementAt(tagIndex) : null,
|
||||
editedAttribute != "" ? editedAttribute : null
|
||||
);
|
||||
|
||||
|
|
@ -88,54 +85,6 @@ public partial class ModEditWindow
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static void EditSubmeshAttribute(MdlFile file, int changedSubmeshIndex, string? old, string? new_)
|
||||
{
|
||||
// Build a hydrated view of all attributes in the model
|
||||
var submeshAttributes = file.SubMeshes
|
||||
.Select(submesh => HydrateAttributes(file, submesh.AttributeIndexMask).ToList())
|
||||
.ToArray();
|
||||
|
||||
// Make changes to the submesh we're actually editing here.
|
||||
var changedSubmesh = submeshAttributes[changedSubmeshIndex];
|
||||
|
||||
if (old != null)
|
||||
changedSubmesh.Remove(old);
|
||||
|
||||
if (new_ != null)
|
||||
changedSubmesh.Add(new_);
|
||||
|
||||
// Re-serialize all the attributes.
|
||||
var allAttributes = new List<string>();
|
||||
foreach (var (attributes, submeshIndex) in submeshAttributes.WithIndex())
|
||||
{
|
||||
var mask = 0u;
|
||||
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
var attributeIndex = allAttributes.IndexOf(attribute);
|
||||
if (attributeIndex == -1)
|
||||
{
|
||||
allAttributes.Add(attribute);
|
||||
attributeIndex = allAttributes.Count() - 1;
|
||||
}
|
||||
|
||||
mask |= 1u << attributeIndex;
|
||||
}
|
||||
|
||||
file.SubMeshes[submeshIndex].AttributeIndexMask = mask;
|
||||
}
|
||||
|
||||
file.Attributes = allAttributes.ToArray();
|
||||
}
|
||||
|
||||
private static IEnumerable<string> HydrateAttributes(MdlFile file, uint mask)
|
||||
{
|
||||
return Enumerable
|
||||
.Range(0, 32)
|
||||
.Where(index => ((mask >> index) & 1) == 1)
|
||||
.Select(index => file.Attributes[index]);
|
||||
}
|
||||
|
||||
private static bool DrawOtherModelDetails(MdlFile file, bool _)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Further Content"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue