Remove static Config.

This commit is contained in:
Ottermandias 2023-04-21 23:52:31 +02:00
parent aa4bc45641
commit be3c1c85aa
30 changed files with 363 additions and 440 deletions

View file

@ -218,7 +218,7 @@ public class CollectionCache : IDisposable
if (addMetaChanges)
{
++_collection.ChangeCounter;
if ((mod is TemporaryMod temp ? temp.TotalManipulations : Penumbra.ModCaches[mod.Index].TotalManipulations) > 0)
if (mod.TotalManipulations > 0)
AddMetaFiles();
_manager.MetaFileManager.ApplyDefaultFiles(_collection);

View file

@ -11,7 +11,6 @@ using OtterGui.Widgets;
using Penumbra.GameData.Enums;
using Penumbra.Import.Structs;
using Penumbra.Mods;
using Penumbra.Mods.Manager;
using Penumbra.Services;
using Penumbra.UI;
using Penumbra.UI.Classes;
@ -106,6 +105,7 @@ public class Configuration : IPluginConfiguration, ISavable
{
_saveService = saveService;
Load(fileNames, migrator);
UI.Classes.Colors.SetColors(this);
}
public void Load(FilenameService fileNames, ConfigMigrationService migrator)

View file

@ -94,12 +94,12 @@ public partial class TexToolsImporter
ImGui.TableNextColumn();
if( ex == null )
{
using var color = ImRaii.PushColor( ImGuiCol.Text, ColorId.FolderExpanded.Value(Penumbra.Config) );
using var color = ImRaii.PushColor( ImGuiCol.Text, ColorId.FolderExpanded.Value() );
ImGui.TextUnformatted( dir?.FullName[ ( _baseDirectory.FullName.Length + 1 ).. ] ?? "Unknown Directory" );
}
else
{
using var color = ImRaii.PushColor( ImGuiCol.Text, ColorId.ConflictingMod.Value(Penumbra.Config) );
using var color = ImRaii.PushColor( ImGuiCol.Text, ColorId.ConflictingMod.Value() );
ImGui.TextUnformatted( ex.Message );
ImGuiUtil.HoverTooltip( ex.ToString() );
}

View file

@ -125,16 +125,12 @@ public sealed class Texture : IDisposable
{
_tmpPath = null;
if (path == Path)
{
return;
}
Path = path;
Clean();
if (path.Length == 0)
{
return;
}
try
{
@ -192,9 +188,7 @@ public sealed class Texture : IDisposable
private Stream OpenTexStream()
{
if (System.IO.Path.IsPathRooted(Path))
{
return File.OpenRead(Path);
}
var file = DalamudServices.SGameData.GetFile(Path);
return file != null ? new MemoryStream(file.Data) : throw new Exception($"Unable to obtain \"{Path}\" from game files.");
@ -211,41 +205,36 @@ public sealed class Texture : IDisposable
var startPath = Path.Length > 0 ? Path : "Choose a modded texture from this mod here...";
using var combo = ImRaii.Combo(label, startPath);
if (combo)
{
foreach (var ((path, game), idx) in paths.WithIndex())
{
if (game)
{
if (!DalamudServices.SGameData.FileExists(path))
{
continue;
}
}
else if (!File.Exists(path))
{
continue;
}
using var id = ImRaii.PushId(idx);
using( var color = ImRaii.PushColor( ImGuiCol.Text, ColorId.FolderExpanded.Value(Penumbra.Config), game ) )
using (var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.FolderExpanded.Value(), game))
{
var p = game ? $"--> {path}" : path[skipPrefix..];
if (ImGui.Selectable(p, path == startPath) && path != startPath)
{
Load(path);
}
}
ImGuiUtil.HoverTooltip(game
? "This is a game path and refers to an unmanipulated file from your game data."
: "This is a path to a modded file on your file system.");
}
}
ImGuiUtil.HoverTooltip(tooltip);
}
public void PathInputBox( string label, string hint, string tooltip, string startPath, FileDialogService fileDialog )
public void PathInputBox(string label, string hint, string tooltip, string startPath, FileDialogService fileDialog,
string defaultModImportPath)
{
_tmpPath ??= Path;
using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing,
@ -253,29 +242,23 @@ public sealed class Texture : IDisposable
ImGui.SetNextItemWidth(-2 * ImGui.GetFrameHeight() - 7 * UiHelpers.Scale);
ImGui.InputTextWithHint(label, hint, ref _tmpPath, Utf8GamePath.MaxGamePathLength);
if (ImGui.IsItemDeactivatedAfterEdit())
{
Load(_tmpPath);
}
ImGuiUtil.HoverTooltip(tooltip);
ImGui.SameLine();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Folder.ToIconString(), new Vector2(ImGui.GetFrameHeight()), string.Empty, false,
true))
{
if( Penumbra.Config.DefaultModImportPath.Length > 0 )
{
startPath = Penumbra.Config.DefaultModImportPath;
}
if (defaultModImportPath.Length > 0)
startPath = defaultModImportPath;
var texture = this;
void UpdatePath(bool success, List<string> paths)
{
if (success && paths.Count > 0)
{
texture.Load(paths[0]);
}
}
fileDialog.OpenFilePicker("Open Image...", "Textures{.png,.dds,.tex}", UpdatePath, 1, startPath, false);
}

View file

@ -1,14 +1,18 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using Dalamud.Data;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Memory;
using Penumbra.Collections;
using Penumbra.Collections.Cache;
using Penumbra.Collections.Manager;
using Penumbra.GameData;
using Penumbra.Import;
using Penumbra.Interop.Services;
using Penumbra.Interop.Structs;
using Penumbra.Meta.Files;
using Penumbra.Mods;
using Penumbra.Services;
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
@ -37,6 +41,33 @@ public unsafe class MetaFileManager
SignatureHelper.Initialise(this);
}
public void WriteAllTexToolsMeta(Mod mod)
{
try
{
TexToolsMeta.WriteTexToolsMeta(this, mod.Default.Manipulations, mod.ModPath);
foreach (var group in mod.Groups)
{
var dir = ModCreator.NewOptionDirectory(mod.ModPath, group.Name);
if (!dir.Exists)
dir.Create();
foreach (var option in group.OfType<SubMod>())
{
var optionDir = ModCreator.NewOptionDirectory(dir, option.Name);
if (!optionDir.Exists)
optionDir.Create();
TexToolsMeta.WriteTexToolsMeta(this, option.Manipulations, optionDir);
}
}
}
catch (Exception e)
{
Penumbra.Log.Error($"Error writing TexToolsMeta:\n{e}");
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void SetFile(MetaBaseFile? file, MetaIndex metaIndex)
{

View file

@ -14,4 +14,7 @@ public interface IMod
public IReadOnlyList< IModGroup > Groups { get; }
public IEnumerable< SubMod > AllSubMods { get; }
// Cache
public int TotalManipulations { get; }
}

View file

@ -13,7 +13,6 @@ namespace Penumbra.Mods;
public class ModNormalizer
{
private readonly ModManager _modManager;
private readonly ModCacheManager _modCacheManager;
private readonly List<List<Dictionary<Utf8GamePath, FullPath>>> _redirections = new();
public Mod Mod { get; private set; } = null!;
@ -26,11 +25,8 @@ public class ModNormalizer
public bool Running
=> Step < TotalSteps;
public ModNormalizer(ModManager modManager, ModCacheManager modCacheManager)
{
_modManager = modManager;
_modCacheManager = modCacheManager;
}
public ModNormalizer(ModManager modManager)
=> _modManager = modManager;
public void Normalize(Mod mod)
{
@ -41,7 +37,7 @@ public class ModNormalizer
_normalizationDirName = Path.Combine(Mod.ModPath.FullName, "TmpNormalization");
_oldDirName = Path.Combine(Mod.ModPath.FullName, "TmpNormalizationOld");
Step = 0;
TotalSteps = _modCacheManager[mod].TotalFileCount + 5;
TotalSteps = mod.TotalFileCount + 5;
Task.Run(NormalizeSync);
}

View file

@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -12,14 +11,12 @@ using Penumbra.Services;
namespace Penumbra.Mods.Manager;
public class ModCacheManager : IDisposable, IReadOnlyList<ModCache>
public class ModCacheManager : IDisposable
{
private readonly CommunicatorService _communicator;
private readonly IdentifierService _identifier;
private readonly ModStorage _modManager;
private readonly List<ModCache> _cache = new();
public ModCacheManager(CommunicatorService communicator, IdentifierService identifier, ModStorage modStorage)
{
_communicator = communicator;
@ -35,20 +32,6 @@ public class ModCacheManager : IDisposable, IReadOnlyList<ModCache>
OnModDiscoveryFinished();
}
public IEnumerator<ModCache> GetEnumerator()
=> _cache.Take(Count).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
public int Count { get; private set; }
public ModCache this[int index]
=> _cache[index];
public ModCache this[Mod mod]
=> _cache[mod.Index];
public void Dispose()
{
_communicator.ModOptionChanged.Unsubscribe(OnModOptionChange);
@ -127,35 +110,30 @@ public class ModCacheManager : IDisposable, IReadOnlyList<ModCache>
private void OnModOptionChange(ModOptionChangeType type, Mod mod, int groupIdx, int _, int _2)
{
ModCache cache;
switch (type)
{
case ModOptionChangeType.GroupAdded:
case ModOptionChangeType.GroupDeleted:
case ModOptionChangeType.OptionAdded:
case ModOptionChangeType.OptionDeleted:
cache = EnsureCount(mod);
UpdateChangedItems(cache, mod);
UpdateCounts(cache, mod);
UpdateChangedItems(mod);
UpdateCounts(mod);
break;
case ModOptionChangeType.GroupTypeChanged:
UpdateHasOptions(EnsureCount(mod), mod);
UpdateHasOptions(mod);
break;
case ModOptionChangeType.OptionFilesChanged:
case ModOptionChangeType.OptionFilesAdded:
cache = EnsureCount(mod);
UpdateChangedItems(cache, mod);
UpdateFileCount(cache, mod);
UpdateChangedItems(mod);
UpdateFileCount(mod);
break;
case ModOptionChangeType.OptionSwapsChanged:
cache = EnsureCount(mod);
UpdateChangedItems(cache, mod);
UpdateSwapCount(cache, mod);
UpdateChangedItems(mod);
UpdateSwapCount(mod);
break;
case ModOptionChangeType.OptionMetaChanged:
cache = EnsureCount(mod);
UpdateChangedItems(cache, mod);
UpdateMetaCount(cache, mod);
UpdateChangedItems(mod);
UpdateMetaCount(mod);
break;
}
}
@ -166,106 +144,79 @@ public class ModCacheManager : IDisposable, IReadOnlyList<ModCache>
{
case ModPathChangeType.Added:
case ModPathChangeType.Reloaded:
Refresh(EnsureCount(mod), mod);
break;
case ModPathChangeType.Deleted:
--Count;
var oldCache = _cache[mod.Index];
oldCache.Reset();
for (var i = mod.Index; i < Count; ++i)
_cache[i] = _cache[i + 1];
_cache[Count] = oldCache;
Refresh(mod);
break;
}
}
private void OnModDataChange(ModDataChangeType type, Mod mod, string? _)
private static void OnModDataChange(ModDataChangeType type, Mod mod, string? _)
{
if ((type & (ModDataChangeType.LocalTags | ModDataChangeType.ModTags)) != 0)
UpdateTags(EnsureCount(mod), mod);
UpdateTags(mod);
}
private void OnModDiscoveryFinished()
{
if (_modManager.Count > _cache.Count)
_cache.AddRange(Enumerable.Range(0, _modManager.Count - _cache.Count).Select(_ => new ModCache()));
Parallel.ForEach(Enumerable.Range(0, _modManager.Count), idx => { Refresh(_cache[idx], _modManager[idx]); });
Count = _modManager.Count;
}
=> Parallel.ForEach(_modManager, Refresh);
private void OnIdentifierCreation()
{
Parallel.ForEach(Enumerable.Range(0, _modManager.Count), idx => { UpdateChangedItems(_cache[idx], _modManager[idx]); });
Parallel.ForEach(_modManager, UpdateChangedItems);
_identifier.FinishedCreation -= OnIdentifierCreation;
}
private static void UpdateFileCount(ModCache cache, Mod mod)
=> cache.TotalFileCount = mod.AllSubMods.Sum(s => s.Files.Count);
private static void UpdateFileCount(Mod mod)
=> mod.TotalFileCount = mod.AllSubMods.Sum(s => s.Files.Count);
private static void UpdateSwapCount(ModCache cache, Mod mod)
=> cache.TotalFileCount = mod.AllSubMods.Sum(s => s.FileSwaps.Count);
private static void UpdateSwapCount(Mod mod)
=> mod.TotalFileCount = mod.AllSubMods.Sum(s => s.FileSwaps.Count);
private static void UpdateMetaCount(ModCache cache, Mod mod)
=> cache.TotalFileCount = mod.AllSubMods.Sum(s => s.Manipulations.Count);
private static void UpdateMetaCount(Mod mod)
=> mod.TotalFileCount = mod.AllSubMods.Sum(s => s.Manipulations.Count);
private static void UpdateHasOptions(ModCache cache, Mod mod)
=> cache.HasOptions = mod.Groups.Any(o => o.IsOption);
private static void UpdateHasOptions(Mod mod)
=> mod.HasOptions = mod.Groups.Any(o => o.IsOption);
private static void UpdateTags(ModCache cache, Mod mod)
=> cache.AllTagsLower = string.Join('\0', mod.ModTags.Concat(mod.LocalTags).Select(s => s.ToLowerInvariant()));
private static void UpdateTags(Mod mod)
=> mod.AllTagsLower = string.Join('\0', mod.ModTags.Concat(mod.LocalTags).Select(s => s.ToLowerInvariant()));
private void UpdateChangedItems(ModCache cache, Mod mod)
private void UpdateChangedItems(Mod mod)
{
cache.ChangedItems.Clear();
var changedItems = (SortedList<string, object?>)mod.ChangedItems;
changedItems.Clear();
if (!_identifier.Valid)
return;
foreach (var gamePath in mod.AllSubMods.SelectMany(m => m.Files.Keys.Concat(m.FileSwaps.Keys)))
_identifier.AwaitedService.Identify(cache.ChangedItems, gamePath.ToString());
_identifier.AwaitedService.Identify(changedItems, gamePath.ToString());
foreach (var manip in mod.AllSubMods.SelectMany(m => m.Manipulations))
ComputeChangedItems(_identifier.AwaitedService, cache.ChangedItems, manip);
ComputeChangedItems(_identifier.AwaitedService, changedItems, manip);
cache.LowerChangedItemsString = string.Join("\0", cache.ChangedItems.Keys.Select(k => k.ToLowerInvariant()));
mod.LowerChangedItemsString = string.Join("\0", mod.ChangedItems.Keys.Select(k => k.ToLowerInvariant()));
}
private static void UpdateCounts(ModCache cache, Mod mod)
private static void UpdateCounts(Mod mod)
{
cache.TotalFileCount = mod.Default.Files.Count;
cache.TotalSwapCount = mod.Default.FileSwaps.Count;
cache.TotalManipulations = mod.Default.Manipulations.Count;
cache.HasOptions = false;
mod.TotalFileCount = mod.Default.Files.Count;
mod.TotalSwapCount = mod.Default.FileSwaps.Count;
mod.TotalManipulations = mod.Default.Manipulations.Count;
mod.HasOptions = false;
foreach (var group in mod.Groups)
{
cache.HasOptions |= group.IsOption;
mod.HasOptions |= group.IsOption;
foreach (var s in group)
{
cache.TotalFileCount += s.Files.Count;
cache.TotalSwapCount += s.FileSwaps.Count;
cache.TotalManipulations += s.Manipulations.Count;
mod.TotalFileCount += s.Files.Count;
mod.TotalSwapCount += s.FileSwaps.Count;
mod.TotalManipulations += s.Manipulations.Count;
}
}
}
private void Refresh(ModCache cache, Mod mod)
private void Refresh(Mod mod)
{
UpdateTags(cache, mod);
UpdateCounts(cache, mod);
UpdateChangedItems(cache, mod);
}
private ModCache EnsureCount(Mod mod)
{
if (mod.Index < Count)
return _cache[mod.Index];
if (mod.Index >= _cache.Count)
_cache.AddRange(Enumerable.Range(0, mod.Index + 1 - _cache.Count).Select(_ => new ModCache()));
for (var i = Count; i < mod.Index; ++i)
Refresh(_cache[i], _modManager[i]);
Count = mod.Index + 1;
return _cache[mod.Index];
UpdateTags(mod);
UpdateCounts(mod);
UpdateChangedItems(mod);
}
}

View file

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using OtterGui;
using OtterGui.Classes;
using Penumbra.Collections.Cache;
using Penumbra.Import;
using Penumbra.Meta;
using Penumbra.String.Classes;
@ -21,8 +22,10 @@ public sealed partial class Mod : IMod
// Main Data
public DirectoryInfo ModPath { get; internal set; }
public string Identifier
=> Index >= 0 ? ModPath.Name : Name;
public int Index { get; internal set; } = -1;
public bool IsTemporary
@ -32,12 +35,15 @@ public sealed partial class Mod : IMod
public int Priority
=> 0;
public Mod(DirectoryInfo modPath)
internal Mod(DirectoryInfo modPath)
{
ModPath = modPath;
Default = new SubMod(this);
}
public override string ToString()
=> Name.Text;
// Meta Data
public LowerString Name { get; internal set; } = "New Mod";
public LowerString Author { get; internal set; } = LowerString.Empty;
@ -80,35 +86,14 @@ public sealed partial class Mod : IMod
.ToList();
}
// Access
public override string ToString()
=> Name.Text;
// Cache
public readonly IReadOnlyDictionary<string, object?> ChangedItems = new SortedList<string, object?>();
public void WriteAllTexToolsMeta(MetaFileManager manager)
{
try
{
TexToolsMeta.WriteTexToolsMeta(manager, Default.Manipulations, ModPath);
foreach (var group in Groups)
{
var dir = ModCreator.NewOptionDirectory(ModPath, group.Name);
if (!dir.Exists)
dir.Create();
foreach (var option in group.OfType<SubMod>())
{
var optionDir = ModCreator.NewOptionDirectory(dir, option.Name);
if (!optionDir.Exists)
optionDir.Create();
TexToolsMeta.WriteTexToolsMeta(manager, option.Manipulations, optionDir);
}
}
}
catch (Exception e)
{
Penumbra.Log.Error($"Error writing TexToolsMeta:\n{e}");
}
}
public string LowerChangedItemsString { get; internal set; } = string.Empty;
public string AllTagsLower { get; internal set; } = string.Empty;
public int TotalFileCount { get; internal set; }
public int TotalSwapCount { get; internal set; }
public int TotalManipulations { get; internal set; }
public bool HasOptions { get; internal set; }
}

View file

@ -1,29 +0,0 @@
using System.Collections.Generic;
namespace Penumbra.Mods;
public class ModCache
{
public int TotalFileCount;
public int TotalSwapCount;
public int TotalManipulations;
public bool HasOptions;
public readonly SortedList<string, object?> ChangedItems = new();
public string LowerChangedItemsString = string.Empty;
public string AllTagsLower = string.Empty;
public ModCache()
{}
public void Reset()
{
TotalFileCount = 0;
TotalSwapCount = 0;
TotalManipulations = 0;
HasOptions = false;
ChangedItems.Clear();
LowerChangedItemsString = string.Empty;
AllTagsLower = string.Empty;
}
}

View file

@ -36,10 +36,8 @@ public class Penumbra : IDalamudPlugin
public static Logger Log { get; private set; } = null!;
public static ChatService ChatService { get; private set; } = null!;
public static Configuration Config { get; private set; } = null!;
public static CharacterUtility CharacterUtility { get; private set; } = null!;
public static ModCacheManager ModCaches { get; private set; } = null!;
public static CollectionManager CollectionManager { get; private set; } = null!;
public static ActorManager Actors { get; private set; } = null!;
@ -53,6 +51,7 @@ public class Penumbra : IDalamudPlugin
private readonly TempModManager _tempMods;
private readonly TempCollectionManager _tempCollections;
private readonly ModManager _modManager;
private readonly Configuration _config;
private PenumbraWindowSystem? _windowSystem;
private bool _disposed;
@ -67,7 +66,7 @@ public class Penumbra : IDalamudPlugin
ChatService = _tmp.Services.GetRequiredService<ChatService>();
_validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>();
_tmp.Services.GetRequiredService<BackupService>();
Config = _tmp.Services.GetRequiredService<Configuration>();
_config = _tmp.Services.GetRequiredService<Configuration>();
CharacterUtility = _tmp.Services.GetRequiredService<CharacterUtility>();
Actors = _tmp.Services.GetRequiredService<ActorService>().AwaitedService;
_tempMods = _tmp.Services.GetRequiredService<TempModManager>();
@ -78,8 +77,8 @@ public class Penumbra : IDalamudPlugin
_tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>();
ModFileSystem = _tmp.Services.GetRequiredService<ModFileSystem>();
RedrawService = _tmp.Services.GetRequiredService<RedrawService>();
_tmp.Services.GetRequiredService<ResourceService>();
ModCaches = _tmp.Services.GetRequiredService<ModCacheManager>();
_tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else.
_tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else.
using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver))
{
_tmp.Services.GetRequiredService<PathResolver>();
@ -146,10 +145,10 @@ public class Penumbra : IDalamudPlugin
public bool SetEnabled(bool enabled)
{
if (enabled == Config.EnableMods)
if (enabled == _config.EnableMods)
return false;
Config.EnableMods = enabled;
_config.EnableMods = enabled;
if (enabled)
{
if (CharacterUtility.Ready)
@ -169,7 +168,7 @@ public class Penumbra : IDalamudPlugin
}
}
Config.Save();
_config.Save();
EnabledChange?.Invoke(enabled);
return true;
@ -190,33 +189,33 @@ public class Penumbra : IDalamudPlugin
public string GatherSupportInformation()
{
var sb = new StringBuilder(10240);
var exists = Config.ModDirectory.Length > 0 && Directory.Exists(Config.ModDirectory);
var drive = exists ? new DriveInfo(new DirectoryInfo(Config.ModDirectory).Root.FullName) : null;
var exists = _config.ModDirectory.Length > 0 && Directory.Exists(_config.ModDirectory);
var drive = exists ? new DriveInfo(new DirectoryInfo(_config.ModDirectory).Root.FullName) : null;
sb.AppendLine("**Settings**");
sb.Append($"> **`Plugin Version: `** {_validityChecker.Version}\n");
sb.Append($"> **`Commit Hash: `** {_validityChecker.CommitHash}\n");
sb.Append($"> **`Enable Mods: `** {Config.EnableMods}\n");
sb.Append($"> **`Enable HTTP API: `** {Config.EnableHttpApi}\n");
sb.Append($"> **`Enable Mods: `** {_config.EnableMods}\n");
sb.Append($"> **`Enable HTTP API: `** {_config.EnableHttpApi}\n");
sb.Append($"> **`Operating System: `** {(DalamudUtil.IsLinux() ? "Mac/Linux (Wine)" : "Windows")}\n");
sb.Append($"> **`Root Directory: `** `{Config.ModDirectory}`, {(exists ? "Exists" : "Not Existing")}\n");
sb.Append($"> **`Root Directory: `** `{_config.ModDirectory}`, {(exists ? "Exists" : "Not Existing")}\n");
sb.Append(
$"> **`Free Drive Space: `** {(drive != null ? Functions.HumanReadableSize(drive.AvailableFreeSpace) : "Unknown")}\n");
sb.Append($"> **`Auto-Deduplication: `** {Config.AutoDeduplicateOnImport}\n");
sb.Append($"> **`Debug Mode: `** {Config.DebugMode}\n");
sb.Append($"> **`Auto-Deduplication: `** {_config.AutoDeduplicateOnImport}\n");
sb.Append($"> **`Debug Mode: `** {_config.DebugMode}\n");
sb.Append(
$"> **`Synchronous Load (Dalamud): `** {(_tmp.Services.GetRequiredService<DalamudServices>().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")}\n");
sb.Append(
$"> **`Logging: `** Log: {Config.EnableResourceLogging}, Watcher: {Config.EnableResourceWatcher} ({Config.MaxResourceWatcherRecords})\n");
sb.Append($"> **`Use Ownership: `** {Config.UseOwnerNameForCharacterCollection}\n");
$"> **`Logging: `** Log: {_config.EnableResourceLogging}, Watcher: {_config.EnableResourceWatcher} ({_config.MaxResourceWatcherRecords})\n");
sb.Append($"> **`Use Ownership: `** {_config.UseOwnerNameForCharacterCollection}\n");
sb.AppendLine("**Mods**");
sb.Append($"> **`Installed Mods: `** {_modManager.Count}\n");
sb.Append($"> **`Mods with Config: `** {ModCaches.Count(m => m.HasOptions)}\n");
sb.Append($"> **`Mods with Config: `** {_modManager.Count(m => m.HasOptions)}\n");
sb.Append(
$"> **`Mods with File Redirections: `** {ModCaches.Count(m => m.TotalFileCount > 0)}, Total: {ModCaches.Sum(m => m.TotalFileCount)}\n");
$"> **`Mods with File Redirections: `** {_modManager.Count(m => m.TotalFileCount > 0)}, Total: {_modManager.Sum(m => m.TotalFileCount)}\n");
sb.Append(
$"> **`Mods with FileSwaps: `** {ModCaches.Count(m => m.TotalSwapCount > 0)}, Total: {ModCaches.Sum(m => m.TotalSwapCount)}\n");
$"> **`Mods with FileSwaps: `** {_modManager.Count(m => m.TotalSwapCount > 0)}, Total: {_modManager.Sum(m => m.TotalSwapCount)}\n");
sb.Append(
$"> **`Mods with Meta Manipulations:`** {ModCaches.Count(m => m.TotalManipulations > 0)}, Total {ModCaches.Sum(m => m.TotalManipulations)}\n");
$"> **`Mods with Meta Manipulations:`** {_modManager.Count(m => m.TotalManipulations > 0)}, Total {_modManager.Sum(m => m.TotalManipulations)}\n");
sb.Append($"> **`IMC Exceptions Thrown: `** {_validityChecker.ImcExceptions.Count}\n");
sb.Append(
$"> **`#Temp Mods: `** {_tempMods.Mods.Sum(kvp => kvp.Value.Count) + _tempMods.ModsForAllCollections.Count}\n");

