mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-01-02 13:53:42 +01:00
Auto-format and stuff.
This commit is contained in:
parent
fff9fb00f8
commit
7db9599511
5 changed files with 43 additions and 35 deletions
|
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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?
|
||||||
|
|
|
||||||
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue