mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-23 08:59:18 +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
|
public enum Priority
|
||||||
{
|
{
|
||||||
|
/// <seealso cref="EphemeralConfig.OnModPathChanged"/>
|
||||||
|
EphemeralConfig = -500,
|
||||||
|
|
||||||
/// <seealso cref="Collections.Cache.CollectionCacheManager.OnModChangeAddition"/>
|
/// <seealso cref="Collections.Cache.CollectionCacheManager.OnModChangeAddition"/>
|
||||||
CollectionCacheManagerAddition = -100,
|
CollectionCacheManagerAddition = -100,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ using Dalamud.Interface.Internal.Notifications;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
|
using Penumbra.Communication;
|
||||||
using Penumbra.Enums;
|
using Penumbra.Enums;
|
||||||
|
using Penumbra.Mods;
|
||||||
|
using Penumbra.Mods.Manager;
|
||||||
using Penumbra.Services;
|
using Penumbra.Services;
|
||||||
using Penumbra.UI;
|
using Penumbra.UI;
|
||||||
using Penumbra.UI.ResourceWatcher;
|
using Penumbra.UI.ResourceWatcher;
|
||||||
|
|
@ -11,11 +14,14 @@ using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||||
|
|
||||||
namespace Penumbra;
|
namespace Penumbra;
|
||||||
|
|
||||||
public class EphemeralConfig : ISavable
|
public class EphemeralConfig : ISavable, IDisposable
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private readonly SaveService _saveService;
|
private readonly SaveService _saveService;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
private readonly ModPathChanged _modPathChanged;
|
||||||
|
|
||||||
public int Version { get; set; } = Configuration.Constants.CurrentVersion;
|
public int Version { get; set; } = Configuration.Constants.CurrentVersion;
|
||||||
public int LastSeenVersion { get; set; } = PenumbraChangelog.LastChangelogVersion;
|
public int LastSeenVersion { get; set; } = PenumbraChangelog.LastChangelogVersion;
|
||||||
public bool DebugSeparateWindow { get; set; } = false;
|
public bool DebugSeparateWindow { get; set; } = false;
|
||||||
|
|
@ -31,17 +37,24 @@ public class EphemeralConfig : ISavable
|
||||||
public TabType SelectedTab { get; set; } = TabType.Settings;
|
public TabType SelectedTab { get; set; } = TabType.Settings;
|
||||||
public ChangedItemDrawer.ChangedItemIcon ChangedItemFilter { get; set; } = ChangedItemDrawer.DefaultFlags;
|
public ChangedItemDrawer.ChangedItemIcon ChangedItemFilter { get; set; } = ChangedItemDrawer.DefaultFlags;
|
||||||
public bool FixMainWindow { get; set; } = false;
|
public bool FixMainWindow { get; set; } = false;
|
||||||
|
public string LastModPath { get; set; } = string.Empty;
|
||||||
|
public bool AdvancedEditingOpen { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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 EphemeralConfig(SaveService saveService)
|
public EphemeralConfig(SaveService saveService, ModPathChanged modPathChanged)
|
||||||
{
|
{
|
||||||
_saveService = saveService;
|
_saveService = saveService;
|
||||||
|
_modPathChanged = modPathChanged;
|
||||||
Load();
|
Load();
|
||||||
|
_modPathChanged.Subscribe(OnModPathChanged, ModPathChanged.Priority.EphemeralConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
=> _modPathChanged.Unsubscribe(OnModPathChanged);
|
||||||
|
|
||||||
private void Load()
|
private void Load()
|
||||||
{
|
{
|
||||||
static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs)
|
static void HandleDeserializationError(object? sender, ErrorEventArgs errorArgs)
|
||||||
|
|
@ -80,8 +93,19 @@ public class EphemeralConfig : ISavable
|
||||||
|
|
||||||
public void Save(StreamWriter writer)
|
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 };
|
var serializer = new JsonSerializer { Formatting = Formatting.Indented };
|
||||||
serializer.Serialize(jWriter, this);
|
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();
|
_materialTab.Reset();
|
||||||
_modelTab.Reset();
|
_modelTab.Reset();
|
||||||
_shaderPackageTab.Reset();
|
_shaderPackageTab.Reset();
|
||||||
|
_config.Ephemeral.AdvancedEditingOpen = false;
|
||||||
|
_config.Ephemeral.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow);
|
using var performance = _performance.Measure(PerformanceType.UiAdvancedWindow);
|
||||||
|
|
||||||
|
if (!_config.Ephemeral.AdvancedEditingOpen)
|
||||||
|
{
|
||||||
|
_config.Ephemeral.AdvancedEditingOpen = true;
|
||||||
|
_config.Ephemeral.Save();
|
||||||
|
}
|
||||||
|
|
||||||
using var tabBar = ImRaii.TabBar("##tabs");
|
using var tabBar = ImRaii.TabBar("##tabs");
|
||||||
if (!tabBar)
|
if (!tabBar)
|
||||||
return;
|
return;
|
||||||
|
|
@ -566,34 +574,36 @@ public partial class ModEditWindow : Window, IDisposable
|
||||||
public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, IDataManager gameData,
|
public ModEditWindow(PerformanceTracker performance, FileDialogService fileDialog, ItemSwapTab itemSwapTab, IDataManager gameData,
|
||||||
Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager,
|
Configuration config, ModEditor editor, ResourceTreeFactory resourceTreeFactory, MetaFileManager metaFileManager,
|
||||||
StainService stainService, ActiveCollections activeCollections, ModMergeTab modMergeTab,
|
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)
|
ChangedItemDrawer changedItemDrawer, IObjectTable objects, IFramework framework, CharacterBaseDestructor characterBaseDestructor)
|
||||||
: base(WindowBaseLabel)
|
: base(WindowBaseLabel)
|
||||||
{
|
{
|
||||||
_performance = performance;
|
_performance = performance;
|
||||||
_itemSwapTab = itemSwapTab;
|
_itemSwapTab = itemSwapTab;
|
||||||
_gameData = gameData;
|
_gameData = gameData;
|
||||||
_config = config;
|
_config = config;
|
||||||
_editor = editor;
|
_editor = editor;
|
||||||
_metaFileManager = metaFileManager;
|
_metaFileManager = metaFileManager;
|
||||||
_stainService = stainService;
|
_stainService = stainService;
|
||||||
_activeCollections = activeCollections;
|
_activeCollections = activeCollections;
|
||||||
_modMergeTab = modMergeTab;
|
_modMergeTab = modMergeTab;
|
||||||
_communicator = communicator;
|
_communicator = communicator;
|
||||||
_dragDropManager = dragDropManager;
|
_dragDropManager = dragDropManager;
|
||||||
_textures = textures;
|
_textures = textures;
|
||||||
_models = models;
|
_models = models;
|
||||||
_fileDialog = fileDialog;
|
_fileDialog = fileDialog;
|
||||||
_objects = objects;
|
_objects = objects;
|
||||||
_framework = framework;
|
_framework = framework;
|
||||||
_characterBaseDestructor = characterBaseDestructor;
|
_characterBaseDestructor = characterBaseDestructor;
|
||||||
_materialTab = new FileEditor<MtrlTab>(this, gameData, config, _editor.Compactor, _fileDialog, "Materials", ".mtrl",
|
_materialTab = new FileEditor<MtrlTab>(this, gameData, config, _editor.Compactor, _fileDialog, "Materials", ".mtrl",
|
||||||
() => PopulateIsOnPlayer(_editor.Files.Mtrl, ResourceType.Mtrl), DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty,
|
() => PopulateIsOnPlayer(_editor.Files.Mtrl, ResourceType.Mtrl), DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty,
|
||||||
(bytes, path, writable) => new MtrlTab(this, new MtrlFile(bytes), path, writable));
|
(bytes, path, writable) => new MtrlTab(this, new MtrlFile(bytes), path, writable));
|
||||||
_modelTab = new FileEditor<MdlTab>(this, gameData, config, _editor.Compactor, _fileDialog, "Models", ".mdl",
|
_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",
|
_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));
|
(bytes, _, _) => new ShpkTab(_fileDialog, bytes));
|
||||||
_center = new CombinedTexture(_left, _right);
|
_center = new CombinedTexture(_left, _right);
|
||||||
_textureSelectCombo = new TextureDrawer.PathSelectCombo(textures, editor, () => GetPlayerResourcesOfType(ResourceType.Tex));
|
_textureSelectCombo = new TextureDrawer.PathSelectCombo(textures, editor, () => GetPlayerResourcesOfType(ResourceType.Tex));
|
||||||
|
|
@ -601,6 +611,7 @@ public partial class ModEditWindow : Window, IDisposable
|
||||||
_quickImportViewer =
|
_quickImportViewer =
|
||||||
new ResourceTreeViewer(_config, resourceTreeFactory, changedItemDrawer, 2, OnQuickImportRefresh, DrawQuickImportActions);
|
new ResourceTreeViewer(_config, resourceTreeFactory, changedItemDrawer, 2, OnQuickImportRefresh, DrawQuickImportActions);
|
||||||
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModEditWindow);
|
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.ModEditWindow);
|
||||||
|
IsOpen = _config is { OpenWindowAtStart: true, Ephemeral.AdvancedEditingOpen: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
|
|
||||||
public ModFileSystemSelector(IKeyState keyState, CommunicatorService communicator, ModFileSystem fileSystem, ModManager modManager,
|
public ModFileSystemSelector(IKeyState keyState, CommunicatorService communicator, ModFileSystem fileSystem, ModManager modManager,
|
||||||
CollectionManager collectionManager, Configuration config, TutorialService tutorial, FileDialogService fileDialog,
|
CollectionManager collectionManager, Configuration config, TutorialService tutorial, FileDialogService fileDialog,
|
||||||
MessageService messager,
|
MessageService messager, ModImportManager modImportManager, IDragDropManager dragDrop)
|
||||||
ModImportManager modImportManager, IDragDropManager dragDrop)
|
|
||||||
: base(fileSystem, keyState, Penumbra.Log, HandleException, allowMultipleSelection: true)
|
: base(fileSystem, keyState, Penumbra.Log, HandleException, allowMultipleSelection: true)
|
||||||
{
|
{
|
||||||
_communicator = communicator;
|
_communicator = communicator;
|
||||||
|
|
@ -77,7 +76,15 @@ public sealed class ModFileSystemSelector : FileSystemSelector<Mod, ModFileSyste
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
SetFilterTooltip();
|
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.CollectionChange.Subscribe(OnCollectionChange, CollectionChange.Priority.ModFileSystemSelector);
|
||||||
_communicator.ModSettingChanged.Subscribe(OnSettingChange, ModSettingChanged.Priority.ModFileSystemSelector);
|
_communicator.ModSettingChanged.Subscribe(OnSettingChange, ModSettingChanged.Priority.ModFileSystemSelector);
|
||||||
_communicator.CollectionInheritanceChanged.Subscribe(OnInheritanceChange, CollectionInheritanceChanged.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, "");
|
OnCollectionChange(CollectionType.Current, null, _collectionManager.Active.Current, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string[] ValidModExtensions = new[]
|
private static readonly string[] ValidModExtensions =
|
||||||
{
|
[
|
||||||
".ttmp",
|
".ttmp",
|
||||||
".ttmp2",
|
".ttmp2",
|
||||||
".pmp",
|
".pmp",
|
||||||
".zip",
|
".zip",
|
||||||
".rar",
|
".rar",
|
||||||
".7z",
|
".7z",
|
||||||
};
|
];
|
||||||
|
|
||||||
public new void Draw(float width)
|
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];
|
(var settings, SelectedSettingCollection) = _collectionManager.Active.Current[newSelection.Index];
|
||||||
SelectedSettings = settings ?? ModSettings.Empty;
|
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.
|
// 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 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 n:[string] to filter only for mod names and no paths.\n"
|
||||||
+ "Enter a:[string] to filter for mods by specific authors.\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.";
|
+ "Use None as a placeholder value that only matches empty lists or names.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue