mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
fix disposes and add TextureWrapIconSource
This commit is contained in:
parent
9644dd9922
commit
42b6f8fd4b
10 changed files with 187 additions and 81 deletions
|
|
@ -56,11 +56,6 @@ public interface IActiveNotification : INotification
|
||||||
/// <inheritdoc cref="INotification.Type"/>
|
/// <inheritdoc cref="INotification.Type"/>
|
||||||
new NotificationType Type { get; set; }
|
new NotificationType Type { get; set; }
|
||||||
|
|
||||||
/// <summary>Gets or sets the icon source.</summary>
|
|
||||||
/// <remarks>Setting a new value to this property does not change the icon. Use <see cref="UpdateIcon"/> to do so.
|
|
||||||
/// </remarks>
|
|
||||||
new INotificationIconSource? IconSource { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="INotification.Expiry"/>
|
/// <inheritdoc cref="INotification.Expiry"/>
|
||||||
new DateTime Expiry { get; set; }
|
new DateTime Expiry { get; set; }
|
||||||
|
|
||||||
|
|
@ -86,25 +81,19 @@ public interface IActiveNotification : INotification
|
||||||
/// <remarks>This includes when the hide animation is being played.</remarks>
|
/// <remarks>This includes when the hide animation is being played.</remarks>
|
||||||
bool IsDismissed { get; }
|
bool IsDismissed { get; }
|
||||||
|
|
||||||
/// <summary>Clones this notification as a <see cref="Notification"/>.</summary>
|
|
||||||
/// <returns>A new instance of <see cref="Notification"/>.</returns>
|
|
||||||
Notification CloneNotification();
|
|
||||||
|
|
||||||
/// <summary>Dismisses this notification.</summary>
|
/// <summary>Dismisses this notification.</summary>
|
||||||
void DismissNow();
|
void DismissNow();
|
||||||
|
|
||||||
/// <summary>Updates the notification data.</summary>
|
/// <summary>Loads the icon again using the same <see cref="INotification.IconSource"/>.</summary>
|
||||||
/// <remarks>
|
|
||||||
/// Call <see cref="UpdateIcon"/> to update the icon using the new <see cref="INotification.IconSource"/>.
|
|
||||||
/// If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="newNotification">The new notification entry.</param>
|
|
||||||
void Update(INotification newNotification);
|
|
||||||
|
|
||||||
/// <summary>Loads the icon again using <see cref="INotification.IconSource"/>.</summary>
|
|
||||||
/// <remarks>If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.</remarks>
|
/// <remarks>If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.</remarks>
|
||||||
void UpdateIcon();
|
void UpdateIcon();
|
||||||
|
|
||||||
|
/// <summary>Disposes the previous icon source, take ownership of the new icon source,
|
||||||
|
/// and calls <see cref="UpdateIcon"/>.</summary>
|
||||||
|
/// <param name="newIconSource">Thew new icon source.</param>
|
||||||
|
/// <remarks>If <see cref="IsDismissed"/> is <c>true</c>, then this function is a no-op.</remarks>
|
||||||
|
void UpdateIconSource(INotificationIconSource? newIconSource);
|
||||||
|
|
||||||
/// <summary>Generates a new value to use for <see cref="Id"/>.</summary>
|
/// <summary>Generates a new value to use for <see cref="Id"/>.</summary>
|
||||||
/// <returns>The new value.</returns>
|
/// <returns>The new value.</returns>
|
||||||
internal static long CreateNewId() => Interlocked.Increment(ref idCounter);
|
internal static long CreateNewId() => Interlocked.Increment(ref idCounter);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ using Dalamud.Interface.Internal.Notifications;
|
||||||
namespace Dalamud.Interface.ImGuiNotification;
|
namespace Dalamud.Interface.ImGuiNotification;
|
||||||
|
|
||||||
/// <summary>Represents a notification.</summary>
|
/// <summary>Represents a notification.</summary>
|
||||||
public interface INotification
|
public interface INotification : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>Gets the content body of the notification.</summary>
|
/// <summary>Gets the content body of the notification.</summary>
|
||||||
string Content { get; }
|
string Content { get; }
|
||||||
|
|
@ -16,10 +16,15 @@ public interface INotification
|
||||||
NotificationType Type { get; }
|
NotificationType Type { get; }
|
||||||
|
|
||||||
/// <summary>Gets the icon source.</summary>
|
/// <summary>Gets the icon source.</summary>
|
||||||
/// <remarks>The following icon sources are currently available.<br />
|
/// <remarks>
|
||||||
|
/// The assigned value will be disposed upon the <see cref="IDisposable.Dispose"/> call on this instance of
|
||||||
|
/// <see cref="INotification"/>.<br />
|
||||||
|
/// <br />
|
||||||
|
/// The following icon sources are currently available.<br />
|
||||||
/// <ul>
|
/// <ul>
|
||||||
/// <li><see cref="SeIconCharIconSource"/></li>
|
/// <li><see cref="SeIconCharIconSource"/></li>
|
||||||
/// <li><see cref="FontAwesomeIconIconSource"/></li>
|
/// <li><see cref="FontAwesomeIconIconSource"/></li>
|
||||||
|
/// <li><see cref="TextureWrapIconSource"/></li>
|
||||||
/// <li><see cref="TextureWrapTaskIconSource"/></li>
|
/// <li><see cref="TextureWrapTaskIconSource"/></li>
|
||||||
/// <li><see cref="GamePathIconSource"/></li>
|
/// <li><see cref="GamePathIconSource"/></li>
|
||||||
/// <li><see cref="FilePathIconSource"/></li>
|
/// <li><see cref="FilePathIconSource"/></li>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using Dalamud.Interface.ImGuiNotification.Internal;
|
||||||
|
using Dalamud.Interface.Internal;
|
||||||
|
using Dalamud.Plugin.Internal.Types;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface.ImGuiNotification.IconSource;
|
||||||
|
|
||||||
|
/// <summary>Represents the use of future <see cref="IDalamudTextureWrap"/> as the icon of a notification.</summary>
|
||||||
|
/// <remarks>If there was no texture loaded for any reason, the plugin icon will be displayed instead.</remarks>
|
||||||
|
public sealed class TextureWrapIconSource : INotificationIconSource.IInternal
|
||||||
|
{
|
||||||
|
private IDalamudTextureWrap? wrap;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="TextureWrapIconSource"/> class.</summary>
|
||||||
|
/// <param name="wrap">The texture wrap to handle over the ownership.</param>
|
||||||
|
/// <param name="takeOwnership">
|
||||||
|
/// If <c>true</c>, this class will own the passed <paramref name="wrap"/>, and you <b>must not</b> call
|
||||||
|
/// <see cref="IDisposable.Dispose"/> on the passed wrap.
|
||||||
|
/// If <c>false</c>, this class will create a new reference of the passed wrap, and you <b>should</b> call
|
||||||
|
/// <see cref="IDisposable.Dispose"/> on the passed wrap.
|
||||||
|
/// In both cases, this class must be disposed after use.</param>
|
||||||
|
public TextureWrapIconSource(IDalamudTextureWrap? wrap, bool takeOwnership) =>
|
||||||
|
this.wrap = takeOwnership ? wrap : wrap?.CreateWrapSharingLowLevelResource();
|
||||||
|
|
||||||
|
/// <summary>Gets the underlying texture wrap.</summary>
|
||||||
|
public IDalamudTextureWrap? Wrap => this.wrap;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public INotificationIconSource Clone() => new TextureWrapIconSource(this.wrap, false);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Interlocked.Exchange(ref this.wrap, null) is { } w)
|
||||||
|
w.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
INotificationMaterializedIcon INotificationIconSource.IInternal.Materialize() =>
|
||||||
|
new MaterializedIcon(this.wrap?.CreateWrapSharingLowLevelResource());
|
||||||
|
|
||||||
|
private sealed class MaterializedIcon : INotificationMaterializedIcon
|
||||||
|
{
|
||||||
|
private IDalamudTextureWrap? wrap;
|
||||||
|
|
||||||
|
public MaterializedIcon(IDalamudTextureWrap? wrap) => this.wrap = wrap;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Interlocked.Exchange(ref this.wrap, null) is { } w)
|
||||||
|
w.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIcon(Vector2 minCoord, Vector2 maxCoord, Vector4 color, LocalPlugin? initiatorPlugin) =>
|
||||||
|
NotificationUtilities.DrawTexture(
|
||||||
|
this.wrap,
|
||||||
|
minCoord,
|
||||||
|
maxCoord,
|
||||||
|
initiatorPlugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,7 +43,10 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
|
||||||
/// <param name="initiatorPlugin">The initiator plugin. Use <c>null</c> if originated by Dalamud.</param>
|
/// <param name="initiatorPlugin">The initiator plugin. Use <c>null</c> if originated by Dalamud.</param>
|
||||||
public ActiveNotification(Notification underlyingNotification, LocalPlugin? initiatorPlugin)
|
public ActiveNotification(Notification underlyingNotification, LocalPlugin? initiatorPlugin)
|
||||||
{
|
{
|
||||||
this.underlyingNotification = underlyingNotification with { };
|
this.underlyingNotification = underlyingNotification with
|
||||||
|
{
|
||||||
|
IconSource = underlyingNotification.IconSource?.Clone(),
|
||||||
|
};
|
||||||
this.InitiatorPlugin = initiatorPlugin;
|
this.InitiatorPlugin = initiatorPlugin;
|
||||||
this.showEasing = new InCubic(NotificationConstants.ShowAnimationDuration);
|
this.showEasing = new InCubic(NotificationConstants.ShowAnimationDuration);
|
||||||
this.hideEasing = new OutCubic(NotificationConstants.HideAnimationDuration);
|
this.hideEasing = new OutCubic(NotificationConstants.HideAnimationDuration);
|
||||||
|
|
@ -51,7 +54,16 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
|
||||||
|
|
||||||
this.showEasing.Start();
|
this.showEasing.Start();
|
||||||
this.progressEasing.Start();
|
this.progressEasing.Start();
|
||||||
this.UpdateIcon();
|
try
|
||||||
|
{
|
||||||
|
this.UpdateIcon();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// Ignore the one caused from ctor only; other UpdateIcon calls are from plugins, and they should handle the
|
||||||
|
// error accordingly.
|
||||||
|
Log.Error(e, $"{nameof(ActiveNotification)}#{this.Id} ctor: {nameof(this.UpdateIcon)} failed and ignored.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
@ -114,17 +126,8 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.IconSource"/>
|
/// <inheritdoc/>
|
||||||
public INotificationIconSource? IconSource
|
public INotificationIconSource? IconSource => this.underlyingNotification.IconSource;
|
||||||
{
|
|
||||||
get => this.underlyingNotification.IconSource;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (this.IsDismissed)
|
|
||||||
return;
|
|
||||||
this.underlyingNotification.IconSource = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IActiveNotification.Expiry"/>
|
/// <inheritdoc cref="IActiveNotification.Expiry"/>
|
||||||
public DateTime Expiry
|
public DateTime Expiry
|
||||||
|
|
@ -264,23 +267,14 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
this.ClearIconTask();
|
this.ClearMaterializedIcon();
|
||||||
this.underlyingNotification.IconSource = null;
|
this.underlyingNotification.Dispose();
|
||||||
this.Dismiss = null;
|
this.Dismiss = null;
|
||||||
this.Click = null;
|
this.Click = null;
|
||||||
this.DrawActions = null;
|
this.DrawActions = null;
|
||||||
this.InitiatorPlugin = null;
|
this.InitiatorPlugin = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public Notification CloneNotification()
|
|
||||||
{
|
|
||||||
var newValue = this.underlyingNotification with { };
|
|
||||||
if (this.newProgress is { } p)
|
|
||||||
newValue.Progress = p;
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void DismissNow() => this.DismissNow(NotificationDismissReason.Programmatical);
|
public void DismissNow() => this.DismissNow(NotificationDismissReason.Programmatical);
|
||||||
|
|
||||||
|
|
@ -504,30 +498,26 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
|
||||||
return windowSize.Y;
|
return windowSize.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void Update(INotification newNotification)
|
|
||||||
{
|
|
||||||
if (this.IsDismissed)
|
|
||||||
return;
|
|
||||||
this.Content = newNotification.Content;
|
|
||||||
this.Title = newNotification.Title;
|
|
||||||
this.Type = newNotification.Type;
|
|
||||||
this.IconSource = newNotification.IconSource;
|
|
||||||
this.Expiry = newNotification.Expiry;
|
|
||||||
this.Interactable = newNotification.Interactable;
|
|
||||||
this.HoverExtendDuration = newNotification.HoverExtendDuration;
|
|
||||||
this.newProgress = newNotification.Progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void UpdateIcon()
|
public void UpdateIcon()
|
||||||
{
|
{
|
||||||
if (this.IsDismissed)
|
if (this.IsDismissed)
|
||||||
return;
|
return;
|
||||||
this.ClearIconTask();
|
this.ClearMaterializedIcon();
|
||||||
this.MaterializedIcon = (this.IconSource as INotificationIconSource.IInternal)?.Materialize();
|
this.MaterializedIcon = (this.IconSource as INotificationIconSource.IInternal)?.Materialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void UpdateIconSource(INotificationIconSource? newIconSource)
|
||||||
|
{
|
||||||
|
if (this.IsDismissed || this.underlyingNotification.IconSource == newIconSource)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.underlyingNotification.IconSource?.Dispose();
|
||||||
|
this.underlyingNotification.IconSource = newIconSource;
|
||||||
|
this.UpdateIcon();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Removes non-Dalamud invocation targets from events.</summary>
|
/// <summary>Removes non-Dalamud invocation targets from events.</summary>
|
||||||
public void RemoveNonDalamudInvocations()
|
public void RemoveNonDalamudInvocations()
|
||||||
{
|
{
|
||||||
|
|
@ -567,7 +557,7 @@ internal sealed class ActiveNotification : IActiveNotification, IDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearIconTask()
|
private void ClearMaterializedIcon()
|
||||||
{
|
{
|
||||||
this.MaterializedIcon?.Dispose();
|
this.MaterializedIcon?.Dispose();
|
||||||
this.MaterializedIcon = null;
|
this.MaterializedIcon = null;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,9 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IActiveNotification AddNotification(Notification notification)
|
public IActiveNotification AddNotification(Notification notification, bool disposeNotification = true)
|
||||||
{
|
{
|
||||||
|
using var disposer = disposeNotification ? notification : null;
|
||||||
var an = new ActiveNotification(notification, null);
|
var an = new ActiveNotification(notification, null);
|
||||||
this.pendingNotifications.Add(an);
|
this.pendingNotifications.Add(an);
|
||||||
return an;
|
return an;
|
||||||
|
|
@ -65,10 +66,13 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
||||||
|
|
||||||
/// <summary>Adds a notification originating from a plugin.</summary>
|
/// <summary>Adds a notification originating from a plugin.</summary>
|
||||||
/// <param name="notification">The notification.</param>
|
/// <param name="notification">The notification.</param>
|
||||||
|
/// <param name="disposeNotification">Dispose <paramref name="notification"/> when this function returns.</param>
|
||||||
/// <param name="plugin">The source plugin.</param>
|
/// <param name="plugin">The source plugin.</param>
|
||||||
/// <returns>The new notification.</returns>
|
/// <returns>The added notification.</returns>
|
||||||
public IActiveNotification AddNotification(Notification notification, LocalPlugin plugin)
|
/// <remarks><paramref name="disposeNotification"/> will be honored even on exceptions.</remarks>
|
||||||
|
public IActiveNotification AddNotification(Notification notification, bool disposeNotification, LocalPlugin plugin)
|
||||||
{
|
{
|
||||||
|
using var disposer = disposeNotification ? notification : null;
|
||||||
var an = new ActiveNotification(notification, plugin);
|
var an = new ActiveNotification(notification, plugin);
|
||||||
this.pendingNotifications.Add(an);
|
this.pendingNotifications.Add(an);
|
||||||
return an;
|
return an;
|
||||||
|
|
@ -88,7 +92,8 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
||||||
Content = content,
|
Content = content,
|
||||||
Title = title,
|
Title = title,
|
||||||
Type = type,
|
Type = type,
|
||||||
});
|
},
|
||||||
|
true);
|
||||||
|
|
||||||
/// <summary>Draw all currently queued notifications.</summary>
|
/// <summary>Draw all currently queued notifications.</summary>
|
||||||
public void Draw()
|
public void Draw()
|
||||||
|
|
@ -101,7 +106,14 @@ internal class NotificationManager : INotificationManager, IServiceType, IDispos
|
||||||
|
|
||||||
var maxWidth = Math.Max(320 * ImGuiHelpers.GlobalScale, viewportSize.X / 3);
|
var maxWidth = Math.Max(320 * ImGuiHelpers.GlobalScale, viewportSize.X / 3);
|
||||||
|
|
||||||
this.notifications.RemoveAll(x => x.UpdateAnimations());
|
this.notifications.RemoveAll(static x =>
|
||||||
|
{
|
||||||
|
if (!x.UpdateAnimations())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
x.Dispose();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
foreach (var tn in this.notifications)
|
foreach (var tn in this.notifications)
|
||||||
height += tn.Draw(maxWidth, height) + NotificationConstants.ScaledWindowGap;
|
height += tn.Draw(maxWidth, height) + NotificationConstants.ScaledWindowGap;
|
||||||
}
|
}
|
||||||
|
|
@ -127,9 +139,9 @@ internal class NotificationManagerPluginScoped : INotificationManager, IServiceT
|
||||||
this.localPlugin = localPlugin;
|
this.localPlugin = localPlugin;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IActiveNotification AddNotification(Notification notification)
|
public IActiveNotification AddNotification(Notification notification, bool disposeNotification = true)
|
||||||
{
|
{
|
||||||
var an = this.notificationManagerService.AddNotification(notification, this.localPlugin);
|
var an = this.notificationManagerService.AddNotification(notification, disposeNotification, this.localPlugin);
|
||||||
_ = this.notifications.TryAdd(an, 0);
|
_ = this.notifications.TryAdd(an, 0);
|
||||||
an.Dismiss += (a, unused) => this.notifications.TryRemove(an, out _);
|
an.Dismiss += (a, unused) => this.notifications.TryRemove(an, out _);
|
||||||
return an;
|
return an;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,22 @@ internal static class NotificationUtilities
|
||||||
Vector2 maxCoord,
|
Vector2 maxCoord,
|
||||||
LocalPlugin? initiatorPlugin)
|
LocalPlugin? initiatorPlugin)
|
||||||
{
|
{
|
||||||
if (texture is null)
|
var handle = nint.Zero;
|
||||||
|
var size = Vector2.Zero;
|
||||||
|
if (texture is not null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
handle = texture.ImGuiHandle;
|
||||||
|
size = texture.Size;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// must have been disposed or something; ignore the texture
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle == nint.Zero)
|
||||||
{
|
{
|
||||||
var dam = Service<DalamudAssetManager>.Get();
|
var dam = Service<DalamudAssetManager>.Get();
|
||||||
if (initiatorPlugin is null)
|
if (initiatorPlugin is null)
|
||||||
|
|
@ -46,14 +61,16 @@ internal static class NotificationUtilities
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle = texture.ImGuiHandle;
|
||||||
|
size = texture.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
var size = texture.Size;
|
|
||||||
if (size.X > maxCoord.X - minCoord.X)
|
if (size.X > maxCoord.X - minCoord.X)
|
||||||
size *= (maxCoord.X - minCoord.X) / size.X;
|
size *= (maxCoord.X - minCoord.X) / size.X;
|
||||||
if (size.Y > maxCoord.Y - minCoord.Y)
|
if (size.Y > maxCoord.Y - minCoord.Y)
|
||||||
size *= (maxCoord.Y - minCoord.Y) / size.Y;
|
size *= (maxCoord.Y - minCoord.Y) / size.Y;
|
||||||
ImGui.SetCursorPos(((minCoord + maxCoord) - size) / 2);
|
ImGui.SetCursorPos(((minCoord + maxCoord) - size) / 2);
|
||||||
ImGui.Image(texture.ImGuiHandle, size);
|
ImGui.Image(handle, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,11 @@ public sealed record Notification : INotification
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public float Progress { get; set; } = 1f;
|
public float Progress { get; set; } = 1f;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.IconSource?.Dispose();
|
||||||
|
this.IconSource = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,27 +79,26 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
NotificationTemplate.IconSourceTitles.Length);
|
NotificationTemplate.IconSourceTitles.Length);
|
||||||
switch (this.notificationTemplate.IconSourceInt)
|
switch (this.notificationTemplate.IconSourceInt)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1 or 2:
|
||||||
case 2:
|
|
||||||
ImGui.InputText(
|
ImGui.InputText(
|
||||||
"Icon Text##iconSourceText",
|
"Icon Text##iconSourceText",
|
||||||
ref this.notificationTemplate.IconSourceText,
|
ref this.notificationTemplate.IconSourceText,
|
||||||
255);
|
255);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3 or 4:
|
||||||
ImGui.Combo(
|
ImGui.Combo(
|
||||||
"Icon Source##iconSourceAssetCombo",
|
"Icon Source##iconSourceAssetCombo",
|
||||||
ref this.notificationTemplate.IconSourceAssetInt,
|
ref this.notificationTemplate.IconSourceAssetInt,
|
||||||
NotificationTemplate.AssetSources,
|
NotificationTemplate.AssetSources,
|
||||||
NotificationTemplate.AssetSources.Length);
|
NotificationTemplate.AssetSources.Length);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 5 or 7:
|
||||||
ImGui.InputText(
|
ImGui.InputText(
|
||||||
"Game Path##iconSourceText",
|
"Game Path##iconSourceText",
|
||||||
ref this.notificationTemplate.IconSourceText,
|
ref this.notificationTemplate.IconSourceText,
|
||||||
255);
|
255);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 6 or 8:
|
||||||
ImGui.InputText(
|
ImGui.InputText(
|
||||||
"File Path##iconSourceText",
|
"File Path##iconSourceText",
|
||||||
ref this.notificationTemplate.IconSourceText,
|
ref this.notificationTemplate.IconSourceText,
|
||||||
|
|
@ -170,17 +169,31 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
(FontAwesomeIcon)(this.notificationTemplate.IconSourceText.Length == 0
|
(FontAwesomeIcon)(this.notificationTemplate.IconSourceText.Length == 0
|
||||||
? 0
|
? 0
|
||||||
: this.notificationTemplate.IconSourceText[0])),
|
: this.notificationTemplate.IconSourceText[0])),
|
||||||
3 => new TextureWrapTaskIconSource(
|
3 => new TextureWrapIconSource(
|
||||||
|
Service<DalamudAssetManager>.Get().GetDalamudTextureWrap(
|
||||||
|
Enum.Parse<DalamudAsset>(
|
||||||
|
NotificationTemplate.AssetSources[
|
||||||
|
this.notificationTemplate.IconSourceAssetInt])),
|
||||||
|
false),
|
||||||
|
4 => new TextureWrapTaskIconSource(
|
||||||
() =>
|
() =>
|
||||||
Service<DalamudAssetManager>.Get().GetDalamudTextureWrapAsync(
|
Service<DalamudAssetManager>.Get().GetDalamudTextureWrapAsync(
|
||||||
Enum.Parse<DalamudAsset>(
|
Enum.Parse<DalamudAsset>(
|
||||||
NotificationTemplate.AssetSources[
|
NotificationTemplate.AssetSources[
|
||||||
this.notificationTemplate.IconSourceAssetInt]))),
|
this.notificationTemplate.IconSourceAssetInt]))),
|
||||||
4 => new GamePathIconSource(this.notificationTemplate.IconSourceText),
|
5 => new GamePathIconSource(this.notificationTemplate.IconSourceText),
|
||||||
5 => new FilePathIconSource(this.notificationTemplate.IconSourceText),
|
6 => new FilePathIconSource(this.notificationTemplate.IconSourceText),
|
||||||
|
7 => new TextureWrapIconSource(
|
||||||
|
Service<TextureManager>.Get().GetTextureFromGame(this.notificationTemplate.IconSourceText),
|
||||||
|
false),
|
||||||
|
8 => new TextureWrapIconSource(
|
||||||
|
Service<TextureManager>.Get().GetTextureFromFile(
|
||||||
|
new(this.notificationTemplate.IconSourceText)),
|
||||||
|
false),
|
||||||
_ => null,
|
_ => null,
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
true);
|
||||||
switch (this.notificationTemplate.ProgressMode)
|
switch (this.notificationTemplate.ProgressMode)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
|
|
@ -276,9 +289,12 @@ internal class ImGuiWidget : IDataWindowWidget
|
||||||
"None (use Type)",
|
"None (use Type)",
|
||||||
"SeIconChar",
|
"SeIconChar",
|
||||||
"FontAwesomeIcon",
|
"FontAwesomeIcon",
|
||||||
|
"TextureWrap from DalamudAssets",
|
||||||
"TextureWrapTask from DalamudAssets",
|
"TextureWrapTask from DalamudAssets",
|
||||||
"GamePath",
|
"GamePath",
|
||||||
"FilePath",
|
"FilePath",
|
||||||
|
"TextureWrap from GamePath",
|
||||||
|
"TextureWrap from FilePath",
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly string[] AssetSources =
|
public static readonly string[] AssetSources =
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,7 @@ public sealed class UiBuilder : IDisposable
|
||||||
Type = type,
|
Type = type,
|
||||||
Expiry = DateTime.Now + TimeSpan.FromMilliseconds(msDelay),
|
Expiry = DateTime.Now + TimeSpan.FromMilliseconds(msDelay),
|
||||||
},
|
},
|
||||||
|
true,
|
||||||
this.localPlugin);
|
this.localPlugin);
|
||||||
_ = this.notifications.TryAdd(an, 0);
|
_ = this.notifications.TryAdd(an, 0);
|
||||||
an.Dismiss += (a, unused) => this.notifications.TryRemove(an, out _);
|
an.Dismiss += (a, unused) => this.notifications.TryRemove(an, out _);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@ public interface INotificationManager
|
||||||
/// Adds a notification.
|
/// Adds a notification.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="notification">The new notification.</param>
|
/// <param name="notification">The new notification.</param>
|
||||||
|
/// <param name="disposeNotification">
|
||||||
|
/// Dispose <paramref name="notification"/> when this function returns, even if the function throws an exception.
|
||||||
|
/// Set to <c>false</c> to reuse <paramref name="notification"/> for multiple calls to this function, in which case,
|
||||||
|
/// you should call <see cref="IDisposable.Dispose"/> on the value supplied to <paramref name="notification"/> at a
|
||||||
|
/// later time.
|
||||||
|
/// </param>
|
||||||
/// <returns>The added notification.</returns>
|
/// <returns>The added notification.</returns>
|
||||||
IActiveNotification AddNotification(Notification notification);
|
IActiveNotification AddNotification(Notification notification, bool disposeNotification = true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue