From 50e05606f35eb4e76051d58e0fd7c33bb4317f5a Mon Sep 17 00:00:00 2001 From: Critical Date: Mon, 1 Jul 2024 19:07:44 +1000 Subject: [PATCH 1/7] Update ITitleScreenMenu --- .../Interface/Internal/DalamudInterface.cs | 8 +-- .../Internal/Windows/TitleScreenMenuWindow.cs | 8 +-- .../TitleScreenMenu/TitleScreenMenu.cs | 38 ++++---------- .../TitleScreenMenu/TitleScreenMenuEntry.cs | 11 ++-- Dalamud/Plugin/Services/ITitleScreenMenu.cs | 10 ++-- Dalamud/Storage/Assets/DalamudAssetTexture.cs | 50 +++++++++++++++++++ 6 files changed, 82 insertions(+), 43 deletions(-) create mode 100644 Dalamud/Storage/Assets/DalamudAssetTexture.cs diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index e95b148a91..83b94147be 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -166,16 +166,16 @@ private DalamudInterface( { titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudPlugins", "Plugin Installer"), - dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall), + new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), this.OpenPluginInstaller); titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudSettings", "Dalamud Settings"), - dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall), + new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), this.OpenSettings); titleScreenMenu.AddEntryCore( "Toggle Dev Menu", - dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall), + new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), () => Service.GetNullable()?.ToggleDevMenu(), VirtualKey.SHIFT); @@ -183,7 +183,7 @@ private DalamudInterface( { titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), - dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall), + new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), () => this.isImGuiDrawDevMenu = true); } }); diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 368a328e10..5b851e02b8 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -355,7 +355,9 @@ private bool DrawEntry( ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1f); } - ImGui.Image(entry.Texture.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale)); + // Wrap should always be valid at this point due to us trying to get the wrap in IsShowConditionSatisfied + var dalamudTextureWrap = entry.Texture.GetWrapOrEmpty(); + ImGui.Image(dalamudTextureWrap.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale)); if (overrideAlpha || isFirst) { ImGui.PopStyleVar(); @@ -369,7 +371,7 @@ private bool DrawEntry( var textHeight = ImGui.GetTextLineHeightWithSpacing(); var cursor = ImGui.GetCursorPos(); - cursor.Y += (entry.Texture.Height * scale / 2) - (textHeight / 2); + cursor.Y += (dalamudTextureWrap.Height * scale / 2) - (textHeight / 2); if (overrideAlpha) { @@ -394,7 +396,7 @@ private bool DrawEntry( ImGui.PopStyleVar(); } - initialCursor.Y += entry.Texture.Height * scale; + initialCursor.Y += dalamudTextureWrap.Height * scale; ImGui.SetCursorPos(initialCursor); return isHover; diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs index 6f98b97574..ee666ab776 100644 --- a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenu.cs @@ -12,6 +12,8 @@ namespace Dalamud.Interface; +using Textures; + /// /// Class responsible for managing elements in the title screen menu. /// @@ -76,13 +78,8 @@ public IReadOnlyList PluginEntries /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - public ITitleScreenMenuEntry AddPluginEntry(string text, IDalamudTextureWrap texture, Action onTriggered) + public ITitleScreenMenuEntry AddPluginEntry(string text, ISharedImmediateTexture texture, Action onTriggered) { - if (texture.Height != TextureSize || texture.Width != TextureSize) - { - throw new ArgumentException("Texture must be 64x64"); - } - TitleScreenMenuEntry entry; lock (this.entries) { @@ -103,13 +100,13 @@ public ITitleScreenMenuEntry AddPluginEntry(string text, IDalamudTextureWrap tex } /// - public IReadOnlyTitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered) + public IReadOnlyTitleScreenMenuEntry AddEntry(string text, ISharedImmediateTexture texture, Action onTriggered) { return this.AddPluginEntry(text, texture, onTriggered); } /// - public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) + public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, ISharedImmediateTexture texture, Action onTriggered) { return this.AddPluginEntry(priority, text, texture, onTriggered); } @@ -123,13 +120,8 @@ public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, IDala /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - public ITitleScreenMenuEntry AddPluginEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) + public ITitleScreenMenuEntry AddPluginEntry(ulong priority, string text, ISharedImmediateTexture texture, Action onTriggered) { - if (texture.Height != TextureSize || texture.Width != TextureSize) - { - throw new ArgumentException("Texture must be 64x64"); - } - TitleScreenMenuEntry entry; lock (this.entries) { @@ -166,13 +158,8 @@ public void RemoveEntry(IReadOnlyTitleScreenMenuEntry entry) /// The action to execute when the option is selected. /// A object that can be used to manage the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - internal TitleScreenMenuEntry AddEntryCore(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) + internal TitleScreenMenuEntry AddEntryCore(ulong priority, string text, ISharedImmediateTexture texture, Action onTriggered) { - if (texture.Height != TextureSize || texture.Width != TextureSize) - { - throw new ArgumentException("Texture must be 64x64"); - } - TitleScreenMenuEntry entry; lock (this.entries) { @@ -199,15 +186,10 @@ internal TitleScreenMenuEntry AddEntryCore(ulong priority, string text, IDalamud /// Thrown when the texture provided does not match the required resolution(64x64). internal TitleScreenMenuEntry AddEntryCore( string text, - IDalamudTextureWrap texture, + ISharedImmediateTexture texture, Action onTriggered, params VirtualKey[] showConditionKeys) { - if (texture.Height != TextureSize || texture.Width != TextureSize) - { - throw new ArgumentException("Texture must be 64x64"); - } - TitleScreenMenuEntry entry; lock (this.entries) { @@ -256,7 +238,7 @@ void IInternalDisposableService.DisposeService() } /// - public IReadOnlyTitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered) + public IReadOnlyTitleScreenMenuEntry AddEntry(string text, ISharedImmediateTexture texture, Action onTriggered) { var entry = this.titleScreenMenuService.AddPluginEntry(text, texture, onTriggered); this.pluginEntries.Add(entry); @@ -265,7 +247,7 @@ public IReadOnlyTitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap t } /// - public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) + public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, ISharedImmediateTexture texture, Action onTriggered) { var entry = this.titleScreenMenuService.AddPluginEntry(priority, text, texture, onTriggered); this.pluginEntries.Add(entry); diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs index 2acb275ad7..e619ea7c71 100644 --- a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs @@ -9,6 +9,8 @@ namespace Dalamud.Interface; +using Textures; + /// /// A interface representing an entry in the title screen menu. /// @@ -64,7 +66,7 @@ public interface IReadOnlyTitleScreenMenuEntry /// /// Gets the texture of this entry. /// - IDalamudTextureWrap Texture { get; } + ISharedImmediateTexture Texture { get; } } /// @@ -87,7 +89,7 @@ internal TitleScreenMenuEntry( Assembly? callingAssembly, ulong priority, string text, - IDalamudTextureWrap texture, + ISharedImmediateTexture texture, Action onTriggered, IEnumerable? showConditionKeys = null) { @@ -106,7 +108,7 @@ internal TitleScreenMenuEntry( public string Name { get; set; } /// - public IDalamudTextureWrap Texture { get; set; } + public ISharedImmediateTexture Texture { get; set; } /// public bool IsInternal { get; set; } @@ -151,7 +153,8 @@ public int CompareTo(TitleScreenMenuEntry? other) /// /// True if met. public bool IsShowConditionSatisfied() => - this.ShowConditionKeys.All(x => Service.GetNullable()?[x] is true); + this.ShowConditionKeys.All(x => Service.GetNullable()?[x] is true) + && this.Texture.TryGetWrap(out var textureWrap, out _) && textureWrap.Width == 64 && textureWrap.Height == 64; /// /// Trigger the action associated with this entry. diff --git a/Dalamud/Plugin/Services/ITitleScreenMenu.cs b/Dalamud/Plugin/Services/ITitleScreenMenu.cs index 5ebd800177..2663c9d066 100644 --- a/Dalamud/Plugin/Services/ITitleScreenMenu.cs +++ b/Dalamud/Plugin/Services/ITitleScreenMenu.cs @@ -6,6 +6,8 @@ namespace Dalamud.Plugin.Services; +using Interface.Textures; + /// /// Interface for class responsible for managing elements in the title screen menu. /// @@ -20,22 +22,22 @@ public interface ITitleScreenMenu /// Adds a new entry to the title screen menu. /// /// The text to show. - /// The texture to show. + /// The texture to show. The texture must be 64x64 or the entry will not draw. /// The action to execute when the option is selected. /// A object that can be reference the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - public IReadOnlyTitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered); + public IReadOnlyTitleScreenMenuEntry AddEntry(string text, ISharedImmediateTexture texture, Action onTriggered); /// /// Adds a new entry to the title screen menu. /// /// Priority of the entry. /// The text to show. - /// The texture to show. + /// The texture to show. The texture must be 64x64 or the entry will not draw. /// The action to execute when the option is selected. /// A object that can be used to reference the entry. /// Thrown when the texture provided does not match the required resolution(64x64). - public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered); + public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, ISharedImmediateTexture texture, Action onTriggered); /// /// Remove an entry from the title screen menu. diff --git a/Dalamud/Storage/Assets/DalamudAssetTexture.cs b/Dalamud/Storage/Assets/DalamudAssetTexture.cs new file mode 100644 index 0000000000..d553538f8e --- /dev/null +++ b/Dalamud/Storage/Assets/DalamudAssetTexture.cs @@ -0,0 +1,50 @@ +using System.Threading; +using System.Threading.Tasks; + +using Dalamud.Interface.Textures; +using Dalamud.Interface.Textures.TextureWraps; + +namespace Dalamud.Storage.Assets; + +/// +/// Wraps a dalamud asset texture allowing interoperability with certain services. +/// +internal class DalamudAssetTexture : ISharedImmediateTexture +{ + private readonly IDalamudTextureWrap textureWrap; + + /// + /// Initializes a new instance of the class. + /// + /// A textureWrap loaded by . + internal DalamudAssetTexture(IDalamudTextureWrap textureWrap) + { + this.textureWrap = textureWrap; + } + + /// + public IDalamudTextureWrap GetWrapOrEmpty() + { + return this.textureWrap; + } + + /// + public IDalamudTextureWrap? GetWrapOrDefault(IDalamudTextureWrap? defaultWrap = null) + { + return this.textureWrap; + } + + /// + public bool TryGetWrap(out IDalamudTextureWrap? texture, out Exception? exception) + { + texture = this.textureWrap; + exception = null; + return true; + } + + /// + public Task RentAsync(CancellationToken cancellationToken = default) + { + return Task.FromResult(this.textureWrap); + } +} From afcc92054f91ce7a1bc1edca22b96a107286ed23 Mon Sep 17 00:00:00 2001 From: Critical Date: Mon, 1 Jul 2024 20:42:25 +1000 Subject: [PATCH 2/7] Make ForwardingSharedImmediateTexture public, remove invalid entries on draw and log error --- .../Interface/Internal/DalamudInterface.cs | 9 +++-- .../Internal/Windows/TitleScreenMenuWindow.cs | 38 ++++++++++++++++++- .../ForwardingSharedImmediateTexture.cs} | 12 +++--- .../TitleScreenMenu/TitleScreenMenuEntry.cs | 3 +- 4 files changed, 49 insertions(+), 13 deletions(-) rename Dalamud/{Storage/Assets/DalamudAssetTexture.cs => Interface/Textures/ForwardingSharedImmediateTexture.cs} (67%) diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index 83b94147be..1d68745202 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -25,6 +25,7 @@ using Dalamud.Interface.Internal.Windows.StyleEditor; using Dalamud.Interface.ManagedFontAtlas.Internals; using Dalamud.Interface.Style; +using Dalamud.Interface.Textures; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; @@ -166,16 +167,16 @@ private DalamudInterface( { titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudPlugins", "Plugin Installer"), - new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), + new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), this.OpenPluginInstaller); titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudSettings", "Dalamud Settings"), - new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), + new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), this.OpenSettings); titleScreenMenu.AddEntryCore( "Toggle Dev Menu", - new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), + new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), () => Service.GetNullable()?.ToggleDevMenu(), VirtualKey.SHIFT); @@ -183,7 +184,7 @@ private DalamudInterface( { titleScreenMenu.AddEntryCore( Loc.Localize("TSMDalamudDevMenu", "Developer Menu"), - new DalamudAssetTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), + new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)), () => this.isImGuiDrawDevMenu = true); } }); diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 5b851e02b8..b5ad77fb64 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -22,6 +22,8 @@ namespace Dalamud.Interface.Internal.Windows; +using Serilog; + /// /// Class responsible for drawing the main plugin window. /// @@ -166,6 +168,23 @@ public override void Draw() if (!entry.IsShowConditionSatisfied()) continue; + if (entry.Texture.TryGetWrap(out var textureWrap, out var exception)) + { + if (textureWrap.Width != 64 && textureWrap.Height != 64) + { + Log.Error("Texture provided for ITitleScreenMenuEntry must be 64x64. Entry will be removed."); + this.titleScreenMenu.RemoveEntry(entry); + continue; + } + } + + if (exception != null) + { + Log.Error(exception, "An exception occurred while attempting to get the texture wrap for a ITitleScreenMenuEntry. Entry will be removed."); + this.titleScreenMenu.RemoveEntry(entry); + continue; + } + if (!this.moveEasings.TryGetValue(entry.Id, out var moveEasing)) { moveEasing = new InOutQuint(TimeSpan.FromMilliseconds(400)); @@ -240,6 +259,23 @@ public override void Draw() if (!entry.IsShowConditionSatisfied()) continue; + if (entry.Texture.TryGetWrap(out var textureWrap, out var exception)) + { + if (textureWrap.Width != 64 && textureWrap.Height != 64) + { + Log.Error($"Texture provided for ITitleScreenMenuEntry {entry.Name} must be 64x64. Entry will be removed."); + this.titleScreenMenu.RemoveEntry(entry); + continue; + } + } + + if (exception != null) + { + Log.Error(exception, $"An exception occurred while attempting to get the texture wrap for ITitleScreenMenuEntry {entry.Name}. Entry will be removed."); + this.titleScreenMenu.RemoveEntry(entry); + continue; + } + var finalPos = (i + 1) * this.shadeTexture.Value.Height * scale; this.DrawEntry(entry, i != 0, true, i == 0, false, false); @@ -355,7 +391,7 @@ private bool DrawEntry( ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1f); } - // Wrap should always be valid at this point due to us trying to get the wrap in IsShowConditionSatisfied + // Wrap should always be valid at this point due to us checking the validity of the image each frame var dalamudTextureWrap = entry.Texture.GetWrapOrEmpty(); ImGui.Image(dalamudTextureWrap.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale)); if (overrideAlpha || isFirst) diff --git a/Dalamud/Storage/Assets/DalamudAssetTexture.cs b/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs similarity index 67% rename from Dalamud/Storage/Assets/DalamudAssetTexture.cs rename to Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs index d553538f8e..bb4c9c2b53 100644 --- a/Dalamud/Storage/Assets/DalamudAssetTexture.cs +++ b/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs @@ -1,23 +1,23 @@ using System.Threading; using System.Threading.Tasks; -using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Storage.Assets; -namespace Dalamud.Storage.Assets; +namespace Dalamud.Interface.Textures; /// -/// Wraps a dalamud asset texture allowing interoperability with certain services. +/// Wraps a dalamud texture allowing interoperability with certain services. Only use this if you need to provide a texture that has been created or rented as a ISharedImmediateTexture. /// -internal class DalamudAssetTexture : ISharedImmediateTexture +public class ForwardingSharedImmediateTexture : ISharedImmediateTexture { private readonly IDalamudTextureWrap textureWrap; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// A textureWrap loaded by . - internal DalamudAssetTexture(IDalamudTextureWrap textureWrap) + public ForwardingSharedImmediateTexture(IDalamudTextureWrap textureWrap) { this.textureWrap = textureWrap; } diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs index e619ea7c71..1d66680049 100644 --- a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs @@ -153,8 +153,7 @@ public int CompareTo(TitleScreenMenuEntry? other) /// /// True if met. public bool IsShowConditionSatisfied() => - this.ShowConditionKeys.All(x => Service.GetNullable()?[x] is true) - && this.Texture.TryGetWrap(out var textureWrap, out _) && textureWrap.Width == 64 && textureWrap.Height == 64; + this.ShowConditionKeys.All(x => Service.GetNullable()?[x] is true); /// /// Trigger the action associated with this entry. From 4e545c496700f83e345936c8934c286b1ba318de Mon Sep 17 00:00:00 2001 From: Critical Date: Tue, 2 Jul 2024 21:33:08 +1000 Subject: [PATCH 3/7] 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 3325163157..f9274cdc51 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 eab0fd1313..e060b728e8 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 16d58bea5a..fabe14024d 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 607c7c49d8..7b884d653a 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 927dd5ba9f..4e88710339 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 2172663e8f..6376f68f5f 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 05d831b577..c5d3abfa4d 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)); } } } From c7d91e0cc3f28711e7784b22db6a64af109c3721 Mon Sep 17 00:00:00 2001 From: Critical Date: Wed, 3 Jul 2024 23:30:42 +1000 Subject: [PATCH 4/7] Clear icon texture when not owned --- .../Interface/ImGuiNotification/Internal/ActiveNotification.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs index 7b884d653a..a40a40fbb4 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs @@ -268,6 +268,9 @@ internal void RemoveNonDalamudInvocations() if (this.Icon is { } previousIcon && !IsOwnedByDalamud(previousIcon.GetType())) this.Icon = null; + if (this.IconTexture is { } iconTexture && iconTexture.TryGetWrap(out var wrap, out _) && !IsOwnedByDalamud(wrap.GetType())) + this.IconTexture = null; + this.isInitiatorUnloaded = true; this.UserDismissable = true; this.ExtensionDurationSinceLastInterest = NotificationConstants.DefaultDuration; From 25565b49cf469e48482401a5cc63bb1dd70ab359 Mon Sep 17 00:00:00 2001 From: Critical Date: Thu, 4 Jul 2024 17:16:22 +1000 Subject: [PATCH 5/7] Restore missing interface methods/properties as wrappers --- .../ImGuiNotification/IActiveNotification.cs | 62 +++++++++++++++++++ .../ImGuiNotification/INotification.cs | 30 ++++++++- .../Internal/ActiveNotification.ImGui.cs | 2 +- .../Internal/ActiveNotification.cs | 54 ++++++++++++++-- .../ImGuiNotification/Notification.cs | 28 ++++++++- .../Windows/Data/Widgets/ImGuiWidget.cs | 2 +- .../ForwardingSharedImmediateTexture.cs | 2 +- Dalamud/Plugin/Services/ITitleScreenMenu.cs | 29 +++++++++ 8 files changed, 200 insertions(+), 9 deletions(-) diff --git a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs index f9274cdc51..ebbdb800d2 100644 --- a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs @@ -62,6 +62,68 @@ public interface IActiveNotification : INotification /// void SetIconTexture(ISharedImmediateTexture? sharedImmediateTexture); + /// 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 . + /// + /// 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. + /// + [Obsolete("Will be removed in API11")] + 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. + /// + [Obsolete("Will be removed in API11")] + 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. + /// + [Obsolete("Will be removed in API11")] + 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. + /// + [Obsolete("Will be removed in API11")] + void SetIconTexture(Task? textureWrapTask, bool leaveOpen); + /// 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 e060b728e8..4ef122010d 100644 --- a/Dalamud/Interface/ImGuiNotification/INotification.cs +++ b/Dalamud/Interface/ImGuiNotification/INotification.cs @@ -40,7 +40,35 @@ 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 ISharedImmediateTexture? IconTexture { get; set; } + public ISharedImmediateTexture? ImmediateIconTexture { get; set; } + + /// 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 + /// . 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 + /// is false (because the task is still in progress or faulted,) + /// the property will return null. Setting this property will set to a new + /// completed with the new value as its result. + /// + [Obsolete("Will be removed in API11")] + 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. + /// + [Obsolete("Will be removed in API11")] + Task? IconTextureTask { 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 fabe14024d..16b42c4c36 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.IconTexture)) + if (NotificationUtilities.DrawIconFrom(minCoord, maxCoord, this.ImmediateIconTexture)) 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 a40a40fbb4..dc65da7fd8 100644 --- a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs +++ b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs @@ -118,12 +118,26 @@ public INotificationIcon? Icon } /// - public ISharedImmediateTexture? IconTexture + public ISharedImmediateTexture? ImmediateIconTexture + { + get => this.underlyingNotification.ImmediateIconTexture; + set => this.underlyingNotification.ImmediateIconTexture = value; + } + + /// + public IDalamudTextureWrap? IconTexture { get => this.underlyingNotification.IconTexture; set => this.underlyingNotification.IconTexture = value; } + /// + public Task? IconTextureTask + { + get => this.underlyingNotification.IconTextureTask; + set => this.underlyingNotification.IconTextureTask = value; + } + /// public DateTime HardExpiry { @@ -246,7 +260,38 @@ public void ExtendBy(TimeSpan extension) /// public void SetIconTexture(ISharedImmediateTexture? sharedImmediateTexture) { - this.underlyingNotification.IconTexture = sharedImmediateTexture; + this.underlyingNotification.ImmediateIconTexture = sharedImmediateTexture; + } + + + /// + [Obsolete("Will be removed in API11")] + public void SetIconTexture(IDalamudTextureWrap? textureWrap) + { + this.SetIconTexture(textureWrap != null ? new ForwardingSharedImmediateTexture(textureWrap) : null); + } + + /// + [Obsolete("Will be removed in API11")] + public void SetIconTexture(Task? textureWrapTask) + { + var result = textureWrapTask?.Result; + this.SetIconTexture(result != null ? new ForwardingSharedImmediateTexture(result) : null); + } + + /// + [Obsolete("Will be removed in API11")] + public void SetIconTexture(IDalamudTextureWrap? textureWrap, bool leaveOpen) + { + this.SetIconTexture(textureWrap != null ? new ForwardingSharedImmediateTexture(textureWrap) : null); + } + + /// + [Obsolete("Will be removed in API11")] + public void SetIconTexture(Task? textureWrapTask, bool leaveOpen) + { + var result = textureWrapTask?.Result; + this.SetIconTexture(result != null ? new ForwardingSharedImmediateTexture(result) : null); } /// Removes non-Dalamud invocation targets from events. @@ -268,8 +313,9 @@ internal void RemoveNonDalamudInvocations() if (this.Icon is { } previousIcon && !IsOwnedByDalamud(previousIcon.GetType())) this.Icon = null; - if (this.IconTexture is { } iconTexture && iconTexture.TryGetWrap(out var wrap, out _) && !IsOwnedByDalamud(wrap.GetType())) - this.IconTexture = null; + + if (this.ImmediateIconTexture is { } iconTexture && (!IsOwnedByDalamud(iconTexture.GetType()) || (iconTexture.TryGetWrap(out var wrap, out _) && !IsOwnedByDalamud(wrap.GetType())))) + this.ImmediateIconTexture = null; this.isInitiatorUnloaded = true; this.UserDismissable = true; diff --git a/Dalamud/Interface/ImGuiNotification/Notification.cs b/Dalamud/Interface/ImGuiNotification/Notification.cs index 4e88710339..b78b94b22e 100644 --- a/Dalamud/Interface/ImGuiNotification/Notification.cs +++ b/Dalamud/Interface/ImGuiNotification/Notification.cs @@ -32,7 +32,33 @@ public sealed record Notification : INotification public INotificationIcon? Icon { get; set; } /// - public ISharedImmediateTexture? IconTexture { get; set; } + public ISharedImmediateTexture? ImmediateIconTexture { get; set; } + + /// + public IDalamudTextureWrap? IconTexture + { + get => this.ImmediateIconTexture?.GetWrapOrDefault(); + set => this.ImmediateIconTexture = value != null ? new ForwardingSharedImmediateTexture(value) : null; + } + + /// + public Task? IconTextureTask + { + get => Task.FromResult(this.ImmediateIconTexture?.GetWrapOrDefault()); + + set + { + if (value == null) + { + this.ImmediateIconTexture = null; + } + else + { + var dalamudTextureWrap = value.Result; + this.ImmediateIconTexture = dalamudTextureWrap == null ? null : new ForwardingSharedImmediateTexture(dalamudTextureWrap); + } + } + } /// public DateTime HardExpiry { get; set; } = DateTime.MaxValue; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs index c5d3abfa4d..adf7bfa8ce 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs @@ -313,7 +313,7 @@ public void Draw() { var i = (uint)Random.Shared.NextInt64(0, 200000); - n.IconTexture = Service.Get().Shared.GetFromGameIcon(new(i, false, false)); + n.ImmediateIconTexture = Service.Get().Shared.GetFromGameIcon(new(i, false, false)); } } } diff --git a/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs b/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs index bb4c9c2b53..12e312b3e3 100644 --- a/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs +++ b/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs @@ -16,7 +16,7 @@ public class ForwardingSharedImmediateTexture : ISharedImmediateTexture /// /// Initializes a new instance of the class. /// - /// A textureWrap loaded by . + /// A textureWrap that has been created or provided by RentAsync. public ForwardingSharedImmediateTexture(IDalamudTextureWrap textureWrap) { this.textureWrap = textureWrap; diff --git a/Dalamud/Plugin/Services/ITitleScreenMenu.cs b/Dalamud/Plugin/Services/ITitleScreenMenu.cs index 2663c9d066..d1b72af8d1 100644 --- a/Dalamud/Plugin/Services/ITitleScreenMenu.cs +++ b/Dalamud/Plugin/Services/ITitleScreenMenu.cs @@ -39,6 +39,35 @@ public interface ITitleScreenMenu /// Thrown when the texture provided does not match the required resolution(64x64). public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, ISharedImmediateTexture texture, Action onTriggered); + /// + /// Adds a new entry to the title screen menu. + /// + /// The text to show. + /// The texture to show. The texture must be 64x64 or the entry will not draw. Please use ISharedImmediateTexture or a ForwardingSharedImmediateTexture if possible. + /// The action to execute when the option is selected. + /// A object that can be reference the entry. + /// Thrown when the texture provided does not match the required resolution(64x64). + [Obsolete("Will be removed in API11")] + public IReadOnlyTitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered) + { + return this.AddEntry(text, new ForwardingSharedImmediateTexture(texture), onTriggered); + } + + /// + /// Adds a new entry to the title screen menu. + /// + /// Priority of the entry. + /// The text to show. + /// The texture to show. The texture must be 64x64 or the entry will not draw. Please use ISharedImmediateTexture or a ForwardingSharedImmediateTexture if possible. + /// The action to execute when the option is selected. + /// A object that can be used to reference the entry. + /// Thrown when the texture provided does not match the required resolution(64x64). + [Obsolete("Will be removed in API11")] + public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered) + { + return this.AddEntry(priority, text, new ForwardingSharedImmediateTexture(texture), onTriggered); + } + /// /// Remove an entry from the title screen menu. /// From 878d4dfd16a46d33d1f7a45aecc9d9a0f0c631db Mon Sep 17 00:00:00 2001 From: Critical Date: Thu, 4 Jul 2024 17:28:21 +1000 Subject: [PATCH 6/7] Catch task exception --- .../ImGuiNotification/Notification.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Dalamud/Interface/ImGuiNotification/Notification.cs b/Dalamud/Interface/ImGuiNotification/Notification.cs index b78b94b22e..e61db25bc1 100644 --- a/Dalamud/Interface/ImGuiNotification/Notification.cs +++ b/Dalamud/Interface/ImGuiNotification/Notification.cs @@ -1,13 +1,11 @@ using System.Threading.Tasks; using Dalamud.Interface.ImGuiNotification.Internal; -using Dalamud.Interface.Internal; +using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; +using Serilog; namespace Dalamud.Interface.ImGuiNotification; - -using Textures; - /// Represents a blueprint for a notification. public sealed record Notification : INotification { @@ -54,8 +52,17 @@ public Task? IconTextureTask } else { - var dalamudTextureWrap = value.Result; - this.ImmediateIconTexture = dalamudTextureWrap == null ? null : new ForwardingSharedImmediateTexture(dalamudTextureWrap); + try + { + var dalamudTextureWrap = value.Result; + this.ImmediateIconTexture = dalamudTextureWrap == null ? null : new ForwardingSharedImmediateTexture(dalamudTextureWrap); + } + catch (Exception exception) + { + Log.Error( + exception, + $"[{nameof(Notification)}: IconTextureTask provided threw exception."); + } } } } From 778f48d7608df0141337ef0a3258d340a2107373 Mon Sep 17 00:00:00 2001 From: Critical Date: Thu, 4 Jul 2024 17:44:40 +1000 Subject: [PATCH 7/7] Add missing properties into TitleScreenMenu --- .../Interface/ImGuiNotification/Notification.cs | 1 + .../Internal/Windows/TitleScreenMenuWindow.cs | 8 ++++---- .../TitleScreenMenu/TitleScreenMenuEntry.cs | 15 ++++++++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Dalamud/Interface/ImGuiNotification/Notification.cs b/Dalamud/Interface/ImGuiNotification/Notification.cs index e61db25bc1..7f82f81407 100644 --- a/Dalamud/Interface/ImGuiNotification/Notification.cs +++ b/Dalamud/Interface/ImGuiNotification/Notification.cs @@ -62,6 +62,7 @@ public Task? IconTextureTask Log.Error( exception, $"[{nameof(Notification)}: IconTextureTask provided threw exception."); + this.ImmediateIconTexture = null; } } } diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index b5ad77fb64..6ea58938a1 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -45,7 +45,7 @@ internal class TitleScreenMenuWindow : Window, IDisposable private readonly Dictionary shadeEasings = new(); private readonly Dictionary moveEasings = new(); private readonly Dictionary logoEasings = new(); - + private readonly IConsoleVariable showTsm; private InOutCubic? fadeOutEasing; @@ -168,7 +168,7 @@ public override void Draw() if (!entry.IsShowConditionSatisfied()) continue; - if (entry.Texture.TryGetWrap(out var textureWrap, out var exception)) + if (entry.ImmediateTexture.TryGetWrap(out var textureWrap, out var exception)) { if (textureWrap.Width != 64 && textureWrap.Height != 64) { @@ -259,7 +259,7 @@ public override void Draw() if (!entry.IsShowConditionSatisfied()) continue; - if (entry.Texture.TryGetWrap(out var textureWrap, out var exception)) + if (entry.ImmediateTexture.TryGetWrap(out var textureWrap, out var exception)) { if (textureWrap.Width != 64 && textureWrap.Height != 64) { @@ -392,7 +392,7 @@ private bool DrawEntry( } // Wrap should always be valid at this point due to us checking the validity of the image each frame - var dalamudTextureWrap = entry.Texture.GetWrapOrEmpty(); + var dalamudTextureWrap = entry.ImmediateTexture.GetWrapOrEmpty(); ImGui.Image(dalamudTextureWrap.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale)); if (overrideAlpha || isFirst) { diff --git a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs index 1d66680049..d25ac619c8 100644 --- a/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs +++ b/Dalamud/Interface/TitleScreenMenu/TitleScreenMenuEntry.cs @@ -66,7 +66,13 @@ public interface IReadOnlyTitleScreenMenuEntry /// /// Gets the texture of this entry. /// - ISharedImmediateTexture Texture { get; } + [Obsolete("Will be removed in API11")] + IDalamudTextureWrap Texture { get; } + + /// + /// Gets the immediate texture of this entry. + /// + ISharedImmediateTexture ImmediateTexture { get; } } /// @@ -96,7 +102,7 @@ internal TitleScreenMenuEntry( this.CallingAssembly = callingAssembly; this.Priority = priority; this.Name = text; - this.Texture = texture; + this.ImmediateTexture = texture; this.onTriggered = onTriggered; this.ShowConditionKeys = (showConditionKeys ?? Array.Empty()).ToImmutableSortedSet(); } @@ -108,7 +114,10 @@ internal TitleScreenMenuEntry( public string Name { get; set; } /// - public ISharedImmediateTexture Texture { get; set; } + public IDalamudTextureWrap Texture => this.ImmediateTexture.GetWrapOrEmpty(); + + /// + public ISharedImmediateTexture ImmediateTexture { get; set; } /// public bool IsInternal { get; set; }