Add EphemeralConfig.

This commit is contained in:
Ottermandias 2023-11-17 16:51:09 +01:00
parent dc1c8f42c0
commit ea65296ab7
17 changed files with 264 additions and 125 deletions

View file

@ -184,8 +184,8 @@ public class CommandHandler : IDisposable
private bool SetUiLockState(string arguments) private bool SetUiLockState(string arguments)
{ {
var value = ParseTrueFalseToggle(arguments) ?? !_config.FixMainWindow; var value = ParseTrueFalseToggle(arguments) ?? !_config.Ephemeral.FixMainWindow;
if (value == _config.FixMainWindow) if (value == _config.Ephemeral.FixMainWindow)
return false; return false;
if (value) if (value)
@ -199,8 +199,8 @@ public class CommandHandler : IDisposable
_configWindow.Flags &= ~(ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize); _configWindow.Flags &= ~(ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize);
} }
_config.FixMainWindow = value; _config.Ephemeral.FixMainWindow = value;
_config.Save(); _config.Ephemeral.Save();
return true; return true;
} }

View file

@ -5,17 +5,13 @@ using OtterGui;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Filesystem; using OtterGui.Filesystem;
using OtterGui.Widgets; using OtterGui.Widgets;
using Penumbra.Api.Enums;
using Penumbra.Enums;
using Penumbra.Import.Structs; using Penumbra.Import.Structs;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.Services; using Penumbra.Services;
using Penumbra.UI;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using Penumbra.UI.ResourceWatcher; using Penumbra.UI.ResourceWatcher;
using Penumbra.UI.Tabs;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
namespace Penumbra; namespace Penumbra;
@ -26,9 +22,11 @@ public class Configuration : IPluginConfiguration, ISavable
[JsonIgnore] [JsonIgnore]
private readonly SaveService _saveService; private readonly SaveService _saveService;
[JsonIgnore]
public readonly EphemeralConfig Ephemeral;
public int Version { get; set; } = Constants.CurrentVersion; public int Version { get; set; } = Constants.CurrentVersion;
public int LastSeenVersion { get; set; } = PenumbraChangelog.LastChangelogVersion;
public ChangeLogDisplayType ChangeLogDisplayType { get; set; } = ChangeLogDisplayType.New; public ChangeLogDisplayType ChangeLogDisplayType { get; set; } = ChangeLogDisplayType.New;
public bool EnableMods { get; set; } = true; public bool EnableMods { get; set; } = true;
@ -53,52 +51,33 @@ public class Configuration : IPluginConfiguration, ISavable
public bool HideRedrawBar { get; set; } = false; public bool HideRedrawBar { get; set; } = false;
public int OptionGroupCollapsibleMin { get; set; } = 5; public int OptionGroupCollapsibleMin { get; set; } = 5;
public bool DebugSeparateWindow = false; public Vector2 MinimumSize = new(Constants.MinimumSizeX, Constants.MinimumSizeY);
public Vector2 MinimumSize = new(Constants.MinimumSizeX, Constants.MinimumSizeY);
#if DEBUG #if DEBUG
public bool DebugMode { get; set; } = true; public bool DebugMode { get; set; } = true;
#else #else
public bool DebugMode { get; set; } = false; public bool DebugMode { get; set; } = false;
#endif #endif
public int MaxResourceWatcherRecords { get; set; } = ResourceWatcher.DefaultMaxEntries;
public int TutorialStep { get; set; } = 0;
public bool EnableResourceLogging { get; set; } = false;
public string ResourceLoggingFilter { get; set; } = string.Empty;
public bool EnableResourceWatcher { get; set; } = false;
public bool OnlyAddMatchingResources { get; set; } = true;
public int MaxResourceWatcherRecords { get; set; } = ResourceWatcher.DefaultMaxEntries;
public ResourceTypeFlag ResourceWatcherResourceTypes { get; set; } = ResourceExtensions.AllResourceTypes;
public ResourceCategoryFlag ResourceWatcherResourceCategories { get; set; } = ResourceExtensions.AllResourceCategories;
public RecordType ResourceWatcherRecordTypes { get; set; } = ResourceWatcher.AllRecords;
[JsonConverter(typeof(SortModeConverter))] [JsonConverter(typeof(SortModeConverter))]
[JsonProperty(Order = int.MaxValue)] [JsonProperty(Order = int.MaxValue)]
public ISortMode<Mod> SortMode = ISortMode<Mod>.FoldersFirst; public ISortMode<Mod> SortMode = ISortMode<Mod>.FoldersFirst;
public bool ScaleModSelector { get; set; } = false; public bool ScaleModSelector { get; set; } = false;
public float ModSelectorAbsoluteSize { get; set; } = Constants.DefaultAbsoluteSize; public float ModSelectorAbsoluteSize { get; set; } = Constants.DefaultAbsoluteSize;
public int ModSelectorScaledSize { get; set; } = Constants.DefaultScaledSize; public int ModSelectorScaledSize { get; set; } = Constants.DefaultScaledSize;
public bool OpenFoldersByDefault { get; set; } = false; public bool OpenFoldersByDefault { get; set; } = false;
public int SingleGroupRadioMax { get; set; } = 2; public int SingleGroupRadioMax { get; set; } = 2;
public string DefaultImportFolder { get; set; } = string.Empty; public string DefaultImportFolder { get; set; } = string.Empty;
public string QuickMoveFolder1 { get; set; } = string.Empty; public string QuickMoveFolder1 { get; set; } = string.Empty;
public string QuickMoveFolder2 { get; set; } = string.Empty; public string QuickMoveFolder2 { get; set; } = string.Empty;
public string QuickMoveFolder3 { get; set; } = string.Empty; public string QuickMoveFolder3 { get; set; } = string.Empty;
public DoubleModifier DeleteModModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift); public DoubleModifier DeleteModModifier { get; set; } = new(ModifierHotkey.Control, ModifierHotkey.Shift);
public CollectionsTab.PanelMode CollectionPanel { get; set; } = CollectionsTab.PanelMode.SimpleAssignment; public bool PrintSuccessfulCommandsToChat { get; set; } = true;
public TabType SelectedTab { get; set; } = TabType.Settings; public bool AutoDeduplicateOnImport { get; set; } = true;
public bool UseFileSystemCompression { get; set; } = true;
public ChangedItemDrawer.ChangedItemIcon ChangedItemFilter { get; set; } = ChangedItemDrawer.DefaultFlags; public bool EnableHttpApi { get; set; } = true;
public bool PrintSuccessfulCommandsToChat { get; set; } = true;
public bool FixMainWindow { get; set; } = false;
public bool AutoDeduplicateOnImport { get; set; } = true;
public bool UseFileSystemCompression { get; set; } = true;
public bool EnableHttpApi { get; set; } = true;
public string DefaultModImportPath { get; set; } = string.Empty; public string DefaultModImportPath { get; set; } = string.Empty;
public bool AlwaysOpenDefaultImport { get; set; } = false; public bool AlwaysOpenDefaultImport { get; set; } = false;
@ -112,9 +91,10 @@ public class Configuration : IPluginConfiguration, ISavable
/// Load the current configuration. /// Load the current configuration.
/// Includes adding new colors and migrating from old versions. /// Includes adding new colors and migrating from old versions.
/// </summary> /// </summary>
public Configuration(CharacterUtility utility, ConfigMigrationService migrator, SaveService saveService) public Configuration(CharacterUtility utility, ConfigMigrationService migrator, SaveService saveService, EphemeralConfig ephemeral)
{ {
_saveService = saveService; _saveService = saveService;
Ephemeral = ephemeral;
Load(utility, migrator); Load(utility, migrator);
} }
@ -148,12 +128,12 @@ public class Configuration : IPluginConfiguration, ISavable
/// <summary> Save the current configuration. </summary> /// <summary> Save the current configuration. </summary>
public void Save() public void Save()
=> _saveService.DelaySave(this); => _saveService.QueueSave(this);
/// <summary> Contains some default values or boundaries for config values. </summary> /// <summary> Contains some default values or boundaries for config values. </summary>
public static class Constants public static class Constants
{ {
public const int CurrentVersion = 7; public const int CurrentVersion = 8;
public const float MaxAbsoluteSize = 600; public const float MaxAbsoluteSize = 600;
public const int DefaultAbsoluteSize = 250; public const int DefaultAbsoluteSize = 250;
public const float MinAbsoluteSize = 50; public const float MinAbsoluteSize = 50;

View file

@ -0,0 +1,86 @@
using Dalamud.Interface.Internal.Notifications;
using Newtonsoft.Json;
using OtterGui.Classes;
using Penumbra.Api.Enums;
using Penumbra.Enums;
using Penumbra.Interop.Services;
using Penumbra.Services;
using Penumbra.UI;
using Penumbra.UI.ResourceWatcher;
using Penumbra.UI.Tabs;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
namespace Penumbra;
public class EphemeralConfig : ISavable
{
[JsonIgnore]
private readonly SaveService _saveService;
public int Version { get; set; } = Configuration.Constants.CurrentVersion;
public int LastSeenVersion { get; set; } = PenumbraChangelog.LastChangelogVersion;
public bool DebugSeparateWindow { get; set; } = false;
public int TutorialStep { get; set; } = 0;
public bool EnableResourceLogging { get; set; } = false;
public string ResourceLoggingFilter { get; set; } = string.Empty;
public bool EnableResourceWatcher { get; set; } = false;
public bool OnlyAddMatchingResources { get; set; } = true;
public ResourceTypeFlag ResourceWatcherResourceTypes { get; set; } = ResourceExtensions.AllResourceTypes;
public ResourceCategoryFlag ResourceWatcherResourceCategories { get; set; } = ResourceExtensions.AllResourceCategories;
public RecordType ResourceWatcherRecordTypes { get; set; } = ResourceWatcher.AllRecords;
public CollectionsTab.PanelMode CollectionPanel { get; set; } = CollectionsTab.PanelMode.SimpleAssignment;
public TabType SelectedTab { get; set; } = TabType.Settings;
public ChangedItemDrawer.ChangedItemIcon ChangedItemFilter { get; set; } = ChangedItemDrawer.DefaultFlags;
public bool FixMainWindow { get; set; } = false;
/// <summary>
/// Load the current configuration.
/// Includes adding new colors and migrating from old versions.
/// </summary>
public EphemeralConfig(SaveService saveService)
{
_saveService = saveService;
Load();
}
private void Load()
{
static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs)
{
Penumbra.Log.Error(
$"Error parsing Configuration at {errorArgs.ErrorContext.Path}, using default or migrating:\n{errorArgs.ErrorContext.Error}");
errorArgs.ErrorContext.Handled = true;
}
if (File.Exists(_saveService.FileNames.EphemeralConfigFile))
try
{
var text = File.ReadAllText(_saveService.FileNames.EphemeralConfigFile);
JsonConvert.PopulateObject(text, this, new JsonSerializerSettings
{
Error = HandleDeserializationError,
});
}
catch (Exception ex)
{
Penumbra.Messager.NotificationMessage(ex,
"Error reading ephemeral Configuration, reverting to default.",
"Error reading ephemeral Configuration", NotificationType.Error);
}
}
/// <summary> Save the current configuration. </summary>
public void Save()
=> _saveService.DelaySave(this, TimeSpan.FromSeconds(5));
public string ToFilename(FilenameService fileNames)
=> fileNames.EphemeralConfigFile;
public void Save(StreamWriter writer)
{
using var jWriter = new JsonTextWriter(writer) { Formatting = Formatting.Indented };
var serializer = new JsonSerializer { Formatting = Formatting.Indented };
serializer.Serialize(jWriter, this);
}
}

View file

@ -201,7 +201,7 @@ public class Penumbra : IDalamudPlugin
sb.Append( sb.Append(
$"> **`Synchronous Load (Dalamud): `** {(_services.GetRequiredService<DalamudServices>().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")}\n"); $"> **`Synchronous Load (Dalamud): `** {(_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.Ephemeral.EnableResourceLogging}, Watcher: {_config.Ephemeral.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");

View file

@ -14,6 +14,10 @@ public class BackupService
Backup.CreateAutomaticBackup(logger, new DirectoryInfo(fileNames.ConfigDirectory), files); Backup.CreateAutomaticBackup(logger, new DirectoryInfo(fileNames.ConfigDirectory), files);
} }
public static void CreatePermanentBackup(FilenameService fileNames)
=> Backup.CreatePermanentBackup(Penumbra.Log, new DirectoryInfo(fileNames.ConfigDirectory), PenumbraFiles(fileNames),
"pre_ephemeral_config");
// Collect all relevant files for penumbra configuration. // Collect all relevant files for penumbra configuration.
private static IReadOnlyList<FileInfo> PenumbraFiles(FilenameService fileNames) private static IReadOnlyList<FileInfo> PenumbraFiles(FilenameService fileNames)
{ {

View file

@ -1,14 +1,20 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OtterGui.Classes;
using OtterGui.Filesystem; using OtterGui.Filesystem;
using Penumbra.Api.Enums;
using Penumbra.Collections; using Penumbra.Collections;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.Enums;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Mods.Editor; using Penumbra.Mods.Editor;
using Penumbra.Mods.Manager; using Penumbra.Mods.Manager;
using Penumbra.Mods.Subclasses; using Penumbra.Mods.Subclasses;
using Penumbra.UI;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using Penumbra.UI.ResourceWatcher;
using Penumbra.UI.Tabs;
namespace Penumbra.Services; namespace Penumbra.Services;
@ -26,7 +32,7 @@ public class ConfigMigrationService
public string CurrentCollection = ModCollection.DefaultCollectionName; public string CurrentCollection = ModCollection.DefaultCollectionName;
public string DefaultCollection = ModCollection.DefaultCollectionName; public string DefaultCollection = ModCollection.DefaultCollectionName;
public string ForcedCollection = string.Empty; public string ForcedCollection = string.Empty;
public Dictionary<string, string> CharacterCollections = new(); public Dictionary<string, string> CharacterCollections = [];
public Dictionary<string, string> ModSortOrder = new(); public Dictionary<string, string> ModSortOrder = new();
public bool InvertModListOrder; public bool InvertModListOrder;
public bool SortFoldersFirst; public bool SortFoldersFirst;
@ -71,9 +77,41 @@ public class ConfigMigrationService
Version4To5(); Version4To5();
Version5To6(); Version5To6();
Version6To7(); Version6To7();
Version7To8();
AddColors(config, true); AddColors(config, true);
} }
// Migrate to ephemeral config.
private void Version7To8()
{
if (_config.Version != 7)
return;
_config.Version = 8;
_config.Ephemeral.Version = 8;
_config.Ephemeral.LastSeenVersion = _data["LastSeenVersion"]?.ToObject<int>() ?? _config.Ephemeral.LastSeenVersion;
_config.Ephemeral.DebugSeparateWindow = _data["DebugSeparateWindow"]?.ToObject<bool>() ?? _config.Ephemeral.DebugSeparateWindow;
_config.Ephemeral.TutorialStep = _data["TutorialStep"]?.ToObject<int>() ?? _config.Ephemeral.TutorialStep;
_config.Ephemeral.EnableResourceLogging = _data["EnableResourceLogging"]?.ToObject<bool>() ?? _config.Ephemeral.EnableResourceLogging;
_config.Ephemeral.ResourceLoggingFilter = _data["ResourceLoggingFilter"]?.ToObject<string>() ?? _config.Ephemeral.ResourceLoggingFilter;
_config.Ephemeral.EnableResourceWatcher = _data["EnableResourceWatcher"]?.ToObject<bool>() ?? _config.Ephemeral.EnableResourceWatcher;
_config.Ephemeral.OnlyAddMatchingResources =
_data["OnlyAddMatchingResources"]?.ToObject<bool>() ?? _config.Ephemeral.OnlyAddMatchingResources;
_config.Ephemeral.ResourceWatcherResourceTypes = _data["ResourceWatcherResourceTypes"]?.ToObject<ResourceTypeFlag>()
?? _config.Ephemeral.ResourceWatcherResourceTypes;
_config.Ephemeral.ResourceWatcherResourceCategories = _data["ResourceWatcherResourceCategories"]?.ToObject<ResourceCategoryFlag>()
?? _config.Ephemeral.ResourceWatcherResourceCategories;
_config.Ephemeral.ResourceWatcherRecordTypes =
_data["ResourceWatcherRecordTypes"]?.ToObject<RecordType>() ?? _config.Ephemeral.ResourceWatcherRecordTypes;
_config.Ephemeral.CollectionPanel = _data["CollectionPanel"]?.ToObject<CollectionsTab.PanelMode>() ?? _config.Ephemeral.CollectionPanel;
_config.Ephemeral.SelectedTab = _data["SelectedTab"]?.ToObject<TabType>() ?? _config.Ephemeral.SelectedTab;
_config.Ephemeral.ChangedItemFilter = _data["ChangedItemFilter"]?.ToObject<ChangedItemDrawer.ChangedItemIcon>()
?? _config.Ephemeral.ChangedItemFilter;
_config.Ephemeral.FixMainWindow = _data["FixMainWindow"]?.ToObject<bool>() ?? _config.Ephemeral.FixMainWindow;
_config.Ephemeral.Save();
}
// Gendered special collections were added. // Gendered special collections were added.
private void Version6To7() private void Version6To7()
{ {
@ -93,8 +131,8 @@ public class ConfigMigrationService
if (_config.Version != 5) if (_config.Version != 5)
return; return;
if (_config.TutorialStep == 25) if (_config.Ephemeral.TutorialStep == 25)
_config.TutorialStep = 27; _config.Ephemeral.TutorialStep = 27;
_config.Version = 6; _config.Version = 6;
} }

View file

@ -11,17 +11,19 @@ public class FilenameService
public readonly string CollectionDirectory; public readonly string CollectionDirectory;
public readonly string LocalDataDirectory; public readonly string LocalDataDirectory;
public readonly string ConfigFile; public readonly string ConfigFile;
public readonly string EphemeralConfigFile;
public readonly string FilesystemFile; public readonly string FilesystemFile;
public readonly string ActiveCollectionsFile; public readonly string ActiveCollectionsFile;
public FilenameService(DalamudPluginInterface pi) public FilenameService(DalamudPluginInterface pi)
{ {
ConfigDirectory = pi.ConfigDirectory.FullName; ConfigDirectory = pi.ConfigDirectory.FullName;
CollectionDirectory = Path.Combine(pi.GetPluginConfigDirectory(), "collections"); CollectionDirectory = Path.Combine(pi.ConfigDirectory.FullName, "collections");
LocalDataDirectory = Path.Combine(pi.ConfigDirectory.FullName, "mod_data"); LocalDataDirectory = Path.Combine(pi.ConfigDirectory.FullName, "mod_data");
ConfigFile = pi.ConfigFile.FullName; ConfigFile = pi.ConfigFile.FullName;
FilesystemFile = Path.Combine(pi.GetPluginConfigDirectory(), "sort_order.json"); FilesystemFile = Path.Combine(pi.ConfigDirectory.FullName, "sort_order.json");
ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json"); ActiveCollectionsFile = Path.Combine(pi.ConfigDirectory.FullName, "active_collections.json");
EphemeralConfigFile = Path.Combine(pi.ConfigDirectory.FullName, "ephemeral_config.json");
} }
/// <summary> Obtain the path of a collection file given its name.</summary> /// <summary> Obtain the path of a collection file given its name.</summary>

View file

@ -95,7 +95,8 @@ public static class ServiceManager
private static IServiceCollection AddConfiguration(this IServiceCollection services) private static IServiceCollection AddConfiguration(this IServiceCollection services)
=> services.AddTransient<ConfigMigrationService>() => services.AddTransient<ConfigMigrationService>()
.AddSingleton<Configuration>(); .AddSingleton<Configuration>()
.AddSingleton<EphemeralConfig>();
private static IServiceCollection AddCollections(this IServiceCollection services) private static IServiceCollection AddCollections(this IServiceCollection services)
=> services.AddSingleton<CollectionStorage>() => services.AddSingleton<CollectionStorage>()

View file

@ -70,7 +70,7 @@ public class ChangedItemDrawer : IDisposable
/// <summary> Check if a changed item should be drawn based on its category. </summary> /// <summary> Check if a changed item should be drawn based on its category. </summary>
public bool FilterChangedItem(string name, object? data, LowerString filter) public bool FilterChangedItem(string name, object? data, LowerString filter)
=> (_config.ChangedItemFilter == AllFlags || _config.ChangedItemFilter.HasFlag(GetCategoryIcon(name, data))) => (_config.Ephemeral.ChangedItemFilter == AllFlags || _config.Ephemeral.ChangedItemFilter.HasFlag(GetCategoryIcon(name, data)))
&& (filter.IsEmpty || filter.IsContained(ChangedItemFilterName(name, data))); && (filter.IsEmpty || filter.IsContained(ChangedItemFilterName(name, data)));
/// <summary> Draw the icon corresponding to the category of a changed item. </summary> /// <summary> Draw the icon corresponding to the category of a changed item. </summary>
@ -172,20 +172,20 @@ public class ChangedItemDrawer : IDisposable
void DrawIcon(ChangedItemIcon type) void DrawIcon(ChangedItemIcon type)
{ {
var icon = _icons[type]; var icon = _icons[type];
var flag = _config.ChangedItemFilter.HasFlag(type); var flag = _config.Ephemeral.ChangedItemFilter.HasFlag(type);
ImGui.Image(icon.ImGuiHandle, size, Vector2.Zero, Vector2.One, flag ? Vector4.One : new Vector4(0.6f, 0.3f, 0.3f, 1f)); ImGui.Image(icon.ImGuiHandle, size, Vector2.Zero, Vector2.One, flag ? Vector4.One : new Vector4(0.6f, 0.3f, 0.3f, 1f));
if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
{ {
_config.ChangedItemFilter = flag ? _config.ChangedItemFilter & ~type : _config.ChangedItemFilter | type; _config.Ephemeral.ChangedItemFilter = flag ? _config.Ephemeral.ChangedItemFilter & ~type : _config.Ephemeral.ChangedItemFilter | type;
_config.Save(); _config.Ephemeral.Save();
} }
using var popup = ImRaii.ContextPopupItem(type.ToString()); using var popup = ImRaii.ContextPopupItem(type.ToString());
if (popup) if (popup)
if (ImGui.MenuItem("Enable Only This")) if (ImGui.MenuItem("Enable Only This"))
{ {
_config.ChangedItemFilter = type; _config.Ephemeral.ChangedItemFilter = type;
_config.Save(); _config.Ephemeral.Save();
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
@ -206,12 +206,12 @@ public class ChangedItemDrawer : IDisposable
ImGui.SetCursorPosX(ImGui.GetContentRegionMax().X - size.X); ImGui.SetCursorPosX(ImGui.GetContentRegionMax().X - size.X);
ImGui.Image(_icons[AllFlags].ImGuiHandle, size, Vector2.Zero, Vector2.One, ImGui.Image(_icons[AllFlags].ImGuiHandle, size, Vector2.Zero, Vector2.One,
_config.ChangedItemFilter == 0 ? new Vector4(0.6f, 0.3f, 0.3f, 1f) : _config.Ephemeral.ChangedItemFilter == 0 ? new Vector4(0.6f, 0.3f, 0.3f, 1f) :
_config.ChangedItemFilter == AllFlags ? new Vector4(0.75f, 0.75f, 0.75f, 1f) : new Vector4(0.5f, 0.5f, 1f, 1f)); _config.Ephemeral.ChangedItemFilter == AllFlags ? new Vector4(0.75f, 0.75f, 0.75f, 1f) : new Vector4(0.5f, 0.5f, 1f, 1f));
if (ImGui.IsItemClicked()) if (ImGui.IsItemClicked())
{ {
_config.ChangedItemFilter = _config.ChangedItemFilter == AllFlags ? 0 : AllFlags; _config.Ephemeral.ChangedItemFilter = _config.Ephemeral.ChangedItemFilter == AllFlags ? 0 : AllFlags;
_config.Save(); _config.Ephemeral.Save();
} }
} }

View file

@ -627,12 +627,20 @@ public class PenumbraChangelog
#endregion #endregion
private (int, ChangeLogDisplayType) ConfigData() private (int, ChangeLogDisplayType) ConfigData()
=> (_config.LastSeenVersion, _config.ChangeLogDisplayType); => (_config.Ephemeral.LastSeenVersion, _config.ChangeLogDisplayType);
private void Save(int version, ChangeLogDisplayType type) private void Save(int version, ChangeLogDisplayType type)
{ {
_config.LastSeenVersion = version; if (_config.Ephemeral.LastSeenVersion != version)
_config.ChangeLogDisplayType = type; {
_config.Save(); _config.Ephemeral.LastSeenVersion = version;
_config.Ephemeral.Save();
}
if (_config.ChangeLogDisplayType != type)
{
_config.ChangeLogDisplayType = type;
_config.Save();
}
} }
} }

View file

@ -39,7 +39,7 @@ public sealed class ConfigWindow : Window
{ {
_penumbra = penumbra; _penumbra = penumbra;
_configTabs = configTabs; _configTabs = configTabs;
_configTabs.SelectTab = _config.SelectedTab; _configTabs.SelectTab = _config.Ephemeral.SelectedTab;
} }
public override bool DrawConditions() public override bool DrawConditions()
@ -47,7 +47,7 @@ public sealed class ConfigWindow : Window
public override void PreDraw() public override void PreDraw()
{ {
if (_config.FixMainWindow) if (_config.Ephemeral.FixMainWindow)
Flags |= ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove; Flags |= ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove;
else else
Flags &= ~(ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove); Flags &= ~(ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove);
@ -99,10 +99,10 @@ public sealed class ConfigWindow : Window
else else
{ {
var type = _configTabs.Draw(); var type = _configTabs.Draw();
if (type != _config.SelectedTab) if (type != _config.Ephemeral.SelectedTab)
{ {
_config.SelectedTab = type; _config.Ephemeral.SelectedTab = type;
_config.Save(); _config.Ephemeral.Save();
} }
} }

View file

@ -21,6 +21,7 @@ public class ResourceWatcher : IDisposable, ITab
public const RecordType AllRecords = RecordType.Request | RecordType.ResourceLoad | RecordType.FileLoad | RecordType.Destruction; public const RecordType AllRecords = RecordType.Request | RecordType.ResourceLoad | RecordType.FileLoad | RecordType.Destruction;
private readonly Configuration _config; private readonly Configuration _config;
private readonly EphemeralConfig _ephemeral;
private readonly ResourceService _resources; private readonly ResourceService _resources;
private readonly ResourceLoader _loader; private readonly ResourceLoader _loader;
private readonly ActorService _actors; private readonly ActorService _actors;
@ -35,14 +36,15 @@ public class ResourceWatcher : IDisposable, ITab
{ {
_actors = actors; _actors = actors;
_config = config; _config = config;
_ephemeral = config.Ephemeral;
_resources = resources; _resources = resources;
_loader = loader; _loader = loader;
_table = new ResourceWatcherTable(config, _records); _table = new ResourceWatcherTable(config.Ephemeral, _records);
_resources.ResourceRequested += OnResourceRequested; _resources.ResourceRequested += OnResourceRequested;
_resources.ResourceHandleDestructor += OnResourceDestroyed; _resources.ResourceHandleDestructor += OnResourceDestroyed;
_loader.ResourceLoaded += OnResourceLoaded; _loader.ResourceLoaded += OnResourceLoaded;
_loader.FileLoaded += OnFileLoaded; _loader.FileLoaded += OnFileLoaded;
UpdateFilter(_config.ResourceLoggingFilter, false); UpdateFilter(_ephemeral.ResourceLoggingFilter, false);
_newMaxEntries = _config.MaxResourceWatcherRecords; _newMaxEntries = _config.MaxResourceWatcherRecords;
} }
@ -71,11 +73,11 @@ public class ResourceWatcher : IDisposable, ITab
UpdateRecords(); UpdateRecords();
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetTextLineHeightWithSpacing() / 2); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetTextLineHeightWithSpacing() / 2);
var isEnabled = _config.EnableResourceWatcher; var isEnabled = _ephemeral.EnableResourceWatcher;
if (ImGui.Checkbox("Enable", ref isEnabled)) if (ImGui.Checkbox("Enable", ref isEnabled))
{ {
_config.EnableResourceWatcher = isEnabled; _ephemeral.EnableResourceWatcher = isEnabled;
_config.Save(); _ephemeral.Save();
} }
ImGui.SameLine(); ImGui.SameLine();
@ -85,19 +87,19 @@ public class ResourceWatcher : IDisposable, ITab
Clear(); Clear();
ImGui.SameLine(); ImGui.SameLine();
var onlyMatching = _config.OnlyAddMatchingResources; var onlyMatching = _ephemeral.OnlyAddMatchingResources;
if (ImGui.Checkbox("Store Only Matching", ref onlyMatching)) if (ImGui.Checkbox("Store Only Matching", ref onlyMatching))
{ {
_config.OnlyAddMatchingResources = onlyMatching; _ephemeral.OnlyAddMatchingResources = onlyMatching;
_config.Save(); _ephemeral.Save();
} }
ImGui.SameLine(); ImGui.SameLine();
var writeToLog = _config.EnableResourceLogging; var writeToLog = _ephemeral.EnableResourceLogging;
if (ImGui.Checkbox("Write to Log", ref writeToLog)) if (ImGui.Checkbox("Write to Log", ref writeToLog))
{ {
_config.EnableResourceLogging = writeToLog; _ephemeral.EnableResourceLogging = writeToLog;
_config.Save(); _ephemeral.Save();
} }
ImGui.SameLine(); ImGui.SameLine();
@ -136,8 +138,8 @@ public class ResourceWatcher : IDisposable, ITab
if (config) if (config)
{ {
_config.ResourceLoggingFilter = newString; _ephemeral.ResourceLoggingFilter = newString;
_config.Save(); _ephemeral.Save();
} }
} }
@ -196,20 +198,20 @@ public class ResourceWatcher : IDisposable, ITab
Utf8GamePath original, Utf8GamePath original,
GetResourceParameters* parameters, ref bool sync, ref ResourceHandle* returnValue) GetResourceParameters* parameters, ref bool sync, ref ResourceHandle* returnValue)
{ {
if (_config.EnableResourceLogging && FilterMatch(original.Path, out var match)) if (_ephemeral.EnableResourceLogging && FilterMatch(original.Path, out var match))
Penumbra.Log.Information($"[ResourceLoader] [REQ] {match} was requested {(sync ? "synchronously." : "asynchronously.")}"); Penumbra.Log.Information($"[ResourceLoader] [REQ] {match} was requested {(sync ? "synchronously." : "asynchronously.")}");
if (!_config.EnableResourceWatcher) if (!_ephemeral.EnableResourceWatcher)
return; return;
var record = Record.CreateRequest(original.Path, sync); var record = Record.CreateRequest(original.Path, sync);
if (!_config.OnlyAddMatchingResources || _table.WouldBeVisible(record)) if (!_ephemeral.OnlyAddMatchingResources || _table.WouldBeVisible(record))
_newRecords.Enqueue(record); _newRecords.Enqueue(record);
} }
private unsafe void OnResourceLoaded(ResourceHandle* handle, Utf8GamePath path, FullPath? manipulatedPath, ResolveData data) private unsafe void OnResourceLoaded(ResourceHandle* handle, Utf8GamePath path, FullPath? manipulatedPath, ResolveData data)
{ {
if (_config.EnableResourceLogging) if (_ephemeral.EnableResourceLogging)
{ {
var log = FilterMatch(path.Path, out var name); var log = FilterMatch(path.Path, out var name);
var name2 = string.Empty; var name2 = string.Empty;
@ -224,41 +226,41 @@ public class ResourceWatcher : IDisposable, ITab
} }
} }
if (!_config.EnableResourceWatcher) if (!_ephemeral.EnableResourceWatcher)
return; return;
var record = manipulatedPath == null var record = manipulatedPath == null
? Record.CreateDefaultLoad(path.Path, handle, data.ModCollection, Name(data)) ? Record.CreateDefaultLoad(path.Path, handle, data.ModCollection, Name(data))
: Record.CreateLoad(manipulatedPath.Value.InternalName, path.Path, handle, data.ModCollection, Name(data)); : Record.CreateLoad(manipulatedPath.Value.InternalName, path.Path, handle, data.ModCollection, Name(data));
if (!_config.OnlyAddMatchingResources || _table.WouldBeVisible(record)) if (!_ephemeral.OnlyAddMatchingResources || _table.WouldBeVisible(record))
_newRecords.Enqueue(record); _newRecords.Enqueue(record);
} }
private unsafe void OnFileLoaded(ResourceHandle* resource, ByteString path, bool success, bool custom, ByteString _) private unsafe void OnFileLoaded(ResourceHandle* resource, ByteString path, bool success, bool custom, ByteString _)
{ {
if (_config.EnableResourceLogging && FilterMatch(path, out var match)) if (_ephemeral.EnableResourceLogging && FilterMatch(path, out var match))
Penumbra.Log.Information( Penumbra.Log.Information(
$"[ResourceLoader] [FILE] [{resource->FileType}] Loading {match} from {(custom ? "local files" : "SqPack")} into 0x{(ulong)resource:X} returned {success}."); $"[ResourceLoader] [FILE] [{resource->FileType}] Loading {match} from {(custom ? "local files" : "SqPack")} into 0x{(ulong)resource:X} returned {success}.");
if (!_config.EnableResourceWatcher) if (!_ephemeral.EnableResourceWatcher)
return; return;
var record = Record.CreateFileLoad(path, resource, success, custom); var record = Record.CreateFileLoad(path, resource, success, custom);
if (!_config.OnlyAddMatchingResources || _table.WouldBeVisible(record)) if (!_ephemeral.OnlyAddMatchingResources || _table.WouldBeVisible(record))
_newRecords.Enqueue(record); _newRecords.Enqueue(record);
} }
private unsafe void OnResourceDestroyed(ResourceHandle* resource) private unsafe void OnResourceDestroyed(ResourceHandle* resource)
{ {
if (_config.EnableResourceLogging && FilterMatch(resource->FileName(), out var match)) if (_ephemeral.EnableResourceLogging && FilterMatch(resource->FileName(), out var match))
Penumbra.Log.Information( Penumbra.Log.Information(
$"[ResourceLoader] [DEST] [{resource->FileType}] Destroyed {match} at 0x{(ulong)resource:X}."); $"[ResourceLoader] [DEST] [{resource->FileType}] Destroyed {match} at 0x{(ulong)resource:X}.");
if (!_config.EnableResourceWatcher) if (!_ephemeral.EnableResourceWatcher)
return; return;
var record = Record.CreateDestruction(resource); var record = Record.CreateDestruction(resource);
if (!_config.OnlyAddMatchingResources || _table.WouldBeVisible(record)) if (!_ephemeral.OnlyAddMatchingResources || _table.WouldBeVisible(record))
_newRecords.Enqueue(record); _newRecords.Enqueue(record);
} }