View file

@ -286,7 +286,7 @@ public class FileEditor<T> where T : class, IWritable
ImGui.TableNextColumn();
UiHelpers.Text(gamePath.Path);
ImGui.TableNextColumn();
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value(_config));
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value());
ImGui.TextUnformatted(option.FullName);
}
}
@ -294,7 +294,7 @@ public class FileEditor<T> where T : class, IWritable
if (file.SubModUsage.Count > 0)
{
ImGui.SameLine();
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value(_config));
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value());
ImGuiUtil.RightAlign(file.SubModUsage[0].Item2.Path.ToString());
}

View file

@ -82,7 +82,7 @@ public partial class ModEditWindow
return f.SubModUsage.Count == 0
? Enumerable.Repeat((file, "Unused", string.Empty, 0x40000080u), 1)
: f.SubModUsage.Select(s => (file, s.Item2.ToString(), s.Item1.FullName,
_editor.Option! == s.Item1 && _modCaches[_mod!].HasOptions ? 0x40008000u : 0u));
_editor.Option! == s.Item1 && _mod!.HasOptions ? 0x40008000u : 0u));
});
void DrawLine((string, string, string, uint) data)
@ -179,7 +179,7 @@ public partial class ModEditWindow
var selected = _selectedFiles.Contains(registry);
var color = registry.SubModUsage.Count == 0 ? ColorId.ConflictingMod :
registry.CurrentUsage == registry.SubModUsage.Count ? ColorId.NewMod : ColorId.InheritedMod;
using var c = ImRaii.PushColor(ImGuiCol.Text, color.Value(Penumbra.Config));
using var c = ImRaii.PushColor(ImGuiCol.Text, color.Value());
if (UiHelpers.Selectable(registry.RelPath.Path, selected))
{
if (selected)

View file

@ -63,7 +63,7 @@ public partial class ModEditWindow
CopyToClipboardButton("Copy all current manipulations to clipboard.", _iconSize, _editor.MetaEditor.Recombine());
ImGui.SameLine();
if (ImGui.Button("Write as TexTools Files"))
_mod!.WriteAllTexToolsMeta(_metaFileManager);
_metaFileManager.WriteAllTexToolsMeta(_mod!);
using var child = ImRaii.Child("##meta", -Vector2.One, true);
if (!child)
@ -776,7 +776,7 @@ public partial class ModEditWindow
var value = meta.Entry;
ImGui.SetNextItemWidth(FloatWidth);
using var color = ImRaii.PushColor(ImGuiCol.FrameBg,
def < value ? ColorId.IncreasedMetaValue.Value(Penumbra.Config) : ColorId.DecreasedMetaValue.Value(Penumbra.Config),
def < value ? ColorId.IncreasedMetaValue.Value() : ColorId.DecreasedMetaValue.Value(),
def != value);
if (ImGui.DragFloat("##rspValue", ref value, 0.001f, 0.01f, 8f) && value is >= 0.01f and <= 8f)
editor.MetaEditor.Change(meta.Copy(value));
@ -805,7 +805,7 @@ public partial class ModEditWindow
private static bool Checkmark(string label, string tooltip, bool currentValue, bool defaultValue, out bool newValue)
{
using var color = ImRaii.PushColor(ImGuiCol.FrameBg,
defaultValue ? ColorId.DecreasedMetaValue.Value(Penumbra.Config) : ColorId.IncreasedMetaValue.Value(Penumbra.Config),
defaultValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(),
defaultValue != currentValue);
newValue = currentValue;
ImGui.Checkbox(label, ref newValue);
@ -820,7 +820,7 @@ public partial class ModEditWindow
{
newValue = currentValue;
using var color = ImRaii.PushColor(ImGuiCol.FrameBg,
defaultValue > currentValue ? ColorId.DecreasedMetaValue.Value(Penumbra.Config) : ColorId.IncreasedMetaValue.Value(Penumbra.Config),
defaultValue > currentValue ? ColorId.DecreasedMetaValue.Value() : ColorId.IncreasedMetaValue.Value(),
defaultValue != currentValue);
ImGui.SetNextItemWidth(width);
if (ImGui.DragInt(label, ref newValue, speed, minValue, maxValue))

View file

@ -42,7 +42,7 @@ public partial class ModEditWindow
ImGui.NewLine();
tex.PathInputBox("##input", "Import Image...", "Can import game paths as well as your own files.", _mod!.ModPath.FullName,
_fileDialog);
_fileDialog, _config.DefaultModImportPath);
var files = _editor.Files.Tex.SelectMany(f => f.SubModUsage.Select(p => (p.Item2.ToString(), true))
.Prepend((f.File.FullName, false)));
tex.PathSelectBox("##combo", "Select the textures included in this mod on your drive or the ones they replace from the game files.",

View file

@ -29,7 +29,6 @@ public partial class ModEditWindow : Window, IDisposable
private readonly PerformanceTracker _performance;
private readonly ModEditor _editor;
private readonly ModCacheManager _modCaches;
private readonly Configuration _config;
private readonly ItemSwapTab _itemSwapTab;
private readonly DataManager _gameData;
@ -277,7 +276,7 @@ public partial class ModEditWindow : Window, IDisposable
var modifier = _config.DeleteModModifier.IsActive();
var tt = _allowReduplicate ? desc :
modifier ? desc : desc + $"\n\nNo duplicates detected! Hold {Penumbra.Config.DeleteModModifier} to force normalization anyway.";
modifier ? desc : desc + $"\n\nNo duplicates detected! Hold {_config.DeleteModModifier} to force normalization anyway.";
if (ImGuiUtil.DrawDisabledButton("Re-Duplicate and Normalize Mod", Vector2.Zero, tt, !_allowReduplicate && !modifier))
{
@ -497,14 +496,14 @@ public partial class ModEditWindow : Window, IDisposable
}
public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, DataManager gameData,
Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, ModCacheManager modCaches, MetaFileManager metaFileManager, StainService stainService)
Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager,
StainService stainService)
: base(WindowBaseLabel)
{
_performance = performance;
_itemSwapTab = itemSwapTab;
_config = config;
_editor = editor;
_modCaches = modCaches;
_metaFileManager = metaFileManager;
_stainService = stainService;
_gameData = gameData;
@ -515,7 +514,8 @@ public partial class ModEditWindow : Window, IDisposable
_modelTab = new FileEditor<MdlFile>(this, gameData, config, _fileDialog, "Models", ".mdl",
() => _editor.Files.Mdl, DrawModelPanel, () => _mod?.ModPath.FullName ?? string.Empty, bytes => new MdlFile(bytes));
_shaderPackageTab = new FileEditor<ShpkTab>(this, gameData, config, _fileDialog, "Shader Packages", ".shpk",
() => _editor.Files.Shpk, DrawShaderPackagePanel, () => _mod?.ModPath.FullName ?? string.Empty, bytes => new ShpkTab(_fileDialog, bytes));
() => _editor.Files.Shpk, DrawShaderPackagePanel, () => _mod?.ModPath.FullName ?? string.Empty,
bytes => new ShpkTab(_fileDialog, bytes));
_center = new CombinedTexture(_left, _right);
_quickImportViewer = new ResourceTreeViewer(_config, resourceTreeFactory, 2, OnQuickImportRefresh, DrawQuickImportActions);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace Penumbra.UI.Classes;
@ -64,6 +65,13 @@ public static class Colors
// @formatter:on
};
public static uint Value(this ColorId color, Configuration config)
=> config.Colors.TryGetValue(color, out var value) ? value : color.Data().DefaultColor;
private static IReadOnlyDictionary<ColorId, uint> _colors = new Dictionary<ColorId, uint>();
/// <summary> Obtain the configured value for a color. </summary>
public static uint Value(this ColorId color)
=> _colors.TryGetValue(color, out var value) ? value : color.Data().DefaultColor;
/// <summary> Set the configurable colors dictionary to a value. </summary>
public static void SetColors(Configuration config)
=> _colors = config.Colors;
}

