diff --git a/Penumbra/Collections/Cache/CollectionCacheManager.cs b/Penumbra/Collections/Cache/CollectionCacheManager.cs
index 001ea952..fc43f654 100644
--- a/Penumbra/Collections/Cache/CollectionCacheManager.cs
+++ b/Penumbra/Collections/Cache/CollectionCacheManager.cs
@@ -51,6 +51,8 @@ public class CollectionCacheManager : IDisposable
_communicator.ModOptionChanged.Subscribe(OnModOptionChange, -100);
_communicator.ModSettingChanged.Subscribe(OnModSettingChange);
_communicator.CollectionInheritanceChanged.Subscribe(OnCollectionInheritanceChange);
+ _communicator.ModDiscoveryStarted.Subscribe(OnModDiscoveryStarted);
+ _communicator.ModDiscoveryFinished.Subscribe(OnModDiscoveryFinished, -100);
if (!MetaFileManager.CharacterUtility.Ready)
MetaFileManager.CharacterUtility.LoadingFinished += IncrementCounters;
@@ -308,4 +310,20 @@ public class CollectionCacheManager : IDisposable
Penumbra.Log.Debug($"Creating {tasks.Length} necessary caches.");
Task.WaitAll(tasks);
}
+
+ private void OnModDiscoveryStarted()
+ {
+ foreach (var collection in Active)
+ {
+ collection._cache!.ResolvedFiles.Clear();
+ collection._cache!.Meta.Reset();
+ collection._cache!._conflicts.Clear();
+ }
+ }
+
+ private void OnModDiscoveryFinished()
+ {
+ var tasks = Active.Select(c => Task.Run(() => CalculateEffectiveFileListInternal(c))).ToArray();
+ Task.WaitAll(tasks);
+ }
}
diff --git a/Penumbra/Mods/Manager/ModCacheManager.cs b/Penumbra/Mods/Manager/ModCacheManager.cs
index 86a26960..1015e4ed 100644
--- a/Penumbra/Mods/Manager/ModCacheManager.cs
+++ b/Penumbra/Mods/Manager/ModCacheManager.cs
@@ -168,10 +168,10 @@ public class ModCacheManager : IDisposable
=> mod.TotalFileCount = mod.AllSubMods.Sum(s => s.Files.Count);
private static void UpdateSwapCount(Mod mod)
- => mod.TotalFileCount = mod.AllSubMods.Sum(s => s.FileSwaps.Count);
+ => mod.TotalSwapCount = mod.AllSubMods.Sum(s => s.FileSwaps.Count);
private static void UpdateMetaCount(Mod mod)
- => mod.TotalFileCount = mod.AllSubMods.Sum(s => s.Manipulations.Count);
+ => mod.TotalManipulations = mod.AllSubMods.Sum(s => s.Manipulations.Count);
private static void UpdateHasOptions(Mod mod)
=> mod.HasOptions = mod.Groups.Any(o => o.IsOption);
diff --git a/Penumbra/Mods/Manager/ModManager.cs b/Penumbra/Mods/Manager/ModManager.cs
index 2ef1c890..8b25f763 100644
--- a/Penumbra/Mods/Manager/ModManager.cs
+++ b/Penumbra/Mods/Manager/ModManager.cs
@@ -29,7 +29,7 @@ public enum ModPathChangeType
StartingReload,
}
-public sealed class ModManager : ModStorage
+public sealed class ModManager : ModStorage, IDisposable
{
private readonly Configuration _config;
private readonly CommunicatorService _communicator;
@@ -49,7 +49,8 @@ public sealed class ModManager : ModStorage
DataEditor = dataEditor;
OptionEditor = optionEditor;
Creator = creator;
- SetBaseDirectory(config.ModDirectory, true);
+ SetBaseDirectory(config.ModDirectory, true);
+ _communicator.ModPathChanged.Subscribe(OnModPathChange);
DiscoverMods();
}
@@ -66,7 +67,7 @@ public sealed class ModManager : ModStorage
public void DiscoverMods()
{
_communicator.ModDiscoveryStarted.Invoke();
- NewMods.Clear();
+ ClearNewMods();
Mods.Clear();
BasePath.Refresh();
@@ -243,11 +244,11 @@ public sealed class ModManager : ModStorage
{
switch (type)
{
- case ModPathChangeType.Added:
- NewMods.Add(mod);
+ case ModPathChangeType.Added:
+ SetNew(mod);
break;
case ModPathChangeType.Deleted:
- NewMods.Remove(mod);
+ SetKnown(mod);
break;
case ModPathChangeType.Moved:
if (oldDirectory != null && newDirectory != null)
@@ -258,7 +259,7 @@ public sealed class ModManager : ModStorage
}
public void Dispose()
- { }
+ => _communicator.ModPathChanged.Unsubscribe(OnModPathChange);
///
/// Set the mod base directory.
diff --git a/Penumbra/Mods/Manager/ModOptionEditor.cs b/Penumbra/Mods/Manager/ModOptionEditor.cs
index ed978000..c30d90c3 100644
--- a/Penumbra/Mods/Manager/ModOptionEditor.cs
+++ b/Penumbra/Mods/Manager/ModOptionEditor.cs
@@ -314,7 +314,7 @@ public class ModOptionEditor
return;
_communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, groupIdx, optionIdx, -1);
- subMod.ManipulationData = manipulations;
+ subMod.ManipulationData.SetTo(manipulations);
_saveService.QueueSave(new ModSaveGroup(mod, groupIdx));
_communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionMetaChanged, mod, groupIdx, optionIdx, -1);
}
@@ -327,7 +327,7 @@ public class ModOptionEditor
return;
_communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, groupIdx, optionIdx, -1);
- subMod.FileData = replacements;
+ subMod.FileData.SetTo(replacements);
_saveService.QueueSave(new ModSaveGroup(mod, groupIdx));
_communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionFilesChanged, mod, groupIdx, optionIdx, -1);
}
@@ -353,7 +353,7 @@ public class ModOptionEditor
return;
_communicator.ModOptionChanged.Invoke(ModOptionChangeType.PrepareChange, mod, groupIdx, optionIdx, -1);
- subMod.FileSwapData = swaps;
+ subMod.FileSwapData.SetTo(swaps);
_saveService.QueueSave(new ModSaveGroup(mod, groupIdx));
_communicator.ModOptionChanged.Invoke(ModOptionChangeType.OptionSwapsChanged, mod, groupIdx, optionIdx, -1);
}
diff --git a/Penumbra/Mods/Manager/ModStorage.cs b/Penumbra/Mods/Manager/ModStorage.cs
index 3aa6d31f..5e8999d7 100644
--- a/Penumbra/Mods/Manager/ModStorage.cs
+++ b/Penumbra/Mods/Manager/ModStorage.cs
@@ -53,14 +53,17 @@ public class ModStorage : IReadOnlyList
/// Mods are removed when they are deleted or when they are toggled in any collection.
/// Also gets cleared on mod rediscovery.
///
- protected readonly HashSet NewMods = new();
+ private readonly HashSet _newMods = new();
public bool IsNew(Mod mod)
- => NewMods.Contains(mod);
+ => _newMods.Contains(mod);
public void SetNew(Mod mod)
- => NewMods.Add(mod);
+ => _newMods.Add(mod);
public void SetKnown(Mod mod)
- => NewMods.Remove(mod);
+ => _newMods.Remove(mod);
+
+ public void ClearNewMods()
+ => _newMods.Clear();
}
diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs
index d9bebeaf..211acc85 100644
--- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs
+++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs
@@ -414,7 +414,7 @@ public partial class ModEditWindow : Window, IDisposable
if (ImGuiUtil.DrawDisabledButton("Revert Changes", Vector2.Zero, tt, setsEqual))
_editor.SwapEditor.Revert(_editor.Option!);
- var otherSwaps = _editor.Mod!.TotalSwapCount - _editor.SwapEditor.Swaps.Count;
+ var otherSwaps = _editor.Mod!.TotalSwapCount - _editor.Option!.FileSwaps.Count;
if (otherSwaps > 0)
{
ImGui.SameLine();
diff --git a/Penumbra/Util/DictionaryExtensions.cs b/Penumbra/Util/DictionaryExtensions.cs
index ad832457..31931fe7 100644
--- a/Penumbra/Util/DictionaryExtensions.cs
+++ b/Penumbra/Util/DictionaryExtensions.cs
@@ -6,7 +6,7 @@ namespace Penumbra.Util;
public static class DictionaryExtensions
{
- // Returns whether two dictionaries contain equal keys and values.
+ /// Returns whether two dictionaries contain equal keys and values.
public static bool SetEquals< TKey, TValue >( this IReadOnlyDictionary< TKey, TValue > lhs, IReadOnlyDictionary< TKey, TValue > rhs )
{
if( ReferenceEquals( lhs, rhs ) )
@@ -46,24 +46,32 @@ public static class DictionaryExtensions
return true;
}
- // Set one dictionary to the other, deleting previous entries and ensuring capacity beforehand.
+ /// Set one dictionary to the other, deleting previous entries and ensuring capacity beforehand.
public static void SetTo< TKey, TValue >( this Dictionary< TKey, TValue > lhs, IReadOnlyDictionary< TKey, TValue > rhs )
where TKey : notnull
{
if( ReferenceEquals( lhs, rhs ) )
- {
return;
- }
lhs.Clear();
lhs.EnsureCapacity( rhs.Count );
foreach( var (key, value) in rhs )
- {
lhs.Add( key, value );
- }
}
- // Add all entries from the other dictionary that would not overwrite current keys.
+ /// Set one set to the other, deleting previous entries and ensuring capacity beforehand.
+ public static void SetTo(this HashSet lhs, IReadOnlySet rhs)
+ {
+ if (ReferenceEquals(lhs, rhs))
+ return;
+
+ lhs.Clear();
+ lhs.EnsureCapacity(rhs.Count);
+ foreach (var value in rhs)
+ lhs.Add(value);
+ }
+
+ /// Add all entries from the other dictionary that would not overwrite current keys.
public static void AddFrom< TKey, TValue >( this Dictionary< TKey, TValue > lhs, IReadOnlyDictionary< TKey, TValue > rhs )
where TKey : notnull
{