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) if (addMetaChanges)
{ {
++_collection.ChangeCounter; ++_collection.ChangeCounter;
if ((mod is TemporaryMod temp ? temp.TotalManipulations : Penumbra.ModCaches[mod.Index].TotalManipulations) > 0) if (mod.TotalManipulations > 0)
AddMetaFiles(); AddMetaFiles();
_manager.MetaFileManager.ApplyDefaultFiles(_collection); _manager.MetaFileManager.ApplyDefaultFiles(_collection);

View file

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

View file

@ -94,12 +94,12 @@ public partial class TexToolsImporter
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if( ex == null ) 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" ); ImGui.TextUnformatted( dir?.FullName[ ( _baseDirectory.FullName.Length + 1 ).. ] ?? "Unknown Directory" );
} }
else 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 ); ImGui.TextUnformatted( ex.Message );
ImGuiUtil.HoverTooltip( ex.ToString() ); ImGuiUtil.HoverTooltip( ex.ToString() );
} }

View file

@ -37,7 +37,7 @@ public sealed class Texture : IDisposable
// The pixels of the main image in RGBA order. // The pixels of the main image in RGBA order.
// Empty if LoadError != null or Path is empty. // Empty if LoadError != null or Path is empty.
public byte[] RGBAPixels = Array.Empty< byte >(); public byte[] RGBAPixels = Array.Empty<byte>();
// The ImGui wrapper to load the image. // The ImGui wrapper to load the image.
// null if LoadError != null or Path is empty. // null if LoadError != null or Path is empty.
@ -53,101 +53,97 @@ public sealed class Texture : IDisposable
public bool IsLoaded public bool IsLoaded
=> TextureWrap != null; => TextureWrap != null;
public void Draw( Vector2 size ) public void Draw(Vector2 size)
{ {
if( TextureWrap != null ) if (TextureWrap != null)
{ {
size = size.X < TextureWrap.Width size = size.X < TextureWrap.Width
? size with { Y = TextureWrap.Height * size.X / TextureWrap.Width } ? size with { Y = TextureWrap.Height * size.X / TextureWrap.Width }
: new Vector2( TextureWrap.Width, TextureWrap.Height ); : new Vector2(TextureWrap.Width, TextureWrap.Height);
ImGui.Image( TextureWrap.ImGuiHandle, size ); ImGui.Image(TextureWrap.ImGuiHandle, size);
DrawData(); DrawData();
} }
else if( LoadError != null ) else if (LoadError != null)
{ {
ImGui.TextUnformatted( "Could not load file:" ); ImGui.TextUnformatted("Could not load file:");
ImGuiUtil.TextColored( Colors.RegexWarningBorder, LoadError.ToString() ); ImGuiUtil.TextColored(Colors.RegexWarningBorder, LoadError.ToString());
} }
} }
public void DrawData() public void DrawData()
{ {
using var table = ImRaii.Table( "##data", 2, ImGuiTableFlags.SizingFixedFit ); using var table = ImRaii.Table("##data", 2, ImGuiTableFlags.SizingFixedFit);
ImGuiUtil.DrawTableColumn( "Width" ); ImGuiUtil.DrawTableColumn("Width");
ImGuiUtil.DrawTableColumn( TextureWrap!.Width.ToString() ); ImGuiUtil.DrawTableColumn(TextureWrap!.Width.ToString());
ImGuiUtil.DrawTableColumn( "Height" ); ImGuiUtil.DrawTableColumn("Height");
ImGuiUtil.DrawTableColumn( TextureWrap!.Height.ToString() ); ImGuiUtil.DrawTableColumn(TextureWrap!.Height.ToString());
ImGuiUtil.DrawTableColumn( "File Type" ); ImGuiUtil.DrawTableColumn("File Type");
ImGuiUtil.DrawTableColumn( Type.ToString() ); ImGuiUtil.DrawTableColumn(Type.ToString());
ImGuiUtil.DrawTableColumn( "Bitmap Size" ); ImGuiUtil.DrawTableColumn("Bitmap Size");
ImGuiUtil.DrawTableColumn( $"{Functions.HumanReadableSize( RGBAPixels.Length )} ({RGBAPixels.Length} Bytes)" ); ImGuiUtil.DrawTableColumn($"{Functions.HumanReadableSize(RGBAPixels.Length)} ({RGBAPixels.Length} Bytes)");
switch( BaseImage ) switch (BaseImage)
{ {
case ScratchImage s: case ScratchImage s:
ImGuiUtil.DrawTableColumn( "Format" ); ImGuiUtil.DrawTableColumn("Format");
ImGuiUtil.DrawTableColumn( s.Meta.Format.ToString() ); ImGuiUtil.DrawTableColumn(s.Meta.Format.ToString());
ImGuiUtil.DrawTableColumn( "Mip Levels" ); ImGuiUtil.DrawTableColumn("Mip Levels");
ImGuiUtil.DrawTableColumn( s.Meta.MipLevels.ToString() ); ImGuiUtil.DrawTableColumn(s.Meta.MipLevels.ToString());
ImGuiUtil.DrawTableColumn( "Data Size" ); ImGuiUtil.DrawTableColumn("Data Size");
ImGuiUtil.DrawTableColumn( $"{Functions.HumanReadableSize( s.Pixels.Length )} ({s.Pixels.Length} Bytes)" ); ImGuiUtil.DrawTableColumn($"{Functions.HumanReadableSize(s.Pixels.Length)} ({s.Pixels.Length} Bytes)");
ImGuiUtil.DrawTableColumn( "Number of Images" ); ImGuiUtil.DrawTableColumn("Number of Images");
ImGuiUtil.DrawTableColumn( s.Images.Length.ToString() ); ImGuiUtil.DrawTableColumn(s.Images.Length.ToString());
break; break;
case TexFile t: case TexFile t:
ImGuiUtil.DrawTableColumn( "Format" ); ImGuiUtil.DrawTableColumn("Format");
ImGuiUtil.DrawTableColumn( t.Header.Format.ToString() ); ImGuiUtil.DrawTableColumn(t.Header.Format.ToString());
ImGuiUtil.DrawTableColumn( "Mip Levels" ); ImGuiUtil.DrawTableColumn("Mip Levels");
ImGuiUtil.DrawTableColumn( t.Header.MipLevels.ToString() ); ImGuiUtil.DrawTableColumn(t.Header.MipLevels.ToString());
ImGuiUtil.DrawTableColumn( "Data Size" ); ImGuiUtil.DrawTableColumn("Data Size");
ImGuiUtil.DrawTableColumn( $"{Functions.HumanReadableSize( t.ImageData.Length )} ({t.ImageData.Length} Bytes)" ); ImGuiUtil.DrawTableColumn($"{Functions.HumanReadableSize(t.ImageData.Length)} ({t.ImageData.Length} Bytes)");
break; break;
} }
} }
private void Clean() private void Clean()
{ {
RGBAPixels = Array.Empty< byte >(); RGBAPixels = Array.Empty<byte>();
TextureWrap?.Dispose(); TextureWrap?.Dispose();
TextureWrap = null; TextureWrap = null;
( BaseImage as IDisposable )?.Dispose(); (BaseImage as IDisposable)?.Dispose();
BaseImage = null; BaseImage = null;
Type = FileType.Unknown; Type = FileType.Unknown;
Loaded?.Invoke( false ); Loaded?.Invoke(false);
} }
public void Dispose() public void Dispose()
=> Clean(); => Clean();
public event Action< bool >? Loaded; public event Action<bool>? Loaded;
private void Load( string path ) private void Load(string path)
{ {
_tmpPath = null; _tmpPath = null;
if( path == Path ) if (path == Path)
{
return; return;
}
Path = path; Path = path;
Clean(); Clean();
if( path.Length == 0 ) if (path.Length == 0)
{
return; return;
}
try try
{ {
var _ = System.IO.Path.GetExtension( Path ).ToLowerInvariant() switch var _ = System.IO.Path.GetExtension(Path).ToLowerInvariant() switch
{ {
".dds" => LoadDds(), ".dds" => LoadDds(),
".png" => LoadPng(), ".png" => LoadPng(),
".tex" => LoadTex(), ".tex" => LoadTex(),
_ => throw new Exception( $"Extension {System.IO.Path.GetExtension( Path )} unknown." ), _ => throw new Exception($"Extension {System.IO.Path.GetExtension(Path)} unknown."),
}; };
Loaded?.Invoke( true ); Loaded?.Invoke(true);
} }
catch( Exception e ) catch (Exception e)
{ {
LoadError = e; LoadError = e;
Clean(); Clean();
@ -157,11 +153,11 @@ public sealed class Texture : IDisposable
private bool LoadDds() private bool LoadDds()
{ {
Type = FileType.Dds; Type = FileType.Dds;
var scratch = ScratchImage.LoadDDS( Path ); var scratch = ScratchImage.LoadDDS(Path);
BaseImage = scratch; BaseImage = scratch;
var rgba = scratch.GetRGBA( out var f ).ThrowIfError( f ); var rgba = scratch.GetRGBA(out var f).ThrowIfError(f);
RGBAPixels = rgba.Pixels[ ..( f.Meta.Width * f.Meta.Height * f.Meta.Format.BitsPerPixel() / 8 ) ].ToArray(); RGBAPixels = rgba.Pixels[..(f.Meta.Width * f.Meta.Height * f.Meta.Format.BitsPerPixel() / 8)].ToArray();
CreateTextureWrap( f.Meta.Width, f.Meta.Height ); CreateTextureWrap(f.Meta.Width, f.Meta.Height);
return true; return true;
} }
@ -169,11 +165,11 @@ public sealed class Texture : IDisposable
{ {
Type = FileType.Png; Type = FileType.Png;
BaseImage = null; BaseImage = null;
using var stream = File.OpenRead( Path ); using var stream = File.OpenRead(Path);
using var png = Image.Load< Rgba32 >( stream ); using var png = Image.Load<Rgba32>(stream);
RGBAPixels = new byte[png.Height * png.Width * 4]; RGBAPixels = new byte[png.Height * png.Width * 4];
png.CopyPixelDataTo( RGBAPixels ); png.CopyPixelDataTo(RGBAPixels);
CreateTextureWrap( png.Width, png.Height ); CreateTextureWrap(png.Width, png.Height);
return true; return true;
} }
@ -181,113 +177,100 @@ public sealed class Texture : IDisposable
{ {
Type = FileType.Tex; Type = FileType.Tex;
using var stream = OpenTexStream(); using var stream = OpenTexStream();
var scratch = TexFileParser.Parse( stream ); var scratch = TexFileParser.Parse(stream);
BaseImage = scratch; BaseImage = scratch;
var rgba = scratch.GetRGBA( out var f ).ThrowIfError( f ); var rgba = scratch.GetRGBA(out var f).ThrowIfError(f);
RGBAPixels = rgba.Pixels[ ..( f.Meta.Width * f.Meta.Height * f.Meta.Format.BitsPerPixel() / 8 ) ].ToArray(); RGBAPixels = rgba.Pixels[..(f.Meta.Width * f.Meta.Height * f.Meta.Format.BitsPerPixel() / 8)].ToArray();
CreateTextureWrap( scratch.Meta.Width, scratch.Meta.Height ); CreateTextureWrap(scratch.Meta.Width, scratch.Meta.Height);
return true; return true;
} }
private Stream OpenTexStream() private Stream OpenTexStream()
{ {
if( System.IO.Path.IsPathRooted( Path ) ) if (System.IO.Path.IsPathRooted(Path))
{ return File.OpenRead(Path);
return File.OpenRead( Path );
}
var file = DalamudServices.SGameData.GetFile( Path ); var file = DalamudServices.SGameData.GetFile(Path);
return file != null ? new MemoryStream( file.Data ) : throw new Exception( $"Unable to obtain \"{Path}\" from game files." ); return file != null ? new MemoryStream(file.Data) : throw new Exception($"Unable to obtain \"{Path}\" from game files.");
} }
private void CreateTextureWrap( int width, int height ) private void CreateTextureWrap(int width, int height)
=> TextureWrap = DalamudServices.PluginInterface.UiBuilder.LoadImageRaw( RGBAPixels, width, height, 4 ); => TextureWrap = DalamudServices.PluginInterface.UiBuilder.LoadImageRaw(RGBAPixels, width, height, 4);
private string? _tmpPath; private string? _tmpPath;
public void PathSelectBox( string label, string tooltip, IEnumerable< (string, bool) > paths, int skipPrefix ) public void PathSelectBox(string label, string tooltip, IEnumerable<(string, bool)> paths, int skipPrefix)
{ {
ImGui.SetNextItemWidth( -0.0001f ); ImGui.SetNextItemWidth(-0.0001f);
var startPath = Path.Length > 0 ? Path : "Choose a modded texture from this mod here..."; var startPath = Path.Length > 0 ? Path : "Choose a modded texture from this mod here...";
using var combo = ImRaii.Combo( label, startPath ); using var combo = ImRaii.Combo(label, startPath);
if( combo ) if (combo)
{ foreach (var ((path, game), idx) in paths.WithIndex())
foreach( var ((path, game), idx) in paths.WithIndex() )
{ {
if( game ) if (game)
{ {
if( !DalamudServices.SGameData.FileExists( path ) ) if (!DalamudServices.SGameData.FileExists(path))
{
continue; continue;
}
} }
else if( !File.Exists( path ) ) else if (!File.Exists(path))
{ {
continue; continue;
} }
using var id = ImRaii.PushId( idx ); 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.. ]; var p = game ? $"--> {path}" : path[skipPrefix..];
if( ImGui.Selectable( p, path == startPath ) && path != startPath ) if (ImGui.Selectable(p, path == startPath) && path != startPath)
{ Load(path);
Load( path );
}
} }
ImGuiUtil.HoverTooltip( game ImGuiUtil.HoverTooltip(game
? "This is a game path and refers to an unmanipulated file from your game data." ? "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." ); : "This is a path to a modded file on your file system.");
} }
}
ImGuiUtil.HoverTooltip( tooltip ); 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; _tmpPath ??= Path;
using var spacing = ImRaii.PushStyle( ImGuiStyleVar.ItemSpacing, using var spacing = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing,
new Vector2( UiHelpers.ScaleX3, ImGui.GetStyle().ItemSpacing.Y ) ); new Vector2(UiHelpers.ScaleX3, ImGui.GetStyle().ItemSpacing.Y));
ImGui.SetNextItemWidth( -2 * ImGui.GetFrameHeight() - 7 * UiHelpers.Scale ); ImGui.SetNextItemWidth(-2 * ImGui.GetFrameHeight() - 7 * UiHelpers.Scale);
ImGui.InputTextWithHint( label, hint, ref _tmpPath, Utf8GamePath.MaxGamePathLength ); ImGui.InputTextWithHint(label, hint, ref _tmpPath, Utf8GamePath.MaxGamePathLength);
if( ImGui.IsItemDeactivatedAfterEdit() ) if (ImGui.IsItemDeactivatedAfterEdit())
{ Load(_tmpPath);
Load( _tmpPath );
}
ImGuiUtil.HoverTooltip( tooltip ); ImGuiUtil.HoverTooltip(tooltip);
ImGui.SameLine(); ImGui.SameLine();
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Folder.ToIconString(), new Vector2( ImGui.GetFrameHeight() ), string.Empty, false, if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Folder.ToIconString(), new Vector2(ImGui.GetFrameHeight()), string.Empty, false,
true ) ) true))
{ {
if( Penumbra.Config.DefaultModImportPath.Length > 0 ) if (defaultModImportPath.Length > 0)
{ startPath = defaultModImportPath;
startPath = Penumbra.Config.DefaultModImportPath;
}
var texture = this; var texture = this;
void UpdatePath( bool success, List< string > paths ) void UpdatePath(bool success, List<string> paths)
{ {
if( success && paths.Count > 0 ) if (success && paths.Count > 0)
{ texture.Load(paths[0]);
texture.Load( paths[ 0 ] );
}
} }
fileDialog.OpenFilePicker( "Open Image...", "Textures{.png,.dds,.tex}", UpdatePath, 1, startPath, false ); fileDialog.OpenFilePicker("Open Image...", "Textures{.png,.dds,.tex}", UpdatePath, 1, startPath, false);
} }
ImGui.SameLine(); ImGui.SameLine();
if( ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.Recycle.ToIconString(), new Vector2( ImGui.GetFrameHeight() ), if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Recycle.ToIconString(), new Vector2(ImGui.GetFrameHeight()),
"Reload the currently selected path.", false, "Reload the currently selected path.", false,
true ) ) true))
{ {
var path = Path; var path = Path;
Path = string.Empty; Path = string.Empty;
Load( path ); Load(path);
} }
} }
} }

