diff --git a/Dalamud/Interface/Textures/Internal/SharedImmediateTextures/SharedImmediateTexture.cs b/Dalamud/Interface/Textures/Internal/SharedImmediateTextures/SharedImmediateTexture.cs
index 07eb52500..ed76223a3 100644
--- a/Dalamud/Interface/Textures/Internal/SharedImmediateTextures/SharedImmediateTexture.cs
+++ b/Dalamud/Interface/Textures/Internal/SharedImmediateTextures/SharedImmediateTexture.cs
@@ -1,9 +1,12 @@
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Interface.Internal;
+using Dalamud.Plugin.Internal.Types;
using Dalamud.Storage.Assets;
using Dalamud.Utility;
@@ -42,6 +45,9 @@ internal abstract class SharedImmediateTexture
this.FirstRequestedTick = this.LatestRequestedTick = Environment.TickCount64;
}
+ /// Gets the list of owner plugins.
+ public List OwnerPlugins { get; } = new();
+
/// Gets the instance ID. Debug use only.
public long InstanceIdForDebug { get; }
@@ -274,6 +280,26 @@ internal abstract class SharedImmediateTexture
return this.availableOnAccessWrapForApi9;
}
+ /// Adds a plugin to , in a thread-safe way.
+ /// The plugin to add.
+ public void AddOwnerPlugin(LocalPlugin plugin)
+ {
+ lock (this.OwnerPlugins)
+ {
+ if (!this.OwnerPlugins.Contains(plugin))
+ {
+ this.OwnerPlugins.Add(plugin);
+ this.UnderlyingWrap?.ContinueWith(
+ r =>
+ {
+ if (r.IsCompletedSuccessfully)
+ Service.Get().Blame(r.Result, plugin);
+ },
+ default(CancellationToken));
+ }
+ }
+ }
+
///
public override string ToString() => $"{this.GetType().Name}#{this.InstanceIdForDebug}({this.SourcePathForDebug})";
@@ -285,11 +311,31 @@ internal abstract class SharedImmediateTexture
}
/// Attempts to restore the reference to this texture.
- protected void LoadUnderlyingWrap() =>
- this.UnderlyingWrap = Service.Get().DynamicPriorityTextureLoader.LoadAsync(
- this,
- this.CreateTextureAsync,
- this.LoadCancellationToken);
+ protected void LoadUnderlyingWrap()
+ {
+ int addLen;
+ lock (this.OwnerPlugins)
+ {
+ this.UnderlyingWrap = Service.Get().DynamicPriorityTextureLoader.LoadAsync(
+ this,
+ this.CreateTextureAsync,
+ this.LoadCancellationToken);
+
+ addLen = this.OwnerPlugins.Count;
+ }
+
+ if (addLen == 0)
+ return;
+ this.UnderlyingWrap.ContinueWith(
+ r =>
+ {
+ if (!r.IsCompletedSuccessfully)
+ return;
+ foreach (var op in this.OwnerPlugins.Take(addLen))
+ Service.Get().Blame(r.Result, op);
+ },
+ default(CancellationToken));
+ }
/// Creates the texture.
/// The cancellation token.
diff --git a/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs b/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs
index a401a9a73..5e47d2c8e 100644
--- a/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs
+++ b/Dalamud/Interface/Textures/Internal/TextureManager.BlameTracker.cs
@@ -48,6 +48,16 @@ internal sealed partial class TextureManager
if (!this.dalamudConfiguration.UseTexturePluginTracking)
return textureWrap;
+ try
+ {
+ if (textureWrap.ImGuiHandle == nint.Zero)
+ return textureWrap;
+ }
+ catch (ObjectDisposedException)
+ {
+ return textureWrap;
+ }
+
using var wrapAux = new WrapAux(textureWrap, true);
var blame = BlameTag.From(wrapAux.ResPtr, out var isNew);
@@ -75,6 +85,16 @@ internal sealed partial class TextureManager
if (!this.dalamudConfiguration.UseTexturePluginTracking)
return textureWrap;
+ try
+ {
+ if (textureWrap.ImGuiHandle == nint.Zero)
+ return textureWrap;
+ }
+ catch (ObjectDisposedException)
+ {
+ return textureWrap;
+ }
+
using var wrapAux = new WrapAux(textureWrap, true);
var blame = BlameTag.From(wrapAux.ResPtr, out var isNew);
blame.Name = name;
diff --git a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.Api9.cs b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.Api9.cs
index 21ee1291c..ca5399d0c 100644
--- a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.Api9.cs
+++ b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.Api9.cs
@@ -14,43 +14,42 @@ internal sealed partial class TextureManagerPluginScoped
///
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
- public IDalamudTextureWrap? GetIcon(
+ string? ITextureProvider.GetIconPath(uint iconId, ITextureProvider.IconFlags flags, ClientLanguage? language)
+ => this.TryGetIconPath(
+ new(
+ iconId,
+ (flags & ITextureProvider.IconFlags.ItemHighQuality) != 0,
+ (flags & ITextureProvider.IconFlags.HiRes) != 0,
+ language),
+ out var path)
+ ? path
+ : null;
+
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ [Obsolete("See interface definition.")]
+ IDalamudTextureWrap? ITextureProvider.GetIcon(
uint iconId,
- ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes,
- ClientLanguage? language = null,
- bool keepAlive = false)
- {
- throw new NotImplementedException();
- }
+ ITextureProvider.IconFlags flags,
+ ClientLanguage? language,
+ bool keepAlive) =>
+ this.ManagerOrThrow.Shared.GetFromGameIcon(
+ new(
+ iconId,
+ (flags & ITextureProvider.IconFlags.ItemHighQuality) != 0,
+ (flags & ITextureProvider.IconFlags.HiRes) != 0,
+ language))
+ .GetAvailableOnAccessWrapForApi9();
///
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
- public string? GetIconPath(
- uint iconId,
- ITextureProvider.IconFlags flags = ITextureProvider.IconFlags.HiRes,
- ClientLanguage? language = null)
- {
- throw new NotImplementedException();
- }
+ IDalamudTextureWrap? ITextureProvider.GetTextureFromGame(string path, bool keepAlive) =>
+ this.ManagerOrThrow.Shared.GetFromGame(path).GetAvailableOnAccessWrapForApi9();
///
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
[Obsolete("See interface definition.")]
- public IDalamudTextureWrap? GetTextureFromGame(
- string path,
- bool keepAlive = false)
- {
- throw new NotImplementedException();
- }
-
- ///
- [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
- [Obsolete("See interface definition.")]
- public IDalamudTextureWrap? GetTextureFromFile(
- FileInfo file,
- bool keepAlive = false)
- {
- throw new NotImplementedException();
- }
+ IDalamudTextureWrap? ITextureProvider.GetTextureFromFile(FileInfo file, bool keepAlive) =>
+ this.ManagerOrThrow.Shared.GetFromFile(file.FullName).GetAvailableOnAccessWrapForApi9();
}
diff --git a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs
index 39b91edda..afdca0f31 100644
--- a/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs
+++ b/Dalamud/Interface/Textures/Internal/TextureManagerPluginScoped.cs
@@ -257,25 +257,33 @@ internal sealed partial class TextureManagerPluginScoped
///
public ISharedImmediateTexture GetFromGameIcon(in GameIconLookup lookup)
{
- return this.ManagerOrThrow.Shared.GetFromGameIcon(lookup);
+ var shared = this.ManagerOrThrow.Shared.GetFromGameIcon(lookup);
+ shared.AddOwnerPlugin(this.plugin);
+ return shared;
}
///
public ISharedImmediateTexture GetFromGame(string path)
{
- return this.ManagerOrThrow.Shared.GetFromGame(path);
+ var shared = this.ManagerOrThrow.Shared.GetFromGame(path);
+ shared.AddOwnerPlugin(this.plugin);
+ return shared;
}
///
public ISharedImmediateTexture GetFromFile(string path)
{
- return this.ManagerOrThrow.Shared.GetFromFile(path);
+ var shared = this.ManagerOrThrow.Shared.GetFromFile(path);
+ shared.AddOwnerPlugin(this.plugin);
+ return shared;
}
///
public ISharedImmediateTexture GetFromManifestResource(Assembly assembly, string name)
{
- return this.ManagerOrThrow.Shared.GetFromManifestResource(assembly, name);
+ var shared = this.ManagerOrThrow.Shared.GetFromManifestResource(assembly, name);
+ shared.AddOwnerPlugin(this.plugin);
+ return shared;
}
///