Make loading mods for advanced editing async.

This commit is contained in:
Ottermandias 2024-08-29 18:38:37 +02:00
parent e5ff9cee9e
commit 5c5e45114f
2 changed files with 124 additions and 43 deletions

View file

@ -25,6 +25,21 @@ public class ModEditor(
public readonly MdlMaterialEditor MdlMaterialEditor = mdlMaterialEditor;
public readonly FileCompactor Compactor = compactor;
public bool IsLoading
{
get
{
lock (_lock)
{
return _loadingMod is { IsCompleted: false };
}
}
}
private readonly object _lock = new();
private Task? _loadingMod;
public Mod? Mod { get; private set; }
public int GroupIdx { get; private set; }
public int DataIdx { get; private set; }
@ -32,10 +47,9 @@ public class ModEditor(
public IModGroup? Group { get; private set; }
public IModDataContainer? Option { get; private set; }
public void LoadMod(Mod mod)
=> LoadMod(mod, -1, 0);
public void LoadMod(Mod mod, int groupIdx, int dataIdx)
public async Task LoadMod(Mod mod, int groupIdx, int dataIdx)
{
await AppendTask(() =>
{
Mod = mod;
LoadOption(groupIdx, dataIdx, true);
@ -44,9 +58,23 @@ public class ModEditor(
MetaEditor.Load(Mod!, Option!);
Duplicates.Clear();
MdlMaterialEditor.ScanModels(Mod!);
});
}
public void LoadOption(int groupIdx, int dataIdx)
private Task AppendTask(Action run)
{
lock (_lock)
{
if (_loadingMod == null || _loadingMod.IsCompleted)
return _loadingMod = Task.Run(run);
return _loadingMod = _loadingMod.ContinueWith(_ => run());
}
}
public async Task LoadOption(int groupIdx, int dataIdx)
{
await AppendTask(() =>
{
LoadOption(groupIdx, dataIdx, true);
SwapEditor.Revert(Option!);
@ -54,6 +82,7 @@ public class ModEditor(
MetaEditor.Load(Mod!, Option!);
FileEditor.Clear();
Duplicates.Clear();
});
}
/// <summary> Load the correct option by indices for the currently loaded mod if possible, unload if not. </summary>

View file

@ -8,6 +8,7 @@ using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Services;
using OtterGui.Text;
using Penumbra.Api.Enums;
using Penumbra.Collections.Manager;
using Penumbra.Communication;
@ -53,12 +54,42 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
public Mod? Mod { get; private set; }
public bool IsLoading
{
get
{
lock (_lock)
{
return _editor.IsLoading || _loadingMod is { IsCompleted: false };
}
}
}
private readonly object _lock = new();
private Task? _loadingMod;
private void AppendTask(Action run)
{
lock (_lock)
{
if (_loadingMod == null || _loadingMod.IsCompleted)
_loadingMod = Task.Run(run);
else
_loadingMod = _loadingMod.ContinueWith(_ => run());
}
}
public void ChangeMod(Mod mod)
{
if (mod == Mod)
return;
_editor.LoadMod(mod, -1, 0);
WindowName = $"{mod.Name} (LOADING){WindowBaseLabel}";
AppendTask(() =>
{
_editor.LoadMod(mod, -1, 0).Wait();
Mod = mod;
SizeConstraints = new WindowSizeConstraints
@ -73,12 +104,16 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
_itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings);
UpdateModels();
_forceTextureStartPath = true;
});
}
public void ChangeOption(IModDataContainer? subMod)
{
AppendTask(() =>
{
var (groupIdx, dataIdx) = subMod?.GetDataIndices() ?? (-1, 0);
_editor.LoadOption(groupIdx, dataIdx);
_editor.LoadOption(groupIdx, dataIdx).Wait();
});
}
public void UpdateModels()
@ -92,6 +127,9 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
public override void PreDraw()
{
if (IsLoading)
return;
using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow);
var sb = new StringBuilder(256);
@ -143,14 +181,17 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
}
public override void OnClose()
{
_config.Ephemeral.AdvancedEditingOpen = false;
_config.Ephemeral.Save();
AppendTask(() =>
{
_left.Dispose();
_right.Dispose();
_materialTab.Reset();
_modelTab.Reset();
_shaderPackageTab.Reset();
_config.Ephemeral.AdvancedEditingOpen = false;
_config.Ephemeral.Save();
});
}
public override void Draw()
@ -163,6 +204,17 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
_config.Ephemeral.Save();
}
if (IsLoading)
{
var radius = 100 * ImUtf8.GlobalScale;
var thickness = (int) (20 * ImUtf8.GlobalScale);
var offsetX = ImGui.GetContentRegionAvail().X / 2 - radius;
var offsetY = ImGui.GetContentRegionAvail().Y / 2 - radius;
ImGui.SetCursorPos(ImGui.GetCursorPos() + new Vector2(offsetX, offsetY));
ImUtf8.Spinner("##spinner"u8, radius, thickness, ImGui.GetColorU32(ImGuiCol.Text));
return;
}
using var tabBar = ImRaii.TabBar("##tabs");
if (!tabBar)
return;
@ -405,14 +457,14 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
if (ImGuiUtil.DrawDisabledButton(defaultOption, width, "Switch to the default option for the mod.\nThis resets unsaved changes.",
_editor.Option is DefaultSubMod))
{
_editor.LoadOption(-1, 0);
_editor.LoadOption(-1, 0).Wait();
ret = true;
}
ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton("Refresh Data", width, "Refresh data for the current option.\nThis resets unsaved changes.", false))
{
_editor.LoadMod(_editor.Mod!, _editor.GroupIdx, _editor.DataIdx);
_editor.LoadMod(_editor.Mod!, _editor.GroupIdx, _editor.DataIdx).Wait();
ret = true;
}
@ -430,7 +482,7 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
if (ImGui.Selectable(option.GetFullName(), option == _editor.Option))
{
var (groupIdx, dataIdx) = option.GetDataIndices();
_editor.LoadOption(groupIdx, dataIdx);
_editor.LoadOption(groupIdx, dataIdx).Wait();
ret = true;
}
}