Move persitence logic to tab file

This commit is contained in:
ackwell 2023-12-21 20:25:01 +11:00
parent f04b295989
commit 28246244cd
2 changed files with 96 additions and 60 deletions

View file

@ -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;

View file

@ -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"))