mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Current state.
This commit is contained in:
parent
67305d507a
commit
98a89bb2b4
28 changed files with 606 additions and 265 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
|
using OtterGui.Log;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
using Penumbra.Api.Helpers;
|
using Penumbra.Api.Helpers;
|
||||||
|
|
@ -24,18 +25,20 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable
|
||||||
private readonly CollectionManager _collectionManager;
|
private readonly CollectionManager _collectionManager;
|
||||||
private readonly CollectionEditor _collectionEditor;
|
private readonly CollectionEditor _collectionEditor;
|
||||||
private readonly CommunicatorService _communicator;
|
private readonly CommunicatorService _communicator;
|
||||||
|
private readonly ApiHelpers _helpers;
|
||||||
|
|
||||||
public ModSettingsApi(CollectionResolver collectionResolver,
|
public ModSettingsApi(CollectionResolver collectionResolver,
|
||||||
ModManager modManager,
|
ModManager modManager,
|
||||||
CollectionManager collectionManager,
|
CollectionManager collectionManager,
|
||||||
CollectionEditor collectionEditor,
|
CollectionEditor collectionEditor,
|
||||||
CommunicatorService communicator)
|
CommunicatorService communicator, ApiHelpers helpers)
|
||||||
{
|
{
|
||||||
_collectionResolver = collectionResolver;
|
_collectionResolver = collectionResolver;
|
||||||
_modManager = modManager;
|
_modManager = modManager;
|
||||||
_collectionManager = collectionManager;
|
_collectionManager = collectionManager;
|
||||||
_collectionEditor = collectionEditor;
|
_collectionEditor = collectionEditor;
|
||||||
_communicator = communicator;
|
_communicator = communicator;
|
||||||
|
_helpers = helpers;
|
||||||
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ApiModSettings);
|
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ApiModSettings);
|
||||||
_communicator.ModSettingChanged.Subscribe(OnModSettingChange, Communication.ModSettingChanged.Priority.Api);
|
_communicator.ModSettingChanged.Subscribe(OnModSettingChange, Communication.ModSettingChanged.Priority.Api);
|
||||||
_communicator.ModOptionChanged.Subscribe(OnModOptionEdited, ModOptionChanged.Priority.Api);
|
_communicator.ModOptionChanged.Subscribe(OnModOptionEdited, ModOptionChanged.Priority.Api);
|
||||||
|
|
@ -63,11 +66,6 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable
|
||||||
return new AvailableModSettings(dict);
|
return new AvailableModSettings(dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, (string[], int)>? GetAvailableModSettingsBase(string modDirectory, string modName)
|
|
||||||
=> _modManager.TryGetMod(modDirectory, modName, out var mod)
|
|
||||||
? mod.Groups.ToDictionary(g => g.Name, g => (g.Options.Select(o => o.Name).ToArray(), (int)g.Type))
|
|
||||||
: null;
|
|
||||||
|
|
||||||
public (PenumbraApiEc, (bool, int, Dictionary<string, List<string>>, bool)?) GetCurrentModSettings(Guid collectionId, string modDirectory,
|
public (PenumbraApiEc, (bool, int, Dictionary<string, List<string>>, bool)?) GetCurrentModSettings(Guid collectionId, string modDirectory,
|
||||||
string modName, bool ignoreInheritance)
|
string modName, bool ignoreInheritance)
|
||||||
{
|
{
|
||||||
|
|
@ -80,14 +78,14 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable
|
||||||
var settings = collection.Identity.Id == Guid.Empty
|
var settings = collection.Identity.Id == Guid.Empty
|
||||||
? null
|
? null
|
||||||
: ignoreInheritance
|
: ignoreInheritance
|
||||||
? collection.Settings[mod.Index]
|
? collection.GetOwnSettings(mod.Index)
|
||||||
: collection[mod.Index].Settings;
|
: collection.GetInheritedSettings(mod.Index).Settings;
|
||||||
if (settings == null)
|
if (settings == null)
|
||||||
return (PenumbraApiEc.Success, null);
|
return (PenumbraApiEc.Success, null);
|
||||||
|
|
||||||
var (enabled, priority, dict) = settings.ConvertToShareable(mod);
|
var (enabled, priority, dict) = settings.ConvertToShareable(mod);
|
||||||
return (PenumbraApiEc.Success,
|
return (PenumbraApiEc.Success,
|
||||||
(enabled, priority.Value, dict, collection.Settings[mod.Index] == null));
|
(enabled, priority.Value, dict, collection.GetOwnSettings(mod.Index) is null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PenumbraApiEc TryInheritMod(Guid collectionId, string modDirectory, string modName, bool inherit)
|
public PenumbraApiEc TryInheritMod(Guid collectionId, string modDirectory, string modName, bool inherit)
|
||||||
|
|
@ -211,11 +209,147 @@ public class ModSettingsApi : IPenumbraApiModSettings, IApiService, IDisposable
|
||||||
return ApiHelpers.Return(PenumbraApiEc.Success, args);
|
return ApiHelpers.Return(PenumbraApiEc.Success, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc SetTemporaryModSetting(Guid collectionId, string modDirectory, string modName, bool enabled, int priority,
|
||||||
|
IReadOnlyDictionary<string, IReadOnlyList<string>> options, string source, int key)
|
||||||
|
{
|
||||||
|
var args = ApiHelpers.Args("CollectionId", collectionId, "ModDirectory", modDirectory, "ModName", modName, "Enabled", enabled,
|
||||||
|
"Priority", priority, "Options", options, "Source", source, "Key", key);
|
||||||
|
if (!_collectionManager.Storage.ById(collectionId, out var collection))
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.CollectionMissing, args);
|
||||||
|
|
||||||
|
return SetTemporaryModSetting(args, collection, modDirectory, modName, enabled, priority, options, source, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc TemporaryModSettingsPlayer(int objectIndex, string modDirectory, string modName, bool enabled, int priority,
|
||||||
|
IReadOnlyDictionary<string, IReadOnlyList<string>> options, string source, int key)
|
||||||
|
{
|
||||||
|
return PenumbraApiEc.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PenumbraApiEc SetTemporaryModSetting(in LazyString args, ModCollection collection, string modDirectory, string modName,
|
||||||
|
bool enabled, int priority,
|
||||||
|
IReadOnlyDictionary<string, IReadOnlyList<string>> options, string source, int key)
|
||||||
|
{
|
||||||
|
if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.ModMissing, args);
|
||||||
|
|
||||||
|
if (collection.GetTempSettings(mod.Index) is { } settings && settings.Lock != 0 && settings.Lock != key)
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.TemporarySettingDisallowed, args);
|
||||||
|
|
||||||
|
settings = new TemporaryModSettings
|
||||||
|
{
|
||||||
|
Enabled = enabled,
|
||||||
|
Priority = new ModPriority(priority),
|
||||||
|
Lock = key,
|
||||||
|
Source = source,
|
||||||
|
Settings = SettingList.Default(mod),
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var (groupName, optionNames) in options)
|
||||||
|
{
|
||||||
|
var groupIdx = mod.Groups.IndexOf(g => g.Name == groupName);
|
||||||
|
if (groupIdx < 0)
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.OptionGroupMissing, args);
|
||||||
|
|
||||||
|
var setting = Setting.Zero;
|
||||||
|
switch (mod.Groups[groupIdx])
|
||||||
|
{
|
||||||
|
case { Behaviour: GroupDrawBehaviour.SingleSelection } single:
|
||||||
|
{
|
||||||
|
var optionIdx = optionNames.Count == 0 ? -1 : single.Options.IndexOf(o => o.Name == optionNames[^1]);
|
||||||
|
if (optionIdx < 0)
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.OptionMissing, args);
|
||||||
|
|
||||||
|
setting = Setting.Single(optionIdx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case { Behaviour: GroupDrawBehaviour.MultiSelection } multi:
|
||||||
|
{
|
||||||
|
foreach (var name in optionNames)
|
||||||
|
{
|
||||||
|
var optionIdx = multi.Options.IndexOf(o => o.Name == name);
|
||||||
|
if (optionIdx < 0)
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.OptionMissing, args);
|
||||||
|
|
||||||
|
setting |= Setting.Multi(optionIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.Settings[groupIdx] = setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
collection.Settings.SetTemporary(mod.Index, settings);
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.Success, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc RemoveTemporaryModSettings(Guid collectionId, string modDirectory, string modName, int key)
|
||||||
|
{
|
||||||
|
var args = ApiHelpers.Args("CollectionId", collectionId, "ModDirectory", modDirectory, "ModName", modName, "Key", key);
|
||||||
|
if (!_collectionManager.Storage.ById(collectionId, out var collection))
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.CollectionMissing, args);
|
||||||
|
|
||||||
|
return RemoveTemporaryModSettings(args, collection, modDirectory, modName, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PenumbraApiEc RemoveTemporaryModSettings(in LazyString args, ModCollection collection, string modDirectory, string modName, int key)
|
||||||
|
{
|
||||||
|
if (!_modManager.TryGetMod(modDirectory, modName, out var mod))
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.ModMissing, args);
|
||||||
|
|
||||||
|
if (collection.GetTempSettings(mod.Index) is not { } settings)
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.NothingChanged, args);
|
||||||
|
|
||||||
|
if (settings.Lock != 0 && settings.Lock != key)
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.TemporarySettingDisallowed, args);
|
||||||
|
|
||||||
|
collection.Settings.SetTemporary(mod.Index, null);
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.Success, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc RemoveTemporaryModSettingsPlayer(int objectIndex, string modDirectory, string modName, int key)
|
||||||
|
{
|
||||||
|
return PenumbraApiEc.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc RemoveAllTemporaryModSettings(Guid collectionId, int key)
|
||||||
|
{
|
||||||
|
var args = ApiHelpers.Args("CollectionId", collectionId, "Key", key);
|
||||||
|
if (!_collectionManager.Storage.ById(collectionId, out var collection))
|
||||||
|
return ApiHelpers.Return(PenumbraApiEc.CollectionMissing, args);
|
||||||
|
|
||||||
|
return RemoveAllTemporaryModSettings(args, collection, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenumbraApiEc RemoveAllTemporaryModSettingsPlayer(int objectIndex, int key)
|
||||||
|
{
|
||||||
|
return PenumbraApiEc.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PenumbraApiEc RemoveAllTemporaryModSettings(in LazyString args, ModCollection collection, int key)
|
||||||
|
{
|
||||||
|
var numRemoved = 0;
|
||||||
|
for (var i = 0; i < collection.Settings.Count; ++i)
|
||||||
|
{
|
||||||
|
if (collection.GetTempSettings(i) is { } settings && (settings.Lock == 0 || settings.Lock == key))
|
||||||
|
{
|
||||||
|
collection.Settings.SetTemporary(i, null);
|
||||||
|
++numRemoved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiHelpers.Return(numRemoved > 0 ? PenumbraApiEc.Success : PenumbraApiEc.NothingChanged, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private void TriggerSettingEdited(Mod mod)
|
private void TriggerSettingEdited(Mod mod)
|
||||||
{
|
{
|
||||||
var collection = _collectionResolver.PlayerCollection();
|
var collection = _collectionResolver.PlayerCollection();
|
||||||
var (settings, parent) = collection[mod.Index];
|
var (settings, parent) = collection.GetActualSettings(mod.Index);
|
||||||
if (settings is { Enabled: true })
|
if (settings is { Enabled: true })
|
||||||
ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Identity.Id, mod.Identifier, parent != collection);
|
ModSettingChanged?.Invoke(ModSettingChange.Edited, collection.Identity.Id, mod.Identifier, parent != collection);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,7 @@ public sealed class CollectionCache : IDisposable
|
||||||
if (mod.Index < 0)
|
if (mod.Index < 0)
|
||||||
return mod.GetData();
|
return mod.GetData();
|
||||||
|
|
||||||
var settings = _collection[mod.Index].Settings;
|
var settings = _collection.GetActualSettings(mod.Index).Settings;
|
||||||
return settings is not { Enabled: true }
|
return settings is not { Enabled: true }
|
||||||
? AppliedModData.Empty
|
? AppliedModData.Empty
|
||||||
: mod.GetData(settings);
|
: mod.GetData(settings);
|
||||||
|
|
@ -342,8 +342,8 @@ public sealed class CollectionCache : IDisposable
|
||||||
// Returns if the added mod takes priority before the existing mod.
|
// Returns if the added mod takes priority before the existing mod.
|
||||||
private bool AddConflict(object data, IMod addedMod, IMod existingMod)
|
private bool AddConflict(object data, IMod addedMod, IMod existingMod)
|
||||||
{
|
{
|
||||||
var addedPriority = addedMod.Index >= 0 ? _collection[addedMod.Index].Settings!.Priority : addedMod.Priority;
|
var addedPriority = addedMod.Index >= 0 ? _collection.GetActualSettings(addedMod.Index).Settings!.Priority : addedMod.Priority;
|
||||||
var existingPriority = existingMod.Index >= 0 ? _collection[existingMod.Index].Settings!.Priority : existingMod.Priority;
|
var existingPriority = existingMod.Index >= 0 ? _collection.GetActualSettings(existingMod.Index).Settings!.Priority : existingMod.Priority;
|
||||||
|
|
||||||
if (existingPriority < addedPriority)
|
if (existingPriority < addedPriority)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -231,11 +231,11 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
{
|
{
|
||||||
case ModPathChangeType.Deleted:
|
case ModPathChangeType.Deleted:
|
||||||
case ModPathChangeType.StartingReload:
|
case ModPathChangeType.StartingReload:
|
||||||
foreach (var collection in _storage.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true))
|
foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(mod.Index).Settings?.Enabled == true))
|
||||||
collection._cache!.RemoveMod(mod, true);
|
collection._cache!.RemoveMod(mod, true);
|
||||||
break;
|
break;
|
||||||
case ModPathChangeType.Moved:
|
case ModPathChangeType.Moved:
|
||||||
foreach (var collection in _storage.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true))
|
foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(mod.Index).Settings?.Enabled == true))
|
||||||
collection._cache!.ReloadMod(mod, true);
|
collection._cache!.ReloadMod(mod, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +246,7 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
if (type is not (ModPathChangeType.Added or ModPathChangeType.Reloaded))
|
if (type is not (ModPathChangeType.Added or ModPathChangeType.Reloaded))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var collection in _storage.Where(c => c.HasCache && c[mod.Index].Settings?.Enabled == true))
|
foreach (var collection in _storage.Where(c => c.HasCache && c.GetActualSettings(mod.Index).Settings?.Enabled == true))
|
||||||
collection._cache!.AddMod(mod, true);
|
collection._cache!.AddMod(mod, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,7 +273,7 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
{
|
{
|
||||||
if (type is ModOptionChangeType.PrepareChange)
|
if (type is ModOptionChangeType.PrepareChange)
|
||||||
{
|
{
|
||||||
foreach (var collection in _storage.Where(collection => collection.HasCache && collection[mod.Index].Settings is { Enabled: true }))
|
foreach (var collection in _storage.Where(collection => collection.HasCache && collection.GetActualSettings(mod.Index).Settings is { Enabled: true }))
|
||||||
collection._cache!.RemoveMod(mod, false);
|
collection._cache!.RemoveMod(mod, false);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -284,7 +284,7 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
if (!recomputeList)
|
if (!recomputeList)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var collection in _storage.Where(collection => collection.HasCache && collection[mod.Index].Settings is { Enabled: true }))
|
foreach (var collection in _storage.Where(collection => collection.HasCache && collection.GetActualSettings(mod.Index).Settings is { Enabled: true }))
|
||||||
{
|
{
|
||||||
if (justAdd)
|
if (justAdd)
|
||||||
collection._cache!.AddMod(mod, true);
|
collection._cache!.AddMod(mod, true);
|
||||||
|
|
@ -317,7 +317,7 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
cache.AddMod(mod!, true);
|
cache.AddMod(mod!, true);
|
||||||
else if (oldValue == Setting.True)
|
else if (oldValue == Setting.True)
|
||||||
cache.RemoveMod(mod!, true);
|
cache.RemoveMod(mod!, true);
|
||||||
else if (collection[mod!.Index].Settings?.Enabled == true)
|
else if (collection.GetActualSettings(mod!.Index).Settings?.Enabled == true)
|
||||||
cache.ReloadMod(mod!, true);
|
cache.ReloadMod(mod!, true);
|
||||||
else
|
else
|
||||||
cache.RemoveMod(mod!, true);
|
cache.RemoveMod(mod!, true);
|
||||||
|
|
@ -329,8 +329,8 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ModSettingChange.Setting:
|
case ModSettingChange.Setting:
|
||||||
if (collection[mod!.Index].Settings?.Enabled == true)
|
if (collection.GetActualSettings(mod!.Index).Settings?.Enabled == true)
|
||||||
cache.ReloadMod(mod!, true);
|
cache.ReloadMod(mod, true);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ModSettingChange.MultiInheritance:
|
case ModSettingChange.MultiInheritance:
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ public class ActiveCollections : ISavable, IDisposable, IService
|
||||||
.Prepend(Interface)
|
.Prepend(Interface)
|
||||||
.Prepend(Default)
|
.Prepend(Default)
|
||||||
.Concat(Individuals.Assignments.Select(kvp => kvp.Collection))
|
.Concat(Individuals.Assignments.Select(kvp => kvp.Collection))
|
||||||
.SelectMany(c => c.GetFlattenedInheritance()).Contains(Current);
|
.SelectMany(c => c.Inheritance.FlatHierarchy).Contains(Current);
|
||||||
|
|
||||||
/// <summary> Save if any of the active collections is changed and set new collections to Current. </summary>
|
/// <summary> Save if any of the active collections is changed and set new collections to Current. </summary>
|
||||||
private void OnCollectionChange(CollectionType collectionType, ModCollection? oldCollection, ModCollection? newCollection, string _3)
|
private void OnCollectionChange(CollectionType collectionType, ModCollection? oldCollection, ModCollection? newCollection, string _3)
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SetModState(ModCollection collection, Mod mod, bool newValue)
|
public bool SetModState(ModCollection collection, Mod mod, bool newValue)
|
||||||
{
|
{
|
||||||
var oldValue = collection.Settings[mod.Index]?.Enabled ?? collection[mod.Index].Settings?.Enabled ?? false;
|
var oldValue = collection.GetInheritedSettings(mod.Index).Settings?.Enabled ?? false;
|
||||||
if (newValue == oldValue)
|
if (newValue == oldValue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var inheritance = FixInheritance(collection, mod, false);
|
var inheritance = FixInheritance(collection, mod, false);
|
||||||
((List<ModSettings?>)collection.Settings)[mod.Index]!.Enabled = newValue;
|
collection.GetOwnSettings(mod.Index)!.Enabled = newValue;
|
||||||
InvokeChange(collection, ModSettingChange.EnableState, mod, inheritance ? Setting.Indefinite : newValue ? Setting.False : Setting.True,
|
InvokeChange(collection, ModSettingChange.EnableState, mod, inheritance ? Setting.Indefinite : newValue ? Setting.False : Setting.True,
|
||||||
0);
|
0);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -55,13 +55,13 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
var changes = false;
|
var changes = false;
|
||||||
foreach (var mod in mods)
|
foreach (var mod in mods)
|
||||||
{
|
{
|
||||||
var oldValue = collection.Settings[mod.Index]?.Enabled;
|
var oldValue = collection.GetOwnSettings(mod.Index)?.Enabled;
|
||||||
if (newValue == oldValue)
|
if (newValue == oldValue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FixInheritance(collection, mod, false);
|
FixInheritance(collection, mod, false);
|
||||||
((List<ModSettings?>)collection.Settings)[mod.Index]!.Enabled = newValue;
|
collection.GetOwnSettings(mod.Index)!.Enabled = newValue;
|
||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changes)
|
if (!changes)
|
||||||
|
|
@ -76,12 +76,12 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SetModPriority(ModCollection collection, Mod mod, ModPriority newValue)
|
public bool SetModPriority(ModCollection collection, Mod mod, ModPriority newValue)
|
||||||
{
|
{
|
||||||
var oldValue = collection.Settings[mod.Index]?.Priority ?? collection[mod.Index].Settings?.Priority ?? ModPriority.Default;
|
var oldValue = collection.GetInheritedSettings(mod.Index).Settings?.Priority ?? ModPriority.Default;
|
||||||
if (newValue == oldValue)
|
if (newValue == oldValue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var inheritance = FixInheritance(collection, mod, false);
|
var inheritance = FixInheritance(collection, mod, false);
|
||||||
((List<ModSettings?>)collection.Settings)[mod.Index]!.Priority = newValue;
|
collection.GetOwnSettings(mod.Index)!.Priority = newValue;
|
||||||
InvokeChange(collection, ModSettingChange.Priority, mod, inheritance ? Setting.Indefinite : oldValue.AsSetting, 0);
|
InvokeChange(collection, ModSettingChange.Priority, mod, inheritance ? Setting.Indefinite : oldValue.AsSetting, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -92,15 +92,13 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SetModSetting(ModCollection collection, Mod mod, int groupIdx, Setting newValue)
|
public bool SetModSetting(ModCollection collection, Mod mod, int groupIdx, Setting newValue)
|
||||||
{
|
{
|
||||||
var settings = collection.Settings[mod.Index] != null
|
var settings = collection.GetInheritedSettings(mod.Index).Settings?.Settings;
|
||||||
? collection.Settings[mod.Index]!.Settings
|
|
||||||
: collection[mod.Index].Settings?.Settings;
|
|
||||||
var oldValue = settings?[groupIdx] ?? mod.Groups[groupIdx].DefaultSettings;
|
var oldValue = settings?[groupIdx] ?? mod.Groups[groupIdx].DefaultSettings;
|
||||||
if (oldValue == newValue)
|
if (oldValue == newValue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var inheritance = FixInheritance(collection, mod, false);
|
var inheritance = FixInheritance(collection, mod, false);
|
||||||
((List<ModSettings?>)collection.Settings)[mod.Index]!.SetValue(mod, groupIdx, newValue);
|
collection.GetOwnSettings(mod.Index)!.SetValue(mod, groupIdx, newValue);
|
||||||
InvokeChange(collection, ModSettingChange.Setting, mod, inheritance ? Setting.Indefinite : oldValue, groupIdx);
|
InvokeChange(collection, ModSettingChange.Setting, mod, inheritance ? Setting.Indefinite : oldValue, groupIdx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -115,10 +113,10 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
// If it does not exist, check unused settings.
|
// If it does not exist, check unused settings.
|
||||||
// If it does not exist and has no unused settings, also use null.
|
// If it does not exist and has no unused settings, also use null.
|
||||||
ModSettings.SavedSettings? savedSettings = sourceMod != null
|
ModSettings.SavedSettings? savedSettings = sourceMod != null
|
||||||
? collection.Settings[sourceMod.Index] != null
|
? collection.GetOwnSettings(sourceMod.Index) is { } ownSettings
|
||||||
? new ModSettings.SavedSettings(collection.Settings[sourceMod.Index]!, sourceMod)
|
? new ModSettings.SavedSettings(ownSettings, sourceMod)
|
||||||
: null
|
: null
|
||||||
: collection.UnusedSettings.TryGetValue(sourceName, out var s)
|
: collection.Settings.Unused.TryGetValue(sourceName, out var s)
|
||||||
? s
|
? s
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
|
@ -148,10 +146,10 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
// or remove any unused settings for the target if they are inheriting.
|
// or remove any unused settings for the target if they are inheriting.
|
||||||
if (savedSettings != null)
|
if (savedSettings != null)
|
||||||
{
|
{
|
||||||
((Dictionary<string, ModSettings.SavedSettings>)collection.UnusedSettings)[targetName] = savedSettings.Value;
|
((Dictionary<string, ModSettings.SavedSettings>)collection.Settings.Unused)[targetName] = savedSettings.Value;
|
||||||
saveService.QueueSave(new ModCollectionSave(modStorage, collection));
|
saveService.QueueSave(new ModCollectionSave(modStorage, collection));
|
||||||
}
|
}
|
||||||
else if (((Dictionary<string, ModSettings.SavedSettings>)collection.UnusedSettings).Remove(targetName))
|
else if (((Dictionary<string, ModSettings.SavedSettings>)collection.Settings.Unused).Remove(targetName))
|
||||||
{
|
{
|
||||||
saveService.QueueSave(new ModCollectionSave(modStorage, collection));
|
saveService.QueueSave(new ModCollectionSave(modStorage, collection));
|
||||||
}
|
}
|
||||||
|
|
@ -166,12 +164,12 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool FixInheritance(ModCollection collection, Mod mod, bool inherit)
|
private static bool FixInheritance(ModCollection collection, Mod mod, bool inherit)
|
||||||
{
|
{
|
||||||
var settings = collection.Settings[mod.Index];
|
var settings = collection.GetOwnSettings(mod.Index);
|
||||||
if (inherit == (settings == null))
|
if (inherit == (settings == null))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
((List<ModSettings?>)collection.Settings)[mod.Index] =
|
ModSettings? settings1 = inherit ? null : collection.GetInheritedSettings(mod.Index).Settings?.DeepCopy() ?? ModSettings.DefaultSettings(mod);
|
||||||
inherit ? null : collection[mod.Index].Settings?.DeepCopy() ?? ModSettings.DefaultSettings(mod);
|
collection.Settings.Set(mod.Index, settings1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,7 +186,7 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private void RecurseInheritors(ModCollection directParent, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx)
|
private void RecurseInheritors(ModCollection directParent, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx)
|
||||||
{
|
{
|
||||||
foreach (var directInheritor in directParent.DirectParentOf)
|
foreach (var directInheritor in directParent.Inheritance.DirectlyInheritedBy)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
|
@ -197,7 +195,7 @@ public class CollectionEditor(SaveService saveService, CommunicatorService commu
|
||||||
communicator.ModSettingChanged.Invoke(directInheritor, type, null, oldValue, groupIdx, true);
|
communicator.ModSettingChanged.Invoke(directInheritor, type, null, oldValue, groupIdx, true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (directInheritor.Settings[mod!.Index] == null)
|
if (directInheritor.GetOwnSettings(mod!.Index) == null)
|
||||||
communicator.ModSettingChanged.Invoke(directInheritor, type, mod, oldValue, groupIdx, true);
|
communicator.ModSettingChanged.Invoke(directInheritor, type, mod, oldValue, groupIdx, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
public ModCollection CreateFromData(Guid id, string name, int version, Dictionary<string, ModSettings.SavedSettings> allSettings,
|
public ModCollection CreateFromData(Guid id, string name, int version, Dictionary<string, ModSettings.SavedSettings> allSettings,
|
||||||
IReadOnlyList<string> inheritances)
|
IReadOnlyList<string> inheritances)
|
||||||
{
|
{
|
||||||
var newCollection = ModCollection.CreateFromData(_saveService, _modStorage, new ModCollectionIdentity(id, CurrentCollectionId, name, Count), version, allSettings,
|
var newCollection = ModCollection.CreateFromData(_saveService, _modStorage,
|
||||||
inheritances);
|
new ModCollectionIdentity(id, CurrentCollectionId, name, Count), version, allSettings, inheritances);
|
||||||
_collectionsByLocal[CurrentCollectionId] = newCollection;
|
_collectionsByLocal[CurrentCollectionId] = newCollection;
|
||||||
CurrentCollectionId += 1;
|
CurrentCollectionId += 1;
|
||||||
return newCollection;
|
return newCollection;
|
||||||
|
|
@ -196,8 +196,8 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
/// <summary> Remove all settings for not currently-installed mods from the given collection. </summary>
|
/// <summary> Remove all settings for not currently-installed mods from the given collection. </summary>
|
||||||
public void CleanUnavailableSettings(ModCollection collection)
|
public void CleanUnavailableSettings(ModCollection collection)
|
||||||
{
|
{
|
||||||
var any = collection.UnusedSettings.Count > 0;
|
var any = collection.Settings.Unused.Count > 0;
|
||||||
((Dictionary<string, ModSettings.SavedSettings>)collection.UnusedSettings).Clear();
|
((Dictionary<string, ModSettings.SavedSettings>)collection.Settings.Unused).Clear();
|
||||||
if (any)
|
if (any)
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +205,7 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
/// <summary> Remove a specific setting for not currently-installed mods from the given collection. </summary>
|
/// <summary> Remove a specific setting for not currently-installed mods from the given collection. </summary>
|
||||||
public void CleanUnavailableSetting(ModCollection collection, string? setting)
|
public void CleanUnavailableSetting(ModCollection collection, string? setting)
|
||||||
{
|
{
|
||||||
if (setting != null && ((Dictionary<string, ModSettings.SavedSettings>)collection.UnusedSettings).Remove(setting))
|
if (setting != null && ((Dictionary<string, ModSettings.SavedSettings>)collection.Settings.Unused).Remove(setting))
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,7 +307,7 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
private void OnModDiscoveryStarted()
|
private void OnModDiscoveryStarted()
|
||||||
{
|
{
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
collection.PrepareModDiscovery(_modStorage);
|
collection.Settings.PrepareModDiscovery(_modStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Restore all settings in all collections to mods. </summary>
|
/// <summary> Restore all settings in all collections to mods. </summary>
|
||||||
|
|
@ -315,7 +315,7 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
{
|
{
|
||||||
// Re-apply all mod settings.
|
// Re-apply all mod settings.
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
collection.ApplyModSettings(_saveService, _modStorage);
|
collection.Settings.ApplyModSettings(collection, _saveService, _modStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Add or remove a mod from all collections, or re-save all collections where the mod has settings. </summary>
|
/// <summary> Add or remove a mod from all collections, or re-save all collections where the mod has settings. </summary>
|
||||||
|
|
@ -326,21 +326,22 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
{
|
{
|
||||||
case ModPathChangeType.Added:
|
case ModPathChangeType.Added:
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
collection.AddMod(mod);
|
collection.Settings.AddMod(mod);
|
||||||
break;
|
break;
|
||||||
case ModPathChangeType.Deleted:
|
case ModPathChangeType.Deleted:
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
collection.RemoveMod(mod);
|
collection.Settings.RemoveMod(mod);
|
||||||
break;
|
break;
|
||||||
case ModPathChangeType.Moved:
|
case ModPathChangeType.Moved:
|
||||||
foreach (var collection in this.Where(collection => collection.Settings[mod.Index] != null))
|
foreach (var collection in this.Where(collection => collection.GetOwnSettings(mod.Index) != null))
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
||||||
break;
|
break;
|
||||||
case ModPathChangeType.Reloaded:
|
case ModPathChangeType.Reloaded:
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
{
|
{
|
||||||
if (collection.Settings[mod.Index]?.Settings.FixAll(mod) ?? false)
|
if (collection.GetOwnSettings(mod.Index)?.Settings.FixAll(mod) ?? false)
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
||||||
|
collection.Settings.SetTemporary(mod.Index, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -357,8 +358,9 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
|
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
{
|
{
|
||||||
if (collection.Settings[mod.Index]?.HandleChanges(type, mod, group, option, movedToIdx) ?? false)
|
if (collection.GetOwnSettings(mod.Index)?.HandleChanges(type, mod, group, option, movedToIdx) ?? false)
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, collection));
|
||||||
|
collection.Settings.SetTemporary(mod.Index, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,7 +372,7 @@ public class CollectionStorage : IReadOnlyList<ModCollection>, IDisposable, ISer
|
||||||
|
|
||||||
foreach (var collection in this)
|
foreach (var collection in this)
|
||||||
{
|
{
|
||||||
var (settings, _) = collection[mod.Index];
|
var (settings, _) = collection.GetActualSettings(mod.Index);
|
||||||
if (settings is { Enabled: true })
|
if (settings is { Enabled: true })
|
||||||
collection.Counters.IncrementChange();
|
collection.Counters.IncrementChange();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using OtterGui.Filesystem;
|
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.Communication;
|
using Penumbra.Communication;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
|
@ -63,10 +62,10 @@ public class InheritanceManager : IDisposable, IService
|
||||||
if (ReferenceEquals(potentialParent, potentialInheritor))
|
if (ReferenceEquals(potentialParent, potentialInheritor))
|
||||||
return ValidInheritance.Self;
|
return ValidInheritance.Self;
|
||||||
|
|
||||||
if (potentialInheritor.DirectlyInheritsFrom.Contains(potentialParent))
|
if (potentialInheritor.Inheritance.DirectlyInheritsFrom.Contains(potentialParent))
|
||||||
return ValidInheritance.Contained;
|
return ValidInheritance.Contained;
|
||||||
|
|
||||||
if (ModCollection.InheritedCollections(potentialParent).Any(c => ReferenceEquals(c, potentialInheritor)))
|
if (potentialParent.Inheritance.FlatHierarchy.Any(c => ReferenceEquals(c, potentialInheritor)))
|
||||||
return ValidInheritance.Circle;
|
return ValidInheritance.Circle;
|
||||||
|
|
||||||
return ValidInheritance.Valid;
|
return ValidInheritance.Valid;
|
||||||
|
|
@ -83,24 +82,22 @@ public class InheritanceManager : IDisposable, IService
|
||||||
/// <summary> Remove an existing inheritance from a collection. </summary>
|
/// <summary> Remove an existing inheritance from a collection. </summary>
|
||||||
public void RemoveInheritance(ModCollection inheritor, int idx)
|
public void RemoveInheritance(ModCollection inheritor, int idx)
|
||||||
{
|
{
|
||||||
var parent = inheritor.DirectlyInheritsFrom[idx];
|
var parent = inheritor.Inheritance.RemoveInheritanceAt(inheritor, idx);
|
||||||
((List<ModCollection>)inheritor.DirectlyInheritsFrom).RemoveAt(idx);
|
|
||||||
((List<ModCollection>)parent.DirectParentOf).Remove(inheritor);
|
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor));
|
||||||
_communicator.CollectionInheritanceChanged.Invoke(inheritor, false);
|
_communicator.CollectionInheritanceChanged.Invoke(inheritor, false);
|
||||||
RecurseInheritanceChanges(inheritor);
|
RecurseInheritanceChanges(inheritor, true);
|
||||||
Penumbra.Log.Debug($"Removed {parent.Identity.AnonymizedName} from {inheritor.Identity.AnonymizedName} inheritances.");
|
Penumbra.Log.Debug($"Removed {parent.Identity.AnonymizedName} from {inheritor.Identity.AnonymizedName} inheritances.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Order in the inheritance list is relevant. </summary>
|
/// <summary> Order in the inheritance list is relevant. </summary>
|
||||||
public void MoveInheritance(ModCollection inheritor, int from, int to)
|
public void MoveInheritance(ModCollection inheritor, int from, int to)
|
||||||
{
|
{
|
||||||
if (!((List<ModCollection>)inheritor.DirectlyInheritsFrom).Move(from, to))
|
if (!inheritor.Inheritance.MoveInheritance(inheritor, from, to))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor));
|
||||||
_communicator.CollectionInheritanceChanged.Invoke(inheritor, false);
|
_communicator.CollectionInheritanceChanged.Invoke(inheritor, false);
|
||||||
RecurseInheritanceChanges(inheritor);
|
RecurseInheritanceChanges(inheritor, true);
|
||||||
Penumbra.Log.Debug($"Moved {inheritor.Identity.AnonymizedName}s inheritance {from} to {to}.");
|
Penumbra.Log.Debug($"Moved {inheritor.Identity.AnonymizedName}s inheritance {from} to {to}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,15 +107,15 @@ public class InheritanceManager : IDisposable, IService
|
||||||
if (CheckValidInheritance(inheritor, parent) != ValidInheritance.Valid)
|
if (CheckValidInheritance(inheritor, parent) != ValidInheritance.Valid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
((List<ModCollection>)inheritor.DirectlyInheritsFrom).Add(parent);
|
inheritor.Inheritance.AddInheritance(inheritor, parent);
|
||||||
((List<ModCollection>)parent.DirectParentOf).Add(inheritor);
|
|
||||||
if (invokeEvent)
|
if (invokeEvent)
|
||||||
{
|
{
|
||||||
_saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor));
|
_saveService.QueueSave(new ModCollectionSave(_modStorage, inheritor));
|
||||||
_communicator.CollectionInheritanceChanged.Invoke(inheritor, false);
|
_communicator.CollectionInheritanceChanged.Invoke(inheritor, false);
|
||||||
RecurseInheritanceChanges(inheritor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecurseInheritanceChanges(inheritor, invokeEvent);
|
||||||
|
|
||||||
Penumbra.Log.Debug($"Added {parent.Identity.AnonymizedName} to {inheritor.Identity.AnonymizedName} inheritances.");
|
Penumbra.Log.Debug($"Added {parent.Identity.AnonymizedName} to {inheritor.Identity.AnonymizedName} inheritances.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -131,11 +128,11 @@ public class InheritanceManager : IDisposable, IService
|
||||||
{
|
{
|
||||||
foreach (var collection in _storage)
|
foreach (var collection in _storage)
|
||||||
{
|
{
|
||||||
if (collection.InheritanceByName == null)
|
if (collection.Inheritance.ConsumeNames() is not { } byName)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var changes = false;
|
var changes = false;
|
||||||
foreach (var subCollectionName in collection.InheritanceByName)
|
foreach (var subCollectionName in byName)
|
||||||
{
|
{
|
||||||
if (Guid.TryParse(subCollectionName, out var guid) && _storage.ById(guid, out var subCollection))
|
if (Guid.TryParse(subCollectionName, out var guid) && _storage.ById(guid, out var subCollection))
|
||||||
{
|
{
|
||||||
|
|
@ -143,7 +140,8 @@ public class InheritanceManager : IDisposable, IService
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
changes = true;
|
changes = true;
|
||||||
Penumbra.Messager.NotificationMessage($"{collection.Identity.Name} can not inherit from {subCollection.Identity.Name}, removed.",
|
Penumbra.Messager.NotificationMessage(
|
||||||
|
$"{collection.Identity.Name} can not inherit from {subCollection.Identity.Name}, removed.",
|
||||||
NotificationType.Warning);
|
NotificationType.Warning);
|
||||||
}
|
}
|
||||||
else if (_storage.ByName(subCollectionName, out subCollection))
|
else if (_storage.ByName(subCollectionName, out subCollection))
|
||||||
|
|
@ -153,7 +151,8 @@ public class InheritanceManager : IDisposable, IService
|
||||||
if (AddInheritance(collection, subCollection, false))
|
if (AddInheritance(collection, subCollection, false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Penumbra.Messager.NotificationMessage($"{collection.Identity.Name} can not inherit from {subCollection.Identity.Name}, removed.",
|
Penumbra.Messager.NotificationMessage(
|
||||||
|
$"{collection.Identity.Name} can not inherit from {subCollection.Identity.Name}, removed.",
|
||||||
NotificationType.Warning);
|
NotificationType.Warning);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -165,7 +164,6 @@ public class InheritanceManager : IDisposable, IService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collection.InheritanceByName = null;
|
|
||||||
if (changes)
|
if (changes)
|
||||||
_saveService.ImmediateSave(new ModCollectionSave(_modStorage, collection));
|
_saveService.ImmediateSave(new ModCollectionSave(_modStorage, collection));
|
||||||
}
|
}
|
||||||
|
|
@ -178,20 +176,22 @@ public class InheritanceManager : IDisposable, IService
|
||||||
|
|
||||||
foreach (var c in _storage)
|
foreach (var c in _storage)
|
||||||
{
|
{
|
||||||
var inheritedIdx = c.DirectlyInheritsFrom.IndexOf(old);
|
var inheritedIdx = c.Inheritance.DirectlyInheritsFrom.IndexOf(old);
|
||||||
if (inheritedIdx >= 0)
|
if (inheritedIdx >= 0)
|
||||||
RemoveInheritance(c, inheritedIdx);
|
RemoveInheritance(c, inheritedIdx);
|
||||||
|
|
||||||
((List<ModCollection>)c.DirectParentOf).Remove(old);
|
c.Inheritance.RemoveChild(old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecurseInheritanceChanges(ModCollection newInheritor)
|
private void RecurseInheritanceChanges(ModCollection newInheritor, bool invokeEvent)
|
||||||
{
|
{
|
||||||
foreach (var inheritor in newInheritor.DirectParentOf)
|
foreach (var inheritor in newInheritor.Inheritance.DirectlyInheritedBy)
|
||||||
{
|
{
|
||||||
_communicator.CollectionInheritanceChanged.Invoke(inheritor, true);
|
ModCollectionInheritance.UpdateFlattenedInheritance(inheritor);
|
||||||
RecurseInheritanceChanges(inheritor);
|
RecurseInheritanceChanges(inheritor, invokeEvent);
|
||||||
|
if (invokeEvent)
|
||||||
|
_communicator.CollectionInheritanceChanged.Invoke(inheritor, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ internal static class ModCollectionMigration
|
||||||
// Remove all completely defaulted settings from active and inactive mods.
|
// Remove all completely defaulted settings from active and inactive mods.
|
||||||
for (var i = 0; i < collection.Settings.Count; ++i)
|
for (var i = 0; i < collection.Settings.Count; ++i)
|
||||||
{
|
{
|
||||||
if (SettingIsDefaultV0(collection.Settings[i]))
|
if (SettingIsDefaultV0(collection.GetOwnSettings(i)))
|
||||||
((List<ModSettings?>)collection.Settings)[i] = null;
|
collection.Settings.SetAll(i, FullModSettings.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (key, _) in collection.UnusedSettings.Where(kvp => SettingIsDefaultV0(kvp.Value)).ToList())
|
foreach (var (key, _) in collection.Settings.Unused.Where(kvp => SettingIsDefaultV0(kvp.Value)).ToList())
|
||||||
((Dictionary<string, ModSettings.SavedSettings>)collection.UnusedSettings).Remove(key);
|
collection.Settings.RemoveUnused(key);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
using Penumbra.Mods;
|
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Collections.Manager;
|
using Penumbra.Collections.Manager;
|
||||||
using Penumbra.Mods.Settings;
|
using Penumbra.Mods.Settings;
|
||||||
|
|
@ -22,70 +21,74 @@ public partial class ModCollection
|
||||||
/// Create the always available Empty Collection that will always sit at index 0,
|
/// Create the always available Empty Collection that will always sit at index 0,
|
||||||
/// can not be deleted and does never create a cache.
|
/// can not be deleted and does never create a cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly ModCollection Empty = new(ModCollectionIdentity.Empty, 0, CurrentVersion, [], [], []);
|
public static readonly ModCollection Empty = new(ModCollectionIdentity.Empty, 0, CurrentVersion, new ModSettingProvider(),
|
||||||
|
new ModCollectionInheritance());
|
||||||
|
|
||||||
public ModCollectionIdentity Identity;
|
public ModCollectionIdentity Identity;
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> Identity.ToString();
|
=> Identity.ToString();
|
||||||
|
|
||||||
public CollectionCounters Counters;
|
public readonly ModSettingProvider Settings;
|
||||||
|
public ModCollectionInheritance Inheritance;
|
||||||
|
public CollectionCounters Counters;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If a ModSetting is null, it can be inherited from other collections.
|
|
||||||
/// If no collection provides a setting for the mod, it is just disabled.
|
|
||||||
/// </summary>
|
|
||||||
public readonly IReadOnlyList<ModSettings?> Settings;
|
|
||||||
|
|
||||||
/// <summary> Settings for deleted mods will be kept via the mods identifier (directory name). </summary>
|
public ModSettings? GetOwnSettings(Index idx)
|
||||||
public readonly IReadOnlyDictionary<string, ModSettings.SavedSettings> UnusedSettings;
|
|
||||||
|
|
||||||
/// <summary> Inheritances stored before they can be applied. </summary>
|
|
||||||
public IReadOnlyList<string>? InheritanceByName;
|
|
||||||
|
|
||||||
/// <summary> Contains all direct parent collections this collection inherits settings from. </summary>
|
|
||||||
public readonly IReadOnlyList<ModCollection> DirectlyInheritsFrom;
|
|
||||||
|
|
||||||
/// <summary> Contains all direct child collections that inherit from this collection. </summary>
|
|
||||||
public readonly IReadOnlyList<ModCollection> DirectParentOf = new List<ModCollection>();
|
|
||||||
|
|
||||||
/// <summary> All inherited collections in application order without filtering for duplicates. </summary>
|
|
||||||
public static IEnumerable<ModCollection> InheritedCollections(ModCollection collection)
|
|
||||||
=> collection.DirectlyInheritsFrom.SelectMany(InheritedCollections).Prepend(collection);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Iterate over all collections inherited from in depth-first order.
|
|
||||||
/// Skip already visited collections to avoid circular dependencies.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<ModCollection> GetFlattenedInheritance()
|
|
||||||
=> InheritedCollections(this).Distinct();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Obtain the actual settings for a given mod via index.
|
|
||||||
/// Also returns the collection the settings are taken from.
|
|
||||||
/// If no collection provides settings for this mod, this collection is returned together with null.
|
|
||||||
/// </summary>
|
|
||||||
public (ModSettings? Settings, ModCollection Collection) this[Index idx]
|
|
||||||
{
|
{
|
||||||
get
|
if (Identity.Index <= 0)
|
||||||
|
return ModSettings.Empty;
|
||||||
|
|
||||||
|
return Settings.Settings[idx].Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemporaryModSettings? GetTempSettings(Index idx)
|
||||||
|
{
|
||||||
|
if (Identity.Index <= 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Settings.Settings[idx].TempSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public (ModSettings? Settings, ModCollection Collection) GetInheritedSettings(Index idx)
|
||||||
|
{
|
||||||
|
if (Identity.Index <= 0)
|
||||||
|
return (ModSettings.Empty, this);
|
||||||
|
|
||||||
|
foreach (var collection in Inheritance.FlatHierarchy)
|
||||||
{
|
{
|
||||||
if (Identity.Index <= 0)
|
var settings = collection.Settings.Settings[idx].Settings;
|
||||||
return (ModSettings.Empty, this);
|
if (settings != null)
|
||||||
|
return (settings, collection);
|
||||||
foreach (var collection in GetFlattenedInheritance())
|
|
||||||
{
|
|
||||||
var settings = collection.Settings[idx];
|
|
||||||
if (settings != null)
|
|
||||||
return (settings, collection);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (null, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (ModSettings? Settings, ModCollection Collection) GetActualSettings(Index idx)
|
||||||
|
{
|
||||||
|
if (Identity.Index <= 0)
|
||||||
|
return (ModSettings.Empty, this);
|
||||||
|
|
||||||
|
// Check temp settings.
|
||||||
|
var ownTempSettings = Settings.Settings[idx].Resolve();
|
||||||
|
if (ownTempSettings != null)
|
||||||
|
return (ownTempSettings, this);
|
||||||
|
|
||||||
|
// Ignore temp settings for inherited collections.
|
||||||
|
foreach (var collection in Inheritance.FlatHierarchy.Skip(1))
|
||||||
|
{
|
||||||
|
var settings = collection.Settings.Settings[idx].Settings;
|
||||||
|
if (settings != null)
|
||||||
|
return (settings, collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Evaluates all settings along the whole inheritance tree. </summary>
|
/// <summary> Evaluates all settings along the whole inheritance tree. </summary>
|
||||||
public IEnumerable<ModSettings?> ActualSettings
|
public IEnumerable<ModSettings?> ActualSettings
|
||||||
=> Enumerable.Range(0, Settings.Count).Select(i => this[i].Settings);
|
=> Enumerable.Range(0, Settings.Count).Select(i => GetActualSettings(i).Settings);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor for duplication. Deep copies all settings and parent collections and adds the new collection to their children lists.
|
/// Constructor for duplication. Deep copies all settings and parent collections and adds the new collection to their children lists.
|
||||||
|
|
@ -93,9 +96,7 @@ public partial class ModCollection
|
||||||
public ModCollection Duplicate(string name, LocalCollectionId localId, int index)
|
public ModCollection Duplicate(string name, LocalCollectionId localId, int index)
|
||||||
{
|
{
|
||||||
Debug.Assert(index > 0, "Collection duplicated with non-positive index.");
|
Debug.Assert(index > 0, "Collection duplicated with non-positive index.");
|
||||||
return new ModCollection(ModCollectionIdentity.New(name, localId, index), 0, CurrentVersion,
|
return new ModCollection(ModCollectionIdentity.New(name, localId, index), 0, CurrentVersion, Settings.Clone(), Inheritance.Clone());
|
||||||
Settings.Select(s => s?.DeepCopy()).ToList(), [.. DirectlyInheritsFrom],
|
|
||||||
UnusedSettings.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.DeepCopy()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Constructor for reading from files. </summary>
|
/// <summary> Constructor for reading from files. </summary>
|
||||||
|
|
@ -103,11 +104,8 @@ public partial class ModCollection
|
||||||
Dictionary<string, ModSettings.SavedSettings> allSettings, IReadOnlyList<string> inheritances)
|
Dictionary<string, ModSettings.SavedSettings> allSettings, IReadOnlyList<string> inheritances)
|
||||||
{
|
{
|
||||||
Debug.Assert(identity.Index > 0, "Collection read with non-positive index.");
|
Debug.Assert(identity.Index > 0, "Collection read with non-positive index.");
|
||||||
var ret = new ModCollection(identity, 0, version, [], [], allSettings)
|
var ret = new ModCollection(identity, 0, version, new ModSettingProvider(allSettings), new ModCollectionInheritance(inheritances));
|
||||||
{
|
ret.Settings.ApplyModSettings(ret, saver, mods);
|
||||||
InheritanceByName = inheritances,
|
|
||||||
};
|
|
||||||
ret.ApplyModSettings(saver, mods);
|
|
||||||
ModCollectionMigration.Migrate(saver, mods, version, ret);
|
ModCollectionMigration.Migrate(saver, mods, version, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +114,8 @@ public partial class ModCollection
|
||||||
public static ModCollection CreateTemporary(string name, LocalCollectionId localId, int index, int changeCounter)
|
public static ModCollection CreateTemporary(string name, LocalCollectionId localId, int index, int changeCounter)
|
||||||
{
|
{
|
||||||
Debug.Assert(index < 0, "Temporary collection created with non-negative index.");
|
Debug.Assert(index < 0, "Temporary collection created with non-negative index.");
|
||||||
var ret = new ModCollection(ModCollectionIdentity.New(name, localId, index), changeCounter, CurrentVersion, [], [], []);
|
var ret = new ModCollection(ModCollectionIdentity.New(name, localId, index), changeCounter, CurrentVersion, new ModSettingProvider(),
|
||||||
|
new ModCollectionInheritance());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,64 +123,18 @@ public partial class ModCollection
|
||||||
public static ModCollection CreateEmpty(string name, LocalCollectionId localId, int index, int modCount)
|
public static ModCollection CreateEmpty(string name, LocalCollectionId localId, int index, int modCount)
|
||||||
{
|
{
|
||||||
Debug.Assert(index >= 0, "Empty collection created with negative index.");
|
Debug.Assert(index >= 0, "Empty collection created with negative index.");
|
||||||
return new ModCollection(ModCollectionIdentity.New(name, localId, index), 0, CurrentVersion,
|
return new ModCollection(ModCollectionIdentity.New(name, localId, index), 0, CurrentVersion, ModSettingProvider.Empty(modCount),
|
||||||
Enumerable.Repeat((ModSettings?)null, modCount).ToList(), [], []);
|
new ModCollectionInheritance());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Add settings for a new appended mod, by checking if the mod had settings from a previous deletion. </summary>
|
private ModCollection(ModCollectionIdentity identity, int changeCounter, int version, ModSettingProvider settings,
|
||||||
internal bool AddMod(Mod mod)
|
ModCollectionInheritance inheritance)
|
||||||
{
|
{
|
||||||
if (UnusedSettings.TryGetValue(mod.ModPath.Name, out var save))
|
Identity = identity;
|
||||||
{
|
Counters = new CollectionCounters(changeCounter);
|
||||||
var ret = save.ToSettings(mod, out var settings);
|
Settings = settings;
|
||||||
((List<ModSettings?>)Settings).Add(settings);
|
Inheritance = inheritance;
|
||||||
((Dictionary<string, ModSettings.SavedSettings>)UnusedSettings).Remove(mod.ModPath.Name);
|
ModCollectionInheritance.UpdateChildren(this);
|
||||||
return ret;
|
ModCollectionInheritance.UpdateFlattenedInheritance(this);
|
||||||
}
|
|
||||||
|
|
||||||
((List<ModSettings?>)Settings).Add(null);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Move settings from the current mod list to the unused mod settings. </summary>
|
|
||||||
internal void RemoveMod(Mod mod)
|
|
||||||
{
|
|
||||||
var settings = Settings[mod.Index];
|
|
||||||
if (settings != null)
|
|
||||||
((Dictionary<string, ModSettings.SavedSettings>)UnusedSettings)[mod.ModPath.Name] = new ModSettings.SavedSettings(settings, mod);
|
|
||||||
|
|
||||||
((List<ModSettings?>)Settings).RemoveAt(mod.Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Move all settings to unused settings for rediscovery. </summary>
|
|
||||||
internal void PrepareModDiscovery(ModStorage mods)
|
|
||||||
{
|
|
||||||
foreach (var (mod, setting) in mods.Zip(Settings).Where(s => s.Second != null))
|
|
||||||
((Dictionary<string, ModSettings.SavedSettings>)UnusedSettings)[mod.ModPath.Name] = new ModSettings.SavedSettings(setting!, mod);
|
|
||||||
|
|
||||||
((List<ModSettings?>)Settings).Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Apply all mod settings from unused settings to the current set of mods.
|
|
||||||
/// Also fixes invalid settings.
|
|
||||||
/// </summary>
|
|
||||||
internal void ApplyModSettings(SaveService saver, ModStorage mods)
|
|
||||||
{
|
|
||||||
((List<ModSettings?>)Settings).Capacity = Math.Max(((List<ModSettings?>)Settings).Capacity, mods.Count);
|
|
||||||
if (mods.Aggregate(false, (current, mod) => current | AddMod(mod)))
|
|
||||||
saver.ImmediateSave(new ModCollectionSave(mods, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
private ModCollection(ModCollectionIdentity identity, int changeCounter, int version, List<ModSettings?> appliedSettings,
|
|
||||||
List<ModCollection> inheritsFrom, Dictionary<string, ModSettings.SavedSettings> settings)
|
|
||||||
{
|
|
||||||
Identity = identity;
|
|
||||||
Counters = new CollectionCounters(changeCounter);
|
|
||||||
Settings = appliedSettings;
|
|
||||||
UnusedSettings = settings;
|
|
||||||
DirectlyInheritsFrom = inheritsFrom;
|
|
||||||
foreach (var c in DirectlyInheritsFrom)
|
|
||||||
((List<ModCollection>)c.DirectParentOf).Add(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
92
Penumbra/Collections/ModCollectionInheritance.cs
Normal file
92
Penumbra/Collections/ModCollectionInheritance.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
using OtterGui.Filesystem;
|
||||||
|
|
||||||
|
namespace Penumbra.Collections;
|
||||||
|
|
||||||
|
public struct ModCollectionInheritance
|
||||||
|
{
|
||||||
|
public IReadOnlyList<string>? InheritanceByName { get; private set; }
|
||||||
|
private readonly List<ModCollection> _directlyInheritsFrom = [];
|
||||||
|
private readonly List<ModCollection> _directlyInheritedBy = [];
|
||||||
|
private readonly List<ModCollection> _flatHierarchy = [];
|
||||||
|
|
||||||
|
public ModCollectionInheritance()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private ModCollectionInheritance(List<ModCollection> inheritsFrom)
|
||||||
|
=> _directlyInheritsFrom = [.. inheritsFrom];
|
||||||
|
|
||||||
|
public ModCollectionInheritance(IReadOnlyList<string> byName)
|
||||||
|
=> InheritanceByName = byName;
|
||||||
|
|
||||||
|
public ModCollectionInheritance Clone()
|
||||||
|
=> new(_directlyInheritsFrom);
|
||||||
|
|
||||||
|
public IEnumerable<string> Identifiers
|
||||||
|
=> InheritanceByName ?? _directlyInheritsFrom.Select(c => c.Identity.Identifier);
|
||||||
|
|
||||||
|
public IReadOnlyList<string>? ConsumeNames()
|
||||||
|
{
|
||||||
|
var ret = InheritanceByName;
|
||||||
|
InheritanceByName = null;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateChildren(ModCollection parent)
|
||||||
|
{
|
||||||
|
foreach (var inheritance in parent.Inheritance.DirectlyInheritsFrom)
|
||||||
|
inheritance.Inheritance._directlyInheritedBy.Add(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddInheritance(ModCollection inheritor, ModCollection newParent)
|
||||||
|
{
|
||||||
|
_directlyInheritsFrom.Add(newParent);
|
||||||
|
newParent.Inheritance._directlyInheritedBy.Add(inheritor);
|
||||||
|
UpdateFlattenedInheritance(inheritor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModCollection RemoveInheritanceAt(ModCollection inheritor, int idx)
|
||||||
|
{
|
||||||
|
var parent = DirectlyInheritsFrom[idx];
|
||||||
|
_directlyInheritsFrom.RemoveAt(idx);
|
||||||
|
parent.Inheritance._directlyInheritedBy.Remove(parent);
|
||||||
|
UpdateFlattenedInheritance(inheritor);
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveInheritance(ModCollection inheritor, int from, int to)
|
||||||
|
{
|
||||||
|
if (!_directlyInheritsFrom.Move(from, to))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UpdateFlattenedInheritance(inheritor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveChild(ModCollection child)
|
||||||
|
=> _directlyInheritedBy.Remove(child);
|
||||||
|
|
||||||
|
/// <summary> Contains all direct parent collections this collection inherits settings from. </summary>
|
||||||
|
public readonly IReadOnlyList<ModCollection> DirectlyInheritsFrom
|
||||||
|
=> _directlyInheritsFrom;
|
||||||
|
|
||||||
|
/// <summary> Contains all direct child collections that inherit from this collection. </summary>
|
||||||
|
public readonly IReadOnlyList<ModCollection> DirectlyInheritedBy
|
||||||
|
=> _directlyInheritedBy;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterate over all collections inherited from in depth-first order.
|
||||||
|
/// Skip already visited collections to avoid circular dependencies.
|
||||||
|
/// </summary>
|
||||||
|
public readonly IReadOnlyList<ModCollection> FlatHierarchy
|
||||||
|
=> _flatHierarchy;
|
||||||
|
|
||||||
|
public static void UpdateFlattenedInheritance(ModCollection parent)
|
||||||
|
{
|
||||||
|
parent.Inheritance._flatHierarchy.Clear();
|
||||||
|
parent.Inheritance._flatHierarchy.AddRange(InheritedCollections(parent).Distinct());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> All inherited collections in application order without filtering for duplicates. </summary>
|
||||||
|
private static IEnumerable<ModCollection> InheritedCollections(ModCollection parent)
|
||||||
|
=> parent.Inheritance.DirectlyInheritsFrom.SelectMany(InheritedCollections).Prepend(parent);
|
||||||
|
}
|
||||||
|
|
@ -32,19 +32,19 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection
|
||||||
j.WriteValue(modCollection.Identity.Identifier);
|
j.WriteValue(modCollection.Identity.Identifier);
|
||||||
j.WritePropertyName(nameof(ModCollectionIdentity.Name));
|
j.WritePropertyName(nameof(ModCollectionIdentity.Name));
|
||||||
j.WriteValue(modCollection.Identity.Name);
|
j.WriteValue(modCollection.Identity.Name);
|
||||||
j.WritePropertyName(nameof(ModCollection.Settings));
|
j.WritePropertyName("Settings");
|
||||||
|
|
||||||
// Write all used and unused settings by mod directory name.
|
// Write all used and unused settings by mod directory name.
|
||||||
j.WriteStartObject();
|
j.WriteStartObject();
|
||||||
var list = new List<(string, ModSettings.SavedSettings)>(modCollection.Settings.Count + modCollection.UnusedSettings.Count);
|
var list = new List<(string, ModSettings.SavedSettings)>(modCollection.Settings.Count + modCollection.Settings.Unused.Count);
|
||||||
for (var i = 0; i < modCollection.Settings.Count; ++i)
|
for (var i = 0; i < modCollection.Settings.Count; ++i)
|
||||||
{
|
{
|
||||||
var settings = modCollection.Settings[i];
|
var settings = modCollection.GetOwnSettings(i);
|
||||||
if (settings != null)
|
if (settings != null)
|
||||||
list.Add((modStorage[i].ModPath.Name, new ModSettings.SavedSettings(settings, modStorage[i])));
|
list.Add((modStorage[i].ModPath.Name, new ModSettings.SavedSettings(settings, modStorage[i])));
|
||||||
}
|
}
|
||||||
|
|
||||||
list.AddRange(modCollection.UnusedSettings.Select(kvp => (kvp.Key, kvp.Value)));
|
list.AddRange(modCollection.Settings.Unused.Select(kvp => (kvp.Key, kvp.Value)));
|
||||||
list.Sort((a, b) => string.Compare(a.Item1, b.Item1, StringComparison.OrdinalIgnoreCase));
|
list.Sort((a, b) => string.Compare(a.Item1, b.Item1, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
foreach (var (modDir, settings) in list)
|
foreach (var (modDir, settings) in list)
|
||||||
|
|
@ -57,7 +57,7 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection
|
||||||
|
|
||||||
// Inherit by collection name.
|
// Inherit by collection name.
|
||||||
j.WritePropertyName("Inheritance");
|
j.WritePropertyName("Inheritance");
|
||||||
x.Serialize(j, modCollection.InheritanceByName ?? modCollection.DirectlyInheritsFrom.Select(c => c.Identity.Identifier));
|
x.Serialize(j, modCollection.Inheritance.Identifiers);
|
||||||
j.WriteEndObject();
|
j.WriteEndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ internal readonly struct ModCollectionSave(ModStorage modStorage, ModCollection
|
||||||
name = obj[nameof(ModCollectionIdentity.Name)]?.ToObject<string>() ?? string.Empty;
|
name = obj[nameof(ModCollectionIdentity.Name)]?.ToObject<string>() ?? string.Empty;
|
||||||
id = obj[nameof(ModCollectionIdentity.Id)]?.ToObject<Guid>() ?? (version == 1 ? Guid.NewGuid() : Guid.Empty);
|
id = obj[nameof(ModCollectionIdentity.Id)]?.ToObject<Guid>() ?? (version == 1 ? Guid.NewGuid() : Guid.Empty);
|
||||||
// Custom deserialization that is converted with the constructor.
|
// Custom deserialization that is converted with the constructor.
|
||||||
settings = obj[nameof(ModCollection.Settings)]?.ToObject<Dictionary<string, ModSettings.SavedSettings>>() ?? settings;
|
settings = obj["Settings"]?.ToObject<Dictionary<string, ModSettings.SavedSettings>>() ?? settings;
|
||||||
inheritance = obj["Inheritance"]?.ToObject<List<string>>() ?? inheritance;
|
inheritance = obj["Inheritance"]?.ToObject<List<string>>() ?? inheritance;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
98
Penumbra/Collections/ModSettingProvider.cs
Normal file
98
Penumbra/Collections/ModSettingProvider.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Settings;
|
||||||
|
using Penumbra.Services;
|
||||||
|
|
||||||
|
namespace Penumbra.Collections;
|
||||||
|
|
||||||
|
public readonly struct ModSettingProvider
|
||||||
|
{
|
||||||
|
private ModSettingProvider(IEnumerable<FullModSettings> settings, Dictionary<string, ModSettings.SavedSettings> unusedSettings)
|
||||||
|
{
|
||||||
|
_settings = settings.Select(s => s.DeepCopy()).ToList();
|
||||||
|
_unused = unusedSettings.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.DeepCopy());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModSettingProvider()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public static ModSettingProvider Empty(int count)
|
||||||
|
=> new(Enumerable.Repeat(FullModSettings.Empty, count), []);
|
||||||
|
|
||||||
|
public ModSettingProvider(Dictionary<string, ModSettings.SavedSettings> allSettings)
|
||||||
|
=> _unused = allSettings;
|
||||||
|
|
||||||
|
private readonly List<FullModSettings> _settings = [];
|
||||||
|
|
||||||
|
/// <summary> Settings for deleted mods will be kept via the mods identifier (directory name). </summary>
|
||||||
|
private readonly Dictionary<string, ModSettings.SavedSettings> _unused = [];
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
=> _settings.Count;
|
||||||
|
|
||||||
|
public bool RemoveUnused(string key)
|
||||||
|
=> _unused.Remove(key);
|
||||||
|
|
||||||
|
internal void Set(Index index, ModSettings? settings)
|
||||||
|
=> _settings[index] = _settings[index] with { Settings = settings };
|
||||||
|
|
||||||
|
internal void SetTemporary(Index index, TemporaryModSettings? settings)
|
||||||
|
=> _settings[index] = _settings[index] with { TempSettings = settings };
|
||||||
|
|
||||||
|
internal void SetAll(Index index, FullModSettings settings)
|
||||||
|
=> _settings[index] = settings;
|
||||||
|
|
||||||
|
public IReadOnlyList<FullModSettings> Settings
|
||||||
|
=> _settings;
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<string, ModSettings.SavedSettings> Unused
|
||||||
|
=> _unused;
|
||||||
|
|
||||||
|
public ModSettingProvider Clone()
|
||||||
|
=> new(_settings, _unused);
|
||||||
|
|
||||||
|
/// <summary> Add settings for a new appended mod, by checking if the mod had settings from a previous deletion. </summary>
|
||||||
|
internal bool AddMod(Mod mod)
|
||||||
|
{
|
||||||
|
if (_unused.Remove(mod.ModPath.Name, out var save))
|
||||||
|
{
|
||||||
|
var ret = save.ToSettings(mod, out var settings);
|
||||||
|
_settings.Add(new FullModSettings(settings));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_settings.Add(FullModSettings.Empty);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Move settings from the current mod list to the unused mod settings. </summary>
|
||||||
|
internal void RemoveMod(Mod mod)
|
||||||
|
{
|
||||||
|
var settings = _settings[mod.Index];
|
||||||
|
if (settings.Settings != null)
|
||||||
|
_unused[mod.ModPath.Name] = new ModSettings.SavedSettings(settings.Settings, mod);
|
||||||
|
|
||||||
|
_settings.RemoveAt(mod.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Move all settings to unused settings for rediscovery. </summary>
|
||||||
|
internal void PrepareModDiscovery(ModStorage mods)
|
||||||
|
{
|
||||||
|
foreach (var (mod, setting) in mods.Zip(_settings).Where(s => s.Second.Settings != null))
|
||||||
|
_unused[mod.ModPath.Name] = new ModSettings.SavedSettings(setting.Settings!, mod);
|
||||||
|
|
||||||
|
_settings.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply all mod settings from unused settings to the current set of mods.
|
||||||
|
/// Also fixes invalid settings.
|
||||||
|
/// </summary>
|
||||||
|
internal void ApplyModSettings(ModCollection parent, SaveService saver, ModStorage mods)
|
||||||
|
{
|
||||||
|
_settings.Capacity = Math.Max(_settings.Capacity, mods.Count);
|
||||||
|
var settings = this;
|
||||||
|
if (mods.Aggregate(false, (current, mod) => current | settings.AddMod(mod)))
|
||||||
|
saver.ImmediateSave(new ModCollectionSave(mods, parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -606,7 +606,7 @@ public class CommandHandler : IDisposable, IApiService
|
||||||
|
|
||||||
private bool HandleModState(int settingState, ModCollection collection, Mod mod)
|
private bool HandleModState(int settingState, ModCollection collection, Mod mod)
|
||||||
{
|
{
|
||||||
var settings = collection.Settings[mod.Index];
|
var settings = collection.GetOwnSettings(mod.Index);
|
||||||
switch (settingState)
|
switch (settingState)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,6 @@ public class ResourceNode : ICloneable
|
||||||
public readonly record struct UiData(string? Name, ChangedItemIconFlag IconFlag)
|
public readonly record struct UiData(string? Name, ChangedItemIconFlag IconFlag)
|
||||||
{
|
{
|
||||||
public UiData PrependName(string prefix)
|
public UiData PrependName(string prefix)
|
||||||
=> Name == null ? this : new UiData(prefix + Name, IconFlag);
|
=> Name == null ? this : this with { Name = prefix + Name };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ public class ModMetaEditor(
|
||||||
dict.ClearForDefault();
|
dict.ClearForDefault();
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
foreach (var value in clone.GlobalEqp)
|
||||||
|
dict.TryAdd(value);
|
||||||
|
|
||||||
foreach (var (key, value) in clone.Imc)
|
foreach (var (key, value) in clone.Imc)
|
||||||
{
|
{
|
||||||
var defaultEntry = ImcChecker.GetDefaultEntry(key, false);
|
var defaultEntry = ImcChecker.GetDefaultEntry(key, false);
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,16 @@ public class ModSelection : EventWrapper<Mod?, Mod?, ModSelection.Priority>
|
||||||
_communicator.ModSettingChanged.Subscribe(OnSettingChange, ModSettingChanged.Priority.ModSelection);
|
_communicator.ModSettingChanged.Subscribe(OnSettingChange, ModSettingChanged.Priority.ModSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModSettings Settings { get; private set; } = ModSettings.Empty;
|
public ModSettings Settings { get; private set; } = ModSettings.Empty;
|
||||||
public ModCollection Collection { get; private set; } = ModCollection.Empty;
|
public ModCollection Collection { get; private set; } = ModCollection.Empty;
|
||||||
public Mod? Mod { get; private set; }
|
public Mod? Mod { get; private set; }
|
||||||
|
public ModSettings? OwnSettings { get; private set; }
|
||||||
|
|
||||||
|
public bool IsTemporary
|
||||||
|
=> OwnSettings != Settings;
|
||||||
|
|
||||||
|
public TemporaryModSettings? AsTemporarySettings
|
||||||
|
=> Settings as TemporaryModSettings;
|
||||||
|
|
||||||
|
|
||||||
public void SelectMod(Mod? mod)
|
public void SelectMod(Mod? mod)
|
||||||
|
|
@ -83,12 +90,14 @@ public class ModSelection : EventWrapper<Mod?, Mod?, ModSelection.Priority>
|
||||||
{
|
{
|
||||||
if (Mod == null)
|
if (Mod == null)
|
||||||
{
|
{
|
||||||
Settings = ModSettings.Empty;
|
Settings = ModSettings.Empty;
|
||||||
Collection = ModCollection.Empty;
|
Collection = ModCollection.Empty;
|
||||||
|
OwnSettings = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(var settings, Collection) = _collections.Current[Mod.Index];
|
(var settings, Collection) = _collections.Current.GetActualSettings(Mod.Index);
|
||||||
|
OwnSettings = _collections.Current.GetOwnSettings(Mod.Index);
|
||||||
Settings = settings ?? ModSettings.Empty;
|
Settings = settings ?? ModSettings.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace Penumbra.Mods.Settings;
|
||||||
public class ModSettings
|
public class ModSettings
|
||||||
{
|
{
|
||||||
public static readonly ModSettings Empty = new();
|
public static readonly ModSettings Empty = new();
|
||||||
public SettingList Settings { get; private init; } = [];
|
public SettingList Settings { get; internal init; } = [];
|
||||||
public ModPriority Priority { get; set; }
|
public ModPriority Priority { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ public class Penumbra : IDalamudPlugin
|
||||||
|
|
||||||
void PrintCollection(ModCollection c, CollectionCache _)
|
void PrintCollection(ModCollection c, CollectionCache _)
|
||||||
=> sb.Append(
|
=> sb.Append(
|
||||||
$"> **`Collection {c.Identity.AnonymizedName + ':',-18}`** Inheritances: `{c.DirectlyInheritsFrom.Count,3}`, Enabled Mods: `{c.ActualSettings.Count(s => s is { Enabled: true }),4}`, Conflicts: `{c.AllConflicts.SelectMany(x => x).Sum(x => x is { HasPriority: true, Solved: true } ? x.Conflicts.Count : 0),5}/{c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority ? x.Conflicts.Count : 0),5}`\n");
|
$"> **`Collection {c.Identity.AnonymizedName + ':',-18}`** Inheritances: `{c.Inheritance.DirectlyInheritsFrom.Count,3}`, Enabled Mods: `{c.ActualSettings.Count(s => s is { Enabled: true }),4}`, Conflicts: `{c.AllConflicts.SelectMany(x => x).Sum(x => x is { HasPriority: true, Solved: true } ? x.Conflicts.Count : 0),5}/{c.AllConflicts.SelectMany(x => x).Sum(x => x.HasPriority ? x.Conflicts.Count : 0),5}`\n");
|
||||||
|
|
||||||
sb.AppendLine("**Collections**");
|
sb.AppendLine("**Collections**");
|
||||||
sb.Append($"> **`#Collections: `** {_collectionManager.Storage.Count - 1}\n");
|
sb.Append($"> **`#Collections: `** {_collectionManager.Storage.Count - 1}\n");
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ public class ConfigMigrationService(SaveService saveService, BackupService backu
|
||||||
if (jObject["Name"]?.ToObject<string>() == ForcedCollection)
|
if (jObject["Name"]?.ToObject<string>() == ForcedCollection)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
jObject[nameof(ModCollection.DirectlyInheritsFrom)] = JToken.FromObject(new List<string> { ForcedCollection });
|
jObject[nameof(ModCollectionInheritance.DirectlyInheritsFrom)] = JToken.FromObject(new List<string> { ForcedCollection });
|
||||||
File.WriteAllText(collection.FullName, jObject.ToString());
|
File.WriteAllText(collection.FullName, jObject.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
||||||
|
|
@ -737,7 +737,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
|
||||||
if (collectionType is not CollectionType.Current || _mod == null || newCollection == null)
|
if (collectionType is not CollectionType.Current || _mod == null || newCollection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateMod(_mod, _mod.Index < newCollection.Settings.Count ? newCollection[_mod.Index].Settings : null);
|
UpdateMod(_mod, _mod.Index < newCollection.Settings.Count ? newCollection.GetInheritedSettings(_mod.Index).Settings : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx, bool inherited)
|
private void OnSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, Setting oldValue, int groupIdx, bool inherited)
|
||||||
|
|
@ -754,7 +754,7 @@ public class ItemSwapTab : IDisposable, ITab, IUiService
|
||||||
if (collection != _collectionManager.Active.Current || _mod == null)
|
if (collection != _collectionManager.Active.Current || _mod == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateMod(_mod, collection[_mod.Index].Settings);
|
UpdateMod(_mod, collection.GetInheritedSettings(_mod.Index).Settings);
|
||||||
_swapData.LoadMod(_mod, _modSettings);
|
_swapData.LoadMod(_mod, _modSettings);
|
||||||
_dirty = true;
|
_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ public partial class ModEditWindow : Window, IDisposable, IUiService
|
||||||
_modelTab.Reset();
|
_modelTab.Reset();
|
||||||
_materialTab.Reset();
|
_materialTab.Reset();
|
||||||
_shaderPackageTab.Reset();
|
_shaderPackageTab.Reset();
|
||||||
_itemSwapTab.UpdateMod(mod, _activeCollections.Current[mod.Index].Settings);
|
_itemSwapTab.UpdateMod(mod, _activeCollections.Current.GetInheritedSettings(mod.Index).Settings);
|
||||||
UpdateModels();
|
UpdateModels();
|
||||||
_forceTextureStartPath = true;
|
_forceTextureStartPath = true;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ using Penumbra.Collections.Manager;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.Mods.Manager;
|
using Penumbra.Mods.Manager;
|
||||||
|
using Penumbra.Mods.Settings;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI.Classes;
|
using Penumbra.UI.Classes;
|
||||||
|
|
||||||
|
|
@ -497,7 +498,7 @@ public sealed class CollectionPanel(
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
var buttonHeight = 2 * ImGui.GetTextLineHeightWithSpacing();
|
var buttonHeight = 2 * ImGui.GetTextLineHeightWithSpacing();
|
||||||
if (_inUseCache.Count == 0 && collection.DirectParentOf.Count == 0)
|
if (_inUseCache.Count == 0 && collection.Inheritance.DirectlyInheritedBy.Count == 0)
|
||||||
{
|
{
|
||||||
ImGui.Dummy(Vector2.One);
|
ImGui.Dummy(Vector2.One);
|
||||||
using var f = _nameFont.Push();
|
using var f = _nameFont.Push();
|
||||||
|
|
@ -559,7 +560,7 @@ public sealed class CollectionPanel(
|
||||||
|
|
||||||
private void DrawInheritanceStatistics(ModCollection collection, Vector2 buttonWidth)
|
private void DrawInheritanceStatistics(ModCollection collection, Vector2 buttonWidth)
|
||||||
{
|
{
|
||||||
if (collection.DirectParentOf.Count <= 0)
|
if (collection.Inheritance.DirectlyInheritedBy.Count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var _ = ImRaii.PushStyle(ImGuiStyleVar.FramePadding, Vector2.Zero))
|
using (var _ = ImRaii.PushStyle(ImGuiStyleVar.FramePadding, Vector2.Zero))
|
||||||
|
|
@ -570,11 +571,11 @@ public sealed class CollectionPanel(
|
||||||
using var f = _nameFont.Push();
|
using var f = _nameFont.Push();
|
||||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale);
|
using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale);
|
||||||
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.MetaInfoText);
|
using var color = ImRaii.PushColor(ImGuiCol.Border, Colors.MetaInfoText);
|
||||||
ImGuiUtil.DrawTextButton(Name(collection.DirectParentOf[0]), Vector2.Zero, 0);
|
ImGuiUtil.DrawTextButton(Name(collection.Inheritance.DirectlyInheritedBy[0]), Vector2.Zero, 0);
|
||||||
var constOffset = (ImGui.GetStyle().FramePadding.X + ImGuiHelpers.GlobalScale) * 2
|
var constOffset = (ImGui.GetStyle().FramePadding.X + ImGuiHelpers.GlobalScale) * 2
|
||||||
+ ImGui.GetStyle().ItemSpacing.X
|
+ ImGui.GetStyle().ItemSpacing.X
|
||||||
+ ImGui.GetStyle().WindowPadding.X;
|
+ ImGui.GetStyle().WindowPadding.X;
|
||||||
foreach (var parent in collection.DirectParentOf.Skip(1))
|
foreach (var parent in collection.Inheritance.DirectlyInheritedBy.Skip(1))
|
||||||
{
|
{
|
||||||
var name = Name(parent);
|
var name = Name(parent);
|
||||||
var size = ImGui.CalcTextSize(name).X;
|
var size = ImGui.CalcTextSize(name).X;
|
||||||
|
|
@ -602,7 +603,7 @@ public sealed class CollectionPanel(
|
||||||
ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, 1.75f * ImGui.GetFrameHeight());
|
ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, 1.75f * ImGui.GetFrameHeight());
|
||||||
ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, 2.5f * ImGui.GetFrameHeight());
|
ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, 2.5f * ImGui.GetFrameHeight());
|
||||||
ImGui.TableHeadersRow();
|
ImGui.TableHeadersRow();
|
||||||
foreach (var (mod, (settings, parent)) in mods.Select(m => (m, collection[m.Index]))
|
foreach (var (mod, (settings, parent)) in mods.Select(m => (m, collection.GetInheritedSettings(m.Index)))
|
||||||
.Where(t => t.Item2.Settings != null)
|
.Where(t => t.Item2.Settings != null)
|
||||||
.OrderBy(t => t.m.Name))
|
.OrderBy(t => t.m.Name))
|
||||||
{
|
{
|
||||||
|
|
@ -625,12 +626,12 @@ public sealed class CollectionPanel(
|
||||||
|
|
||||||
private void DrawInactiveSettingsList(ModCollection collection)
|
private void DrawInactiveSettingsList(ModCollection collection)
|
||||||
{
|
{
|
||||||
if (collection.UnusedSettings.Count == 0)
|
if (collection.Settings.Unused.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui.Dummy(Vector2.One);
|
ImGui.Dummy(Vector2.One);
|
||||||
var text = collection.UnusedSettings.Count > 1
|
var text = collection.Settings.Unused.Count > 1
|
||||||
? $"Clear all {collection.UnusedSettings.Count} unused settings from deleted mods."
|
? $"Clear all {collection.Settings.Unused.Count} unused settings from deleted mods."
|
||||||
: "Clear the currently unused setting from a deleted mods.";
|
: "Clear the currently unused setting from a deleted mods.";
|
||||||
if (ImGui.Button(text, new Vector2(ImGui.GetContentRegionAvail().X, 0)))
|
if (ImGui.Button(text, new Vector2(ImGui.GetContentRegionAvail().X, 0)))
|
||||||
_collections.CleanUnavailableSettings(collection);
|
_collections.CleanUnavailableSettings(collection);
|
||||||
|
|
@ -638,7 +639,7 @@ public sealed class CollectionPanel(
|
||||||
ImGui.Dummy(Vector2.One);
|
ImGui.Dummy(Vector2.One);
|
||||||
|
|
||||||
var size = new Vector2(ImGui.GetContentRegionAvail().X,
|
var size = new Vector2(ImGui.GetContentRegionAvail().X,
|
||||||
Math.Min(10, collection.UnusedSettings.Count + 1) * ImGui.GetFrameHeightWithSpacing());
|
Math.Min(10, collection.Settings.Unused.Count + 1) * ImGui.GetFrameHeightWithSpacing());
|
||||||
using var table = ImRaii.Table("##inactiveSettings", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, size);
|
using var table = ImRaii.Table("##inactiveSettings", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY, size);
|
||||||
if (!table)
|
if (!table)
|
||||||
return;
|
return;
|
||||||
|
|
@ -650,7 +651,7 @@ public sealed class CollectionPanel(
|
||||||
ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, 2.5f * ImGui.GetFrameHeight());
|
ImGui.TableSetupColumn("Priority", ImGuiTableColumnFlags.WidthFixed, 2.5f * ImGui.GetFrameHeight());
|
||||||
ImGui.TableHeadersRow();
|
ImGui.TableHeadersRow();
|
||||||
string? delete = null;
|
string? delete = null;
|
||||||
foreach (var (name, settings) in collection.UnusedSettings.OrderBy(n => n.Key))
|
foreach (var (name, settings) in collection.Settings.Unused.OrderBy(n => n.Key))
|
||||||
{
|
{
|
||||||
using var id = ImRaii.PushId(name);
|
using var id = ImRaii.PushId(name);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
var lineEnd = lineStart;
|
var lineEnd = lineStart;
|
||||||
|
|
||||||
// Skip the collection itself.
|
// Skip the collection itself.
|
||||||
foreach (var inheritance in collection.GetFlattenedInheritance().Skip(1))
|
foreach (var inheritance in collection.Inheritance.FlatHierarchy.Skip(1))
|
||||||
{
|
{
|
||||||
// Draw the child, already seen collections are colored as conflicts.
|
// Draw the child, already seen collections are colored as conflicts.
|
||||||
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(),
|
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(),
|
||||||
|
|
@ -150,7 +150,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
DrawInheritedChildren(collection);
|
DrawInheritedChildren(collection);
|
||||||
else
|
else
|
||||||
// We still want to keep track of conflicts.
|
// We still want to keep track of conflicts.
|
||||||
_seenInheritedCollections.UnionWith(collection.GetFlattenedInheritance());
|
_seenInheritedCollections.UnionWith(collection.Inheritance.FlatHierarchy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw the list box containing the current inheritance information. </summary>
|
/// <summary> Draw the list box containing the current inheritance information. </summary>
|
||||||
|
|
@ -163,7 +163,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
|
|
||||||
_seenInheritedCollections.Clear();
|
_seenInheritedCollections.Clear();
|
||||||
_seenInheritedCollections.Add(_active.Current);
|
_seenInheritedCollections.Add(_active.Current);
|
||||||
foreach (var collection in _active.Current.DirectlyInheritsFrom.ToList())
|
foreach (var collection in _active.Current.Inheritance.DirectlyInheritsFrom.ToList())
|
||||||
DrawInheritance(collection);
|
DrawInheritance(collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
|
|
||||||
using var target = ImRaii.DragDropTarget();
|
using var target = ImRaii.DragDropTarget();
|
||||||
if (target.Success && ImGuiUtil.IsDropping(InheritanceDragDropLabel))
|
if (target.Success && ImGuiUtil.IsDropping(InheritanceDragDropLabel))
|
||||||
_inheritanceAction = (_active.Current.DirectlyInheritsFrom.IndexOf(_movedInheritance!), -1);
|
_inheritanceAction = (_active.Current.Inheritance.DirectlyInheritsFrom.IndexOf(_movedInheritance!), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -244,7 +244,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
{
|
{
|
||||||
ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton);
|
ImGui.SetNextItemWidth(UiHelpers.InputTextMinusButton);
|
||||||
_newInheritance ??= _collections.FirstOrDefault(c
|
_newInheritance ??= _collections.FirstOrDefault(c
|
||||||
=> c != _active.Current && !_active.Current.DirectlyInheritsFrom.Contains(c))
|
=> c != _active.Current && !_active.Current.Inheritance.DirectlyInheritsFrom.Contains(c))
|
||||||
?? ModCollection.Empty;
|
?? ModCollection.Empty;
|
||||||
using var combo = ImRaii.Combo("##newInheritance", Name(_newInheritance));
|
using var combo = ImRaii.Combo("##newInheritance", Name(_newInheritance));
|
||||||
if (!combo)
|
if (!combo)
|
||||||
|
|
@ -271,8 +271,8 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
|
|
||||||
if (_movedInheritance != null)
|
if (_movedInheritance != null)
|
||||||
{
|
{
|
||||||
var idx1 = _active.Current.DirectlyInheritsFrom.IndexOf(_movedInheritance);
|
var idx1 = _active.Current.Inheritance.DirectlyInheritsFrom.IndexOf(_movedInheritance);
|
||||||
var idx2 = _active.Current.DirectlyInheritsFrom.IndexOf(collection);
|
var idx2 = _active.Current.Inheritance.DirectlyInheritsFrom.IndexOf(collection);
|
||||||
if (idx1 >= 0 && idx2 >= 0)
|
if (idx1 >= 0 && idx2 >= 0)
|
||||||
_inheritanceAction = (idx1, idx2);
|
_inheritanceAction = (idx1, idx2);
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +302,7 @@ public class InheritanceUi(CollectionManager collectionManager, IncognitoService
|
||||||
if (ImGui.GetIO().KeyCtrl && ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
if (ImGui.GetIO().KeyCtrl && ImGui.IsItemClicked(ImGuiMouseButton.Right))
|
||||||
{
|
{
|
||||||
if (withDelete && ImGui.GetIO().KeyShift)
|
if (withDelete && ImGui.GetIO().KeyShift)
|
||||||
_inheritanceAction = (_active.Current.DirectlyInheritsFrom.IndexOf(collection), -1);
|
_inheritanceAction = (_active.Current.Inheritance.DirectlyInheritsFrom.IndexOf(collection), -1);
|
||||||
else
|
else
|
||||||
_newCurrentCollection = collection;
|
_newCurrentCollection = collection;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
if (ImGui.IsItemClicked(ImGuiMouseButton.Middle))
|
if (ImGui.IsItemClicked(ImGuiMouseButton.Middle))
|
||||||
{
|
{
|
||||||
_modManager.SetKnown(leaf.Value);
|
_modManager.SetKnown(leaf.Value);
|
||||||
var (setting, collection) = _collectionManager.Active.Current[leaf.Value.Index];
|
var (setting, collection) = _collectionManager.Active.Current.GetActualSettings(leaf.Value.Index);
|
||||||
if (_config.DeleteModModifier.ForcedModifier(new DoubleModifier(ModifierHotkey.Control, ModifierHotkey.Shift)).IsActive())
|
if (_config.DeleteModModifier.ForcedModifier(new DoubleModifier(ModifierHotkey.Control, ModifierHotkey.Shift)).IsActive())
|
||||||
{
|
{
|
||||||
_collectionManager.Editor.SetModInheritance(_collectionManager.Active.Current, leaf.Value, true);
|
_collectionManager.Editor.SetModInheritance(_collectionManager.Active.Current, leaf.Value, true);
|
||||||
|
|
@ -580,7 +580,14 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
return ColorId.UndefinedMod;
|
return ColorId.UndefinedMod;
|
||||||
|
|
||||||
if (!settings.Enabled)
|
if (!settings.Enabled)
|
||||||
return collection != _collectionManager.Active.Current ? ColorId.InheritedDisabledMod : ColorId.DisabledMod;
|
return collection != _collectionManager.Active.Current
|
||||||
|
? ColorId.InheritedDisabledMod
|
||||||
|
: settings is TemporaryModSettings
|
||||||
|
? ColorId.TemporaryDisabledMod
|
||||||
|
: ColorId.DisabledMod;
|
||||||
|
|
||||||
|
if (settings is TemporaryModSettings)
|
||||||
|
return ColorId.TemporaryEnabledMod;
|
||||||
|
|
||||||
var conflicts = _collectionManager.Active.Current.Conflicts(mod);
|
var conflicts = _collectionManager.Active.Current.Conflicts(mod);
|
||||||
if (conflicts.Count == 0)
|
if (conflicts.Count == 0)
|
||||||
|
|
@ -631,7 +638,11 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
}
|
}
|
||||||
else if (!settings.Enabled)
|
else if (!settings.Enabled)
|
||||||
{
|
{
|
||||||
state.Color = collection == _collectionManager.Active.Current ? ColorId.DisabledMod : ColorId.InheritedDisabledMod;
|
state.Color = collection != _collectionManager.Active.Current
|
||||||
|
? ColorId.InheritedDisabledMod
|
||||||
|
: settings is TemporaryModSettings
|
||||||
|
? ColorId.TemporaryDisabledMod
|
||||||
|
: ColorId.DisabledMod;
|
||||||
if (!_stateFilter.HasFlag(ModFilter.Disabled)
|
if (!_stateFilter.HasFlag(ModFilter.Disabled)
|
||||||
|| !_stateFilter.HasFlag(ModFilter.NoConflict))
|
|| !_stateFilter.HasFlag(ModFilter.NoConflict))
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -641,7 +652,10 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
if (!_stateFilter.HasFlag(ModFilter.Enabled))
|
if (!_stateFilter.HasFlag(ModFilter.Enabled))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Conflicts can only be relevant if the mod is enabled.
|
if (settings is TemporaryModSettings)
|
||||||
|
state.Color = ColorId.TemporaryEnabledMod;
|
||||||
|
|
||||||
|
// Conflicts can only be relevant if the mod is enabled.
|
||||||
var conflicts = _collectionManager.Active.Current.Conflicts(mod);
|
var conflicts = _collectionManager.Active.Current.Conflicts(mod);
|
||||||
if (conflicts.Count > 0)
|
if (conflicts.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -650,14 +664,14 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
if (!_stateFilter.HasFlag(ModFilter.UnsolvedConflict))
|
if (!_stateFilter.HasFlag(ModFilter.UnsolvedConflict))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
state.Color = ColorId.ConflictingMod;
|
state.Color = settings is TemporaryModSettings ? ColorId.TemporaryEnabledMod : ColorId.ConflictingMod;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_stateFilter.HasFlag(ModFilter.SolvedConflict))
|
if (!_stateFilter.HasFlag(ModFilter.SolvedConflict))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
state.Color = ColorId.HandledConflictMod;
|
state.Color = settings is TemporaryModSettings ? ColorId.TemporaryEnabledMod : ColorId.HandledConflictMod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!_stateFilter.HasFlag(ModFilter.NoConflict))
|
else if (!_stateFilter.HasFlag(ModFilter.NoConflict))
|
||||||
|
|
@ -677,7 +691,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
private bool ApplyFiltersAndState(ModFileSystem.Leaf leaf, out ModState state)
|
private bool ApplyFiltersAndState(ModFileSystem.Leaf leaf, out ModState state)
|
||||||
{
|
{
|
||||||
var mod = leaf.Value;
|
var mod = leaf.Value;
|
||||||
var (settings, collection) = _collectionManager.Active.Current[mod.Index];
|
var (settings, collection) = _collectionManager.Active.Current.GetActualSettings(mod.Index);
|
||||||
|
|
||||||
state = new ModState
|
state = new ModState
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ public class ModPanelCollectionsTab(CollectionManager manager, ModFileSystemSele
|
||||||
var inheritedCount = 0;
|
var inheritedCount = 0;
|
||||||
foreach (var collection in manager.Storage)
|
foreach (var collection in manager.Storage)
|
||||||
{
|
{
|
||||||
var (settings, parent) = collection[mod.Index];
|
var (settings, parent) = collection.GetInheritedSettings(mod.Index);
|
||||||
var (color, text) = settings == null
|
var (color, text) = settings == null
|
||||||
? (undefined, ModState.Unconfigured)
|
? (undefined, ModState.Unconfigured)
|
||||||
: settings.Enabled
|
: settings.Enabled
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy
|
||||||
if (conflicts.Mod2.Index < 0)
|
if (conflicts.Mod2.Index < 0)
|
||||||
return conflicts.Mod2.Priority;
|
return conflicts.Mod2.Priority;
|
||||||
|
|
||||||
return collectionManager.Active.Current[conflicts.Mod2.Index].Settings?.Priority ?? ModPriority.Default;
|
return collectionManager.Active.Current.GetActualSettings(conflicts.Mod2.Index).Settings?.Priority ?? ModPriority.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawContent()
|
public void DrawContent()
|
||||||
|
|
@ -74,22 +74,27 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy
|
||||||
ImGui.AlignTextToFramePadding();
|
ImGui.AlignTextToFramePadding();
|
||||||
ImGui.TextUnformatted(selector.Selected!.Name);
|
ImGui.TextUnformatted(selector.Selected!.Name);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
var priority = collectionManager.Active.Current[selector.Selected!.Index].Settings!.Priority.Value;
|
var actualSettings = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!;
|
||||||
ImGui.SetNextItemWidth(priorityWidth);
|
var priority = actualSettings.Priority.Value;
|
||||||
if (ImGui.InputInt("##priority", ref priority, 0, 0, ImGuiInputTextFlags.EnterReturnsTrue))
|
// TODO
|
||||||
_currentPriority = priority;
|
using (ImRaii.Disabled(actualSettings is TemporaryModSettings))
|
||||||
|
|
||||||
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
|
|
||||||
{
|
{
|
||||||
if (_currentPriority != collectionManager.Active.Current[selector.Selected!.Index].Settings!.Priority.Value)
|
ImGui.SetNextItemWidth(priorityWidth);
|
||||||
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!,
|
if (ImGui.InputInt("##priority", ref priority, 0, 0, ImGuiInputTextFlags.EnterReturnsTrue))
|
||||||
new ModPriority(_currentPriority.Value));
|
_currentPriority = priority;
|
||||||
|
|
||||||
_currentPriority = null;
|
if (ImGui.IsItemDeactivatedAfterEdit() && _currentPriority.HasValue)
|
||||||
}
|
{
|
||||||
else if (ImGui.IsItemDeactivated())
|
if (_currentPriority != actualSettings.Priority.Value)
|
||||||
{
|
collectionManager.Editor.SetModPriority(collectionManager.Active.Current, selector.Selected!,
|
||||||
_currentPriority = null;
|
new ModPriority(_currentPriority.Value));
|
||||||
|
|
||||||
|
_currentPriority = null;
|
||||||
|
}
|
||||||
|
else if (ImGui.IsItemDeactivated())
|
||||||
|
{
|
||||||
|
_currentPriority = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
|
|
@ -138,7 +143,7 @@ public class ModPanelConflictsTab(CollectionManager collectionManager, ModFileSy
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
var conflictPriority = DrawPriorityInput(conflict, priorityWidth);
|
var conflictPriority = DrawPriorityInput(conflict, priorityWidth);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
var selectedPriority = collectionManager.Active.Current[selector.Selected!.Index].Settings!.Priority.Value;
|
var selectedPriority = collectionManager.Active.Current.GetActualSettings(selector.Selected!.Index).Settings!.Priority.Value;
|
||||||
DrawPriorityButtons(conflict.Mod2 as Mod, conflictPriority, selectedPriority, buttonSize);
|
DrawPriorityButtons(conflict.Mod2 as Mod, conflictPriority, selectedPriority, buttonSize);
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
DrawExpandButton(conflict.Mod2, expanded, buttonSize);
|
DrawExpandButton(conflict.Mod2, expanded, buttonSize);
|
||||||
|
|
|
||||||
|
|
@ -204,11 +204,45 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
if (collection.HasCache)
|
if (collection.HasCache)
|
||||||
{
|
{
|
||||||
using var color = PushColor(ImGuiCol.Text, ColorId.FolderExpanded.Value());
|
using var color = PushColor(ImGuiCol.Text, ColorId.FolderExpanded.Value());
|
||||||
using var node = TreeNode($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})###{collection.Identity.Name}");
|
using var node =
|
||||||
|
TreeNode($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})###{collection.Identity.Name}");
|
||||||
if (!node)
|
if (!node)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
color.Pop();
|
color.Pop();
|
||||||
|
using (var inheritanceNode = ImUtf8.TreeNode("Inheritance"u8))
|
||||||
|
{
|
||||||
|
if (inheritanceNode)
|
||||||
|
{
|
||||||
|
using var table = ImUtf8.Table("table"u8, 3,
|
||||||
|
ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersInnerV);
|
||||||
|
if (table)
|
||||||
|
{
|
||||||
|
var max = Math.Max(
|
||||||
|
Math.Max(collection.Inheritance.DirectlyInheritedBy.Count, collection.Inheritance.DirectlyInheritsFrom.Count),
|
||||||
|
collection.Inheritance.FlatHierarchy.Count);
|
||||||
|
for (var i = 0; i < max; ++i)
|
||||||
|
{
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
if (i < collection.Inheritance.DirectlyInheritsFrom.Count)
|
||||||
|
ImUtf8.Text(collection.Inheritance.DirectlyInheritsFrom[i].Identity.Name);
|
||||||
|
else
|
||||||
|
ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetTextLineHeight()));
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
if (i < collection.Inheritance.DirectlyInheritedBy.Count)
|
||||||
|
ImUtf8.Text(collection.Inheritance.DirectlyInheritedBy[i].Identity.Name);
|
||||||
|
else
|
||||||
|
ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetTextLineHeight()));
|
||||||
|
ImGui.TableNextColumn();
|
||||||
|
if (i < collection.Inheritance.FlatHierarchy.Count)
|
||||||
|
ImUtf8.Text(collection.Inheritance.FlatHierarchy[i].Identity.Name);
|
||||||
|
else
|
||||||
|
ImGui.Dummy(new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetTextLineHeight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using (var resourceNode = ImUtf8.TreeNode("Custom Resources"u8))
|
using (var resourceNode = ImUtf8.TreeNode("Custom Resources"u8))
|
||||||
{
|
{
|
||||||
if (resourceNode)
|
if (resourceNode)
|
||||||
|
|
@ -239,7 +273,7 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
using var color = PushColor(ImGuiCol.Text, ColorId.UndefinedMod.Value());
|
using var color = PushColor(ImGuiCol.Text, ColorId.UndefinedMod.Value());
|
||||||
TreeNode($"{collection.Identity.AnonymizedName} (Change Counter {collection.Counters.Change})",
|
TreeNode($"{collection.Identity.Name} (Change Counter {collection.Counters.Change})",
|
||||||
ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose();
|
ImGuiTreeNodeFlags.Bullet | ImGuiTreeNodeFlags.Leaf).Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -682,13 +716,11 @@ public class DebugTab : Window, ITab, IUiService
|
||||||
{
|
{
|
||||||
using var table = Table("###TmbTable", 2, ImGuiTableFlags.SizingFixedFit);
|
using var table = Table("###TmbTable", 2, ImGuiTableFlags.SizingFixedFit);
|
||||||
if (table)
|
if (table)
|
||||||
{
|
|
||||||
foreach (var (id, name) in _schedulerService.ListedTmbs.OrderBy(kvp => kvp.Key))
|
foreach (var (id, name) in _schedulerService.ListedTmbs.OrderBy(kvp => kvp.Key))
|
||||||
{
|
{
|
||||||
ImUtf8.DrawTableColumn($"{id:D6}");
|
ImUtf8.DrawTableColumn($"{id:D6}");
|
||||||
ImUtf8.DrawTableColumn(name.Span);
|
ImUtf8.DrawTableColumn(name.Span);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ public class ModsTab(
|
||||||
+ $"{selector.SortMode.Name} Sort Mode\n"
|
+ $"{selector.SortMode.Name} Sort Mode\n"
|
||||||
+ $"{selector.SelectedLeaf?.Name ?? "NULL"} Selected Leaf\n"
|
+ $"{selector.SelectedLeaf?.Name ?? "NULL"} Selected Leaf\n"
|
||||||
+ $"{selector.Selected?.Name ?? "NULL"} Selected Mod\n"
|
+ $"{selector.Selected?.Name ?? "NULL"} Selected Mod\n"
|
||||||
+ $"{string.Join(", ", _activeCollections.Current.DirectlyInheritsFrom.Select(c => c.Identity.AnonymizedName))} Inheritances\n");
|
+ $"{string.Join(", ", _activeCollections.Current.Inheritance.DirectlyInheritsFrom.Select(c => c.Identity.AnonymizedName))} Inheritances\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue