From 1b3dd819f6b3d2c1e226d77f31c18731503241bf Mon Sep 17 00:00:00 2001 From: Critical Date: Tue, 2 Jul 2024 21:33:08 +1000 Subject: [PATCH] Use IImmediateTexture for notifications --- .../ImGuiNotification/IActiveNotification.cs | 60 ++------------- .../ImGuiNotification/INotification.cs | 20 ++--- .../Internal/ActiveNotification.ImGui.cs | 2 +- .../Internal/ActiveNotification.cs | 73 ++----------------- .../ImGuiNotification/Notification.cs | 11 +-- .../NotificationUtilities.cs | 25 ++++--- .../Windows/Data/Widgets/ImGuiWidget.cs | 60 +++++++-------- 7 files changed, 67 insertions(+), 184 deletions(-) diff --git a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs index 332516315..f9274cdc5 100644 --- a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs @@ -7,6 +7,8 @@ namespace Dalamud.Interface.ImGuiNotification; +using Textures; + /// Represents an active notification. /// Not to be implemented by plugins. public interface IActiveNotification : INotification @@ -52,63 +54,13 @@ public interface IActiveNotification : INotification /// This does not override . void ExtendBy(TimeSpan extension); - /// Sets the icon from , overriding the icon. - /// The new texture wrap to use, or null to clear and revert back to the icon specified + /// Sets the icon from , overriding the icon. + /// The new shared immediate texture to use, or null to clear and revert back to the icon specified /// from . /// - /// The texture passed will be disposed when the notification is dismissed or a new different texture is set - /// via another call to this function or overwriting the property. You do not have to dispose it yourself. - /// If is not null, then calling this function will simply dispose the - /// passed without actually updating the icon. - /// - 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 over overwriting the property. - /// 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); - - /// 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 . - /// Whether to keep the passed not disposed. - /// - /// If is false, the texture 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 it yourself. - /// If is not null and is false, then - /// calling this function will simply dispose the passed without actually updating - /// the icon. - /// - void SetIconTexture(IDalamudTextureWrap? textureWrap, bool leaveOpen); - - /// 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 . - /// Whether to keep the result from the passed not - /// disposed. - /// - /// If is false, 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. + /// If you need to provide a IDalamudTextureWrap that you will be responsible for disposing of, wrap it with . /// - void SetIconTexture(Task? textureWrapTask, bool leaveOpen); + void SetIconTexture(ISharedImmediateTexture? sharedImmediateTexture); /// Generates a new value to use for . /// The new value. diff --git a/Dalamud/Interface/ImGuiNotification/INotification.cs b/Dalamud/Interface/ImGuiNotification/INotification.cs index eab0fd131..e060b728e 100644 --- a/Dalamud/Interface/ImGuiNotification/INotification.cs +++ b/Dalamud/Interface/ImGuiNotification/INotification.cs @@ -6,6 +6,8 @@ namespace Dalamud.Interface.ImGuiNotification; +using Textures; + /// Represents a notification. /// Not to be implemented by plugins. public interface INotification @@ -29,8 +31,8 @@ public interface INotification /// Gets or sets a texture wrap that will be used in place of if set. /// /// A texture wrap set via this property will NOT be disposed when the notification is dismissed. - /// Use or - /// 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. /// This property and are bound together. If the task is not null but @@ -38,19 +40,7 @@ public interface INotification /// the property will return null. Setting this property will set to a new /// completed with the new value as its result. /// - public IDalamudTextureWrap? IconTexture { get; set; } - - /// Gets or sets a task that results in a texture wrap that will be used in place of if - /// available. - /// - /// A texture wrap set via this property will NOT be disposed when the notification is dismissed. - /// Use or - /// to use a texture, after calling - /// . Call either of those functions with null to revert - /// the effective icon back to this property. - /// This property and are bound together. - /// - Task? IconTextureTask { get; set; } + public ISharedImmediateTexture? IconTexture { get; set; } /// Gets or sets the hard expiry. /// diff --git a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.ImGui.cs b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.ImGui.cs index 16d58bea5..fabe14024 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.ImGui.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.ImGui.cs @@ -404,7 +404,7 @@ private void DrawIcon(Vector2 minCoord, Vector2 size) var maxCoord = minCoord + size; var iconColor = this.Type.ToColor(); - if (NotificationUtilities.DrawIconFrom(minCoord, maxCoord, this.IconTextureTask)) + if (NotificationUtilities.DrawIconFrom(minCoord, maxCoord, this.IconTexture)) return; if (this.Icon?.DrawIcon(minCoord, maxCoord, iconColor) is true) diff --git a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs index 607c7c49d..7b884d653 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs @@ -13,6 +13,8 @@ namespace Dalamud.Interface.ImGuiNotification.Internal; +using Textures; + /// Represents an active notification. internal sealed partial class ActiveNotification : IActiveNotification { @@ -23,9 +25,6 @@ internal sealed partial class ActiveNotification : IActiveNotification private readonly Easing progressEasing; private readonly Easing expandoEasing; - /// Whether to call on . - private bool hasIconTextureOwnership; - /// Gets the time of starting to count the timer for the expiration. private DateTime lastInterestTime; @@ -119,31 +118,10 @@ public INotificationIcon? Icon } /// - public IDalamudTextureWrap? IconTexture + public ISharedImmediateTexture? IconTexture { get => this.underlyingNotification.IconTexture; - set => this.IconTextureTask = value is null ? null : Task.FromResult(value); - } - - /// - public Task? IconTextureTask - { - get => this.underlyingNotification.IconTextureTask; - set - { - // Do nothing if the value did not change. - if (this.underlyingNotification.IconTextureTask == value) - return; - - if (this.hasIconTextureOwnership) - { - _ = this.underlyingNotification.IconTextureTask?.ToContentDisposedTask(true); - this.underlyingNotification.IconTextureTask = null; - this.hasIconTextureOwnership = false; - } - - this.underlyingNotification.IconTextureTask = value; - } + set => this.underlyingNotification.IconTexture = value; } /// @@ -266,36 +244,9 @@ public void ExtendBy(TimeSpan extension) } /// - public void SetIconTexture(IDalamudTextureWrap? textureWrap) => - this.SetIconTexture(textureWrap, false); - - /// - public void SetIconTexture(IDalamudTextureWrap? textureWrap, bool leaveOpen) => - this.SetIconTexture(textureWrap is null ? null : Task.FromResult(textureWrap), leaveOpen); - - /// - public void SetIconTexture(Task? textureWrapTask) => - this.SetIconTexture(textureWrapTask, false); - - /// - public void SetIconTexture(Task? textureWrapTask, bool leaveOpen) + public void SetIconTexture(ISharedImmediateTexture? sharedImmediateTexture) { - // If we're requested to replace the texture with the same texture, do nothing. - if (this.underlyingNotification.IconTextureTask == textureWrapTask) - return; - - if (this.DismissReason is not null) - { - if (!leaveOpen) - textureWrapTask?.ToContentDisposedTask(true); - return; - } - - if (this.hasIconTextureOwnership) - _ = this.underlyingNotification.IconTextureTask?.ToContentDisposedTask(true); - - this.hasIconTextureOwnership = !leaveOpen; - this.underlyingNotification.IconTextureTask = textureWrapTask; + this.underlyingNotification.IconTexture = sharedImmediateTexture; } /// Removes non-Dalamud invocation targets from events. @@ -317,11 +268,6 @@ internal void RemoveNonDalamudInvocations() if (this.Icon is { } previousIcon && !IsOwnedByDalamud(previousIcon.GetType())) this.Icon = null; - // Clear the texture if we don't have the ownership. - // The texture probably was owned by the plugin being unloaded in such case. - if (!this.hasIconTextureOwnership) - this.IconTextureTask = null; - this.isInitiatorUnloaded = true; this.UserDismissable = true; this.ExtensionDurationSinceLastInterest = NotificationConstants.DefaultDuration; @@ -400,13 +346,6 @@ internal bool UpdateOrDisposeInternal() /// Clears the resources associated with this instance of . internal void DisposeInternal() { - if (this.hasIconTextureOwnership) - { - _ = this.underlyingNotification.IconTextureTask?.ToContentDisposedTask(true); - this.underlyingNotification.IconTextureTask = null; - this.hasIconTextureOwnership = false; - } - this.Dismiss = null; this.Click = null; this.DrawActions = null; diff --git a/Dalamud/Interface/ImGuiNotification/Notification.cs b/Dalamud/Interface/ImGuiNotification/Notification.cs index 927dd5ba9..4e8871033 100644 --- a/Dalamud/Interface/ImGuiNotification/Notification.cs +++ b/Dalamud/Interface/ImGuiNotification/Notification.cs @@ -6,6 +6,8 @@ namespace Dalamud.Interface.ImGuiNotification; +using Textures; + /// Represents a blueprint for a notification. public sealed record Notification : INotification { @@ -30,14 +32,7 @@ public sealed record Notification : INotification public INotificationIcon? Icon { get; set; } /// - public IDalamudTextureWrap? IconTexture - { - get => this.IconTextureTask?.IsCompletedSuccessfully is true ? this.IconTextureTask.Result : null; - set => this.IconTextureTask = value is null ? null : Task.FromResult(value); - } - - /// - public Task? IconTextureTask { get; set; } + public ISharedImmediateTexture? IconTexture { get; set; } /// public DateTime HardExpiry { get; set; } = DateTime.MaxValue; diff --git a/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs b/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs index 2172663e8..6376f68f5 100644 --- a/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs +++ b/Dalamud/Interface/ImGuiNotification/NotificationUtilities.cs @@ -16,6 +16,8 @@ namespace Dalamud.Interface.ImGuiNotification; +using Textures; + /// Utilities for implementing stuff under . public static class NotificationUtilities { @@ -78,6 +80,19 @@ internal static unsafe bool DrawIconFrom( return true; } + /// 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. + /// The texture. + /// true if anything has been drawn. + internal static bool DrawIconFrom(Vector2 minCoord, Vector2 maxCoord, ISharedImmediateTexture? texture) + { + if (texture is null) + return false; + + return DrawIconFrom(minCoord, maxCoord, texture.GetWrapOrEmpty()); + } + /// 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. @@ -105,16 +120,6 @@ internal static bool DrawIconFrom(Vector2 minCoord, Vector2 maxCoord, IDalamudTe } } - /// 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 05d831b57..c5d3abfa4 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs @@ -15,6 +15,8 @@ namespace Dalamud.Interface.Internal.Windows.Data.Widgets; +using Textures; + /// /// Widget for displaying ImGui test. /// @@ -144,8 +146,6 @@ public void Draw() "Action Bar (always on if not user dismissable for the example)", ref this.notificationTemplate.ActionBar); - ImGui.Checkbox("Leave Textures Open", ref this.notificationTemplate.LeaveTexturesOpen); - if (ImGui.Button("Add notification")) { var text = @@ -212,35 +212,37 @@ public void Draw() switch (this.notificationTemplate.IconInt) { case 5: - n.SetIconTexture( - DisposeLoggingTextureWrap.Wrap( - dam.GetDalamudTextureWrap( - Enum.Parse( - NotificationTemplate.AssetSources[this.notificationTemplate.IconAssetInt]))), - this.notificationTemplate.LeaveTexturesOpen); - break; - case 6: - n.SetIconTexture( - dam.GetDalamudTextureWrapAsync( - Enum.Parse( - NotificationTemplate.AssetSources[this.notificationTemplate.IconAssetInt])) - .ContinueWith( - r => r.IsCompletedSuccessfully - ? Task.FromResult(DisposeLoggingTextureWrap.Wrap(r.Result)) - : r).Unwrap(), - this.notificationTemplate.LeaveTexturesOpen); + var textureWrap = DisposeLoggingTextureWrap.Wrap( + dam.GetDalamudTextureWrap( + Enum.Parse( + NotificationTemplate.AssetSources[this.notificationTemplate.IconAssetInt]))); + + if (textureWrap != null) + { + n.SetIconTexture( + new ForwardingSharedImmediateTexture(textureWrap)); + } + break; case 7: - n.SetIconTexture( - DisposeLoggingTextureWrap.Wrap( - tm.Shared.GetFromGame(this.notificationTemplate.IconText).GetWrapOrDefault()), - this.notificationTemplate.LeaveTexturesOpen); + var textureWrap2 = DisposeLoggingTextureWrap.Wrap( + tm.Shared.GetFromGame(this.notificationTemplate.IconText).GetWrapOrDefault()); + if (textureWrap2 != null) + { + n.SetIconTexture( + new ForwardingSharedImmediateTexture(textureWrap2)); + } + break; case 8: - n.SetIconTexture( - DisposeLoggingTextureWrap.Wrap( - tm.Shared.GetFromFile(this.notificationTemplate.IconText).GetWrapOrDefault()), - this.notificationTemplate.LeaveTexturesOpen); + var textureWrap3 = DisposeLoggingTextureWrap.Wrap( + tm.Shared.GetFromFile(this.notificationTemplate.IconText).GetWrapOrDefault()); + if (textureWrap3 != null) + { + n.SetIconTexture( + new ForwardingSharedImmediateTexture(textureWrap3)); + } + break; } @@ -310,8 +312,8 @@ public void Draw() foreach (var n in this.notifications) { var i = (uint)Random.Shared.NextInt64(0, 200000); - n.IconTexture = DisposeLoggingTextureWrap.Wrap( - Service.Get().Shared.GetFromGameIcon(new(i)).GetWrapOrDefault()); + + n.IconTexture = Service.Get().Shared.GetFromGameIcon(new(i, false, false)); } } }