Merge branch 'master' into AeAstralis/tagging

This commit is contained in:
Ottermandias 2024-03-18 16:51:21 +01:00
commit c34cc4638c
16 changed files with 119 additions and 39 deletions

@ -1 +1 @@
Subproject commit cf42043c2b0e76b59919688dc250a762fe52d4b1 Subproject commit 5a2e12a1acd6760a3a592447a92215135e79197c

@ -1 +1 @@
Subproject commit c0c7eb0dedb32ea83b019626abba041e90a95319 Subproject commit c39f683d65d4541e9f97ed4ea1abcb10e8ca5690

View file

@ -10,6 +10,7 @@ using Penumbra.Meta.Manipulations;
using Penumbra.Mods; using Penumbra.Mods;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using OtterGui.Compression; using OtterGui.Compression;
using OtterGui.Log;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.Interop.ResourceLoading; using Penumbra.Interop.ResourceLoading;
@ -642,10 +643,10 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
CheckInitialized(); CheckInitialized();
if (!_modManager.TryGetMod(modDirectory, modName, out var mod)) if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
return PenumbraApiEc.ModMissing; return Return(PenumbraApiEc.ModMissing, Args("ModDirectory", modDirectory, "ModName", modName));
_modManager.ReloadMod(mod); _modManager.ReloadMod(mod);
return PenumbraApiEc.Success; return Return(PenumbraApiEc.Success, Args("ModDirectory", modDirectory, "ModName", modName));
} }
public PenumbraApiEc InstallMod(string modFilePackagePath) public PenumbraApiEc InstallMod(string modFilePackagePath)
@ -653,11 +654,11 @@ public class PenumbraApi : IDisposable, IPenumbraApi
if (File.Exists(modFilePackagePath)) if (File.Exists(modFilePackagePath))
{ {
_modImportManager.AddUnpack(modFilePackagePath); _modImportManager.AddUnpack(modFilePackagePath);
return PenumbraApiEc.Success; return Return(PenumbraApiEc.Success, Args("ModFilePackagePath", modFilePackagePath));
} }
else else
{ {
return PenumbraApiEc.FileMissing; return Return(PenumbraApiEc.FileMissing, Args("ModFilePackagePath", modFilePackagePath));
} }
} }
@ -666,23 +667,24 @@ public class PenumbraApi : IDisposable, IPenumbraApi
CheckInitialized(); CheckInitialized();
var dir = new DirectoryInfo(Path.Join(_modManager.BasePath.FullName, Path.GetFileName(modDirectory))); var dir = new DirectoryInfo(Path.Join(_modManager.BasePath.FullName, Path.GetFileName(modDirectory)));
if (!dir.Exists) if (!dir.Exists)
return PenumbraApiEc.FileMissing; return Return(PenumbraApiEc.FileMissing, Args("ModDirectory", modDirectory));
_modManager.AddMod(dir); _modManager.AddMod(dir);
if (_config.UseFileSystemCompression) if (_config.UseFileSystemCompression)
new FileCompactor(Penumbra.Log).StartMassCompact(dir.EnumerateFiles("*.*", SearchOption.AllDirectories), new FileCompactor(Penumbra.Log).StartMassCompact(dir.EnumerateFiles("*.*", SearchOption.AllDirectories),
CompressionAlgorithm.Xpress8K); CompressionAlgorithm.Xpress8K);
return PenumbraApiEc.Success; return Return(PenumbraApiEc.Success, Args("ModDirectory", modDirectory));
} }
public PenumbraApiEc DeleteMod(string modDirectory, string modName) public PenumbraApiEc DeleteMod(string modDirectory, string modName)
{ {
CheckInitialized(); CheckInitialized();
if (!_modManager.TryGetMod(modDirectory, modName, out var mod)) if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
return PenumbraApiEc.NothingChanged; return Return(PenumbraApiEc.NothingChanged, Args("ModDirectory", modDirectory, "ModName", modName));
_modManager.DeleteMod(mod); _modManager.DeleteMod(mod);
return PenumbraApiEc.Success; return Return(PenumbraApiEc.Success, Args("ModDirectory", modDirectory, "ModName", modName));
} }
public event Action<string>? ModDeleted; public event Action<string>? ModDeleted;
@ -784,22 +786,33 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
CheckInitialized(); CheckInitialized();
if (!_collectionManager.Storage.ByName(collectionName, out var collection)) if (!_collectionManager.Storage.ByName(collectionName, out var collection))
return PenumbraApiEc.CollectionMissing; return Return(PenumbraApiEc.CollectionMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"OptionName", optionName));
if (!_modManager.TryGetMod(modDirectory, modName, out var mod)) if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
return PenumbraApiEc.ModMissing; return Return(PenumbraApiEc.ModMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"OptionName", optionName));
var groupIdx = mod.Groups.IndexOf(g => g.Name == optionGroupName); var groupIdx = mod.Groups.IndexOf(g => g.Name == optionGroupName);
if (groupIdx < 0) if (groupIdx < 0)
return PenumbraApiEc.OptionGroupMissing; return Return(PenumbraApiEc.OptionGroupMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"OptionName", optionName));
var optionIdx = mod.Groups[groupIdx].IndexOf(o => o.Name == optionName); var optionIdx = mod.Groups[groupIdx].IndexOf(o => o.Name == optionName);
if (optionIdx < 0) if (optionIdx < 0)
return PenumbraApiEc.OptionMissing; return Return(PenumbraApiEc.OptionMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"OptionName", optionName));
var setting = mod.Groups[groupIdx].Type == GroupType.Multi ? 1u << optionIdx : (uint)optionIdx; var setting = mod.Groups[groupIdx].Type == GroupType.Multi ? 1u << optionIdx : (uint)optionIdx;
return _collectionEditor.SetModSetting(collection, mod, groupIdx, setting) ? PenumbraApiEc.Success : PenumbraApiEc.NothingChanged; return Return(
_collectionEditor.SetModSetting(collection, mod, groupIdx, setting) ? PenumbraApiEc.Success : PenumbraApiEc.NothingChanged,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"OptionName", optionName));
} }
public PenumbraApiEc TrySetModSettings(string collectionName, string modDirectory, string modName, string optionGroupName, public PenumbraApiEc TrySetModSettings(string collectionName, string modDirectory, string modName, string optionGroupName,
@ -807,14 +820,20 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
CheckInitialized(); CheckInitialized();
if (!_collectionManager.Storage.ByName(collectionName, out var collection)) if (!_collectionManager.Storage.ByName(collectionName, out var collection))
return PenumbraApiEc.CollectionMissing; return Return(PenumbraApiEc.CollectionMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"#optionNames", optionNames.Count.ToString()));
if (!_modManager.TryGetMod(modDirectory, modName, out var mod)) if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
return PenumbraApiEc.ModMissing; return Return(PenumbraApiEc.ModMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"#optionNames", optionNames.Count.ToString()));
var groupIdx = mod.Groups.IndexOf(g => g.Name == optionGroupName); var groupIdx = mod.Groups.IndexOf(g => g.Name == optionGroupName);
if (groupIdx < 0) if (groupIdx < 0)
return PenumbraApiEc.OptionGroupMissing; return Return(PenumbraApiEc.OptionGroupMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"#optionNames", optionNames.Count.ToString()));
var group = mod.Groups[groupIdx]; var group = mod.Groups[groupIdx];
@ -823,7 +842,9 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
var optionIdx = optionNames.Count == 0 ? -1 : group.IndexOf(o => o.Name == optionNames[^1]); var optionIdx = optionNames.Count == 0 ? -1 : group.IndexOf(o => o.Name == optionNames[^1]);
if (optionIdx < 0) if (optionIdx < 0)
return PenumbraApiEc.OptionMissing; return Return(PenumbraApiEc.OptionMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"#optionNames", optionNames.Count.ToString()));
setting = (uint)optionIdx; setting = (uint)optionIdx;
} }
@ -833,13 +854,18 @@ public class PenumbraApi : IDisposable, IPenumbraApi
{ {
var optionIdx = group.IndexOf(o => o.Name == name); var optionIdx = group.IndexOf(o => o.Name == name);
if (optionIdx < 0) if (optionIdx < 0)
return PenumbraApiEc.OptionMissing; return Return(PenumbraApiEc.OptionMissing,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName",
optionGroupName, "#optionNames", optionNames.Count.ToString()));
setting |= 1u << optionIdx; setting |= 1u << optionIdx;
} }
} }
return _collectionEditor.SetModSetting(collection, mod, groupIdx, setting) ? PenumbraApiEc.Success : PenumbraApiEc.NothingChanged; return Return(
_collectionEditor.SetModSetting(collection, mod, groupIdx, setting) ? PenumbraApiEc.Success : PenumbraApiEc.NothingChanged,
Args("CollectionName", collectionName, "ModDirectory", modDirectory, "ModName", modName, "OptionGroupName", optionGroupName,
"#optionNames", optionNames.Count.ToString()));
} }
@ -1296,4 +1322,33 @@ public class PenumbraApi : IDisposable, IPenumbraApi
if (settings is { Enabled: true }) if (settings is { Enabled: true })
ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Name, mod.Identifier, parent != collection); ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Name, mod.Identifier, parent != collection);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static LazyString Args(params string[] arguments)
{
if (arguments.Length == 0)
return new LazyString(() => "no arguments");
return new LazyString(() =>
{
var sb = new StringBuilder();
for (var i = 0; i < arguments.Length / 2; ++i)
{
sb.Append(arguments[2 * i]);
sb.Append(" = ");
sb.Append(arguments[2 * i + 1]);
sb.Append(", ");
}
return sb.ToString(0, sb.Length - 2);
});
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static PenumbraApiEc Return(PenumbraApiEc ec, LazyString args, [CallerMemberName] string name = "Unknown")
{
Penumbra.Log.Debug(
$"[{name}] Called with {args}, returned {ec}.");
return ec;
}
} }

