Material editor: tear down previewers bound to a CharacterBase that goes away

This commit is contained in:
Exter-N 2023-08-30 01:51:43 +02:00
parent bb8d9441f4
commit 5346abaadf
3 changed files with 33 additions and 2 deletions

View file

@ -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;

View file

@ -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,8 +688,11 @@ 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

View file

@ -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<MtrlTab>(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));