Auto-format and stuff.

This commit is contained in:
Ottermandias 2024-01-20 16:06:33 +01:00
parent fff9fb00f8
commit 7db9599511
5 changed files with 43 additions and 35 deletions

View file

@ -38,7 +38,9 @@ public class MeshExporter
public string[] Attributes; public string[] Attributes;
} }
public static Mesh Export(ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) public static Mesh Export(in ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials,
GltfSkeleton? skeleton,
IoNotifier notifier)
{ {
var self = new MeshExporter(config, mdl, lod, meshIndex, materials, skeleton, notifier); var self = new MeshExporter(config, mdl, lod, meshIndex, materials, skeleton, notifier);
return new Mesh(self.BuildMeshes(), skeleton); return new Mesh(self.BuildMeshes(), skeleton);
@ -65,7 +67,8 @@ public class MeshExporter
private readonly Type _skinningType; private readonly Type _skinningType;
// TODO: This signature is getting out of control. // TODO: This signature is getting out of control.
private MeshExporter(ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) private MeshExporter(in ExportConfig config, MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials,
GltfSkeleton? skeleton, IoNotifier notifier)
{ {
_config = config; _config = config;
_notifier = notifier; _notifier = notifier;
@ -118,9 +121,10 @@ public class MeshExporter
Ensure all dependencies are enabled in the current collection, and EST entries (if required) are configured. Ensure all dependencies are enabled in the current collection, and EST entries (if required) are configured.
If this is a known issue with this model and you would like to export anyway, enable the ""Generate missing bones"" option." If this is a known issue with this model and you would like to export anyway, enable the ""Generate missing bones"" option."
); );
(_, gltfBoneIndex) = skeleton.GenerateBone(boneName); (_, gltfBoneIndex) = skeleton.GenerateBone(boneName);
_notifier.Warning($"Generated missing bone \"{boneName}\". Vertices weighted to this bone will not move with the rest of the armature."); _notifier.Warning(
$"Generated missing bone \"{boneName}\". Vertices weighted to this bone will not move with the rest of the armature.");
} }
indexMap.Add((ushort)tableIndex, gltfBoneIndex); indexMap.Add((ushort)tableIndex, gltfBoneIndex);
@ -144,7 +148,7 @@ public class MeshExporter
.Take(XivMesh.SubMeshCount) .Take(XivMesh.SubMeshCount)
.WithIndex() .WithIndex()
.Select(subMesh => BuildMesh($"mesh {_meshIndex}.{subMesh.Index}", indices, vertices, .Select(subMesh => BuildMesh($"mesh {_meshIndex}.{subMesh.Index}", indices, vertices,
(int)(subMesh.Value.IndexOffset - XivMesh.StartIndex), (int)subMesh.Value.IndexCount, (int)(subMesh.Value.IndexOffset - XivMesh.StartIndex), (int)subMesh.Value.IndexCount,
subMesh.Value.AttributeIndexMask)) subMesh.Value.AttributeIndexMask))
.ToArray(); .ToArray();
} }
@ -233,7 +237,7 @@ public class MeshExporter
return new MeshData return new MeshData
{ {
Mesh = meshBuilder, Mesh = meshBuilder,
Attributes = attributes, Attributes = attributes,
}; };
} }

View file