View file

@ -1,14 +1,18 @@
using System; using System;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Memory; using FFXIVClientStructs.FFXIV.Client.System.Memory;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.Collections.Cache;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.Import;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Interop.Structs; using Penumbra.Interop.Structs;
using Penumbra.Meta.Files; using Penumbra.Meta.Files;
using Penumbra.Mods;
using Penumbra.Services; using Penumbra.Services;
using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager; using ResidentResourceManager = Penumbra.Interop.Services.ResidentResourceManager;
@ -37,6 +41,33 @@ public unsafe class MetaFileManager
SignatureHelper.Initialise(this); 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)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void SetFile(MetaBaseFile? file, MetaIndex metaIndex) public void SetFile(MetaBaseFile? file, MetaIndex metaIndex)
{ {

View file

@ -13,5 +13,8 @@ public interface IMod
public ISubMod Default { get; } public ISubMod Default { get; }
public IReadOnlyList< IModGroup > Groups { get; } public IReadOnlyList< IModGroup > Groups { get; }
public IEnumerable< SubMod > AllSubMods { get; } public IEnumerable< SubMod > AllSubMods { get; }
// Cache
public int TotalManipulations { get; }
} }

View file

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

View file

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

View file

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using OtterGui; using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using Penumbra.Collections.Cache;
using Penumbra.Import; using Penumbra.Import;
using Penumbra.Meta; using Penumbra.Meta;
using Penumbra.String.Classes; using Penumbra.String.Classes;
@ -21,8 +22,10 @@ public sealed partial class Mod : IMod
// Main Data // Main Data
public DirectoryInfo ModPath { get; internal set; } public DirectoryInfo ModPath { get; internal set; }
public string Identifier public string Identifier
=> Index >= 0 ? ModPath.Name : Name; => Index >= 0 ? ModPath.Name : Name;
public int Index { get; internal set; } = -1; public int Index { get; internal set; } = -1;
public bool IsTemporary public bool IsTemporary
@ -32,12 +35,15 @@ public sealed partial class Mod : IMod
public int Priority public int Priority
=> 0; => 0;
public Mod(DirectoryInfo modPath) internal Mod(DirectoryInfo modPath)
{ {
ModPath = modPath; ModPath = modPath;
Default = new SubMod(this); Default = new SubMod(this);
} }
public override string ToString()
=> Name.Text;
// Meta Data // Meta Data
public LowerString Name { get; internal set; } = "New Mod"; public LowerString Name { get; internal set; } = "New Mod";
public LowerString Author { get; internal set; } = LowerString.Empty; public LowerString Author { get; internal set; } = LowerString.Empty;
@ -80,35 +86,14 @@ public sealed partial class Mod : IMod
.ToList(); .ToList();
} }
// Access // Cache
public override string ToString() public readonly IReadOnlyDictionary<string, object?> ChangedItems = new SortedList<string, object?>();
=> Name.Text;
public void WriteAllTexToolsMeta(MetaFileManager manager) public string LowerChangedItemsString { get; internal set; } = string.Empty;
{ public string AllTagsLower { get; internal set; } = string.Empty;
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 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 Logger Log { get; private set; } = null!;
public static ChatService ChatService { 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 CharacterUtility CharacterUtility { get; private set; } = null!;
public static ModCacheManager ModCaches { get; private set; } = null!;
public static CollectionManager CollectionManager { get; private set; } = null!; public static CollectionManager CollectionManager { get; private set; } = null!;
public static ActorManager Actors { 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 TempModManager _tempMods;
private readonly TempCollectionManager _tempCollections; private readonly TempCollectionManager _tempCollections;
private readonly ModManager _modManager; private readonly ModManager _modManager;
private readonly Configuration _config;
private PenumbraWindowSystem? _windowSystem; private PenumbraWindowSystem? _windowSystem;
private bool _disposed; private bool _disposed;
@ -67,7 +66,7 @@ public class Penumbra : IDalamudPlugin
ChatService = _tmp.Services.GetRequiredService<ChatService>(); ChatService = _tmp.Services.GetRequiredService<ChatService>();
_validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>(); _validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>();
_tmp.Services.GetRequiredService<BackupService>(); _tmp.Services.GetRequiredService<BackupService>();
Config = _tmp.Services.GetRequiredService<Configuration>(); _config = _tmp.Services.GetRequiredService<Configuration>();
CharacterUtility = _tmp.Services.GetRequiredService<CharacterUtility>(); CharacterUtility = _tmp.Services.GetRequiredService<CharacterUtility>();
Actors = _tmp.Services.GetRequiredService<ActorService>().AwaitedService; Actors = _tmp.Services.GetRequiredService<ActorService>().AwaitedService;
_tempMods = _tmp.Services.GetRequiredService<TempModManager>(); _tempMods = _tmp.Services.GetRequiredService<TempModManager>();
@ -78,8 +77,8 @@ public class Penumbra : IDalamudPlugin
_tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>(); _tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>();
ModFileSystem = _tmp.Services.GetRequiredService<ModFileSystem>(); ModFileSystem = _tmp.Services.GetRequiredService<ModFileSystem>();
RedrawService = _tmp.Services.GetRequiredService<RedrawService>(); RedrawService = _tmp.Services.GetRequiredService<RedrawService>();
_tmp.Services.GetRequiredService<ResourceService>(); _tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else.
ModCaches = _tmp.Services.GetRequiredService<ModCacheManager>(); _tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else.
using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver)) using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver))
{ {
_tmp.Services.GetRequiredService<PathResolver>(); _tmp.Services.GetRequiredService<PathResolver>();
@ -146,10 +145,10 @@ public class Penumbra : IDalamudPlugin
public bool SetEnabled(bool enabled) public bool SetEnabled(bool enabled)
{ {
if (enabled == Config.EnableMods) if (enabled == _config.EnableMods)
return false; return false;
Config.EnableMods = enabled; _config.EnableMods = enabled;
if (enabled) if (enabled)
{ {
if (CharacterUtility.Ready) if (CharacterUtility.Ready)
@ -169,7 +168,7 @@ public class Penumbra : IDalamudPlugin
} }
} }
Config.Save(); _config.Save();
EnabledChange?.Invoke(enabled); EnabledChange?.Invoke(enabled);
return true; return true;
@ -190,33 +189,33 @@ public class Penumbra : IDalamudPlugin
public string GatherSupportInformation() public string GatherSupportInformation()
{ {
var sb = new StringBuilder(10240); var sb = new StringBuilder(10240);
var exists = Config.ModDirectory.Length > 0 && Directory.Exists(Config.ModDirectory); var exists = _config.ModDirectory.Length > 0 && Directory.Exists(_config.ModDirectory);
var drive = exists ? new DriveInfo(new DirectoryInfo(Config.ModDirectory).Root.FullName) : null; var drive = exists ? new DriveInfo(new DirectoryInfo(_config.ModDirectory).Root.FullName) : null;
sb.AppendLine("**Settings**"); sb.AppendLine("**Settings**");
sb.Append($"> **`Plugin Version: `** {_validityChecker.Version}\n"); sb.Append($"> **`Plugin Version: `** {_validityChecker.Version}\n");
sb.Append($"> **`Commit Hash: `** {_validityChecker.CommitHash}\n"); sb.Append($"> **`Commit Hash: `** {_validityChecker.CommitHash}\n");
sb.Append($"> **`Enable Mods: `** {Config.EnableMods}\n"); sb.Append($"> **`Enable Mods: `** {_config.EnableMods}\n");
sb.Append($"> **`Enable HTTP API: `** {Config.EnableHttpApi}\n"); sb.Append($"> **`Enable HTTP API: `** {_config.EnableHttpApi}\n");
sb.Append($"> **`Operating System: `** {(DalamudUtil.IsLinux() ? "Mac/Linux (Wine)" : "Windows")}\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( sb.Append(
$"> **`Free Drive Space: `** {(drive != null ? Functions.HumanReadableSize(drive.AvailableFreeSpace) : "Unknown")}\n"); $"> **`Free Drive Space: `** {(drive != null ? Functions.HumanReadableSize(drive.AvailableFreeSpace) : "Unknown")}\n");
sb.Append($"> **`Auto-Deduplication: `** {Config.AutoDeduplicateOnImport}\n"); sb.Append($"> **`Auto-Deduplication: `** {_config.AutoDeduplicateOnImport}\n");
sb.Append($"> **`Debug Mode: `** {Config.DebugMode}\n"); sb.Append($"> **`Debug Mode: `** {_config.DebugMode}\n");
sb.Append( sb.Append(
$"> **`Synchronous Load (Dalamud): `** {(_tmp.Services.GetRequiredService<DalamudServices>().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")}\n"); $"> **`Synchronous Load (Dalamud): `** {(_tmp.Services.GetRequiredService<DalamudServices>().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")}\n");
sb.Append( sb.Append(
$"> **`Logging: `** Log: {Config.EnableResourceLogging}, Watcher: {Config.EnableResourceWatcher} ({Config.MaxResourceWatcherRecords})\n"); $"> **`Logging: `** Log: {_config.EnableResourceLogging}, Watcher: {_config.EnableResourceWatcher} ({_config.MaxResourceWatcherRecords})\n");
sb.Append($"> **`Use Ownership: `** {Config.UseOwnerNameForCharacterCollection}\n"); sb.Append($"> **`Use Ownership: `** {_config.UseOwnerNameForCharacterCollection}\n");
sb.AppendLine("**Mods**"); sb.AppendLine("**Mods**");
sb.Append($"> **`Installed Mods: `** {_modManager.Count}\n"); 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( 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( 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( 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($"> **`IMC Exceptions Thrown: `** {_validityChecker.ImcExceptions.Count}\n");
sb.Append( sb.Append(
$"> **`#Temp Mods: `** {_tempMods.Mods.Sum(kvp => kvp.Value.Count) + _tempMods.ModsForAllCollections.Count}\n"); $"> **`#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(); ImGui.TableNextColumn();
UiHelpers.Text(gamePath.Path); UiHelpers.Text(gamePath.Path);
ImGui.TableNextColumn(); 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); ImGui.TextUnformatted(option.FullName);
} }
} }
@ -294,7 +294,7 @@ public class FileEditor<T> where T : class, IWritable
if (file.SubModUsage.Count > 0) if (file.SubModUsage.Count > 0)
{ {
ImGui.SameLine(); 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()); ImGuiUtil.RightAlign(file.SubModUsage[0].Item2.Path.ToString());
} }

View file

@ -82,7 +82,7 @@ public partial class ModEditWindow
return f.SubModUsage.Count == 0 return f.SubModUsage.Count == 0
? Enumerable.Repeat((file, "Unused", string.Empty, 0x40000080u), 1) ? Enumerable.Repeat((file, "Unused", string.Empty, 0x40000080u), 1)
: f.SubModUsage.Select(s => (file, s.Item2.ToString(), s.Item1.FullName, : 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) void DrawLine((string, string, string, uint) data)
@ -179,7 +179,7 @@ public partial class ModEditWindow
var selected = _selectedFiles.Contains(registry); var selected = _selectedFiles.Contains(registry);
var color = registry.SubModUsage.Count == 0 ? ColorId.ConflictingMod : var color = registry.SubModUsage.Count == 0 ? ColorId.ConflictingMod :
registry.CurrentUsage == registry.SubModUsage.Count ? ColorId.NewMod : ColorId.InheritedMod; 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 (UiHelpers.Selectable(registry.RelPath.Path, selected))
{ {
if (selected) if (selected)

View file

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

View file

@ -42,7 +42,7 @@ public partial class ModEditWindow
ImGui.NewLine(); ImGui.NewLine();
tex.PathInputBox("##input", "Import Image...", "Can import game paths as well as your own files.", _mod!.ModPath.FullName, 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)) var files = _editor.Files.Tex.SelectMany(f => f.SubModUsage.Select(p => (p.Item2.ToString(), true))
.Prepend((f.File.FullName, false))); .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.", 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 PerformanceTracker _performance;
private readonly ModEditor _editor; private readonly ModEditor _editor;
private readonly ModCacheManager _modCaches;
private readonly Configuration _config; private readonly Configuration _config;
private readonly ItemSwapTab _itemSwapTab; private readonly ItemSwapTab _itemSwapTab;
private readonly DataManager _gameData; private readonly DataManager _gameData;
@ -277,7 +276,7 @@ public partial class ModEditWindow : Window, IDisposable
var modifier = _config.DeleteModModifier.IsActive(); var modifier = _config.DeleteModModifier.IsActive();
var tt = _allowReduplicate ? desc : 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)) if (ImGuiUtil.DrawDisabledButton("Re-Duplicate and Normalize Mod", Vector2.Zero, tt, !_allowReduplicate && !modifier))
{ {
@ -497,25 +496,26 @@ public partial class ModEditWindow : Window, IDisposable
} }
public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, DataManager gameData, 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) : base(WindowBaseLabel)
{ {
_performance = performance; _performance = performance;
_itemSwapTab = itemSwapTab; _itemSwapTab = itemSwapTab;
_config = config; _config = config;
_editor = editor; _editor = editor;
_modCaches = modCaches; _metaFileManager = metaFileManager;
_metaFileManager = metaFileManager; _stainService = stainService;
_stainService = stainService; _gameData = gameData;
_gameData = gameData; _fileDialog = fileDialog;
_fileDialog = fileDialog;
_materialTab = new FileEditor<MtrlTab>(this, gameData, config, _fileDialog, "Materials", ".mtrl", _materialTab = new FileEditor<MtrlTab>(this, gameData, config, _fileDialog, "Materials", ".mtrl",
() => _editor.Files.Mtrl, DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty, () => _editor.Files.Mtrl, DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty,
bytes => new MtrlTab(this, new MtrlFile(bytes))); bytes => new MtrlTab(this, new MtrlFile(bytes)));
_modelTab = new FileEditor<MdlFile>(this, gameData, config, _fileDialog, "Models", ".mdl", _modelTab = new FileEditor<MdlFile>(this, gameData, config, _fileDialog, "Models", ".mdl",
() => _editor.Files.Mdl, DrawModelPanel, () => _mod?.ModPath.FullName ?? string.Empty, bytes => new MdlFile(bytes)); () => _editor.Files.Mdl, DrawModelPanel, () => _mod?.ModPath.FullName ?? string.Empty, bytes => new MdlFile(bytes));
_shaderPackageTab = new FileEditor<ShpkTab>(this, gameData, config, _fileDialog, "Shader Packages", ".shpk", _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); _center = new CombinedTexture(_left, _right);
_quickImportViewer = new ResourceTreeViewer(_config, resourceTreeFactory, 2, OnQuickImportRefresh, DrawQuickImportActions); _quickImportViewer = new ResourceTreeViewer(_config, resourceTreeFactory, 2, OnQuickImportRefresh, DrawQuickImportActions);
} }

View file

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

View file

@ -75,7 +75,7 @@ public sealed class CollectionSelector : ItemSelector<ModCollection>, IDisposabl
protected override bool OnDraw(int idx) 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); var ret = ImGui.Selectable(Name(Items[idx]), idx == CurrentIdx);
using var source = ImRaii.DragDropSource(); using var source = ImRaii.DragDropSource();

