diff --git a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs
index 3325163157..ebbdb800d2 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,6 +54,14 @@ public interface IActiveNotification : INotification
/// This does not override .
void ExtendBy(TimeSpan extension);
+ /// 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 .
+ ///
+ /// If you need to provide a IDalamudTextureWrap that you will be responsible for disposing of, wrap it with .
+ ///
+ 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 .
@@ -61,6 +71,7 @@ public interface IActiveNotification : INotification
/// 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
@@ -76,6 +87,7 @@ public interface IActiveNotification : INotification
/// 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.
@@ -90,6 +102,7 @@ public interface IActiveNotification : INotification
/// 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
@@ -108,6 +121,7 @@ public interface IActiveNotification : INotification
/// 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 .
diff --git a/Dalamud/Interface/ImGuiNotification/INotification.cs b/Dalamud/Interface/ImGuiNotification/INotification.cs
index eab0fd1313..4ef122010d 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
@@ -26,6 +28,20 @@ public interface INotification
///
INotificationIcon? Icon { 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.
+ ///
+ 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.
@@ -38,6 +54,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.
///
+ [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
@@ -50,6 +67,7 @@ public interface INotification
/// 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 16d58bea5a..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.IconTextureTask))
+ 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 607c7c49d8..dc65da7fd8 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;
@@ -118,32 +117,25 @@ public INotificationIcon? Icon
set => this.underlyingNotification.Icon = value;
}
+ ///
+ public ISharedImmediateTexture? ImmediateIconTexture
+ {
+ get => this.underlyingNotification.ImmediateIconTexture;
+ set => this.underlyingNotification.ImmediateIconTexture = value;
+ }
+
///
public IDalamudTextureWrap? IconTexture
{
get => this.underlyingNotification.IconTexture;
- set => this.IconTextureTask = value is null ? null : Task.FromResult(value);
+ set => this.underlyingNotification.IconTexture = 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.IconTextureTask = value;
}
///
@@ -266,36 +258,40 @@ public void ExtendBy(TimeSpan extension)
}
///
- public void SetIconTexture(IDalamudTextureWrap? textureWrap) =>
- this.SetIconTexture(textureWrap, false);
+ public void SetIconTexture(ISharedImmediateTexture? sharedImmediateTexture)
+ {
+ this.underlyingNotification.ImmediateIconTexture = sharedImmediateTexture;
+ }
- ///
- 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);
+ [Obsolete("Will be removed in API11")]
+ public void SetIconTexture(IDalamudTextureWrap? textureWrap)
+ {
+ this.SetIconTexture(textureWrap != null ? new ForwardingSharedImmediateTexture(textureWrap) : null);
+ }
///
- public void SetIconTexture(Task? textureWrapTask, bool leaveOpen)
+ [Obsolete("Will be removed in API11")]
+ public void SetIconTexture(Task? textureWrapTask)
{
- // 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;
- }
+ var result = textureWrapTask?.Result;
+ this.SetIconTexture(result != null ? new ForwardingSharedImmediateTexture(result) : null);
+ }
- if (this.hasIconTextureOwnership)
- _ = this.underlyingNotification.IconTextureTask?.ToContentDisposedTask(true);
+ ///
+ [Obsolete("Will be removed in API11")]
+ public void SetIconTexture(IDalamudTextureWrap? textureWrap, bool leaveOpen)
+ {
+ this.SetIconTexture(textureWrap != null ? new ForwardingSharedImmediateTexture(textureWrap) : null);
+ }
- this.hasIconTextureOwnership = !leaveOpen;
- this.underlyingNotification.IconTextureTask = textureWrapTask;
+ ///
+ [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.
@@ -317,10 +313,9 @@ 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;
+
+ 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;
@@ -400,13 +395,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..7f82f81407 100644
--- a/Dalamud/Interface/ImGuiNotification/Notification.cs
+++ b/Dalamud/Interface/ImGuiNotification/Notification.cs
@@ -1,11 +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;
-
/// Represents a blueprint for a notification.
public sealed record Notification : INotification
{
@@ -29,15 +29,44 @@ public sealed record Notification : INotification
///
public INotificationIcon? Icon { get; set; }
+ ///
+ public ISharedImmediateTexture? ImmediateIconTexture { 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);
+ get => this.ImmediateIconTexture?.GetWrapOrDefault();
+ set => this.ImmediateIconTexture = value != null ? new ForwardingSharedImmediateTexture(value) : null;
}
///
- public Task? IconTextureTask { get; set; }
+ public Task? IconTextureTask
+ {
+ get => Task.FromResult(this.ImmediateIconTexture?.GetWrapOrDefault());
+
+ set
+ {
+ if (value == null)
+ {
+ this.ImmediateIconTexture = null;
+ }
+ else
+ {
+ 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.");
+ this.ImmediateIconTexture = null;
+ }
+ }
+ }
+ }
///
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/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs
index e95b148a91..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"),
- dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall),
+ new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)),
this.OpenPluginInstaller);
titleScreenMenu.AddEntryCore(
Loc.Localize("TSMDalamudSettings", "Dalamud Settings"),
- dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall),
+ new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)),
this.OpenSettings);
titleScreenMenu.AddEntryCore(
"Toggle Dev Menu",
- 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"),
- dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall),
+ new ForwardingSharedImmediateTexture(dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.LogoSmall)),
() => this.isImGuiDrawDevMenu = true);
}
});
diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs
index 05d831b577..adf7bfa8ce 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.ImmediateIconTexture = Service.Get().Shared.GetFromGameIcon(new(i, false, false));
}
}
}
diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs
index 368a328e10..6ea58938a1 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.
///
@@ -43,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;
@@ -166,6 +168,23 @@ public override void Draw()
if (!entry.IsShowConditionSatisfied())
continue;
+ if (entry.ImmediateTexture.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.ImmediateTexture.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,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 checking the validity of the image each frame
+ var dalamudTextureWrap = entry.ImmediateTexture.GetWrapOrEmpty();
+ ImGui.Image(dalamudTextureWrap.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale));
if (overrideAlpha || isFirst)
{
ImGui.PopStyleVar();
@@ -369,7 +407,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 +432,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/Textures/ForwardingSharedImmediateTexture.cs b/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs
new file mode 100644
index 0000000000..12e312b3e3
--- /dev/null
+++ b/Dalamud/Interface/Textures/ForwardingSharedImmediateTexture.cs
@@ -0,0 +1,50 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+using Dalamud.Interface.Textures.TextureWraps;
+using Dalamud.Storage.Assets;
+
+namespace Dalamud.Interface.Textures;
+
+///
+/// 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.
+///
+public class ForwardingSharedImmediateTexture : ISharedImmediateTexture
+{
+ private readonly IDalamudTextureWrap textureWrap;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A textureWrap that has been created or provided by RentAsync.
+ public ForwardingSharedImmediateTexture(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);
+ }
+}
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..d25ac619c8 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,13 @@ public interface IReadOnlyTitleScreenMenuEntry
///
/// Gets the texture of this entry.
///
+ [Obsolete("Will be removed in API11")]
IDalamudTextureWrap Texture { get; }
+
+ ///
+ /// Gets the immediate texture of this entry.
+ ///
+ ISharedImmediateTexture ImmediateTexture { get; }
}
///
@@ -87,14 +95,14 @@ internal TitleScreenMenuEntry(
Assembly? callingAssembly,
ulong priority,
string text,
- IDalamudTextureWrap texture,
+ ISharedImmediateTexture texture,
Action onTriggered,
IEnumerable? showConditionKeys = null)
{
this.CallingAssembly = callingAssembly;
this.Priority = priority;
this.Name = text;
- this.Texture = texture;
+ this.ImmediateTexture = texture;
this.onTriggered = onTriggered;
this.ShowConditionKeys = (showConditionKeys ?? Array.Empty()).ToImmutableSortedSet();
}
@@ -106,7 +114,10 @@ internal TitleScreenMenuEntry(
public string Name { get; set; }
///
- public IDalamudTextureWrap Texture { get; set; }
+ public IDalamudTextureWrap Texture => this.ImmediateTexture.GetWrapOrEmpty();
+
+ ///
+ public ISharedImmediateTexture ImmediateTexture { get; set; }
///
public bool IsInternal { get; set; }
diff --git a/Dalamud/Plugin/Services/ITitleScreenMenu.cs b/Dalamud/Plugin/Services/ITitleScreenMenu.cs
index 5ebd800177..d1b72af8d1 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,51 @@ 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, 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 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, 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).
- public IReadOnlyTitleScreenMenuEntry AddEntry(string text, IDalamudTextureWrap texture, Action onTriggered);
+ [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 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).
- public IReadOnlyTitleScreenMenuEntry AddEntry(ulong priority, string text, IDalamudTextureWrap texture, Action onTriggered);
+ [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.