Clean up model import UI/wiring

This commit is contained in:
ackwell 2024-01-07 11:29:31 +11:00
parent 1a88cefd52
commit b62bc44564
3 changed files with 72 additions and 31 deletions

View file

@ -10,7 +10,7 @@ using SharpGLTF.Schema2;
namespace Penumbra.Import.Models; namespace Penumbra.Import.Models;
public sealed class ModelManager(IFramework framework, GamePathParser _parser) : SingleTaskQueue, IDisposable public sealed class ModelManager(IFramework framework, GamePathParser parser) : SingleTaskQueue, IDisposable
{ {
private readonly IFramework _framework = framework; private readonly IFramework _framework = framework;
@ -29,17 +29,17 @@ public sealed class ModelManager(IFramework framework, GamePathParser _parser) :
public Task ExportToGltf(MdlFile mdl, SklbFile? sklb, string outputPath) public Task ExportToGltf(MdlFile mdl, SklbFile? sklb, string outputPath)
=> Enqueue(new ExportToGltfAction(this, mdl, sklb, outputPath)); => Enqueue(new ExportToGltfAction(this, mdl, sklb, outputPath));
public Task<MdlFile> ImportGltf() public Task<MdlFile?> ImportGltf(string inputPath)
{ {
var action = new ImportGltfAction(); var action = new ImportGltfAction(inputPath);
return Enqueue(action).ContinueWith(_ => action.Out!); return Enqueue(action).ContinueWith(_ => action.Out);
} }
/// <summary> Try to find the .sklb path for a .mdl file. </summary> /// <summary> Try to find the .sklb path for a .mdl file. </summary>
/// <param name="mdlPath"> .mdl file to look up the skeleton for. </param> /// <param name="mdlPath"> .mdl file to look up the skeleton for. </param>
public string? ResolveSklbForMdl(string mdlPath) public string? ResolveSklbForMdl(string mdlPath)
{ {
var info = _parser.GetFileInfo(mdlPath); var info = parser.GetFileInfo(mdlPath);
if (info.FileType is not FileType.Model) if (info.FileType is not FileType.Model)
return null; return null;
@ -126,18 +126,13 @@ public sealed class ModelManager(IFramework framework, GamePathParser _parser) :
} }
} }
private partial class ImportGltfAction : IAction private partial class ImportGltfAction(string inputPath) : IAction
{ {
public MdlFile? Out; public MdlFile? Out;
public ImportGltfAction()
{
//
}
public void Execute(CancellationToken cancel) public void Execute(CancellationToken cancel)
{ {
var model = ModelRoot.Load("C:\\Users\\ackwell\\blender\\gltf-tests\\c0201e6180_top.gltf"); var model = ModelRoot.Load(inputPath);
Out = ModelImporter.Import(model); Out = ModelImporter.Import(model);
} }

View file

@ -18,8 +18,9 @@ public partial class ModEditWindow
public List<Utf8GamePath>? GamePaths { get; private set; } public List<Utf8GamePath>? GamePaths { get; private set; }
public int GamePathIndex; public int GamePathIndex;
public bool PendingIo { get; private set; } private bool _dirty;
public string? IoException { get; private set; } public bool PendingIo { get; private set; }
public string? IoException { get; private set; }
public MdlTab(ModEditWindow edit, byte[] bytes, string path, IMod? mod) public MdlTab(ModEditWindow edit, byte[] bytes, string path, IMod? mod)
{ {
@ -46,6 +47,16 @@ public partial class ModEditWindow
public byte[] Write() public byte[] Write()
=> Mdl.Write(); => Mdl.Write();
public bool Dirty
{
get
{
var dirty = _dirty;
_dirty = false;
return dirty;
}
}
/// <summary> Find the list of game paths that may correspond to this model. </summary> /// <summary> Find the list of game paths that may correspond to this model. </summary>
/// <param name="path"> Resolved path to a .mdl. </param> /// <param name="path"> Resolved path to a .mdl. </param>
/// <param name="mod"> Mod within which the .mdl is resolved. </param> /// <param name="mod"> Mod within which the .mdl is resolved. </param>
@ -77,14 +88,28 @@ public partial class ModEditWindow
}); });
} }
public void Import() /// <summary> Import a model from an interchange format. </summary>
/// <param name="inputPath"> Disk path to load model data from. </param>
public void Import(string inputPath)
{ {
// TODO: this needs to be fleshed out a bunch. PendingIo = true;
_edit._models.ImportGltf().ContinueWith(v => Initialize(v.Result ?? Mdl)); _edit._models.ImportGltf(inputPath)
.ContinueWith(task =>
{
IoException = task.Exception?.ToString();
PendingIo = false;
if (task.IsCompletedSuccessfully && task.Result != null)
{
Initialize(task.Result);
_dirty = true;
}
});
} }
/// <summary> Export model to an interchange format. </summary> /// <summary> Export model to an interchange format. </summary>
/// <param name="outputPath"> Disk path to save the resulting file to. </param> /// <param name="outputPath"> Disk path to save the resulting file to. </param>
/// <param name="mdlPath"> Game path to consider as the canonical .mdl path during export, used for resolution of other files. </param>
public void Export(string outputPath, Utf8GamePath mdlPath) public void Export(string outputPath, Utf8GamePath mdlPath)
{ {
SklbFile? sklb = null; SklbFile? sklb = null;

View file

@ -35,15 +35,9 @@ public partial class ModEditWindow
); );
} }
DrawExport(tab, disabled); DrawImportExport(tab, disabled);
var ret = false; var ret = tab.Dirty;
if (ImGui.Button("import test"))
{
tab.Import();
ret |= true;
}
ret |= DrawModelMaterialDetails(tab, disabled); ret |= DrawModelMaterialDetails(tab, disabled);
@ -56,11 +50,41 @@ public partial class ModEditWindow
return !disabled && ret; return !disabled && ret;
} }
private void DrawExport(MdlTab tab, bool disabled) private void DrawImportExport(MdlTab tab, bool disabled)
{ {
if (!ImGui.CollapsingHeader("Export")) if (!ImGui.CollapsingHeader("Import / Export"))
return; return;
var windowWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X;
var childWidth = (windowWidth - ImGui.GetStyle().ItemSpacing.X * 3) / 2;
var childSize = new Vector2(childWidth, 0);
DrawImport(tab, childSize, disabled);
ImGui.SameLine();
DrawExport(tab, childSize, disabled);
if (tab.IoException != null)
ImGuiUtil.TextWrapped(tab.IoException);
}
private void DrawImport(MdlTab tab, Vector2 size, bool disabled)
{
using var frame = ImRaii.FramedGroup("Import", size);
if (ImGuiUtil.DrawDisabledButton("Import from glTF", Vector2.Zero, "Imports a glTF file, overriding the content of this mdl.", tab.PendingIo))
{
_fileDialog.OpenFilePicker("Load model from glTF.", "glTF{.gltf,.glb}", (success, paths) =>
{
if (success && paths.Count > 0)
tab.Import(paths[0]);
}, 1, _mod!.ModPath.FullName, false);
}
}
private void DrawExport(MdlTab tab, Vector2 size, bool disabled)
{
using var frame = ImRaii.FramedGroup("Export", size);
if (tab.GamePaths == null) if (tab.GamePaths == null)
{ {
if (tab.IoException == null) if (tab.IoException == null)
@ -89,9 +113,6 @@ public partial class ModEditWindow
_mod!.ModPath.FullName, _mod!.ModPath.FullName,
false false
); );
if (tab.IoException != null)
ImGuiUtil.TextWrapped(tab.IoException);
} }
private void DrawGamePathCombo(MdlTab tab) private void DrawGamePathCombo(MdlTab tab)
@ -116,7 +137,7 @@ public partial class ModEditWindow
const string label = "Game Path"; const string label = "Game Path";
var preview = tab.GamePaths![tab.GamePathIndex].ToString(); var preview = tab.GamePaths![tab.GamePathIndex].ToString();
var labelWidth = ImGui.CalcTextSize(label).X + ImGui.GetStyle().ItemInnerSpacing.X; var labelWidth = ImGui.CalcTextSize(label).X + ImGui.GetStyle().ItemInnerSpacing.X;
var buttonWidth = ImGui.GetContentRegionAvail().X - labelWidth; var buttonWidth = ImGui.GetContentRegionAvail().X - labelWidth - ImGui.GetStyle().ItemSpacing.X;
if (tab.GamePaths!.Count == 1) if (tab.GamePaths!.Count == 1)
{ {
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f)); using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));