diff --git a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs
index 2e0c62783..fecccf092 100644
--- a/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs
+++ b/Dalamud/Interface/ImGuiNotification/IActiveNotification.cs
@@ -1,5 +1,4 @@
using System.Threading;
-using System.Threading.Tasks;
using Dalamud.Interface.Internal.Notifications;
@@ -57,8 +56,10 @@ public interface IActiveNotification : INotification
///
new NotificationType Type { get; set; }
- ///
- new Func>? IconCreator { get; set; }
+ /// Gets or sets the icon source.
+ /// Setting a new value to this property does not change the icon. Use to do so.
+ ///
+ new INotificationIconSource? IconSource { get; set; }
///
new DateTime Expiry { get; set; }
@@ -91,13 +92,13 @@ public interface IActiveNotification : INotification
/// Updates the notification data.
///
- /// Call to update the icon using the new .
+ /// Call to update the icon using the new .
/// If is true, then this function is a no-op.
///
/// The new notification entry.
void Update(INotification newNotification);
- /// Loads the icon again using .
+ /// Loads the icon again using .
/// If is true, then this function is a no-op.
void UpdateIcon();
diff --git a/Dalamud/Interface/ImGuiNotification/INotification.cs b/Dalamud/Interface/ImGuiNotification/INotification.cs
index a5d56d783..c4a7b46ac 100644
--- a/Dalamud/Interface/ImGuiNotification/INotification.cs
+++ b/Dalamud/Interface/ImGuiNotification/INotification.cs
@@ -1,7 +1,4 @@
-using System.Threading.Tasks;
-
-using Dalamud.Game.Text;
-using Dalamud.Interface.Internal;
+using Dalamud.Interface.ImGuiNotification.IconSource;
using Dalamud.Interface.Internal.Notifications;
namespace Dalamud.Interface.ImGuiNotification;
@@ -18,18 +15,17 @@ public interface INotification
/// Gets the type of the notification.
NotificationType Type { get; }
- /// Gets the icon creator function for the notification.
- /// Currently , , and types
- /// are accepted.
- ///
- /// The icon created by the task returned will be owned by Dalamud,
- /// i.e. it will be d automatically as needed.
- /// If null is supplied for this property or of the returned task
- /// is false, then the corresponding icon with will be used.
- /// Use if you have an instance of that you
- /// can transfer ownership to Dalamud and is available for use right away.
+ /// Gets the icon source.
+ /// The following icon sources are currently available.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
///
- Func>? IconCreator { get; }
+ INotificationIconSource? IconSource { get; }
/// Gets the expiry.
/// Set to to make the notification not have an expiry time
diff --git a/Dalamud/Interface/ImGuiNotification/INotificationIconSource.cs b/Dalamud/Interface/ImGuiNotification/INotificationIconSource.cs
new file mode 100644
index 000000000..8a73e2a64
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/INotificationIconSource.cs
@@ -0,0 +1,20 @@
+namespace Dalamud.Interface.ImGuiNotification;
+
+/// Icon source for .
+/// Plugins should NOT implement this interface.
+public interface INotificationIconSource : ICloneable, IDisposable
+{
+ /// The internal interface.
+ internal interface IInternal : INotificationIconSource
+ {
+ /// Materializes the icon resource.
+ /// The materialized resource.
+ INotificationMaterializedIcon Materialize();
+ }
+
+ ///
+ new INotificationIconSource Clone();
+
+ ///
+ object ICloneable.Clone() => this.Clone();
+}
diff --git a/Dalamud/Interface/ImGuiNotification/INotificationMaterializedIcon.cs b/Dalamud/Interface/ImGuiNotification/INotificationMaterializedIcon.cs
new file mode 100644
index 000000000..9be498af1
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/INotificationMaterializedIcon.cs
@@ -0,0 +1,18 @@
+using System.Numerics;
+
+using Dalamud.Plugin.Internal.Types;
+
+namespace Dalamud.Interface.ImGuiNotification;
+
+///
+/// Represents a materialized icon.
+///
+internal interface INotificationMaterializedIcon : IDisposable
+{
+ /// Draws the icon.
+ /// The coordinates of the top left of the icon area.
+ /// The coordinates of the bottom right of the icon area.
+ /// The foreground color.
+ /// The initiator plugin.
+ void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin);
+}
diff --git a/Dalamud/Interface/ImGuiNotification/IconSource/FilePathIconSource.cs b/Dalamud/Interface/ImGuiNotification/IconSource/FilePathIconSource.cs
new file mode 100644
index 000000000..b1886154a
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/IconSource/FilePathIconSource.cs
@@ -0,0 +1,50 @@
+using System.IO;
+using System.Numerics;
+
+using Dalamud.Interface.ImGuiNotification.Internal;
+using Dalamud.Interface.Internal;
+using Dalamud.Plugin.Internal.Types;
+
+namespace Dalamud.Interface.ImGuiNotification.IconSource;
+
+/// Represents the use of a texture from a file as the icon of a notification.
+/// If there was no texture loaded for any reason, the plugin icon will be displayed instead.
+public readonly struct FilePathIconSource : INotificationIconSource.IInternal
+{
+ /// The path to a .tex file inside the game resources.
+ public readonly string FilePath;
+
+ /// Initializes a new instance of the struct.
+ /// The path to a .tex file inside the game resources.
+ public FilePathIconSource(string filePath) => this.FilePath = filePath;
+
+ ///
+ public INotificationIconSource Clone() => this;
+
+ ///
+ void IDisposable.Dispose()
+ {
+ }
+
+ ///
+ INotificationMaterializedIcon INotificationIconSource.IInternal.Materialize() =>
+ new MaterializedIcon(this.FilePath);
+
+ private sealed class MaterializedIcon : INotificationMaterializedIcon
+ {
+ private readonly FileInfo fileInfo;
+
+ public MaterializedIcon(string filePath) => this.fileInfo = new(filePath);
+
+ public void Dispose()
+ {
+ }
+
+ public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
+ NotificationUtilities.DrawTexture(
+ Service.Get().GetTextureFromFile(this.fileInfo),
+ minCoord,
+ maxCoord,
+ initiatorPlugin);
+ }
+}
diff --git a/Dalamud/Interface/ImGuiNotification/IconSource/FontAwesomeIconIconSource.cs b/Dalamud/Interface/ImGuiNotification/IconSource/FontAwesomeIconIconSource.cs
new file mode 100644
index 000000000..8e28940ba
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/IconSource/FontAwesomeIconIconSource.cs
@@ -0,0 +1,62 @@
+using System.Numerics;
+
+using Dalamud.Interface.ImGuiNotification.Internal;
+using Dalamud.Plugin.Internal.Types;
+
+using ImGuiNET;
+
+namespace Dalamud.Interface.ImGuiNotification.IconSource;
+
+/// Represents the use of as the icon of a notification.
+public readonly struct FontAwesomeIconIconSource : INotificationIconSource.IInternal
+{
+ /// The icon character.
+ public readonly FontAwesomeIcon Char;
+
+ /// Initializes a new instance of the struct.
+ /// The character.
+ public FontAwesomeIconIconSource(FontAwesomeIcon c) => this.Char = c;
+
+ ///
+ public INotificationIconSource Clone() => this;
+
+ ///
+ void IDisposable.Dispose()
+ {
+ }
+
+ ///
+ INotificationMaterializedIcon INotificationIconSource.IInternal.Materialize() => new MaterializedIcon(this.Char);
+
+ /// Draws the icon.
+ /// The icon string.
+ /// The coordinates of the top left of the icon area.
+ /// The coordinates of the bottom right of the icon area.
+ /// The foreground color.
+ internal static void DrawIconStatic(string iconString, Vector2 minCoord, Vector2 maxCoord, Vector4 color)
+ {
+ using (Service.Get().IconFontAwesomeFontHandle.Push())
+ {
+ var size = ImGui.CalcTextSize(iconString);
+ var pos = ((minCoord + maxCoord) - size) / 2;
+ ImGui.SetCursorPos(pos);
+ ImGui.PushStyleColor(ImGuiCol.Text, color);
+ ImGui.TextUnformatted(iconString);
+ ImGui.PopStyleColor();
+ }
+ }
+
+ private sealed class MaterializedIcon : INotificationMaterializedIcon
+ {
+ private readonly string iconString;
+
+ public MaterializedIcon(FontAwesomeIcon c) => this.iconString = c.ToIconString();
+
+ public void Dispose()
+ {
+ }
+
+ public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
+ DrawIconStatic(this.iconString, minCoord, maxCoord, color);
+ }
+}
diff --git a/Dalamud/Interface/ImGuiNotification/IconSource/GamePathIconSource.cs b/Dalamud/Interface/ImGuiNotification/IconSource/GamePathIconSource.cs
new file mode 100644
index 000000000..9b669e62a
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/IconSource/GamePathIconSource.cs
@@ -0,0 +1,51 @@
+using System.Numerics;
+
+using Dalamud.Interface.ImGuiNotification.Internal;
+using Dalamud.Interface.Internal;
+using Dalamud.Plugin.Internal.Types;
+using Dalamud.Plugin.Services;
+
+namespace Dalamud.Interface.ImGuiNotification.IconSource;
+
+/// Represents the use of a game-shipped texture as the icon of a notification.
+/// If there was no texture loaded for any reason, the plugin icon will be displayed instead.
+public readonly struct GamePathIconSource : INotificationIconSource.IInternal
+{
+ /// The path to a .tex file inside the game resources.
+ public readonly string GamePath;
+
+ /// Initializes a new instance of the struct.
+ /// The path to a .tex file inside the game resources.
+ /// Use to get the game path from icon IDs.
+ public GamePathIconSource(string gamePath) => this.GamePath = gamePath;
+
+ ///
+ public INotificationIconSource Clone() => this;
+
+ ///
+ void IDisposable.Dispose()
+ {
+ }
+
+ ///
+ INotificationMaterializedIcon INotificationIconSource.IInternal.Materialize() =>
+ new MaterializedIcon(this.GamePath);
+
+ private sealed class MaterializedIcon : INotificationMaterializedIcon
+ {
+ private readonly string gamePath;
+
+ public MaterializedIcon(string gamePath) => this.gamePath = gamePath;
+
+ public void Dispose()
+ {
+ }
+
+ public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
+ NotificationUtilities.DrawTexture(
+ Service.Get().GetTextureFromGame(this.gamePath),
+ minCoord,
+ maxCoord,
+ initiatorPlugin);
+ }
+}
diff --git a/Dalamud/Interface/ImGuiNotification/IconSource/SeIconCharIconSource.cs b/Dalamud/Interface/ImGuiNotification/IconSource/SeIconCharIconSource.cs
new file mode 100644
index 000000000..d34b776bc
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/IconSource/SeIconCharIconSource.cs
@@ -0,0 +1,55 @@
+using System.Numerics;
+
+using Dalamud.Game.Text;
+using Dalamud.Interface.ImGuiNotification.Internal;
+using Dalamud.Plugin.Internal.Types;
+
+using ImGuiNET;
+
+namespace Dalamud.Interface.ImGuiNotification.IconSource;
+
+/// Represents the use of as the icon of a notification.
+public readonly struct SeIconCharIconSource : INotificationIconSource.IInternal
+{
+ /// The icon character.
+ public readonly SeIconChar Char;
+
+ /// Initializes a new instance of the struct.
+ /// The character.
+ public SeIconCharIconSource(SeIconChar c) => this.Char = c;
+
+ ///
+ public INotificationIconSource Clone() => this;
+
+ ///
+ void IDisposable.Dispose()
+ {
+ }
+
+ ///
+ INotificationMaterializedIcon INotificationIconSource.IInternal.Materialize() => new MaterializedIcon(this.Char);
+
+ private sealed class MaterializedIcon : INotificationMaterializedIcon
+ {
+ private readonly string iconString;
+
+ public MaterializedIcon(SeIconChar c) => this.iconString = c.ToIconString();
+
+ public void Dispose()
+ {
+ }
+
+ public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin)
+ {
+ using (Service.Get().IconAxisFontHandle.Push())
+ {
+ var size = ImGui.CalcTextSize(this.iconString);
+ var pos = ((minCoord + maxCoord) - size) / 2;
+ ImGui.SetCursorPos(pos);
+ ImGui.PushStyleColor(ImGuiCol.Text, color);
+ ImGui.TextUnformatted(this.iconString);
+ ImGui.PopStyleColor();
+ }
+ }
+ }
+}
diff --git a/Dalamud/Interface/ImGuiNotification/IconSource/TextureWrapTaskIconSource.cs b/Dalamud/Interface/ImGuiNotification/IconSource/TextureWrapTaskIconSource.cs
new file mode 100644
index 000000000..28fdc4d96
--- /dev/null
+++ b/Dalamud/Interface/ImGuiNotification/IconSource/TextureWrapTaskIconSource.cs
@@ -0,0 +1,59 @@
+using System.Numerics;
+using System.Threading.Tasks;
+
+using Dalamud.Interface.ImGuiNotification.Internal;
+using Dalamud.Interface.Internal;
+using Dalamud.Plugin.Internal.Types;
+using Dalamud.Utility;
+
+namespace Dalamud.Interface.ImGuiNotification.IconSource;
+
+/// Represents the use of future as the icon of a notification.
+/// If there was no texture loaded for any reason, the plugin icon will be displayed instead.
+public readonly struct TextureWrapTaskIconSource : INotificationIconSource.IInternal
+{
+ /// The function that returns a task resulting in a new instance of .
+ ///
+ /// Dalamud will take ownership of the result. Do not call .
+ public readonly Func?>? TextureWrapTaskFunc;
+
+ /// Gets the default materialized icon, for the purpose of displaying the plugin icon.
+ internal static readonly INotificationMaterializedIcon DefaultMaterializedIcon = new MaterializedIcon(null);
+
+ /// Initializes a new instance of the struct.
+ /// The function.
+ public TextureWrapTaskIconSource(Func?>? taskFunc) =>
+ this.TextureWrapTaskFunc = taskFunc;
+
+ ///
+ public INotificationIconSource Clone() => this;
+
+ ///
+ void IDisposable.Dispose()
+ {
+ }
+
+ ///
+ INotificationMaterializedIcon INotificationIconSource.IInternal.Materialize() =>
+ new MaterializedIcon(this.TextureWrapTaskFunc);
+
+ private sealed class MaterializedIcon : INotificationMaterializedIcon
+ {
+ private Task? task;
+
+ public MaterializedIcon(Func?>? taskFunc) => this.task = taskFunc?.Invoke();
+
+ public void Dispose()
+ {
+ this.task?.ToContentDisposedTask(true);
+ this.task = null;
+ }
+
+ public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
+ NotificationUtilities.DrawTexture(
+ this.task?.IsCompletedSuccessfully is true ? this.task.Result : null,
+ minCoord,
+ maxCoord,
+ initiatorPlugin);
+ }
+}
diff --git a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs
index 963b74b6c..64b812197 100644
--- a/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs
+++ b/Dalamud/Interface/ImGuiNotification/Internal/ActiveNotification.cs
@@ -1,25 +1,21 @@
using System.Numerics;
using System.Runtime.Loader;
-using System.Threading.Tasks;
-using Dalamud.Game.Text;
using Dalamud.Interface.Animation;
using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.Colors;
-using Dalamud.Interface.ImGuiNotification;
-using Dalamud.Interface.ImGuiNotification.Internal;
-using Dalamud.Interface.Internal.Windows;
-using Dalamud.Interface.ManagedFontAtlas;
+using Dalamud.Interface.ImGuiNotification.IconSource;
+using Dalamud.Interface.Internal;
+using Dalamud.Interface.Internal.Notifications;
using Dalamud.Interface.Utility;
using Dalamud.Plugin.Internal.Types;
-using Dalamud.Storage.Assets;
using Dalamud.Utility;
using ImGuiNET;
using Serilog;
-namespace Dalamud.Interface.Internal.Notifications;
+namespace Dalamud.Interface.ImGuiNotification.Internal;
/// Represents an active notification.
internal sealed class ActiveNotification : IActiveNotification, IDisposable
@@ -115,15 +111,15 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
}
}
- ///
- public Func>? IconCreator
+ ///
+ public INotificationIconSource? IconSource
{
- get => this.underlyingNotification.IconCreator;
+ get => this.underlyingNotification.IconSource;
set
{
if (this.IsDismissed)
return;
- this.underlyingNotification.IconCreator = value;
+ this.underlyingNotification.IconSource = value;
}
}
@@ -192,7 +188,7 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
public LocalPlugin? InitiatorPlugin { get; set; }
/// Gets or sets the icon of this notification.
- public Task