View file

@ -17,15 +17,13 @@ public class InheritanceUi
private const int InheritedCollectionHeight = 9; private const int InheritedCollectionHeight = 9;
private const string InheritanceDragDropLabel = "##InheritanceMove"; private const string InheritanceDragDropLabel = "##InheritanceMove";
private readonly Configuration _config;
private readonly CollectionStorage _collections; private readonly CollectionStorage _collections;
private readonly ActiveCollections _active; private readonly ActiveCollections _active;
private readonly InheritanceManager _inheritance; private readonly InheritanceManager _inheritance;
private readonly CollectionSelector _selector; private readonly CollectionSelector _selector;
public InheritanceUi(Configuration config, CollectionManager collectionManager, CollectionSelector selector) public InheritanceUi(CollectionManager collectionManager, CollectionSelector selector)
{ {
_config = config;
_selector = selector; _selector = selector;
_collections = collectionManager.Storage; _collections = collectionManager.Storage;
_active = collectionManager.Active; _active = collectionManager.Active;
@ -37,7 +35,7 @@ public class InheritanceUi
public void Draw() public void Draw()
{ {
using var id = ImRaii.PushId("##Inheritance"); 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); ImGui.Dummy(Vector2.One);
DrawCurrentCollectionInheritance(); DrawCurrentCollectionInheritance();
@ -124,7 +122,7 @@ public class InheritanceUi
foreach (var inheritance in collection.GetFlattenedInheritance().Skip(1)) foreach (var inheritance in collection.GetFlattenedInheritance().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(Penumbra.Config), using var color = ImRaii.PushColor(ImGuiCol.Text, ColorId.HandledConflictMod.Value(),
_seenInheritedCollections.Contains(inheritance)); _seenInheritedCollections.Contains(inheritance));
_seenInheritedCollections.Add(inheritance); _seenInheritedCollections.Add(inheritance);
@ -150,7 +148,7 @@ public class InheritanceUi
/// <summary> Draw a single primary inherited collection. </summary> /// <summary> Draw a single primary inherited collection. </summary>
private void DrawInheritance(ModCollection collection) 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.Contains(collection));
_seenInheritedCollections.Add(collection); _seenInheritedCollections.Add(collection);
using var tree = ImRaii.TreeNode($"{Name(collection)}###{collection.Name}", ImGuiTreeNodeFlags.NoTreePushOnOpen); 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 Configuration _config;
private readonly FileDialogService _fileDialog; private readonly FileDialogService _fileDialog;
private readonly ModManager _modManager; private readonly ModManager _modManager;
private readonly ModCacheManager _modCaches;
private readonly CollectionManager _collectionManager; private readonly CollectionManager _collectionManager;
private readonly TutorialService _tutorial; private readonly TutorialService _tutorial;
private readonly ModImportManager _modImportManager; private readonly ModImportManager _modImportManager;
@ -37,7 +36,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
public ModFileSystemSelector(CommunicatorService communicator, ModFileSystem fileSystem, ModManager modManager, public ModFileSystemSelector(CommunicatorService communicator, ModFileSystem fileSystem, ModManager modManager,
CollectionManager collectionManager, Configuration config, TutorialService tutorial, FileDialogService fileDialog, ChatService chat, CollectionManager collectionManager, Configuration config, TutorialService tutorial, FileDialogService fileDialog, ChatService chat,
ModCacheManager modCaches, ModImportManager modImportManager) ModImportManager modImportManager)
: base(fileSystem, DalamudServices.KeyState, HandleException) : base(fileSystem, DalamudServices.KeyState, HandleException)
{ {
_communicator = communicator; _communicator = communicator;
@ -47,7 +46,6 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
_tutorial = tutorial; _tutorial = tutorial;
_fileDialog = fileDialog; _fileDialog = fileDialog;
_chat = chat; _chat = chat;
_modCaches = modCaches;
_modImportManager = modImportManager; _modImportManager = modImportManager;
// @formatter:off // @formatter:off
@ -73,7 +71,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
SetFilterTooltip(); SetFilterTooltip();
SelectionChanged += OnSelectionChange; SelectionChanged += OnSelectionChange;
_communicator.CollectionChange.Subscribe(OnCollectionChange); _communicator.CollectionChange.Subscribe(OnCollectionChange);
_communicator.ModSettingChanged.Subscribe(OnSettingChange); _communicator.ModSettingChanged.Subscribe(OnSettingChange);
_communicator.CollectionInheritanceChanged.Subscribe(OnInheritanceChange); _communicator.CollectionInheritanceChanged.Subscribe(OnInheritanceChange);
_communicator.ModDataChanged.Subscribe(OnModDataChange); _communicator.ModDataChanged.Subscribe(OnModDataChange);
@ -103,13 +101,13 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
=> _config.SortMode; => _config.SortMode;
protected override uint ExpandedFolderColor protected override uint ExpandedFolderColor
=> ColorId.FolderExpanded.Value(_config); => ColorId.FolderExpanded.Value();
protected override uint CollapsedFolderColor protected override uint CollapsedFolderColor
=> ColorId.FolderCollapsed.Value(_config); => ColorId.FolderCollapsed.Value();
protected override uint FolderLineColor protected override uint FolderLineColor
=> ColorId.FolderLine.Value(_config); => ColorId.FolderLine.Value();
protected override bool FoldersDefaultOpen protected override bool FoldersDefaultOpen
=> _config.OpenFoldersByDefault; => _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) protected override void DrawLeafName(FileSystem<Mod>.Leaf leaf, in ModState state, bool selected)
{ {
var flags = selected ? ImGuiTreeNodeFlags.Selected | LeafFlags : LeafFlags; 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); .Push(ImGuiCol.HeaderHovered, 0x4000FFFF, leaf.Value.Favorite);
using var id = ImRaii.PushId(leaf.Value.Index); using var id = ImRaii.PushId(leaf.Value.Index);
ImRaii.TreeNode(leaf.Value.Name, flags).Dispose(); ImRaii.TreeNode(leaf.Value.Name, flags).Dispose();
@ -285,7 +283,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
if (leaf == null) if (leaf == null)
throw new Exception("Mod was not found at root."); 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); FileSystem.Move(leaf, folder);
} }
catch (Exception e) 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("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:"); ImGui.BulletText("Names are colored according to your config and their current state in the collection:");
indent.Push(); indent.Push();
ImGuiUtil.BulletTextColored(ColorId.EnabledMod.Value(_config), "enabled in the current collection."); ImGuiUtil.BulletTextColored(ColorId.EnabledMod.Value(), "enabled in the current collection.");
ImGuiUtil.BulletTextColored(ColorId.DisabledMod.Value(_config), "disabled in the current collection."); ImGuiUtil.BulletTextColored(ColorId.DisabledMod.Value(), "disabled in the current collection.");
ImGuiUtil.BulletTextColored(ColorId.InheritedMod.Value(_config), "enabled due to inheritance from another collection."); ImGuiUtil.BulletTextColored(ColorId.InheritedMod.Value(), "enabled due to inheritance from another collection.");
ImGuiUtil.BulletTextColored(ColorId.InheritedDisabledMod.Value(_config), "disabled due to inheritance from another collection."); ImGuiUtil.BulletTextColored(ColorId.InheritedDisabledMod.Value(), "disabled due to inheritance from another collection.");
ImGuiUtil.BulletTextColored(ColorId.UndefinedMod.Value(_config), "unconfigured in all inherited collections."); ImGuiUtil.BulletTextColored(ColorId.UndefinedMod.Value(), "unconfigured in all inherited collections.");
ImGuiUtil.BulletTextColored(ColorId.NewMod.Value(_config), ImGuiUtil.BulletTextColored(ColorId.NewMod.Value(),
"newly imported during this session. Will go away when first enabling a mod or when Penumbra is reloaded."); "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)."); "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."); "enabled and conflicting with another enabled Mod on the same priority.");
ImGuiUtil.BulletTextColored(ColorId.FolderExpanded.Value(_config), "expanded mod folder."); ImGuiUtil.BulletTextColored(ColorId.FolderExpanded.Value(), "expanded mod folder.");
ImGuiUtil.BulletTextColored(ColorId.FolderCollapsed.Value(_config), "collapsed mod folder"); ImGuiUtil.BulletTextColored(ColorId.FolderCollapsed.Value(), "collapsed mod folder");
indent.Pop(1); 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."); ImGui.BulletText("Right-click a mod to enter its sort order, which is its name by default, possibly with a duplicate number.");
indent.Push(); indent.Push();
@ -359,7 +357,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
private void OnSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, int oldValue, int groupIdx, bool inherited) private void OnSettingChange(ModCollection collection, ModSettingChange type, Mod? mod, int oldValue, int groupIdx, bool inherited)
{ {
if (collection != _collectionManager.Active.Current) if (collection != _collectionManager.Active.Current)
return; return;
SetFilterDirty(); SetFilterDirty();
if (mod == Selected) if (mod == Selected)
@ -383,7 +381,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
private void OnInheritanceChange(ModCollection collection, bool _) private void OnInheritanceChange(ModCollection collection, bool _)
{ {
if (collection != _collectionManager.Active.Current) if (collection != _collectionManager.Active.Current)
return; return;
SetFilterDirty(); SetFilterDirty();
OnSelectionChange(Selected, Selected, default); OnSelectionChange(Selected, Selected, default);
@ -524,8 +522,8 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
0 => !(leaf.FullName().Contains(_modFilter.Lower, IgnoreCase) || mod.Name.Contains(_modFilter)), 0 => !(leaf.FullName().Contains(_modFilter.Lower, IgnoreCase) || mod.Name.Contains(_modFilter)),
1 => !mod.Name.Contains(_modFilter), 1 => !mod.Name.Contains(_modFilter),
2 => !mod.Author.Contains(_modFilter), 2 => !mod.Author.Contains(_modFilter),
3 => !_modCaches[mod].LowerChangedItemsString.Contains(_modFilter.Lower), 3 => !mod.LowerChangedItemsString.Contains(_modFilter.Lower),
4 => !_modCaches[mod].AllTagsLower.Contains(_modFilter.Lower), 4 => !mod.AllTagsLower.Contains(_modFilter.Lower),
_ => false, // Should never happen _ => false, // Should never happen
}; };
} }
@ -554,13 +552,12 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
private bool CheckStateFilters(Mod mod, ModSettings? settings, ModCollection collection, ref ModState state) private bool CheckStateFilters(Mod mod, ModSettings? settings, ModCollection collection, ref ModState state)
{ {
var isNew = _modManager.IsNew(mod); var isNew = _modManager.IsNew(mod);
var cache = _modCaches[mod.Index];
// Handle mod details. // Handle mod details.
if (CheckFlags(cache.TotalFileCount, ModFilter.HasNoFiles, ModFilter.HasFiles) if (CheckFlags(mod.TotalFileCount, ModFilter.HasNoFiles, ModFilter.HasFiles)
|| CheckFlags(cache.TotalSwapCount, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps) || CheckFlags(mod.TotalSwapCount, ModFilter.HasNoFileSwaps, ModFilter.HasFileSwaps)
|| CheckFlags(cache.TotalManipulations, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations) || CheckFlags(mod.TotalManipulations, ModFilter.HasNoMetaManipulations, ModFilter.HasMetaManipulations)
|| CheckFlags(cache.HasOptions ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig) || CheckFlags(mod.HasOptions ? 1 : 0, ModFilter.HasNoConfig, ModFilter.HasConfig)
|| CheckFlags(isNew ? 1 : 0, ModFilter.NotNew, ModFilter.IsNew)) || CheckFlags(isNew ? 1 : 0, ModFilter.NotNew, ModFilter.IsNew))
return true; return true;
// Handle Favoritism // Handle Favoritism

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using ImGuiNET; using ImGuiNET;
using OtterGui; using OtterGui;
@ -14,20 +15,18 @@ public class ModPanelChangedItemsTab : ITab
{ {
private readonly ModFileSystemSelector _selector; private readonly ModFileSystemSelector _selector;
private readonly PenumbraApi _api; private readonly PenumbraApi _api;
private readonly ModCacheManager _modCaches;
public ReadOnlySpan<byte> Label public ReadOnlySpan<byte> Label
=> "Changed Items"u8; => "Changed Items"u8;
public ModPanelChangedItemsTab(PenumbraApi api, ModFileSystemSelector selector, ModCacheManager modCaches) public ModPanelChangedItemsTab(PenumbraApi api, ModFileSystemSelector selector)
{ {
_api = api; _api = api;
_selector = selector; _selector = selector;
_modCaches = modCaches;
} }
public bool IsVisible public bool IsVisible
=> _modCaches[_selector.Selected!].ChangedItems.Count > 0; => _selector.Selected!.ChangedItems.Count > 0;
public void DrawContent() public void DrawContent()
{ {
@ -35,7 +34,7 @@ public class ModPanelChangedItemsTab : ITab
if (!list) if (!list)
return; return;
var zipList = ZipList.FromSortedList(_modCaches[_selector.Selected!].ChangedItems); var zipList = ZipList.FromSortedList((SortedList<string, object?>)_selector.Selected!.ChangedItems);
var height = ImGui.GetTextLineHeight(); var height = ImGui.GetTextLineHeight();
ImGuiClip.ClippedDraw(zipList, kvp => UiHelpers.DrawChangedItem(_api, kvp.Item1, kvp.Item2, true), height); 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 System.Collections.Generic;
using Dalamud.Interface; using Dalamud.Interface;
using ImGuiNET; using ImGuiNET;
using Lumina.Data.Parsing.Layer;
using OtterGui; using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using OtterGui.Widgets; using OtterGui.Widgets;
@ -15,15 +14,13 @@ namespace Penumbra.UI.ModsTab;
public class ModPanelCollectionsTab : ITab public class ModPanelCollectionsTab : ITab
{ {
private readonly Configuration _config;
private readonly ModFileSystemSelector _selector; private readonly ModFileSystemSelector _selector;
private readonly CollectionStorage _collections; private readonly CollectionStorage _collections;
private readonly List<(ModCollection, ModCollection, uint, string)> _cache = new(); 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; _collections = storage;
_selector = selector; _selector = selector;
} }
@ -42,9 +39,8 @@ public class ModPanelCollectionsTab : ITab
else else
ImGui.TextUnformatted($"This Mod is directly configured in {direct} collections."); ImGui.TextUnformatted($"This Mod is directly configured in {direct} collections.");
if (inherited > 0) if (inherited > 0)
{ ImGui.TextUnformatted(
ImGui.TextUnformatted($"It is also implicitly used in {inherited} {(inherited == 1 ? "collection" : "collections")} through inheritance."); $"It is also implicitly used in {inherited} {(inherited == 1 ? "collection" : "collections")} through inheritance.");
}
ImGui.NewLine(); ImGui.NewLine();
ImGui.Separator(); ImGui.Separator();
@ -79,13 +75,13 @@ public class ModPanelCollectionsTab : ITab
private (int Direct, int Inherited) CountUsage(Mod mod) private (int Direct, int Inherited) CountUsage(Mod mod)
{ {
_cache.Clear(); _cache.Clear();
var undefined = ColorId.UndefinedMod.Value(_config); var undefined = ColorId.UndefinedMod.Value();
var enabled = ColorId.EnabledMod.Value(_config); var enabled = ColorId.EnabledMod.Value();
var inherited = ColorId.InheritedMod.Value(_config); var inherited = ColorId.InheritedMod.Value();
var disabled = ColorId.DisabledMod.Value(_config); var disabled = ColorId.DisabledMod.Value();
var disInherited = ColorId.InheritedDisabledMod.Value(_config); var disInherited = ColorId.InheritedDisabledMod.Value();
var directCount = 0; var directCount = 0;
var inheritedCount = 0; var inheritedCount = 0;
foreach (var collection in _collections) foreach (var collection in _collections)
{ {
var (settings, parent) = collection[mod.Index]; var (settings, parent) = collection[mod.Index];

View file

@ -43,7 +43,7 @@ public class ModPanelConflictsTab : ITab
ImGui.SameLine(); ImGui.SameLine();
using (var color = ImRaii.PushColor(ImGuiCol.Text, 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 var priority = conflict.Mod2.Index < 0
? conflict.Mod2.Priority ? conflict.Mod2.Priority

View file

@ -18,18 +18,18 @@ internal sealed class ResourceWatcherTable : Table<Record>
public ResourceWatcherTable(Configuration config, ICollection<Record> records) public ResourceWatcherTable(Configuration config, ICollection<Record> records)
: base("##records", : base("##records",
records, records,
new PathColumn { Label = "Path" }, new PathColumn { Label = "Path" },
new RecordTypeColumn(config) { Label = "Record" }, new RecordTypeColumn(config) { Label = "Record" },
new CollectionColumn { Label = "Collection" }, new CollectionColumn { Label = "Collection" },
new ObjectColumn { Label = "Game Object" }, new ObjectColumn { Label = "Game Object" },
new CustomLoadColumn { Label = "Custom" }, new CustomLoadColumn { Label = "Custom" },
new SynchronousLoadColumn { Label = "Sync" }, new SynchronousLoadColumn { Label = "Sync" },
new OriginalPathColumn { Label = "Original Path" }, new OriginalPathColumn { Label = "Original Path" },
new ResourceCategoryColumn { Label = "Category" }, new ResourceCategoryColumn(config) { Label = "Category" },
new ResourceTypeColumn { Label = "Type" }, new ResourceTypeColumn(config) { Label = "Type" },
new HandleColumn { Label = "Resource" }, new HandleColumn { Label = "Resource" },
new RefCountColumn { Label = "#Ref" }, new RefCountColumn { Label = "#Ref" },
new DateColumn { Label = "Time" } new DateColumn { Label = "Time" }
) )
{ } { }
@ -111,7 +111,7 @@ internal sealed class ResourceWatcherTable : Table<Record>
else else
_config.ResourceWatcherRecordTypes &= ~value; _config.ResourceWatcherRecordTypes &= ~value;
Penumbra.Config.Save(); _config.Save();
} }
public override void DrawColumn(Record item, int idx) 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> private sealed class ResourceCategoryColumn : ColumnFlags<ResourceCategoryFlag, Record>
{ {
public ResourceCategoryColumn() private readonly Configuration _config;
=> AllFlags = ResourceExtensions.AllResourceCategories;
public ResourceCategoryColumn(Configuration config)
{
_config = config;
AllFlags = ResourceExtensions.AllResourceCategories;
}
public override float Width public override float Width
=> 80 * UiHelpers.Scale; => 80 * UiHelpers.Scale;
@ -185,16 +190,16 @@ internal sealed class ResourceWatcherTable : Table<Record>
=> FilterValue.HasFlag(item.Category); => FilterValue.HasFlag(item.Category);
public override ResourceCategoryFlag FilterValue public override ResourceCategoryFlag FilterValue
=> Penumbra.Config.ResourceWatcherResourceCategories; => _config.ResourceWatcherResourceCategories;
protected override void SetValue(ResourceCategoryFlag value, bool enable) protected override void SetValue(ResourceCategoryFlag value, bool enable)
{ {
if (enable) if (enable)
Penumbra.Config.ResourceWatcherResourceCategories |= value; _config.ResourceWatcherResourceCategories |= value;
else else
Penumbra.Config.ResourceWatcherResourceCategories &= ~value; _config.ResourceWatcherResourceCategories &= ~value;
Penumbra.Config.Save(); _config.Save();
} }
public override void DrawColumn(Record item, int idx) 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> 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); AllFlags = Enum.GetValues<ResourceTypeFlag>().Aggregate((v, f) => v | f);
for (var i = 0; i < Names.Length; ++i) for (var i = 0; i < Names.Length; ++i)
Names[i] = Names[i].ToLowerInvariant(); Names[i] = Names[i].ToLowerInvariant();
@ -219,16 +227,16 @@ internal sealed class ResourceWatcherTable : Table<Record>
=> FilterValue.HasFlag(item.ResourceType); => FilterValue.HasFlag(item.ResourceType);
public override ResourceTypeFlag FilterValue public override ResourceTypeFlag FilterValue
=> Penumbra.Config.ResourceWatcherResourceTypes; => _config.ResourceWatcherResourceTypes;
protected override void SetValue(ResourceTypeFlag value, bool enable) protected override void SetValue(ResourceTypeFlag value, bool enable)
{ {
if (enable) if (enable)
Penumbra.Config.ResourceWatcherResourceTypes |= value; _config.ResourceWatcherResourceTypes |= value;
else else
Penumbra.Config.ResourceWatcherResourceTypes &= ~value; _config.ResourceWatcherResourceTypes &= ~value;
Penumbra.Config.Save(); _config.Save();
} }
public override void DrawColumn(Record item, int idx) 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)) if (!UiHelpers.GetChangedItemObject(item.Value.Item2, out var text))
return; 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); ImGuiUtil.RightAlign(text);
} }
} }

View file

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

View file

@ -111,7 +111,7 @@ public class ModsTab : ITab
private void DrawRedrawLine() private void DrawRedrawLine()
{ {
if (Penumbra.Config.HideRedrawBar) if (_config.HideRedrawBar)
{ {
_tutorial.SkipTutorial(BasicTutorialSteps.Redrawing); _tutorial.SkipTutorial(BasicTutorialSteps.Redrawing);
return; return;
@ -172,7 +172,7 @@ public class ModsTab : ITab
ImGui.SameLine(); ImGui.SameLine();
DrawInheritedCollectionButton(3 * buttonSize); DrawInheritedCollectionButton(3 * buttonSize);
ImGui.SameLine(); 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); _tutorial.OpenTutorial(BasicTutorialSteps.CollectionSelectors);

View file

@ -69,8 +69,8 @@ public class SettingsTab : ITab
return; return;
DrawEnabledBox(); DrawEnabledBox();
Checkbox("Lock Main Window", "Prevent the main window from being resized or moved.", Penumbra.Config.FixMainWindow, Checkbox("Lock Main Window", "Prevent the main window from being resized or moved.", _config.FixMainWindow,
v => Penumbra.Config.FixMainWindow = v); v => _config.FixMainWindow = v);
ImGui.NewLine(); ImGui.NewLine();
DrawRootFolder(); DrawRootFolder();
@ -220,7 +220,7 @@ public class SettingsTab : ITab
if (_config.ModDirectory != _newModDirectory if (_config.ModDirectory != _newModDirectory
&& _newModDirectory.Length != 0 && _newModDirectory.Length != 0
&& DrawPressEnterWarning(_newModDirectory, Penumbra.Config.ModDirectory, pos, save, selected)) && DrawPressEnterWarning(_newModDirectory, _config.ModDirectory, pos, save, selected))
_modManager.DiscoverMods(_newModDirectory); _modManager.DiscoverMods(_newModDirectory);
} }
@ -344,14 +344,14 @@ public class SettingsTab : ITab
_dalamud.UiBuilder.DisableUserUiHide = !v; _dalamud.UiBuilder.DisableUserUiHide = !v;
}); });
Checkbox("Hide Config Window when in Cutscenes", 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 => v =>
{ {
_config.HideUiInCutscenes = v; _config.HideUiInCutscenes = v;
_dalamud.UiBuilder.DisableCutsceneUiHide = !v; _dalamud.UiBuilder.DisableCutsceneUiHide = !v;
}); });
Checkbox("Hide Config Window when in GPose", 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 => v =>
{ {
_config.HideUiInGPose = v; _config.HideUiInGPose = v;
@ -481,7 +481,7 @@ public class SettingsTab : ITab
Widget.DoubleModifierSelector("Mod Deletion Modifier", 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, "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 => v =>
{ {
_config.DeleteModModifier = v; _config.DeleteModModifier = v;
@ -742,8 +742,8 @@ public class SettingsTab : ITab
ImGui.SetCursorPos(new Vector2(xPos, 3 * ImGui.GetFrameHeightWithSpacing())); ImGui.SetCursorPos(new Vector2(xPos, 3 * ImGui.GetFrameHeightWithSpacing()));
if (ImGui.Button("Restart Tutorial", new Vector2(width, 0))) if (ImGui.Button("Restart Tutorial", new Vector2(width, 0)))
{ {
Penumbra.Config.TutorialStep = 0; _config.TutorialStep = 0;
Penumbra.Config.Save(); _config.Save();
} }
ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing())); ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing()));

View file

@ -86,7 +86,7 @@ public static class UiHelpers
return; return;
ImGui.SameLine(ImGui.GetContentRegionAvail().X); 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> /// <summary> Return more detailed object information in text, if it exists. </summary>