View file

@ -265,6 +265,14 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable
foreach (var collection in this.Where(collection => collection.Settings[mod.Index] != null)) foreach (var collection in this.Where(collection => collection.Settings[mod.Index] != null))
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection)); _saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
break; break;
case ModPathChangeType.Reloaded:
foreach (var collection in this)
{
if (collection.Settings[mod.Index]?.FixAllSettings(mod) ?? false)
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
}
break;
} }
} }

View file

@ -41,7 +41,7 @@ public partial class IndividualCollections
saver.ImmediateSave(parent); saver.ImmediateSave(parent);
IsLoaded = true; IsLoaded = true;
Loaded.Invoke(); Loaded.Invoke();
}); }, TaskScheduler.Default);
return false; return false;
} }

View file

@ -162,7 +162,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
{ {
return _tasks.TryRemove(a, out var unused); return _tasks.TryRemove(a, out var unused);
} }
}, CancellationToken.None); }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
return (t, token); return (t, token);
}).Item1; }).Item1;
} }
@ -178,7 +178,7 @@ public sealed class ModelManager(IFramework framework, ActiveCollections collect
throw task.Exception; throw task.Exception;
return process(action); return process(action);
}); }, TaskScheduler.Default);
private class ExportToGltfAction( private class ExportToGltfAction(
ModelManager manager, ModelManager manager,

View file

@ -46,12 +46,12 @@ public partial class TexToolsImporter : IDisposable
ExtractedMods = new List<(FileInfo, DirectoryInfo?, Exception?)>(count); ExtractedMods = new List<(FileInfo, DirectoryInfo?, Exception?)>(count);
_token = _cancellation.Token; _token = _cancellation.Token;
Task.Run(ImportFiles, _token) Task.Run(ImportFiles, _token)
.ContinueWith(_ => CloseStreams()) .ContinueWith(_ => CloseStreams(), TaskScheduler.Default)
.ContinueWith(_ => .ContinueWith(_ =>
{ {
foreach (var (file, dir, error) in ExtractedMods) foreach (var (file, dir, error) in ExtractedMods)
handler(file, dir, error); handler(file, dir, error);
}); }, TaskScheduler.Default);
} }
private void CloseStreams() private void CloseStreams()