View file

@ -23,7 +23,6 @@ namespace Penumbra.UI.CollectionTab;
public sealed class CollectionPanel : IDisposable
{
private readonly Configuration _config;
private readonly CollectionStorage _collections;
private readonly ActiveCollections _active;
private readonly CollectionSelector _selector;
@ -39,10 +38,9 @@ public sealed class CollectionPanel : IDisposable
private static readonly IReadOnlyList<(CollectionType, bool, bool, string, uint)> AdvancedTree = CreateTree();
private readonly List<(CollectionType Type, ActorIdentifier Identifier)> _inUseCache = new();
public CollectionPanel(DalamudPluginInterface pi, Configuration config, CommunicatorService communicator, CollectionManager manager,
public CollectionPanel(DalamudPluginInterface pi, CommunicatorService communicator, CollectionManager manager,
CollectionSelector selector, ActorService actors, TargetManager targets, ModStorage mods)
{
_config = config;
_collections = manager.Storage;
_active = manager.Active;
_selector = selector;
@ -50,7 +48,7 @@ public sealed class CollectionPanel : IDisposable
_targets = targets;
_mods = mods;
_individualAssignmentUi = new IndividualAssignmentUi(communicator, actors, manager);
_inheritanceUi = new InheritanceUi(_config, manager, _selector);
_inheritanceUi = new InheritanceUi(manager, _selector);
_nameFont = pi.UiBuilder.GetGameFontHandle(new GameFontStyle(GameFontFamilyAndSize.Jupiter23));
}
@ -81,7 +79,7 @@ public sealed class CollectionPanel : IDisposable
DrawSimpleCollectionButton(CollectionType.MaleNonPlayerCharacter, buttonWidth);
DrawSimpleCollectionButton(CollectionType.FemaleNonPlayerCharacter, buttonWidth);
ImGuiUtil.DrawColoredText(("Individual ", ColorId.NewMod.Value(_config)),
ImGuiUtil.DrawColoredText(("Individual ", ColorId.NewMod.Value()),
("Assignments take precedence before anything else and only apply to one specific character or monster.", 0));
ImGui.Dummy(Vector2.UnitX);
@ -254,13 +252,13 @@ public sealed class CollectionPanel : IDisposable
collection ??= _active.ByType(type, id);
using var color = ImRaii.PushColor(ImGuiCol.Button,
collection == null
? ColorId.NoAssignment.Value(_config)
? ColorId.NoAssignment.Value()
: redundancy.Length > 0
? ColorId.RedundantAssignment.Value(_config)
? ColorId.RedundantAssignment.Value()
: collection == _active.Current
? ColorId.SelectedCollection.Value(_config)
? ColorId.SelectedCollection.Value()
: collection == ModCollection.Empty
? ColorId.NoModsAssignment.Value(_config)
? ColorId.NoModsAssignment.Value()
: ImGui.GetColorU32(ImGuiCol.Button), !invalid)
.Push(ImGuiCol.Border, borderColor == 0 ? ImGui.GetColorU32(ImGuiCol.TextDisabled) : borderColor);
using var disabled = ImRaii.Disabled(invalid);
@ -295,27 +293,27 @@ public sealed class CollectionPanel : IDisposable
ImGui.TextUnformatted("Overruled by any other Assignment.");
break;
case CollectionType.Yourself:
ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Individual ", ColorId.NewMod.Value(_config)), ("Assignments.", 0));
ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Individual ", ColorId.NewMod.Value()), ("Assignments.", 0));
break;
case CollectionType.MalePlayerCharacter:
ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Male Racial Player", Colors.DiscordColor), (", ", 0),
("Your Character", ColorId.HandledConflictMod.Value(_config)), (", or ", 0),
("Individual ", ColorId.NewMod.Value(_config)), ("Assignments.", 0));
("Your Character", ColorId.HandledConflictMod.Value()), (", or ", 0),
("Individual ", ColorId.NewMod.Value()), ("Assignments.", 0));
break;
case CollectionType.FemalePlayerCharacter:
ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Female Racial Player", Colors.ReniColorActive), (", ", 0),
("Your Character", ColorId.HandledConflictMod.Value(_config)), (", or ", 0),
("Individual ", ColorId.NewMod.Value(_config)), ("Assignments.", 0));
("Your Character", ColorId.HandledConflictMod.Value()), (", or ", 0),
("Individual ", ColorId.NewMod.Value()), ("Assignments.", 0));
break;
case CollectionType.MaleNonPlayerCharacter:
ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Male Racial NPC", Colors.DiscordColor), (", ", 0),
("Children", ColorId.FolderLine.Value(_config)), (", ", 0), ("Elderly", Colors.MetaInfoText), (", or ", 0),
("Individual ", ColorId.NewMod.Value(_config)), ("Assignments.", 0));
("Children", ColorId.FolderLine.Value()), (", ", 0), ("Elderly", Colors.MetaInfoText), (", or ", 0),
("Individual ", ColorId.NewMod.Value()), ("Assignments.", 0));
break;
case CollectionType.FemaleNonPlayerCharacter:
ImGuiUtil.DrawColoredText(("Overruled by ", 0), ("Female Racial NPC", Colors.ReniColorActive), (", ", 0),
("Children", ColorId.FolderLine.Value(_config)), (", ", 0), ("Elderly", Colors.MetaInfoText), (", or ", 0),
("Individual ", ColorId.NewMod.Value(_config)), ("Assignments.", 0));
("Children", ColorId.FolderLine.Value()), (", ", 0), ("Elderly", Colors.MetaInfoText), (", or ", 0),
("Individual ", ColorId.NewMod.Value()), ("Assignments.", 0));
break;
}
}

