From 5346abaadf34171d81a0525f16e44d1437eb2a9b Mon Sep 17 00:00:00 2001 From: Exter-N Date: Wed, 30 Aug 2023 01:51:43 +0200 Subject: [PATCH] Material editor: tear down previewers bound to a CharacterBase that goes away --- .../ModEditWindow.Materials.LivePreview.cs | 2 +- .../ModEditWindow.Materials.MtrlTab.cs | 28 +++++++++++++++++++ Penumbra/UI/AdvancedWindow/ModEditWindow.cs | 5 +++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.LivePreview.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.LivePreview.cs index 7d400a71..76ac8915 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.LivePreview.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.LivePreview.cs @@ -154,7 +154,7 @@ public partial class ModEditWindow protected readonly int ModelSlot; protected readonly int MaterialSlot; - protected readonly CharacterBase* DrawObject; + public readonly CharacterBase* DrawObject; protected readonly Material* Material; protected bool Valid; diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs index 9061cc98..6677db5b 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs @@ -512,6 +512,29 @@ public partial class ModEditWindow ColorSetPreviewers.Clear(); } + public unsafe void UnbindFromDrawObjectMaterialInstances(nint characterBase) + { + for (var i = MaterialPreviewers.Count; i-- > 0; ) + { + var previewer = MaterialPreviewers[i]; + if ((nint)previewer.DrawObject != characterBase) + continue; + + previewer.Dispose(); + MaterialPreviewers.RemoveAt(i); + } + + for (var i = ColorSetPreviewers.Count; i-- > 0;) + { + var previewer = ColorSetPreviewers[i]; + if ((nint)previewer.DrawObject != characterBase) + continue; + + previewer.Dispose(); + ColorSetPreviewers.RemoveAt(i); + } + } + public void SetShaderPackageFlags(uint shPkFlags) { foreach (var previewer in MaterialPreviewers) @@ -665,7 +688,10 @@ public partial class ModEditWindow AssociatedBaseDevkit = TryLoadShpkDevkit( "_base", out LoadedBaseDevkitPathName ); LoadShpk( FindAssociatedShpk( out _, out _ ) ); if (writable) + { + _edit._gameEvents.CharacterBaseDestructor += UnbindFromDrawObjectMaterialInstances; BindToMaterialInstances(); + } } ~MtrlTab() @@ -682,6 +708,8 @@ public partial class ModEditWindow private void DoDispose() { UnbindFromMaterialInstances(); + if (Writable) + _edit._gameEvents.CharacterBaseDestructor -= UnbindFromDrawObjectMaterialInstances; } public bool Valid diff --git a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs index f1c78bf7..e40a7915 100644 --- a/Penumbra/UI/AdvancedWindow/ModEditWindow.cs +++ b/Penumbra/UI/AdvancedWindow/ModEditWindow.cs @@ -19,6 +19,7 @@ using Penumbra.GameData.Enums; using Penumbra.GameData.Files; using Penumbra.Import.Textures; using Penumbra.Interop.ResourceTree; +using Penumbra.Interop.Services; using Penumbra.Meta; using Penumbra.Mods; using Penumbra.Mods.Manager; @@ -45,6 +46,7 @@ public partial class ModEditWindow : Window, IDisposable private readonly ModMergeTab _modMergeTab; private readonly CommunicatorService _communicator; private readonly IDragDropManager _dragDropManager; + private readonly GameEventManager _gameEvents; private Mod? _mod; private Vector2 _iconSize = Vector2.Zero; @@ -546,7 +548,7 @@ 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, DalamudServices dalamud, ModMergeTab modMergeTab, - CommunicatorService communicator, TextureManager textures, IDragDropManager dragDropManager) + CommunicatorService communicator, TextureManager textures, IDragDropManager dragDropManager, GameEventManager gameEvents) : base(WindowBaseLabel) { _performance = performance; @@ -562,6 +564,7 @@ public partial class ModEditWindow : Window, IDisposable _dragDropManager = dragDropManager; _textures = textures; _fileDialog = fileDialog; + _gameEvents = gameEvents; _materialTab = new FileEditor(this, gameData, config, _fileDialog, "Materials", ".mtrl", () => _editor.Files.Mtrl, DrawMaterialPanel, () => _mod?.ModPath.FullName ?? string.Empty, (bytes, path, writable) => new MtrlTab(this, new MtrlFile(bytes), path, writable));