diff --git a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs index c3ea2b9de..e677471b4 100644 --- a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs @@ -1,4 +1,5 @@ using System.Threading; +using System.Threading.Tasks; using Dalamud.Interface.ImGuiNotification.EventArgs; using Dalamud.Interface.Internal; @@ -50,7 +51,7 @@ public interface IActiveNotification : INotification /// This does not override . void ExtendBy(TimeSpan extension); - /// Sets the icon from , overriding the icon . + /// Sets the icon from , overriding the icon. /// The new texture wrap to use, or null to clear and revert back to the icon specified /// from . /// @@ -61,6 +62,21 @@ public interface IActiveNotification : INotification /// void SetIconTexture(IDalamudTextureWrap? textureWrap); + /// Sets the icon from , overriding the icon, once the given task + /// completes. + /// The task that will result in a new texture wrap to use, or null to clear and + /// revert back to the icon specified from . + /// + /// The texture resulted from the passed will be disposed when the notification + /// is dismissed or a new different texture is set via another call to this function. You do not have to dispose the + /// resulted instance of yourself. + /// If the task fails for any reason, the exception will be silently ignored and the icon specified from + /// will be used instead. + /// If is not null, then calling this function will simply dispose the + /// result of the passed without actually updating the icon. + /// + void SetIconTexture(Task? textureWrapTask); + /// Generates a new value to use for . /// The new value. internal static long CreateNewId() => Interlocked.Increment(ref idCounter); diff --git a/Dalamud/Interface/ImGuiNotification/INotification.cs b/Dalamud/Interface/ImGuiNotification/INotification.cs index 2bc8e751c..207722c56 100644 --- a/Dalamud/Interface/ImGuiNotification/INotification.cs +++ b/Dalamud/Interface/ImGuiNotification/INotification.cs @@ -1,3 +1,6 @@ +using System.Threading.Tasks; + +using Dalamud.Interface.Internal; using Dalamud.Interface.Internal.Notifications; using Dalamud.Plugin.Services; @@ -20,8 +23,10 @@ public interface INotification NotificationType Type { get; set; } /// Gets or sets the icon source. - /// Use to use a texture, after calling - /// . + /// Use or + /// to use a texture, after calling + /// . Call either of those functions with null to revert + /// the effective icon back to this property. INotificationIcon? Icon { get; set; } /// Gets or sets the hard expiry. diff --git a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs index a9950745d..c54a9c6fa 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs @@ -1,5 +1,6 @@ using System.Runtime.Loader; using System.Threading; +using System.Threading.Tasks; using Dalamud.Interface.Animation; using Dalamud.Interface.Animation.EasingFunctions; @@ -29,7 +30,7 @@ internal sealed partial class ActiveNotification : IActiveNotification private DateTime extendedExpiry; /// The icon texture to use if specified; otherwise, icon will be used from . - private IDalamudTextureWrap? iconTextureWrap; + private Task? iconTextureWrap; /// The plugin that initiated this notification. private LocalPlugin? initiatorPlugin; @@ -229,18 +230,24 @@ internal sealed partial class ActiveNotification : IActiveNotification /// public void SetIconTexture(IDalamudTextureWrap? textureWrap) + { + this.SetIconTexture(textureWrap is null ? null : Task.FromResult(textureWrap)); + } + + /// + public void SetIconTexture(Task? textureWrapTask) { if (this.DismissReason is not null) { - textureWrap?.Dispose(); + textureWrapTask?.ToContentDisposedTask(true); return; } // After replacing, if the old texture is not the old texture, then dispose the old texture. - if (Interlocked.Exchange(ref this.iconTextureWrap, textureWrap) is { } wrapToDispose && - wrapToDispose != textureWrap) + if (Interlocked.Exchange(ref this.iconTextureWrap, textureWrapTask) is { } wrapTaskToDispose && + wrapTaskToDispose != textureWrapTask) { - wrapToDispose.Dispose(); + wrapTaskToDispose.ToContentDisposedTask(true); } } @@ -333,8 +340,8 @@ internal sealed partial class ActiveNotification : IActiveNotification /// Clears the resources associated with this instance of . internal void DisposeInternal() { - if (Interlocked.Exchange(ref this.iconTextureWrap, null) is { } wrapToDispose) - wrapToDispose.Dispose(); + if (Interlocked.Exchange(ref this.iconTextureWrap, null) is { } wrapTaskToDispose) + wrapTaskToDispose.ToContentDisposedTask(true); this.Dismiss = null; this.Click = null; this.DrawActions = null; diff --git a/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs b/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs index 0ec2561fd..0ed552b42 100644 --- a/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs +++ b/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs @@ -1,6 +1,7 @@ using System.IO; using System.Numerics; using System.Runtime.CompilerServices; +using System.Threading.Tasks; using Dalamud.Game.Text; using Dalamud.Interface.Internal; @@ -103,6 +104,16 @@ public static class NotificationUtilities } } + /// Draws an icon from an instance of that results in an + /// . + /// The coordinates of the top left of the icon area. + /// The coordinates of the bottom right of the icon area. + /// The task that results in a texture. + /// true if anything has been drawn. + /// Exceptions from the task will be treated as if no texture is provided. + internal static bool DrawIconFrom(Vector2 minCoord, Vector2 maxCoord, Task? textureTask) => + textureTask?.IsCompletedSuccessfully is true && DrawIconFrom(minCoord, maxCoord, textureTask.Result); + /// Draws an icon from an instance of . /// The coordinates of the top left of the icon area. /// The coordinates of the bottom right of the icon area. diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs index 47c5993cd..95119bb48 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs @@ -88,20 +88,20 @@ internal class ImGuiWidget : IDataWindowWidget ref this.notificationTemplate.IconText, 255); break; - case 3 or 4: + case 5 or 6: ImGui.Combo( "Asset##iconAssetCombo", ref this.notificationTemplate.IconAssetInt, NotificationTemplate.AssetSources, NotificationTemplate.AssetSources.Length); break; - case 5 or 7: + case 3 or 7: ImGui.InputText( "Game Path##iconText", ref this.notificationTemplate.IconText, 255); break; - case 6 or 8: + case 4 or 8: ImGui.InputText( "File Path##iconText", ref this.notificationTemplate.IconText, @@ -206,9 +206,15 @@ internal class ImGuiWidget : IDataWindowWidget NotificationTemplate.AssetSources[this.notificationTemplate.IconAssetInt]))); break; case 6: - n.SetIconTexture(tm.GetTextureFromGame(this.notificationTemplate.IconText)); + n.SetIconTexture( + dam.GetDalamudTextureWrapAsync( + Enum.Parse( + NotificationTemplate.AssetSources[this.notificationTemplate.IconAssetInt]))); break; case 7: + n.SetIconTexture(tm.GetTextureFromGame(this.notificationTemplate.IconText)); + break; + case 8: n.SetIconTexture(tm.GetTextureFromFile(new(this.notificationTemplate.IconText))); break; } @@ -315,6 +321,7 @@ internal class ImGuiWidget : IDataWindowWidget "GamePath", "FilePath", "TextureWrap from DalamudAssets", + "TextureWrap from DalamudAssets(Async)", "TextureWrap from GamePath", "TextureWrap from FilePath", };