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;
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;
@ -29,17 +29,17 @@ public sealed class ModelManager(IFramework framework, GamePathParser _parser) :
public Task ExportToGltf(MdlFile mdl, SklbFile? sklb, string outputPath)
=> Enqueue(new ExportToGltfAction(this, mdl, sklb, outputPath));
public Task<MdlFile> ImportGltf()
public Task<MdlFile?> ImportGltf(string inputPath)
{
var action = new ImportGltfAction();
return Enqueue(action).ContinueWith(_ => action.Out!);
var action = new ImportGltfAction(inputPath);
return Enqueue(action).ContinueWith(_ => action.Out);
}
/// <summary> Try to find the .sklb path for a .mdl file. </summary>
/// <param name="mdlPath"> .mdl file to look up the skeleton for. </param>
public string? ResolveSklbForMdl(string mdlPath)
{
var info = _parser.GetFileInfo(mdlPath);
var info = parser.GetFileInfo(mdlPath);
if (info.FileType is not FileType.Model)
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 ImportGltfAction()
{
//
}
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);
}

View file

@ -18,8 +18,9 @@ public partial class ModEditWindow
public List<Utf8GamePath>? GamePaths { get; private set; }
public int GamePathIndex;
public bool PendingIo { get; private set; }
public string? IoException { get; private set; }
private bool _dirty;
public bool PendingIo { get; private set; }
public string? IoException { get; private set; }
public MdlTab(ModEditWindow edit, byte[] bytes, string path, IMod? mod)
{
@ -46,6 +47,16 @@ public partial class ModEditWindow
public byte[] 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>
/// <param name="path"> Resolved path to a .mdl. </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.
_edit._models.ImportGltf().ContinueWith(v => Initialize(v.Result ?? Mdl));
PendingIo = true;
_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>
/// <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)
{
SklbFile? sklb = null;

View file

@ -35,15 +35,9 @@ public partial class ModEditWindow
);
}
DrawExport(tab, disabled);
DrawImportExport(tab, disabled);
var ret = false;
if (ImGui.Button("import test"))
{
tab.Import();
ret |= true;
}
var ret = tab.Dirty;
ret |= DrawModelMaterialDetails(tab, disabled);
@ -56,11 +50,41 @@ public partial class ModEditWindow
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;
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.IoException == null)
@ -89,9 +113,6 @@ public partial class ModEditWindow
_mod!.ModPath.FullName,
false
);
if (tab.IoException != null)
ImGuiUtil.TextWrapped(tab.IoException);
}
private void DrawGamePathCombo(MdlTab tab)
@ -116,7 +137,7 @@ public partial class ModEditWindow
const string label = "Game Path";
var preview = tab.GamePaths![tab.GamePathIndex].ToString();
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)
{
using var style = ImRaii.PushStyle(ImGuiStyleVar.ButtonTextAlign, new Vector2(0, 0.5f));