@ -23,7 +23,7 @@ public class ModelExporter
} }
/// <summary> Export a model in preparation for usage in a glTF file. If provided, skeleton will be used to skin the resulting meshes where appropriate. </summary> /// <summary> Export a model in preparation for usage in a glTF file. If provided, skeleton will be used to skin the resulting meshes where appropriate. </summary>
public static Model Export(ExportConfig config, MdlFile mdl, IEnumerable<XivSkeleton> xivSkeletons, Dictionary<string, MaterialExporter.Material> rawMaterials, IoNotifier notifier) public static Model Export(in ExportConfig config, MdlFile mdl, IEnumerable<XivSkeleton> xivSkeletons, Dictionary<string, MaterialExporter.Material> rawMaterials, IoNotifier notifier)
{ {
var gltfSkeleton = ConvertSkeleton(xivSkeletons); var gltfSkeleton = ConvertSkeleton(xivSkeletons);
var materials = ConvertMaterials(mdl, rawMaterials, notifier); var materials = ConvertMaterials(mdl, rawMaterials, notifier);
@ -32,7 +32,7 @@ public class ModelExporter
} }
/// <summary> Convert a .mdl to a mesh (group) per LoD. </summary> /// <summary> Convert a .mdl to a mesh (group) per LoD. </summary>
private static List<MeshExporter.Mesh> ConvertMeshes(ExportConfig config, MdlFile mdl, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier) private static List<MeshExporter.Mesh> ConvertMeshes(in ExportConfig config, MdlFile mdl, MaterialBuilder[] materials, GltfSkeleton? skeleton, IoNotifier notifier)
{ {
var meshes = new List<MeshExporter.Mesh>(); var meshes = new List<MeshExporter.Mesh>();

View file

@ -37,7 +37,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
_tasks.Clear(); _tasks.Clear();
} }
public Task<IoNotifier> ExportToGltf(ExportConfig config, MdlFile mdl, IEnumerable<string> sklbPaths, Func<string, byte[]?> read, string outputPath) public Task<IoNotifier> ExportToGltf(in ExportConfig config, MdlFile mdl, IEnumerable<string> sklbPaths, Func<string, byte[]?> read, string outputPath)
=> EnqueueWithResult( => EnqueueWithResult(
new ExportToGltfAction(this, config, mdl, sklbPaths, read, outputPath), new ExportToGltfAction(this, config, mdl, sklbPaths, read, outputPath),
action => action.Notifier action => action.Notifier
@ -189,7 +189,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
string outputPath) string outputPath)
: IAction : IAction
{ {
public IoNotifier Notifier = new IoNotifier(); public readonly IoNotifier Notifier = new();
public void Execute(CancellationToken cancel) public void Execute(CancellationToken cancel)
{ {
@ -224,7 +224,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
// be picked up, if relevant, when the model tries to create mappings // be picked up, if relevant, when the model tries to create mappings
// for a bone in the failed sklb. // for a bone in the failed sklb.
var havokTasks = sklbPaths var havokTasks = sklbPaths
.Select(path => read(path)) .Select(read)
.Where(bytes => bytes != null) .Where(bytes => bytes != null)
.Select(bytes => new SklbFile(bytes!)) .Select(bytes => new SklbFile(bytes!))
.WithIndex() .WithIndex()
@ -280,7 +280,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
return pngImage ?? throw new Exception("Failed to convert texture to png."); return pngImage ?? throw new Exception("Failed to convert texture to png.");
} }
private Image<Rgba32> CreateDummyImage() private static Image<Rgba32> CreateDummyImage()
{ {
var image = new Image<Rgba32>(1, 1); var image = new Image<Rgba32>(1, 1);
image[0, 0] = Color.White; image[0, 0] = Color.White;
@ -299,8 +299,8 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
private partial class ImportGltfAction(string inputPath) : IAction private partial class ImportGltfAction(string inputPath) : IAction
{ {
public MdlFile? Out; public MdlFile? Out;
public IoNotifier Notifier = new IoNotifier(); public readonly IoNotifier Notifier = new();
public void Execute(CancellationToken cancel) public void Execute(CancellationToken cancel)
{ {

View file

@ -15,7 +15,7 @@ public partial class ModEditWindow
{ {
private readonly ModEditWindow _edit; private readonly ModEditWindow _edit;
public MdlFile Mdl { get; private set; } public MdlFile Mdl { get; private set; }
private List<string>?[] _attributes; private List<string>?[] _attributes;
public bool ImportKeepMaterials; public bool ImportKeepMaterials;
@ -43,7 +43,7 @@ public partial class ModEditWindow
[MemberNotNull(nameof(Mdl), nameof(_attributes))] [MemberNotNull(nameof(Mdl), nameof(_attributes))]
private void Initialize(MdlFile mdl) private void Initialize(MdlFile mdl)
{ {
Mdl = mdl; Mdl = mdl;
_attributes = CreateAttributes(Mdl); _attributes = CreateAttributes(Mdl);
} }
@ -95,14 +95,14 @@ public partial class ModEditWindow
task.ContinueWith(t => task.ContinueWith(t =>
{ {
RecordIoExceptions(t.Exception); RecordIoExceptions(t.Exception);
GamePaths = t.Result; GamePaths = t.Result;
PendingIo = false; PendingIo = false;
}); });
} }
private EstManipulation[] GetCurrentEstManipulations() private EstManipulation[] GetCurrentEstManipulations()
{ {
var mod = _edit._editor.Mod; var mod = _edit._editor.Mod;
var option = _edit._editor.Option; var option = _edit._editor.Option;
if (mod == null || option == null) if (mod == null || option == null)
return []; return [];
@ -140,17 +140,17 @@ public partial class ModEditWindow
RecordIoExceptions(task.Exception); RecordIoExceptions(task.Exception);
if (task is { IsCompletedSuccessfully: true, Result: not null }) if (task is { IsCompletedSuccessfully: true, Result: not null })
IoWarnings = task.Result.GetWarnings().ToList(); IoWarnings = task.Result.GetWarnings().ToList();
PendingIo = false; PendingIo = false;
}); });
} }
/// <summary> Import a model from an interchange format. </summary> /// <summary> Import a model from an interchange format. </summary>
/// <param name="inputPath"> Disk path to load model data from. </param> /// <param name="inputPath"> Disk path to load model data from. </param>
public void Import(string inputPath) public void Import(string inputPath)
{ {
PendingIo = true; PendingIo = true;
_edit._models.ImportGltf(inputPath) _edit._models.ImportGltf(inputPath)
.ContinueWith((Task<(MdlFile?, IoNotifier)> task) => .ContinueWith(task =>
{ {
RecordIoExceptions(task.Exception); RecordIoExceptions(task.Exception);
if (task is { IsCompletedSuccessfully: true, Result: (not null, _) }) if (task is { IsCompletedSuccessfully: true, Result: (not null, _) })
@ -158,6 +158,7 @@ public partial class ModEditWindow
IoWarnings = task.Result.Item2.GetWarnings().ToList(); IoWarnings = task.Result.Item2.GetWarnings().ToList();
FinalizeImport(task.Result.Item1); FinalizeImport(task.Result.Item1);
} }
PendingIo = false; PendingIo = false;
}); });
} }
@ -178,11 +179,11 @@ public partial class ModEditWindow
// TODO: Add flag editing. // TODO: Add flag editing.
newMdl.Flags1 = Mdl.Flags1; newMdl.Flags1 = Mdl.Flags1;
newMdl.Flags2 = Mdl.Flags2; newMdl.Flags2 = Mdl.Flags2;
Initialize(newMdl); Initialize(newMdl);
_dirty = true; _dirty = true;
} }
/// <summary> Merge material configuration from the source onto the target. </summary> /// <summary> Merge material configuration from the source onto the target. </summary>
/// <param name="target"> Model that will be updated. </param> /// <param name="target"> Model that will be updated. </param>
/// <param name="source"> Model to copy material configuration from. </param> /// <param name="source"> Model to copy material configuration from. </param>
@ -218,10 +219,12 @@ public partial class ModEditWindow
// to maintain semantic connection between mesh index and sub mesh attributes. // to maintain semantic connection between mesh index and sub mesh attributes.
if (meshIndex >= source.Meshes.Length) if (meshIndex >= source.Meshes.Length)
continue; continue;
var sourceMesh = source.Meshes[meshIndex]; var sourceMesh = source.Meshes[meshIndex];
if (subMeshOffset >= sourceMesh.SubMeshCount) if (subMeshOffset >= sourceMesh.SubMeshCount)
continue; continue;
var sourceSubMesh = source.SubMeshes[sourceMesh.SubMeshIndex + subMeshOffset]; var sourceSubMesh = source.SubMeshes[sourceMesh.SubMeshIndex + subMeshOffset];
target.SubMeshes[subMeshIndex].AttributeIndexMask = sourceSubMesh.AttributeIndexMask; target.SubMeshes[subMeshIndex].AttributeIndexMask = sourceSubMesh.AttributeIndexMask;
@ -237,11 +240,13 @@ public partial class ModEditWindow
foreach (var sourceElement in source.ElementIds) foreach (var sourceElement in source.ElementIds)
{ {
var sourceBone = source.Bones[sourceElement.ParentBoneName]; var sourceBone = source.Bones[sourceElement.ParentBoneName];
var targetIndex = target.Bones.IndexOf(sourceBone); var targetIndex = target.Bones.IndexOf(sourceBone);
// Given that there's no means of authoring these at the moment, this should probably remain a hard error. // Given that there's no means of authoring these at the moment, this should probably remain a hard error.
if (targetIndex == -1) if (targetIndex == -1)
throw new Exception($"Failed to merge element IDs. Original model contains element IDs targeting bone {sourceBone}, which is not present on the imported model."); throw new Exception(
$"Failed to merge element IDs. Original model contains element IDs targeting bone {sourceBone}, which is not present on the imported model.");
elementIds.Add(sourceElement with elementIds.Add(sourceElement with
{ {
ParentBoneName = (uint)targetIndex, ParentBoneName = (uint)targetIndex,
@ -253,13 +258,14 @@ public partial class ModEditWindow
private void RecordIoExceptions(Exception? exception) private void RecordIoExceptions(Exception? exception)
{ {
IoExceptions = exception switch { IoExceptions = exception switch
{
null => [], null => [],
AggregateException ae => [.. ae.Flatten().InnerExceptions], AggregateException ae => [.. ae.Flatten().InnerExceptions],
_ => [exception], _ => [exception],
}; };
} }
/// <summary> Read a file from the active collection or game. </summary> /// <summary> Read a file from the active collection or game. </summary>
/// <param name="path"> Game path to the file to load. </param> /// <param name="path"> Game path to the file to load. </param>
// TODO: Also look up files within the current mod regardless of mod state? // TODO: Also look up files within the current mod regardless of mod state?
@ -297,7 +303,7 @@ public partial class ModEditWindow
/// <summary> Create a list of attributes per sub mesh. </summary> /// <summary> Create a list of attributes per sub mesh. </summary>
private static List<string>?[] CreateAttributes(MdlFile mdl) private static List<string>?[] CreateAttributes(MdlFile mdl)
=> mdl.SubMeshes.Select(s => => mdl.SubMeshes.Select(s =>
{ {
var maxAttribute = 31 - BitOperations.LeadingZeroCount(s.AttributeIndexMask); var maxAttribute = 31 - BitOperations.LeadingZeroCount(s.AttributeIndexMask);
// TODO: Research what results in this - it seems to primarily be reproducible on bgparts, is it garbage data, or an alternative usage of the value? // TODO: Research what results in this - it seems to primarily be reproducible on bgparts, is it garbage data, or an alternative usage of the value?

View file

@ -170,8 +170,7 @@ public partial class ModEditWindow
using var exceptionNode = ImRaii.TreeNode(message); using var exceptionNode = ImRaii.TreeNode(message);
if (exceptionNode) if (exceptionNode)
{ {
ImGui.Dummy(new Vector2(ImGui.GetStyle().IndentSpacing, 0)); using var indent = ImRaii.PushIndent();
ImGui.SameLine();
ImGuiUtil.TextWrapped(exception.ToString()); ImGuiUtil.TextWrapped(exception.ToString());
} }
} }
@ -202,9 +201,8 @@ public partial class ModEditWindow
using var warningNode = ImRaii.TreeNode(firstLine); using var warningNode = ImRaii.TreeNode(firstLine);
if (warningNode) if (warningNode)
{ {
ImGui.Dummy(new Vector2(ImGui.GetStyle().IndentSpacing, 0)); using var indent = ImRaii.PushIndent();
ImGui.SameLine(); ImGuiUtil.TextWrapped(warning);
ImGuiUtil.TextWrapped(warning.ToString());
} }
} }
} }