View file

@ -13,7 +13,7 @@ namespace Penumbra.UI.ResourceWatcher;
internal sealed class ResourceWatcherTable : Table<Record> internal sealed class ResourceWatcherTable : Table<Record>
{ {
public ResourceWatcherTable(Configuration config, IReadOnlyCollection<Record> records) public ResourceWatcherTable(EphemeralConfig config, IReadOnlyCollection<Record> records)
: base("##records", : base("##records",
records, records,
new PathColumn { Label = "Path" }, new PathColumn { Label = "Path" },
@ -86,9 +86,9 @@ internal sealed class ResourceWatcherTable : Table<Record>
private sealed class RecordTypeColumn : ColumnFlags<RecordType, Record> private sealed class RecordTypeColumn : ColumnFlags<RecordType, Record>
{ {
private readonly Configuration _config; private readonly EphemeralConfig _config;
public RecordTypeColumn(Configuration config) public RecordTypeColumn(EphemeralConfig config)
{ {
AllFlags = ResourceWatcher.AllRecords; AllFlags = ResourceWatcher.AllRecords;
_config = config; _config = config;
@ -174,9 +174,9 @@ internal sealed class ResourceWatcherTable : Table<Record>
private sealed class ResourceCategoryColumn : ColumnFlags<ResourceCategoryFlag, Record> private sealed class ResourceCategoryColumn : ColumnFlags<ResourceCategoryFlag, Record>
{ {
private readonly Configuration _config; private readonly EphemeralConfig _config;
public ResourceCategoryColumn(Configuration config) public ResourceCategoryColumn(EphemeralConfig config)
{ {
_config = config; _config = config;
AllFlags = ResourceExtensions.AllResourceCategories; AllFlags = ResourceExtensions.AllResourceCategories;
@ -209,9 +209,9 @@ internal sealed class ResourceWatcherTable : Table<Record>
private sealed class ResourceTypeColumn : ColumnFlags<ResourceTypeFlag, Record> private sealed class ResourceTypeColumn : ColumnFlags<ResourceTypeFlag, Record>
{ {
private readonly Configuration _config; private readonly EphemeralConfig _config;
public ResourceTypeColumn(Configuration config) public ResourceTypeColumn(EphemeralConfig config)
{ {
_config = config; _config = config;
AllFlags = Enum.GetValues<ResourceTypeFlag>().Aggregate((v, f) => v | f); AllFlags = Enum.GetValues<ResourceTypeFlag>().Aggregate((v, f) => v | f);

View file

@ -16,7 +16,7 @@ namespace Penumbra.UI.Tabs;
public class CollectionsTab : IDisposable, ITab public class CollectionsTab : IDisposable, ITab
{ {
private readonly Configuration _config; private readonly EphemeralConfig _config;
private readonly CollectionSelector _selector; private readonly CollectionSelector _selector;
private readonly CollectionPanel _panel; private readonly CollectionPanel _panel;
private readonly TutorialService _tutorial; private readonly TutorialService _tutorial;
@ -42,7 +42,7 @@ public class CollectionsTab : IDisposable, ITab
public CollectionsTab(DalamudPluginInterface pi, Configuration configuration, CommunicatorService communicator, public CollectionsTab(DalamudPluginInterface pi, Configuration configuration, CommunicatorService communicator,
CollectionManager collectionManager, ModStorage modStorage, ActorService actors, ITargetManager targets, TutorialService tutorial) CollectionManager collectionManager, ModStorage modStorage, ActorService actors, ITargetManager targets, TutorialService tutorial)
{ {
_config = configuration; _config = configuration.Ephemeral;
_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, communicator, collectionManager, _selector, actors, targets, modStorage); _panel = new CollectionPanel(pi, communicator, collectionManager, _selector, actors, targets, modStorage);

View file

@ -115,7 +115,7 @@ public class DebugTab : Window, ITab
=> "Debug"u8; => "Debug"u8;
public bool IsVisible public bool IsVisible
=> _config.DebugMode && !_config.DebugSeparateWindow; => _config is { DebugMode: true, Ephemeral.DebugSeparateWindow: false };
#if DEBUG #if DEBUG
private const string DebugVersionString = "(Debug)"; private const string DebugVersionString = "(Debug)";
@ -201,12 +201,12 @@ public class DebugTab : Window, ITab
if (!ImGui.CollapsingHeader("General")) if (!ImGui.CollapsingHeader("General"))
return; return;
var separateWindow = _config.DebugSeparateWindow; var separateWindow = _config.Ephemeral.DebugSeparateWindow;
if (ImGui.Checkbox("Draw as Separate Window", ref separateWindow)) if (ImGui.Checkbox("Draw as Separate Window", ref separateWindow))
{ {
IsOpen = true; IsOpen = true;
_config.DebugSeparateWindow = separateWindow; _config.Ephemeral.DebugSeparateWindow = separateWindow;
_config.Save(); _config.Ephemeral.Save();
} }
using (var table = Table("##DebugGeneralTable", 2, ImGuiTableFlags.SizingFixedFit)) using (var table = Table("##DebugGeneralTable", 2, ImGuiTableFlags.SizingFixedFit))
@ -949,11 +949,11 @@ public class DebugTab : Window, ITab
=> DrawContent(); => DrawContent();
public override bool DrawConditions() public override bool DrawConditions()
=> _config.DebugMode && _config.DebugSeparateWindow; => _config.DebugMode && _config.Ephemeral.DebugSeparateWindow;
public override void OnClose() public override void OnClose()
{ {
_config.DebugSeparateWindow = false; _config.Ephemeral.DebugSeparateWindow = false;
_config.Save(); _config.Ephemeral.Save();
} }
} }

View file

@ -78,8 +78,8 @@ public class SettingsTab : ITab
return; return;
DrawEnabledBox(); DrawEnabledBox();
Checkbox("Lock Main Window", "Prevent the main window from being resized or moved.", _config.FixMainWindow, EphemeralCheckbox("Lock Main Window", "Prevent the main window from being resized or moved.", _config.Ephemeral.FixMainWindow,
v => _config.FixMainWindow = v); v => _config.Ephemeral.FixMainWindow = v);
ImGui.NewLine(); ImGui.NewLine();
DrawRootFolder(); DrawRootFolder();
@ -107,6 +107,21 @@ public class SettingsTab : ITab
ImGuiUtil.LabeledHelpMarker(label, tooltip); ImGuiUtil.LabeledHelpMarker(label, tooltip);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private void EphemeralCheckbox(string label, string tooltip, bool current, Action<bool> setter)
{
using var id = ImRaii.PushId(label);
var tmp = current;
if (ImGui.Checkbox(string.Empty, ref tmp) && tmp != current)
{
setter(tmp);
_config.Ephemeral.Save();
}
ImGui.SameLine();
ImGuiUtil.LabeledHelpMarker(label, tooltip);
}
#region Main Settings #region Main Settings
/// <summary> /// <summary>
@ -384,7 +399,10 @@ public class SettingsTab : ITab
{ {
_config.HideChangedItemFilters = v; _config.HideChangedItemFilters = v;
if (v) if (v)
_config.ChangedItemFilter = ChangedItemDrawer.AllFlags; {
_config.Ephemeral.ChangedItemFilter = ChangedItemDrawer.AllFlags;
_config.Ephemeral.Save();
}
}); });
Checkbox("Hide Priority Numbers in Mod Selector", Checkbox("Hide Priority Numbers in Mod Selector",
"Hides the bracketed non-zero priority numbers displayed in the mod selector when there is enough space for them.", "Hides the bracketed non-zero priority numbers displayed in the mod selector when there is enough space for them.",
@ -863,8 +881,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)))
{ {
_config.TutorialStep = 0; _config.Ephemeral.TutorialStep = 0;
_config.Save(); _config.Ephemeral.Save();
} }
ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing())); ImGui.SetCursorPos(new Vector2(xPos, 4 * ImGui.GetFrameHeightWithSpacing()));

View file

@ -55,10 +55,10 @@ public class TutorialService
+ " - 'furniture': most indoor furniture, does not currently work outdoors\n" + " - 'furniture': most indoor furniture, does not currently work outdoors\n"
+ " - any specific actor name to redraw all actors of that exactly matching name."; + " - any specific actor name to redraw all actors of that exactly matching name.";
private readonly Configuration _config; private readonly EphemeralConfig _config;
private readonly Tutorial _tutorial; private readonly Tutorial _tutorial;
public TutorialService(Configuration config) public TutorialService(EphemeralConfig config)
{ {
_config = config; _config = config;
_tutorial = new Tutorial() _tutorial = new Tutorial()