View file

@ -64,7 +64,7 @@ public sealed class TextureManager : SingleTaskQueue, IDisposable
{ {
var token = new CancellationTokenSource(); var token = new CancellationTokenSource();
var task = Enqueue(a, token.Token); var task = Enqueue(a, token.Token);
task.ContinueWith(_ => _tasks.TryRemove(a, out var unused), CancellationToken.None); task.ContinueWith(_ => _tasks.TryRemove(a, out var unused), CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
return (task, token); return (task, token);
}).Item1; }).Item1;
} }

View file

@ -23,7 +23,7 @@ public class ModCacheManager : IDisposable
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModCacheManager); _communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModCacheManager);
_communicator.ModDataChanged.Subscribe(OnModDataChange, ModDataChanged.Priority.ModCacheManager); _communicator.ModDataChanged.Subscribe(OnModDataChange, ModDataChanged.Priority.ModCacheManager);
_communicator.ModDiscoveryFinished.Subscribe(OnModDiscoveryFinished, ModDiscoveryFinished.Priority.ModCacheManager); _communicator.ModDiscoveryFinished.Subscribe(OnModDiscoveryFinished, ModDiscoveryFinished.Priority.ModCacheManager);
identifier.Awaiter.ContinueWith(_ => OnIdentifierCreation()); identifier.Awaiter.ContinueWith(_ => OnIdentifierCreation(), TaskScheduler.Default);
OnModDiscoveryFinished(); OnModDiscoveryFinished();
} }

View file

@ -138,6 +138,22 @@ public class ModSettings
} }
} }
public bool FixAllSettings(Mod mod)
{
var ret = false;
for (var i = 0; i < Settings.Count; ++i)
{
var newValue = FixSetting(mod.Groups[i], Settings[i]);
if (newValue != Settings[i])
{
ret = true;
Settings[i] = newValue;
}
}
return AddMissingSettings(mod) || ret;
}
// Ensure that a value is valid for a group. // Ensure that a value is valid for a group.
private static uint FixSetting(IModGroup group, uint value) private static uint FixSetting(IModGroup group, uint value)
=> group.Type switch => group.Type switch

View file

@ -74,7 +74,7 @@ public abstract class AsyncServiceWrapper<T> : IDisposable
{ {
if (!_isDisposed) if (!_isDisposed)
FinishedCreation?.Invoke(); FinishedCreation?.Invoke();
}, null); }, TaskScheduler.Default);
} }
public void Dispose() public void Dispose()

View file

@ -92,7 +92,7 @@ public partial class ModEditWindow
.ToList(); .ToList();
}); });
task.ContinueWith(t => { GamePaths = FinalizeIo(t); }); task.ContinueWith(t => { GamePaths = FinalizeIo(t); }, TaskScheduler.Default);
} }
private EstManipulation[] GetCurrentEstManipulations() private EstManipulation[] GetCurrentEstManipulations()
@ -130,7 +130,7 @@ public partial class ModEditWindow
BeginIo(); BeginIo();
_edit._models.ExportToGltf(ExportConfig, Mdl, sklbPaths, ReadFile, outputPath) _edit._models.ExportToGltf(ExportConfig, Mdl, sklbPaths, ReadFile, outputPath)
.ContinueWith(FinalizeIo); .ContinueWith(FinalizeIo, TaskScheduler.Default);
} }
/// <summary> Import a model from an interchange format. </summary> /// <summary> Import a model from an interchange format. </summary>
@ -144,7 +144,7 @@ public partial class ModEditWindow
var mdlFile = FinalizeIo(task, result => result.Item1, result => result.Item2); var mdlFile = FinalizeIo(task, result => result.Item1, result => result.Item2);
if (mdlFile != null) if (mdlFile != null)
FinalizeImport(mdlFile); FinalizeImport(mdlFile);
}); }, TaskScheduler.Default);
} }
/// <summary> Finalise the import of a .mdl, applying any post-import transformations and state updates. </summary> /// <summary> Finalise the import of a .mdl, applying any post-import transformations and state updates. </summary>

