diff --git a/Penumbra/Communication/ModPathChanged.cs b/Penumbra/Communication/ModPathChanged.cs
index 3ec64f7e..e6291781 100644
--- a/Penumbra/Communication/ModPathChanged.cs
+++ b/Penumbra/Communication/ModPathChanged.cs
@@ -19,6 +19,9 @@ public sealed class ModPathChanged()
{
public enum Priority
{
+ ///
+ EphemeralConfig = -500,
+
///
CollectionCacheManagerAddition = -100,
diff --git a/Penumbra/EphemeralConfig.cs b/Penumbra/EphemeralConfig.cs
index 6c87d331..8cf23de6 100644
--- a/Penumbra/EphemeralConfig.cs
+++ b/Penumbra/EphemeralConfig.cs
@@ -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;
///
/// Load the current configuration.
/// Includes adding new colors and migrating from old versions.
///
- 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);
}
+
+ /// Overwrite the last saved mod path if it changes.
+ 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();
+ }
}
diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs
index 96957ba8..167adafe 100644
--- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs
+++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs
@@ -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(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(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(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()
diff --git a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs
index c42b1018..0990f27b 100644
--- a/Penumbra/UI/ModsTab/ModFileSystemSelector.cs
+++ b/Penumbra/UI/ModsTab/ModFileSystemSelector.cs
@@ -39,8 +39,7 @@ public sealed class ModFileSystemSelector : FileSystemSelector 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