Memorize last selected mod and state of advanced editing window.

This commit is contained in:
Ottermandias 2024-01-05 18:13:03 +01:00
parent 306a9c217a
commit 55f38865e3
4 changed files with 82 additions and 30 deletions

View file

@ -19,6 +19,9 @@ public sealed class ModPathChanged()
{
public enum Priority
{
/// <seealso cref="EphemeralConfig.OnModPathChanged"/>
EphemeralConfig = -500,
/// <seealso cref="Collections.Cache.CollectionCacheManager.OnModChangeAddition"/>
CollectionCacheManagerAddition = -100,

View file

@ -2,7 +2,10 @@ using Dalamud.Interface.Internal.Notifications;
using Newtonsoft.Json;
using OtterGui.Classes;
using Penumbra.Api.Enums;
using Penumbra.Communication;
using Penumbra.Enums;
using Penumbra.Mods;
using Penumbra.Mods.Manager;
using Penumbra.Services;
using Penumbra.UI;
using Penumbra.UI.ResourceWatcher;
@ -11,11 +14,14 @@ using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
namespace Penumbra;
public class EphemeralConfig : ISavable
public class EphemeralConfig : ISavable, IDisposable
{
[JsonIgnore]
private readonly SaveService _saveService;
[JsonIgnore]
private readonly ModPathChanged _modPathChanged;
public int Version { get; set; } = Configuration.Constants.CurrentVersion;
public int LastSeenVersion { get; set; } = PenumbraChangelog.LastChangelogVersion;
public bool DebugSeparateWindow { get; set; } = false;
@ -31,17 +37,24 @@ public class EphemeralConfig : ISavable
public TabType SelectedTab { get; set; } = TabType.Settings;
public ChangedItemDrawer.ChangedItemIcon ChangedItemFilter { get; set; } = ChangedItemDrawer.DefaultFlags;
public bool FixMainWindow { get; set; } = false;
public string LastModPath { get; set; } = string.Empty;
public bool AdvancedEditingOpen { get; set; } = false;
/// <summary>
/// Load the current configuration.
/// Includes adding new colors and migrating from old versions.
/// </summary>
public EphemeralConfig(SaveService saveService)
public EphemeralConfig(SaveService saveService, ModPathChanged modPathChanged)
{
_saveService = saveService;
_saveService = saveService;
_modPathChanged = modPathChanged;
Load();
_modPathChanged.Subscribe(OnModPathChanged, ModPathChanged.Priority.EphemeralConfig);
}
public void Dispose()
=> _modPathChanged.Unsubscribe(OnModPathChanged);
private void Load()
{
static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs)
@ -80,8 +93,19 @@ public class EphemeralConfig : ISavable
public void Save(StreamWriter writer)
{
using var jWriter = new JsonTextWriter(writer) { Formatting = Formatting.Indented };
using var jWriter = new JsonTextWriter(writer);
jWriter.Formatting = Formatting.Indented;
var serializer = new JsonSerializer { Formatting = Formatting.Indented };
serializer.Serialize(jWriter, this);
}
/// <summary> Overwrite the last saved mod path if it changes. </summary>
private void OnModPathChanged(ModPathChangeType type, Mod mod, DirectoryInfo? old, DirectoryInfo? _)
{
if (type is not ModPathChangeType.Moved || !string.Equals(old?.Name, LastModPath, StringComparison.OrdinalIgnoreCase))
return;
LastModPath = mod.Identifier;
Save();
}
}

View file

@ -145,12 +145,20 @@ public partial class ModEditWindow : Window, IDisposable
_materialTab.Reset();
_modelTab.Reset();
_shaderPackageTab.Reset();
_config.Ephemeral.AdvancedEditingOpen = false;
_config.Ephemeral.Save();
}
public override void Draw()
{
using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow);
if (!_config.Ephemeral.AdvancedEditingOpen)
{
_config.Ephemeral.AdvancedEditingOpen = true;
_config.Ephemeral.Save();
}
using var tabBar = ImRaii.TabBar("##tabs");
if (!tabBar)
return;
@ -566,34 +574,36 @@ public partial class ModEditWindow : Window, IDisposable
public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, IDataManager gameData,
Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager,
StainService stainService, ActiveCollections activeCollections, ModMergeTab modMergeTab,
CommunicatorService communicator, TextureManager textures, ModelManager models, IDragDropManager dragDropManager,
CommunicatorService communicator, TextureManager textures, ModelManager models, IDragDropManager dragDropManager,
ChangedItemDrawer changedItemDrawer, IObjectTable objects, IFramework framework, CharacterBaseDestructor characterBaseDestructor)
: base(WindowBaseLabel)
{
_performance = performance;
_itemSwapTab = itemSwapTab;
_gameData = gameData;
_config = config;
_editor = editor;
_metaFileManager = metaFileManager;
_stainService = stainService;
_activeCollections = activeCollections;
_modMergeTab = modMergeTab;
_communicator = communicator;
_dragDropManager = dragDropManager;
_textures = textures;
_models = models;
_fileDialog = fileDialog;
_objects = objects;
_framework = framework;
_performance = performance;
_itemSwapTab = itemSwapTab;
_gameData = gameData;
_config = config;
_editor = editor;
_metaFileManager = metaFileManager;
_stainService = stainService;
_activeCollections = activeCollections;
_modMergeTab = modMergeTab;
_communicator = communicator;
_dragDropManager = dragDropManager;
_textures = textures;
_models = models;
_fileDialog = fileDialog;
_objects = objects;
_framework = framework;
_characterBaseDestructor = characterBaseDestructor;
_materialTab = new FileEditor<MtrlTab>(this, gameData, config, _editor.Compactor, _fileDialog, "Materials", ".mtrl",
() => PopulateIsOnPlayer(_editor.Files.Mtrl, ResourceType.Mtrl), DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty,
(bytes, path, writable) => new MtrlTab(this, new MtrlFile(bytes), path, writable));
_modelTab = new FileEditor<MdlTab>(this, gameData, config, _editor.Compactor, _fileDialog, "Models", ".mdl",
() => PopulateIsOnPlayer(_editor.Files.Mdl, ResourceType.Mdl), DrawModelPanel, () => _mod?.ModPath.FullName ?? string.Empty, (bytes, path, _) => new MdlTab(this, bytes, path, _mod));
() => PopulateIsOnPlayer(_editor.Files.Mdl, ResourceType.Mdl), DrawModelPanel, () => _mod?.ModPath.FullName ?? string.Empty,
(bytes, path, _) => new MdlTab(this, bytes, path, _mod));
_shaderPackageTab = new FileEditor<ShpkTab>(this, gameData, config, _editor.Compactor, _fileDialog, "Shaders", ".shpk",
() => PopulateIsOnPlayer(_editor.Files.Shpk, ResourceType.Shpk), DrawShaderPackagePanel, () => _mod?.ModPath.FullName ?? string.Empty,
() => PopulateIsOnPlayer(_editor.Files.Shpk, ResourceType.Shpk), DrawShaderPackagePanel,
() => _mod?.ModPath.FullName ?? string.Empty,
(bytes, _, _) => new ShpkTab(_fileDialog, bytes));
_center = new CombinedTexture(_left, _right);
_textureSelectCombo = new TextureDrawer.PathSelectCombo(textures, editor, () => GetPlayerResourcesOfType(ResourceType.Tex));
@ -601,6 +611,7 @@ public partial class ModEditWindow : Window, IDisposable
_quickImportViewer =
new ResourceTreeViewer(_config, resourceTreeFactory, changedItemDrawer, 2, OnQuickImportRefresh, DrawQuickImportActions);
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModEditWindow);
IsOpen = _config is { OpenWindowAtStart: true, Ephemeral.AdvancedEditingOpen: true };
}
public void Dispose()

View file

@ -39,8 +39,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
public ModFileSystemSelector(IKeyState keyState, CommunicatorService communicator, ModFileSystem fileSystem, ModManager modManager,
CollectionManager collectionManager, Configuration config, TutorialService tutorial, FileDialogService fileDialog,
MessageService messager,
ModImportManager modImportManager, IDragDropManager dragDrop)
MessageService messager, ModImportManager modImportManager, IDragDropManager dragDrop)
: base(fileSystem, keyState, Penumbra.Log, HandleException, allowMultipleSelection: true)
{
_communicator = communicator;
@ -77,7 +76,15 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
// @formatter:on
SetFilterTooltip();
SelectionChanged += OnSelectionChange;
SelectionChanged += OnSelectionChange;
if (_config.Ephemeral.LastModPath.Length > 0)
{
var mod = _modManager.FirstOrDefault(m
=> string.Equals(m.Identifier, _config.Ephemeral.LastModPath, StringComparison.OrdinalIgnoreCase));
if (mod != null)
SelectByValue(mod);
}
_communicator.CollectionChange.Subscribe(OnCollectionChange, CollectionChange.Priority.ModFileSystemSelector);
_communicator.ModSettingChanged.Subscribe(OnSettingChange, ModSettingChanged.Priority.ModFileSystemSelector);
_communicator.CollectionInheritanceChanged.Subscribe(OnInheritanceChange, CollectionInheritanceChanged.Priority.ModFileSystemSelector);
@ -87,15 +94,15 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
OnCollectionChange(CollectionType.Current, null, _collectionManager.Active.Current, "");
}
private static readonly string[] ValidModExtensions = new[]
{
private static readonly string[] ValidModExtensions =
[
".ttmp",
".ttmp2",
".pmp",
".zip",
".rar",
".7z",
};
];
public new void Draw(float width)
{
@ -476,6 +483,13 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
(var settings, SelectedSettingCollection) = _collectionManager.Active.Current[newSelection.Index];
SelectedSettings = settings ?? ModSettings.Empty;
}
var name = newSelection?.Identifier ?? string.Empty;
if (name != _config.Ephemeral.LastModPath)
{
_config.Ephemeral.LastModPath = name;
_config.Ephemeral.Save();
}
}
// Keep selections across rediscoveries if possible.
@ -522,7 +536,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
+ "Enter t:[string] to filter for mods set to specific tags.\n"
+ "Enter n:[string] to filter only for mod names and no paths.\n"
+ "Enter a:[string] to filter for mods by specific authors.\n"
+ $"Enter s:[string] to filter for mods by the categories of the items they change (1-{ChangedItemDrawer.NumCategories+1} or partial category name).\n"
+ $"Enter s:[string] to filter for mods by the categories of the items they change (1-{ChangedItemDrawer.NumCategories + 1} or partial category name).\n"
+ "Use None as a placeholder value that only matches empty lists or names.";
}