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? IconTask { get; set; } + public INotificationMaterializedIcon? MaterializedIcon { get; set; } /// Gets the eased progress. private float ProgressEased @@ -255,7 +251,7 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable public void Dispose() { this.ClearIconTask(); - this.underlyingNotification.IconCreator = null; + this.underlyingNotification.IconSource = null; this.Dismiss = null; this.Click = null; this.DrawActions = null; @@ -487,7 +483,7 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable this.Content = newNotification.Content; this.Title = newNotification.Title; this.Type = newNotification.Type; - this.IconCreator = newNotification.IconCreator; + this.IconSource = newNotification.IconSource; this.Expiry = newNotification.Expiry; this.Interactible = newNotification.Interactible; this.HoverExtendDuration = newNotification.HoverExtendDuration; @@ -500,7 +496,7 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable if (this.IsDismissed) return; this.ClearIconTask(); - this.IconTask = this.IconCreator?.Invoke(); + this.MaterializedIcon = (this.IconSource as INotificationIconSource.IInternal)?.Materialize(); } /// Removes non-Dalamud invocation targets from events. @@ -546,20 +542,14 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable private void ClearIconTask() { - _ = this.IconTask?.ContinueWith( - r => - { - if (r.IsCompletedSuccessfully && r.Result is IDisposable d) - d.Dispose(); - }); - this.IconTask = null; + this.MaterializedIcon?.Dispose(); + this.MaterializedIcon = null; } private void DrawNotificationMainWindowContent(NotificationManager notificationManager, float width) { var basePos = ImGui.GetCursorPos(); this.DrawIcon( - notificationManager, basePos, basePos + new Vector2(NotificationConstants.ScaledIconSize)); basePos.X += NotificationConstants.ScaledIconSize + NotificationConstants.ScaledWindowPadding; @@ -633,84 +623,26 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable ImGui.PopClipRect(); } - private void DrawIcon(NotificationManager notificationManager, Vector2 minCoord, Vector2 maxCoord) + private void DrawIcon(Vector2 minCoord, Vector2 maxCoord) { - string? iconString = null; - IFontHandle? fontHandle = null; - IDalamudTextureWrap? iconTexture = null; - switch (this.IconTask?.IsCompletedSuccessfully is true ? this.IconTask.Result : null) + if (this.MaterializedIcon is not null) { - case IDalamudTextureWrap wrap: - iconTexture = wrap; - break; - case SeIconChar icon: - iconString = string.Empty + (char)icon; - fontHandle = notificationManager.IconAxisFontHandle; - break; - case FontAwesomeIcon icon: - iconString = icon.ToIconString(); - fontHandle = notificationManager.IconFontAwesomeFontHandle; - break; - default: - iconString = this.DefaultIconString; - fontHandle = notificationManager.IconFontAwesomeFontHandle; - break; + this.MaterializedIcon.DrawIcon(minCoord, maxCoord, this.DefaultIconColor, this.InitiatorPlugin); + return; } - if (string.IsNullOrWhiteSpace(iconString)) + var defaultIconString = this.DefaultIconString; + if (!string.IsNullOrWhiteSpace(defaultIconString)) { - var dam = Service.Get(); - if (this.InitiatorPlugin is null) - { - iconTexture = dam.GetDalamudTextureWrap(DalamudAsset.LogoSmall); - } - else - { - if (!Service.Get().TryGetIcon( - this.InitiatorPlugin, - this.InitiatorPlugin.Manifest, - this.InitiatorPlugin.IsThirdParty, - out iconTexture) || iconTexture is null) - { - iconTexture = this.InitiatorPlugin switch - { - { IsDev: true } => dam.GetDalamudTextureWrap(DalamudAsset.DevPluginIcon), - { IsThirdParty: true } => dam.GetDalamudTextureWrap(DalamudAsset.ThirdInstalledIcon), - _ => dam.GetDalamudTextureWrap(DalamudAsset.InstalledIcon), - }; - } - } + FontAwesomeIconIconSource.DrawIconStatic(defaultIconString, minCoord, maxCoord, this.DefaultIconColor); + return; } - if (iconTexture is not null) - { - var size = iconTexture.Size; - if (size.X > maxCoord.X - minCoord.X) - size *= (maxCoord.X - minCoord.X) / size.X; - if (size.Y > maxCoord.Y - minCoord.Y) - size *= (maxCoord.Y - minCoord.Y) / size.Y; - var pos = ((minCoord + maxCoord) - size) / 2; - ImGui.SetCursorPos(pos); - ImGui.Image(iconTexture.ImGuiHandle, size); - } - else - { - // Just making it extremely sure - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - if (fontHandle is null || iconString is null) - // ReSharper disable once HeuristicUnreachableCode - return; - - using (fontHandle.Push()) - { - var size = ImGui.CalcTextSize(iconString); - var pos = ((minCoord + maxCoord) - size) / 2; - ImGui.SetCursorPos(pos); - ImGui.PushStyleColor(ImGuiCol.Text, this.DefaultIconColor); - ImGui.TextUnformatted(iconString); - ImGui.PopStyleColor(); - } - } + TextureWrapTaskIconSource.DefaultMaterializedIcon.DrawIcon( + minCoord, + maxCoord, + this.DefaultIconColor, + this.InitiatorPlugin); } private void DrawTitle(Vector2 minCoord, Vector2 maxCoord) diff --git a/Dalamud/Interface/ImGuiNotification/Internal/NotificationUtilities.cs b/Dalamud/Interface/ImGuiNotification/Internal/NotificationUtilities.cs new file mode 100644 index 000000000..f442ef553 --- /dev/null +++ b/Dalamud/Interface/ImGuiNotification/Internal/NotificationUtilities.cs @@ -0,0 +1,63 @@ +using System.Numerics; + +using Dalamud.Interface.Internal; +using Dalamud.Interface.Internal.Windows; +using Dalamud.Plugin.Internal.Types; +using Dalamud.Storage.Assets; + +using ImGuiNET; + +namespace Dalamud.Interface.ImGuiNotification.Internal; + +/// +/// Utilities for implementing stuff under . +/// +internal static class NotificationUtilities +{ + /// + /// Draws the given texture, or the icon of the plugin if texture is null. + /// + /// The texture. + /// The coordinates of the top left of the icon area. + /// The coordinates of the bottom right of the icon area. + /// The initiator plugin. + public static void DrawTexture( + IDalamudTextureWrap? texture, + Vector2 minCoord, + Vector2 maxCoord, + LocalPlugin? initiatorPlugin) + { + if (texture is null) + { + var dam = Service.Get(); + if (initiatorPlugin is null) + { + texture = dam.GetDalamudTextureWrap(DalamudAsset.LogoSmall); + } + else + { + if (!Service.Get().TryGetIcon( + initiatorPlugin, + initiatorPlugin.Manifest, + initiatorPlugin.IsThirdParty, + out texture) || texture is null) + { + texture = initiatorPlugin switch + { + { IsDev: true } => dam.GetDalamudTextureWrap(DalamudAsset.DevPluginIcon), + { IsThirdParty: true } => dam.GetDalamudTextureWrap(DalamudAsset.ThirdInstalledIcon), + _ => dam.GetDalamudTextureWrap(DalamudAsset.InstalledIcon), + }; + } + } + } + + var size = texture.Size; + if (size.X > maxCoord.X - minCoord.X) + size *= (maxCoord.X - minCoord.X) / size.X; + if (size.Y > maxCoord.Y - minCoord.Y) + size *= (maxCoord.Y - minCoord.Y) / size.Y; + ImGui.SetCursorPos(((minCoord + maxCoord) - size) / 2); + ImGui.Image(texture.ImGuiHandle, size); + } +} diff --git a/Dalamud/Interface/ImGuiNotification/Notification.cs b/Dalamud/Interface/ImGuiNotification/Notification.cs index bab6f6f23..8f5ec2423 100644 --- a/Dalamud/Interface/ImGuiNotification/Notification.cs +++ b/Dalamud/Interface/ImGuiNotification/Notification.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - using Dalamud.Interface.ImGuiNotification.Internal; using Dalamud.Interface.Internal.Notifications; @@ -20,7 +18,7 @@ public sealed record Notification : INotification public NotificationType Type { get; set; } = NotificationType.None; /// - public Func>? IconCreator { get; set; } + public INotificationIconSource? IconSource { get; set; } /// public DateTime Expiry { get; set; } = DateTime.Now + NotificationConstants.DefaultDisplayDuration; diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs index 67a65f74f..71cba3297 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/ImGuiWidget.cs @@ -1,8 +1,13 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; +using Dalamud.Game.Text; +using Dalamud.Interface.ImGuiNotification.IconSource; using Dalamud.Interface.ImGuiNotification.Internal; using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Windowing; +using Dalamud.Storage.Assets; +using Dalamud.Utility; using ImGuiNET; @@ -66,6 +71,41 @@ internal class ImGuiWidget : IDataWindowWidget NotificationTemplate.TypeTitles, NotificationTemplate.TypeTitles.Length); + ImGui.Combo( + "Icon Source##iconSourceCombo", + ref this.notificationTemplate.IconSourceInt, + NotificationTemplate.IconSourceTitles, + NotificationTemplate.IconSourceTitles.Length); + switch (this.notificationTemplate.IconSourceInt) + { + case 1: + case 2: + ImGui.InputText( + "Icon Text##iconSourceText", + ref this.notificationTemplate.IconSourceText, + 255); + break; + case 3: + ImGui.Combo( + "Icon Source##iconSourceAssetCombo", + ref this.notificationTemplate.IconSourceAssetInt, + NotificationTemplate.AssetSources, + NotificationTemplate.AssetSources.Length); + break; + case 4: + ImGui.InputText( + "Game Path##iconSourceText", + ref this.notificationTemplate.IconSourceText, + 255); + break; + case 5: + ImGui.InputText( + "File Path##iconSourceText", + ref this.notificationTemplate.IconSourceText, + 255); + break; + } + ImGui.Combo( "Duration", ref this.notificationTemplate.DurationInt, @@ -114,6 +154,26 @@ internal class ImGuiWidget : IDataWindowWidget 4 => -1f, _ => 0.5f, }, + IconSource = this.notificationTemplate.IconSourceInt switch + { + 1 => new SeIconCharIconSource( + (SeIconChar)(this.notificationTemplate.IconSourceText.Length == 0 + ? 0 + : this.notificationTemplate.IconSourceText[0])), + 2 => new FontAwesomeIconIconSource( + (FontAwesomeIcon)(this.notificationTemplate.IconSourceText.Length == 0 + ? 0 + : this.notificationTemplate.IconSourceText[0])), + 3 => new TextureWrapTaskIconSource( + () => + Service.Get().GetDalamudTextureWrapAsync( + Enum.Parse( + NotificationTemplate.AssetSources[ + this.notificationTemplate.IconSourceAssetInt]))), + 4 => new GamePathIconSource(this.notificationTemplate.IconSourceText), + 5 => new FilePathIconSource(this.notificationTemplate.IconSourceText), + _ => null, + }, }); switch (this.notificationTemplate.ProgressMode) { @@ -205,6 +265,22 @@ internal class ImGuiWidget : IDataWindowWidget private struct NotificationTemplate { + public static readonly string[] IconSourceTitles = + { + "None (use Type)", + "SeIconChar", + "FontAwesomeIcon", + "TextureWrapTask from DalamudAssets", + "GamePath", + "FilePath", + }; + + public static readonly string[] AssetSources = + Enum.GetValues() + .Where(x => x.GetAttribute()?.Purpose is DalamudAssetPurpose.TextureFromPng) + .Select(Enum.GetName) + .ToArray(); + public static readonly string[] ProgressModeTitles = { "Default", @@ -243,6 +319,9 @@ internal class ImGuiWidget : IDataWindowWidget public string Content; public bool ManualTitle; public string Title; + public int IconSourceInt; + public string IconSourceText; + public int IconSourceAssetInt; public bool ManualType; public int TypeInt; public int DurationInt; @@ -256,6 +335,9 @@ internal class ImGuiWidget : IDataWindowWidget this.Content = string.Empty; this.ManualTitle = false; this.Title = string.Empty; + this.IconSourceInt = 0; + this.IconSourceText = "ui/icon/000000/000004_hr1.tex"; + this.IconSourceAssetInt = 0; this.ManualType = false; this.TypeInt = (int)NotificationType.None; this.DurationInt = 2;