View file

@ -255,7 +255,7 @@ public partial class ModEditWindow
return; return;
_framework.RunOnFrameworkThread(() => tex.Reload(_textures)); _framework.RunOnFrameworkThread(() => tex.Reload(_textures));
}); }, TaskScheduler.Default);
} }
private Vector2 GetChildWidth() private Vector2 GetChildWidth()

View file

@ -326,7 +326,7 @@ public partial class ModEditWindow : Window, IDisposable
else if (ImGuiUtil.DrawDisabledButton("Re-Duplicate and Normalize Mod", Vector2.Zero, tt, !_allowReduplicate && !modifier)) else if (ImGuiUtil.DrawDisabledButton("Re-Duplicate and Normalize Mod", Vector2.Zero, tt, !_allowReduplicate && !modifier))
{ {
_editor.ModNormalizer.Normalize(Mod!); _editor.ModNormalizer.Normalize(Mod!);
_editor.ModNormalizer.Worker.ContinueWith(_ => _editor.LoadMod(Mod!, _editor.GroupIdx, _editor.OptionIdx)); _editor.ModNormalizer.Worker.ContinueWith(_ => _editor.LoadMod(Mod!, _editor.GroupIdx, _editor.OptionIdx), TaskScheduler.Default);
} }
if (!_editor.Duplicates.Worker.IsCompleted) if (!_editor.Duplicates.Worker.IsCompleted)

View file

@ -33,7 +33,7 @@ public class IndividualAssignmentUi : IDisposable
_actors = actors; _actors = actors;
_collectionManager = collectionManager; _collectionManager = collectionManager;
_communicator.CollectionChange.Subscribe(UpdateIdentifiers, CollectionChange.Priority.IndividualAssignmentUi); _communicator.CollectionChange.Subscribe(UpdateIdentifiers, CollectionChange.Priority.IndividualAssignmentUi);
_actors.Awaiter.ContinueWith(_ => SetupCombos()); _actors.Awaiter.ContinueWith(_ => SetupCombos(), TaskScheduler.Default);
} }
public string PlayerTooltip { get; private set; } = NewPlayerTooltipEmpty; public string PlayerTooltip { get; private set; } = NewPlayerTooltipEmpty;

View file

@ -211,6 +211,11 @@ public class ModPanelSettingsTab : ITab
var selectedOption = _empty ? (int)group.DefaultSettings : (int)_settings.Settings[groupIdx]; var selectedOption = _empty ? (int)group.DefaultSettings : (int)_settings.Settings[groupIdx];
var minWidth = Widget.BeginFramedGroup(group.Name, description:group.Description); var minWidth = Widget.BeginFramedGroup(group.Name, description:group.Description);
DrawCollapseHandling(group, minWidth, DrawOptions);
Widget.EndFramedGroup();
return;
void DrawOptions() void DrawOptions()
{ {
for (var idx = 0; idx < group.Count; ++idx) for (var idx = 0; idx < group.Count; ++idx)
@ -227,10 +232,6 @@ public class ModPanelSettingsTab : ITab
ImGuiComponents.HelpMarker(option.Description); ImGuiComponents.HelpMarker(option.Description);
} }
} }
DrawCollapseHandling(group, minWidth, DrawOptions);
Widget.EndFramedGroup();
} }