View file

@ -75,7 +75,7 @@ public sealed class CollectionSelector : ItemSelector<ModCollection>, IDisposabl
protected override bool OnDraw(int idx)
{
using var color = ImRaii.PushColor(ImGuiCol.Header, ColorId.SelectedCollection.Value(_config));
using var color = ImRaii.PushColor(ImGuiCol.Header, ColorId.SelectedCollection.Value());
var ret = ImGui.Selectable(Name(Items[idx]), idx == CurrentIdx);
using var source = ImRaii.DragDropSource();

View file

@ -17,15 +17,13 @@ public class InheritanceUi
private const int InheritedCollectionHeight = 9;
private const string InheritanceDragDropLabel = "##InheritanceMove";
private readonly Configuration _config;
private readonly CollectionStorage _collections;
private readonly ActiveCollections _active;
private readonly InheritanceManager _inheritance;
private readonly CollectionSelector _selector;
public InheritanceUi(Configuration config, CollectionManager collectionManager, CollectionSelector selector)
public InheritanceUi(CollectionManager collectionManager, CollectionSelector selector)
{
_config = config;
_selector = selector;
_collections = collectionManager.Storage;
_active = collectionManager.Active;
@ -37,7 +35,7 @@ public class InheritanceUi
public void Draw()
{
using var id = ImRaii.PushId("##Inheritance");
ImGuiUtil.DrawColoredText(($"The {TutorialService.SelectedCollection} ", 0), (Name(_active.Current), ColorId.SelectedCollection.Value(_config) | 0xFF000000), (" inherits from:", 0));
ImGuiUtil.DrawColoredText(($"The {TutorialService.SelectedCollection} ", 0), (Name(_active.Current), ColorId.SelectedCollection.Value() | 0xFF000000), (" inherits from:", 0));
ImGui.Dummy(Vector2.One);
DrawCurrentCollectionInheritance();
@ -124,7 +122,7 @@ public class InheritanceUi
foreach (var inheritance in collection.GetFlattenedInheritance().Skip(1))
{
// Draw the child, already seen collections are colored as conflicts.
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(Penumbra.Config),
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(),
_seenInheritedCollections.Contains(inheritance));
_seenInheritedCollections.Add(inheritance);
@ -150,7 +148,7 @@ public class InheritanceUi
/// <summary> Draw a single primary inherited collection. </summary>
private void DrawInheritance(ModCollection collection)
{
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(Penumbra.Config),
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(),
_seenInheritedCollections.Contains(collection));
_seenInheritedCollections.Add(collection);
using var tree = ImRaii.TreeNode($"{Name(collection)}###{collection.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen);

View file

@ -28,7 +28,6 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
private readonly Configuration _config;
private readonly FileDialogService _fileDialog;
private readonly ModManager _modManager;
private readonly ModCacheManager _modCaches;
private readonly CollectionManager _collectionManager;
private readonly TutorialService _tutorial;
private readonly ModImportManager _modImportManager;
@ -37,7 +36,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
public ModFileSystemSelector(CommunicatorService communicator, ModFileSystem fileSystem, ModManager modManager,
CollectionManager collectionManager, Configuration config, TutorialService tutorial, FileDialogService fileDialog, ChatService chat,
ModCacheManager modCaches, ModImportManager modImportManager)
ModImportManager modImportManager)
: base(fileSystem, DalamudServices.KeyState, HandleException)
{
_communicator = communicator;
@ -47,7 +46,6 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
_tutorial = tutorial;
_fileDialog = fileDialog;
_chat = chat;
_modCaches = modCaches;
_modImportManager = modImportManager;
// @formatter:off
@ -103,13 +101,13 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
=> _config.SortMode;
protected override uint ExpandedFolderColor
=> ColorId.FolderExpanded.Value(_config);
=> ColorId.FolderExpanded.Value();
protected override uint CollapsedFolderColor
=> ColorId.FolderCollapsed.Value(_config);
=> ColorId.FolderCollapsed.Value();
protected override uint FolderLineColor
=> ColorId.FolderLine.Value(_config);
=> ColorId.FolderLine.Value();
protected override bool FoldersDefaultOpen
=> _config.OpenFoldersByDefault;
@ -138,7 +136,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
protected override void DrawLeafName(FileSystem<Mod>.Leaf leaf, in ModState state, bool selected)
{
var flags = selected ? ImGuiTreeNodeFlags.Selected | LeafFlags : LeafFlags;
using var c = ImRaii.PushColor(ImGuiCol.Text, state.Color.Value(_config))
using var c = ImRaii.PushColor(ImGuiCol.Text, state.Color.Value())
.Push(ImGuiCol.HeaderHovered, 0x4000FFFF, leaf.Value.Favorite);
using var id = ImRaii.PushId(leaf.Value.Index);
ImRaii.TreeNode(leaf.Value.Name, flags).Dispose();
@ -285,7 +283,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
if (leaf == null)
throw new Exception("Mod was not found at root.");
var folder = FileSystem.FindOrCreateAllFolders(Penumbra.Config.DefaultImportFolder);
var folder = FileSystem.FindOrCreateAllFolders(_config.DefaultImportFolder);
FileSystem.Move(leaf, folder);
}
catch (Exception e)
@ -315,19 +313,19 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
ImGui.BulletText("Select a mod to obtain more information or change settings.");
ImGui.BulletText("Names are colored according to your config and their current state in the collection:");
indent.Push();
ImGuiUtil.BulletTextColored(ColorId.EnabledMod.Value(_config), "enabled in the current collection.");
ImGuiUtil.BulletTextColored(ColorId.DisabledMod.Value(_config), "disabled in the current collection.");
ImGuiUtil.BulletTextColored(ColorId.InheritedMod.Value(_config), "enabled due to inheritance from another collection.");
ImGuiUtil.BulletTextColored(ColorId.InheritedDisabledMod.Value(_config), "disabled due to inheritance from another collection.");
ImGuiUtil.BulletTextColored(ColorId.UndefinedMod.Value(_config), "unconfigured in all inherited collections.");
ImGuiUtil.BulletTextColored(ColorId.NewMod.Value(_config),
ImGuiUtil.BulletTextColored(ColorId.EnabledMod.Value(), "enabled in the current collection.");
ImGuiUtil.BulletTextColored(ColorId.DisabledMod.Value(), "disabled in the current collection.");
ImGuiUtil.BulletTextColored(ColorId.InheritedMod.Value(), "enabled due to inheritance from another collection.");
ImGuiUtil.BulletTextColored(ColorId.InheritedDisabledMod.Value(), "disabled due to inheritance from another collection.");
ImGuiUtil.BulletTextColored(ColorId.UndefinedMod.Value(), "unconfigured in all inherited collections.");
ImGuiUtil.BulletTextColored(ColorId.NewMod.Value(),
"newly imported during this session. Will go away when first enabling a mod or when Penumbra is reloaded.");
ImGuiUtil.BulletTextColored(ColorId.HandledConflictMod.Value(_config),
ImGuiUtil.BulletTextColored(ColorId.HandledConflictMod.Value(),
"enabled and conflicting with another enabled Mod, but on different priorities (i.e. the conflict is solved).");
ImGuiUtil.BulletTextColored(ColorId.ConflictingMod.Value(_config),
ImGuiUtil.BulletTextColored(ColorId.ConflictingMod.Value(),
"enabled and conflicting with another enabled Mod on the same priority.");
ImGuiUtil.BulletTextColored(ColorId.FolderExpanded.Value(_config), "expanded mod folder.");
ImGuiUtil.BulletTextColored(ColorId.FolderCollapsed.Value(_config), "collapsed mod folder");
ImGuiUtil.BulletTextColored(ColorId.FolderExpanded.Value(), "expanded mod folder.");
ImGuiUtil.BulletTextColored(ColorId.FolderCollapsed.Value(), "collapsed mod folder");
indent.Pop(1);
ImGui.BulletText("Right-click a mod to enter its sort order, which is its name by default, possibly with a duplicate number.");
indent.Push();
@ -524,8 +522,8 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
0 => !(leaf.FullName().Contains(_modFilter.Lower, IgnoreCase) || mod.Name.Contains(_modFilter)),
1 => !mod.Name.Contains(_modFilter),
2 => !mod.Author.Contains(_modFilter),
3 => !_modCaches[mod].LowerChangedItemsString.Contains(_modFilter.Lower),
4 => !_modCaches[mod].AllTagsLower.Contains(_modFilter.Lower),
3 => !mod.LowerChangedItemsString.Contains(_modFilter.Lower),
4 => !mod.AllTagsLower.Contains(_modFilter.Lower),
_ => false, // Should never happen
};
}
@ -554,12 +552,11 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
private bool CheckStateFilters(Mod mod, ModSettings? settings, ModCollection collection, ref ModState state)
{
var isNew = _modManager.IsNew(mod);
var cache = _modCaches[mod.Index];
// Handle mod details.
if (CheckFlags(cache.TotalFileCount, ModFilter.HasNoFiles, ModFilter.HasFiles)
|| CheckFlags(cache.TotalSwapCount, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps)
|| CheckFlags(cache.TotalManipulations, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations)
|| CheckFlags(cache.HasOptions ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig)
if (CheckFlags(mod.TotalFileCount, ModFilter.HasNoFiles, ModFilter.HasFiles)
|| CheckFlags(mod.TotalSwapCount, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps)
|| CheckFlags(mod.TotalManipulations, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations)
|| CheckFlags(mod.HasOptions ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig)
|| CheckFlags(isNew ? 1 : 0, ModFilter.NotNew, ModFilter.IsNew))
return true;

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using ImGuiNET;
using OtterGui;
@ -14,20 +15,18 @@ public class ModPanelChangedItemsTab : ITab
{
private readonly ModFileSystemSelector _selector;
private readonly PenumbraApi _api;
private readonly ModCacheManager _modCaches;
public ReadOnlySpan<byte> Label
=> "Changed Items"u8;
public ModPanelChangedItemsTab(PenumbraApi api, ModFileSystemSelector selector, ModCacheManager modCaches)
public ModPanelChangedItemsTab(PenumbraApi api, ModFileSystemSelector selector)
{
_api = api;
_selector = selector;
_modCaches = modCaches;
}
public bool IsVisible
=> _modCaches[_selector.Selected!].ChangedItems.Count > 0;
=> _selector.Selected!.ChangedItems.Count > 0;
public void DrawContent()
{
@ -35,7 +34,7 @@ public class ModPanelChangedItemsTab : ITab
if (!list)
return;
var zipList = ZipList.FromSortedList(_modCaches[_selector.Selected!].ChangedItems);
var zipList = ZipList.FromSortedList((SortedList<string, object?>)_selector.Selected!.ChangedItems);
var height = ImGui.GetTextLineHeight();
ImGuiClip.ClippedDraw(zipList, kvp => UiHelpers.DrawChangedItem(_api, kvp.Item1, kvp.Item2, true), height);
}

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using Dalamud.Interface;
using ImGuiNET;
using Lumina.Data.Parsing.Layer;
using OtterGui;
using OtterGui.Raii;
using OtterGui.Widgets;
@ -15,15 +14,13 @@ namespace Penumbra.UI.ModsTab;
public class ModPanelCollectionsTab : ITab
{
private readonly Configuration _config;
private readonly ModFileSystemSelector _selector;
private readonly CollectionStorage _collections;
private readonly List<(ModCollection, ModCollection, uint, string)> _cache = new();
public ModPanelCollectionsTab(Configuration config, CollectionStorage storage, ModFileSystemSelector selector)
public ModPanelCollectionsTab(CollectionStorage storage, ModFileSystemSelector selector)
{
_config = config;
_collections = storage;
_selector = selector;
}
@ -42,9 +39,8 @@ public class ModPanelCollectionsTab : ITab
else
ImGui.TextUnformatted($"This Mod is directly configured in {direct} collections.");
if (inherited > 0)
{
ImGui.TextUnformatted($"It is also implicitly used in {inherited} {(inherited == 1 ? "collection" : "collections")} through inheritance.");
}
ImGui.TextUnformatted(
$"It is also implicitly used in {inherited} {(inherited == 1 ? "collection" : "collections")} through inheritance.");
ImGui.NewLine();
ImGui.Separator();
@ -79,11 +75,11 @@ public class ModPanelCollectionsTab : ITab
private (int Direct, int Inherited) CountUsage(Mod mod)
{
_cache.Clear();
var undefined = ColorId.UndefinedMod.Value(_config);
var enabled = ColorId.EnabledMod.Value(_config);
var inherited = ColorId.InheritedMod.Value(_config);
var disabled = ColorId.DisabledMod.Value(_config);
var disInherited = ColorId.InheritedDisabledMod.Value(_config);
var undefined = ColorId.UndefinedMod.Value();
var enabled = ColorId.EnabledMod.Value();
var inherited = ColorId.InheritedMod.Value();
var disabled = ColorId.DisabledMod.Value();
var disInherited = ColorId.InheritedDisabledMod.Value();
var directCount = 0;
var inheritedCount = 0;
foreach (var collection in _collections)

View file

@ -43,7 +43,7 @@ public class ModPanelConflictsTab : ITab
ImGui.SameLine();
using (var color = ImRaii.PushColor(ImGuiCol.Text,
conflict.HasPriority ? ColorId.HandledConflictMod.Value(Penumbra.Config) : ColorId.ConflictingMod.Value(Penumbra.Config)))
conflict.HasPriority ? ColorId.HandledConflictMod.Value() : ColorId.ConflictingMod.Value()))
{
var priority = conflict.Mod2.Index < 0
? conflict.Mod2.Priority

View file

@ -25,8 +25,8 @@ internal sealed class ResourceWatcherTable : Table<Record>
new CustomLoadColumn { Label = "Custom" },
new SynchronousLoadColumn { Label = "Sync" },
new OriginalPathColumn { Label = "Original Path" },
new ResourceCategoryColumn { Label = "Category" },
new ResourceTypeColumn { Label = "Type" },
new ResourceCategoryColumn(config) { Label = "Category" },
new ResourceTypeColumn(config) { Label = "Type" },
new HandleColumn { Label = "Resource" },
new RefCountColumn { Label = "#Ref" },
new DateColumn { Label = "Time" }
@ -111,7 +111,7 @@ internal sealed class ResourceWatcherTable : Table<Record>
else
_config.ResourceWatcherRecordTypes &= ~value;
Penumbra.Config.Save();
_config.Save();
}
public override void DrawColumn(Record item, int idx)
@ -175,8 +175,13 @@ internal sealed class ResourceWatcherTable : Table<Record>
private sealed class ResourceCategoryColumn : ColumnFlags<ResourceCategoryFlag, Record>
{
public ResourceCategoryColumn()
=> AllFlags = ResourceExtensions.AllResourceCategories;
private readonly Configuration _config;
public ResourceCategoryColumn(Configuration config)
{
_config = config;
AllFlags = ResourceExtensions.AllResourceCategories;
}
public override float Width
=> 80 * UiHelpers.Scale;
@ -185,16 +190,16 @@ internal sealed class ResourceWatcherTable : Table<Record>
=> FilterValue.HasFlag(item.Category);
public override ResourceCategoryFlag FilterValue
=> Penumbra.Config.ResourceWatcherResourceCategories;
=> _config.ResourceWatcherResourceCategories;
protected override void SetValue(ResourceCategoryFlag value, bool enable)
{
if (enable)
Penumbra.Config.ResourceWatcherResourceCategories |= value;
_config.ResourceWatcherResourceCategories |= value;
else
Penumbra.Config.ResourceWatcherResourceCategories &= ~value;
_config.ResourceWatcherResourceCategories &= ~value;
Penumbra.Config.Save();
_config.Save();
}
public override void DrawColumn(Record item, int idx)
@ -205,8 +210,11 @@ internal sealed class ResourceWatcherTable : Table<Record>
private sealed class ResourceTypeColumn : ColumnFlags<ResourceTypeFlag, Record>
{
public ResourceTypeColumn()
private readonly Configuration _config;
public ResourceTypeColumn(Configuration config)
{
_config = config;
AllFlags = Enum.GetValues<ResourceTypeFlag>().Aggregate((v, f) => v | f);
for (var i = 0; i < Names.Length; ++i)
Names[i] = Names[i].ToLowerInvariant();
@ -219,16 +227,16 @@ internal sealed class ResourceWatcherTable : Table<Record>
=> FilterValue.HasFlag(item.ResourceType);
public override ResourceTypeFlag FilterValue
=> Penumbra.Config.ResourceWatcherResourceTypes;
=> _config.ResourceWatcherResourceTypes;
protected override void SetValue(ResourceTypeFlag value, bool enable)
{
if (enable)
Penumbra.Config.ResourceWatcherResourceTypes |= value;
_config.ResourceWatcherResourceTypes |= value;
else
Penumbra.Config.ResourceWatcherResourceTypes &= ~value;
_config.ResourceWatcherResourceTypes &= ~value;
Penumbra.Config.Save();
_config.Save();
}
public override void DrawColumn(Record item, int idx)

View file

@ -94,7 +94,7 @@ public class ChangedItemsTab : ITab
if (!UiHelpers.GetChangedItemObject(item.Value.Item2, out var text))
return;
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value(Penumbra.Config));
using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.ItemId.Value());
ImGuiUtil.RightAlign(text);
}
}

View file

@ -46,7 +46,7 @@ public class CollectionsTab : IDisposable, ITab
_config = configuration;
_tutorial = tutorial;
_selector = new CollectionSelector(configuration, communicator, collectionManager.Storage, collectionManager.Active, _tutorial);
_panel = new CollectionPanel(pi, configuration, communicator, collectionManager, _selector, actors, targets, modStorage);
_panel = new CollectionPanel(pi, communicator, collectionManager, _selector, actors, targets, modStorage);
}
public void Dispose()
@ -116,8 +116,8 @@ public class CollectionsTab : IDisposable, ITab
ImGui.SameLine();
style.Push(ImGuiStyleVar.FrameBorderSize, ImGuiHelpers.GlobalScale);
color.Push(ImGuiCol.Text, ColorId.FolderExpanded.Value(_config))
.Push(ImGuiCol.Border, ColorId.FolderExpanded.Value(_config));
color.Push(ImGuiCol.Text, ColorId.FolderExpanded.Value())
.Push(ImGuiCol.Border, ColorId.FolderExpanded.Value());
if (ImGuiUtil.DrawDisabledButton(
$"{(_selector.IncognitoMode ? FontAwesomeIcon.Eye : FontAwesomeIcon.EyeSlash).ToIconString()}###IncognitoMode",
buttonSize with { X = withSpacing }, string.Empty, false, true))

View file

@ -111,7 +111,7 @@ public class ModsTab : ITab
private void DrawRedrawLine()
{
if (Penumbra.Config.HideRedrawBar)
if (_config.HideRedrawBar)
{
_tutorial.SkipTutorial(BasicTutorialSteps.Redrawing);
return;
@ -172,7 +172,7 @@ public class ModsTab : ITab
ImGui.SameLine();
DrawInheritedCollectionButton(3 * buttonSize);
ImGui.SameLine();
_collectionCombo.Draw("##collectionSelector", 2 * buttonSize.X, ColorId.SelectedCollection.Value(_config));
_collectionCombo.Draw("##collectionSelector", 2 * buttonSize.X, ColorId.SelectedCollection.Value());
}
_tutorial.OpenTutorial(BasicTutorialSteps.CollectionSelectors);

View file

@ -69,8 +69,8 @@ public class SettingsTab : ITab
return;
DrawEnabledBox();
Checkbox("Lock Main Window", "Prevent the main window from being resized or moved.", Penumbra.Config.FixMainWindow,
v => Penumbra.Config.FixMainWindow = v);
Checkbox("Lock Main Window", "Prevent the main window from being resized or moved.", _config.FixMainWindow,
v => _config.FixMainWindow = v);
ImGui.NewLine();
DrawRootFolder();
@ -220,7 +220,7 @@ public class SettingsTab : ITab
if (_config.ModDirectory != _newModDirectory
&& _newModDirectory.Length != 0
&& DrawPressEnterWarning(_newModDirectory, Penumbra.Config.ModDirectory, pos, save, selected))
&& DrawPressEnterWarning(_newModDirectory, _config.ModDirectory, pos, save, selected))
_modManager.DiscoverMods(_newModDirectory);
}
@ -344,14 +344,14 @@ public class SettingsTab : ITab
_dalamud.UiBuilder.DisableUserUiHide = !v;
});
Checkbox("Hide Config Window when in Cutscenes",
"Hide the penumbra main window when you are currently watching a cutscene.", Penumbra.Config.HideUiInCutscenes,
"Hide the penumbra main window when you are currently watching a cutscene.", _config.HideUiInCutscenes,
v =>
{
_config.HideUiInCutscenes = v;
_dalamud.UiBuilder.DisableCutsceneUiHide = !v;
});
Checkbox("Hide Config Window when in GPose",
"Hide the penumbra main window when you are currently in GPose mode.", Penumbra.Config.HideUiInGPose,
"Hide the penumbra main window when you are currently in GPose mode.", _config.HideUiInGPose,
v =>
{
_config.HideUiInGPose = v;
@ -481,7 +481,7 @@ public class SettingsTab : ITab
Widget.DoubleModifierSelector("Mod Deletion Modifier",
"A modifier you need to hold while clicking the Delete Mod button for it to take effect.", UiHelpers.InputTextWidth.X,
Penumbra.Config.DeleteModModifier,
_config.DeleteModModifier,
v =>
{
_config.DeleteModModifier = v;
@ -742,8 +742,8 @@ public class SettingsTab : ITab
ImGui.SetCursorPos(new Vector2(xPos, 3 * ImGui.GetFrameHeightWithSpacing()));
if (ImGui.Button("Restart Tutorial", new Vector2(width, 0)))
{
Penumbra.Config.TutorialStep = 0;
Penumbra.Config.Save();
_config.TutorialStep = 0;
_config.Save();
}
ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing()));

View file

@ -86,7 +86,7 @@ public static class UiHelpers
return;
ImGui.SameLine(ImGui.GetContentRegionAvail().X);
ImGuiUtil.RightJustify(text, ColorId.ItemId.Value(Penumbra.Config));
ImGuiUtil.RightJustify(text, ColorId.ItemId.Value());
}
/// <summary> Return more detailed object information in text, if it exists. </summary>