mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Make loading mods for advanced editing async.
This commit is contained in:
parent
e5ff9cee9e
commit
5c5e45114f
2 changed files with 124 additions and 43 deletions
|
|
@ -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,28 +47,42 @@ 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);
|
|
||||||
|
|
||||||
public void LoadMod(Mod mod, int groupIdx, int dataIdx)
|
|
||||||
{
|
{
|
||||||
Mod = mod;
|
await AppendTask(() =>
|
||||||
LoadOption(groupIdx, dataIdx, true);
|
{
|
||||||
Files.UpdateAll(mod, Option!);
|
Mod = mod;
|
||||||
SwapEditor.Revert(Option!);
|
LoadOption(groupIdx, dataIdx, true);
|
||||||
MetaEditor.Load(Mod!, Option!);
|
Files.UpdateAll(mod, Option!);
|
||||||
Duplicates.Clear();
|
SwapEditor.Revert(Option!);
|
||||||
MdlMaterialEditor.ScanModels(Mod!);
|
MetaEditor.Load(Mod!, Option!);
|
||||||
|
Duplicates.Clear();
|
||||||
|
MdlMaterialEditor.ScanModels(Mod!);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadOption(int groupIdx, int dataIdx)
|
private Task AppendTask(Action run)
|
||||||
{
|
{
|
||||||
LoadOption(groupIdx, dataIdx, true);
|
lock (_lock)
|
||||||
SwapEditor.Revert(Option!);
|
{
|
||||||
Files.UpdatePaths(Mod!, Option!);
|
if (_loadingMod == null || _loadingMod.IsCompleted)
|
||||||
MetaEditor.Load(Mod!, Option!);
|
return _loadingMod = Task.Run(run);
|
||||||
FileEditor.Clear();
|
|
||||||
Duplicates.Clear();
|
return _loadingMod = _loadingMod.ContinueWith(_ => run());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadOption(int groupIdx, int dataIdx)
|
||||||
|
{
|
||||||
|
await AppendTask(() =>
|
||||||
|
{
|
||||||
|
LoadOption(groupIdx, dataIdx, true);
|
||||||
|
SwapEditor.Revert(Option!);
|
||||||
|
Files.UpdatePaths(Mod!, Option!);
|
||||||
|
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>
|
/// <summary> Load the correct option by indices for the currently loaded mod if possible, unload if not. </summary>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -51,34 +52,68 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
|
||||||
private Vector2 _iconSize = Vector2.Zero;
|
private Vector2 _iconSize = Vector2.Zero;
|
||||||
private bool _allowReduplicate;
|
private bool _allowReduplicate;
|
||||||
|
|
||||||
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}";
|
||||||
Mod = mod;
|
AppendTask(() =>
|
||||||
|
|
||||||
SizeConstraints = new WindowSizeConstraints
|
|
||||||
{
|
{
|
||||||
MinimumSize = new Vector2(1240, 600),
|
_editor.LoadMod(mod, -1, 0).Wait();
|
||||||
MaximumSize = 4000 * Vector2.One,
|
Mod = mod;
|
||||||
};
|
|
||||||
_selectedFiles.Clear();
|
SizeConstraints = new WindowSizeConstraints
|
||||||
_modelTab.Reset();
|
{
|
||||||
_materialTab.Reset();
|
MinimumSize = new Vector2(1240, 600),
|
||||||
_shaderPackageTab.Reset();
|
MaximumSize = 4000 * Vector2.One,
|
||||||
_itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings);
|
};
|
||||||
UpdateModels();
|
_selectedFiles.Clear();
|
||||||
_forceTextureStartPath = true;
|
_modelTab.Reset();
|
||||||
|
_materialTab.Reset();
|
||||||
|
_shaderPackageTab.Reset();
|
||||||
|
_itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings);
|
||||||
|
UpdateModels();
|
||||||
|
_forceTextureStartPath = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeOption(IModDataContainer? subMod)
|
public void ChangeOption(IModDataContainer? subMod)
|
||||||
{
|
{
|
||||||
var (groupIdx, dataIdx) = subMod?.GetDataIndices() ?? (-1, 0);
|
AppendTask(() =>
|
||||||
_editor.LoadOption(groupIdx, dataIdx);
|
{
|
||||||
|
var (groupIdx, dataIdx) = subMod?.GetDataIndices() ?? (-1, 0);
|
||||||
|
_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);
|
||||||
|
|
@ -144,13 +182,16 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
|
||||||
|
|
||||||
public override void OnClose()
|
public override void OnClose()
|
||||||
{
|
{
|
||||||
_left.Dispose();
|
|
||||||
_right.Dispose();
|
|
||||||
_materialTab.Reset();
|
|
||||||
_modelTab.Reset();
|
|
||||||
_shaderPackageTab.Reset();
|
|
||||||
_config.Ephemeral.AdvancedEditingOpen = false;
|
_config.Ephemeral.AdvancedEditingOpen = false;
|
||||||
_config.Ephemeral.Save();
|
_config.Ephemeral.Save();
|
||||||
|
AppendTask(() =>
|
||||||
|
{
|
||||||
|
_left.Dispose();
|
||||||
|
_right.Dispose();
|
||||||
|
_materialTab.Reset();
|
||||||
|
_modelTab.Reset();
|
||||||
|
_shaderPackageTab.Reset();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue