mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-15 13:14:17 +01:00
Memorize last selected mod and state of advanced editing window.
This commit is contained in:
parent
306a9c217a
commit
55f38865e3
4 changed files with 82 additions and 30 deletions
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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.";
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue