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 MdlMaterialEditor MdlMaterialEditor = mdlMaterialEditor;
public readonly FileCompactor Compactor = compactor; 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 Mod? Mod { get; private set; }
public int GroupIdx { get; private set; } public int GroupIdx { get; private set; }
public int DataIdx { get; private set; } public int DataIdx { get; private set; }
@ -32,10 +47,9 @@ public class ModEditor(
public IModGroup? Group { get; private set; } public IModGroup? Group { get; private set; }
public IModDataContainer? Option { get; private set; } public IModDataContainer? Option { get; private set; }
public void LoadMod(Mod mod) public async Task LoadMod(Mod mod, int groupIdx, int dataIdx)
=> LoadMod(mod, -1, 0); {
await AppendTask(() =>
public void LoadMod(Mod mod, int groupIdx, int dataIdx)
{ {
Mod = mod; Mod = mod;
LoadOption(groupIdx, dataIdx, true); LoadOption(groupIdx, dataIdx, true);
@ -44,9 +58,23 @@ public class ModEditor(
MetaEditor.Load(Mod!, Option!); MetaEditor.Load(Mod!, Option!);
Duplicates.Clear(); Duplicates.Clear();
MdlMaterialEditor.ScanModels(Mod!); 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); LoadOption(groupIdx, dataIdx, true);
SwapEditor.Revert(Option!); SwapEditor.Revert(Option!);
@ -54,6 +82,7 @@ public class ModEditor(
MetaEditor.Load(Mod!, Option!); MetaEditor.Load(Mod!, Option!);
FileEditor.Clear(); FileEditor.Clear();
Duplicates.Clear(); Duplicates.Clear();
});
} }
/// <summary> Load the correct option by indices for the currently loaded mod if possible, unload if not. </summary> /// <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;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Services; using OtterGui.Services;
using OtterGui.Text;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Communication; using Penumbra.Communication;
@ -53,12 +54,42 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
public Mod? Mod { get; private set; } 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) public void ChangeMod(Mod mod)
{ {
if (mod == Mod) if (mod == Mod)
return; return;
_editor.LoadMod(mod, -1, 0); WindowName = $"{mod.Name} (LOADING){WindowBaseLabel}";
AppendTask(() =>
{
_editor.LoadMod(mod, -1, 0).Wait();
Mod = mod; Mod = mod;
SizeConstraints = new WindowSizeConstraints SizeConstraints = new WindowSizeConstraints
@ -73,12 +104,16 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
_itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings); _itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings);
UpdateModels(); UpdateModels();
_forceTextureStartPath = true; _forceTextureStartPath = true;
});
} }
public void ChangeOption(IModDataContainer? subMod) public void ChangeOption(IModDataContainer? subMod)
{
AppendTask(() =>
{ {
var (groupIdx, dataIdx) = subMod?.GetDataIndices() ?? (-1, 0); var (groupIdx, dataIdx) = subMod?.GetDataIndices() ?? (-1, 0);
_editor.LoadOption(groupIdx, dataIdx); _editor.LoadOption(groupIdx, dataIdx).Wait();
});
} }
public void UpdateModels() public void UpdateModels()
@ -92,6 +127,9 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
public override void PreDraw() public override void PreDraw()
{ {
if (IsLoading)
return;
using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow); using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow);
var sb = new StringBuilder(256); var sb = new StringBuilder(256);
@ -143,14 +181,17 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
} }
public override void OnClose() public override void OnClose()
{
_config.Ephemeral.AdvancedEditingOpen = false;
_config.Ephemeral.Save();
AppendTask(() =>
{ {
_left.Dispose(); _left.Dispose();
_right.Dispose(); _right.Dispose();
_materialTab.Reset(); _materialTab.Reset();
_modelTab.Reset(); _modelTab.Reset();
_shaderPackageTab.Reset(); _shaderPackageTab.Reset();
_config.Ephemeral.AdvancedEditingOpen = false; });
_config.Ephemeral.Save();
} }
public override void Draw() public override void Draw()
@ -163,6 +204,17 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
_config.Ephemeral.Save(); _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"); using var tabBar = ImRaii.TabBar("##tabs");
if (!tabBar) if (!tabBar)
return; 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.", if (ImGuiUtil.DrawDisabledButton(defaultOption, width, "Switch to the default option for the mod.\nThis resets unsaved changes.",
_editor.Option is DefaultSubMod)) _editor.Option is DefaultSubMod))
{ {
_editor.LoadOption(-1, 0); _editor.LoadOption(-1, 0).Wait();
ret = true; ret = true;
} }
ImGui.SameLine(); ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton("Refresh Data", width, "Refresh data for the current option.\nThis resets unsaved changes.", false)) 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; ret = true;
} }
@ -430,7 +482,7 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
if (ImGui.Selectable(option.GetFullName(), option == _editor.Option)) if (ImGui.Selectable(option.GetFullName(), option == _editor.Option))
{ {
var (groupIdx, dataIdx) = option.GetDataIndices(); var (groupIdx, dataIdx) = option.GetDataIndices();
_editor.LoadOption(groupIdx, dataIdx); _editor.LoadOption(groupIdx, dataIdx).Wait();
ret = true; ret = true;
} }
} }