installer: fade icons when loading

This commit is contained in:
goaaats 2024-03-19 23:17:15 +01:00
parent 4e7531f703
commit 148de97331
4 changed files with 32 additions and 17 deletions

View file

@ -129,7 +129,7 @@ public static class NotificationUtilities
plugin, plugin,
plugin.Manifest, plugin.Manifest,
plugin.IsThirdParty, plugin.IsThirdParty,
out var texture) || texture is null) out var texture, out _) || texture is null)
{ {
texture = dam.GetDalamudTextureWrap(DalamudAsset.DefaultIcon); texture = dam.GetDalamudTextureWrap(DalamudAsset.DefaultIcon);
} }

View file

@ -55,7 +55,9 @@ internal class PluginImageCache : IInternalDisposableService
private readonly Task downloadTask; private readonly Task downloadTask;
private readonly Task loadTask; private readonly Task loadTask;
private readonly ConcurrentDictionary<string, IDalamudTextureWrap?> pluginIconMap = new(); private record LoadedIcon(IDalamudTextureWrap Texture, DateTime LoadedSince);
private readonly ConcurrentDictionary<string, LoadedIcon?> pluginIconMap = new();
private readonly ConcurrentDictionary<string, IDalamudTextureWrap?[]?> pluginImagesMap = new(); private readonly ConcurrentDictionary<string, IDalamudTextureWrap?[]?> pluginImagesMap = new();
private readonly DalamudAssetManager dalamudAssetManager; private readonly DalamudAssetManager dalamudAssetManager;
@ -153,7 +155,7 @@ internal class PluginImageCache : IInternalDisposableService
foreach (var icon in this.pluginIconMap.Values) foreach (var icon in this.pluginIconMap.Values)
{ {
icon?.Dispose(); icon?.Texture.Dispose();
} }
foreach (var images in this.pluginImagesMap.Values) foreach (var images in this.pluginImagesMap.Values)
@ -185,10 +187,12 @@ internal class PluginImageCache : IInternalDisposableService
/// <param name="manifest">The plugin manifest.</param> /// <param name="manifest">The plugin manifest.</param>
/// <param name="isThirdParty">If the plugin was third party sourced.</param> /// <param name="isThirdParty">If the plugin was third party sourced.</param>
/// <param name="iconTexture">Cached image textures, or an empty array.</param> /// <param name="iconTexture">Cached image textures, or an empty array.</param>
/// <param name="loadedSince">The time the icon was successfully downloaded.</param>
/// <returns>True if an entry exists, may be null if currently downloading.</returns> /// <returns>True if an entry exists, may be null if currently downloading.</returns>
public bool TryGetIcon(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, out IDalamudTextureWrap? iconTexture) public bool TryGetIcon(LocalPlugin? plugin, IPluginManifest manifest, bool isThirdParty, out IDalamudTextureWrap? iconTexture, out DateTime? loadedSince)
{ {
iconTexture = null; iconTexture = null;
loadedSince = null;
if (manifest == null || manifest.InternalName == null) if (manifest == null || manifest.InternalName == null)
{ {
@ -198,7 +202,13 @@ internal class PluginImageCache : IInternalDisposableService
if (!this.pluginIconMap.TryAdd(manifest.InternalName, null)) if (!this.pluginIconMap.TryAdd(manifest.InternalName, null))
{ {
iconTexture = this.pluginIconMap[manifest.InternalName]; var loaded = this.pluginIconMap[manifest.InternalName];
if (loaded != null)
{
iconTexture = loaded.Texture;
loadedSince = loaded.LoadedSince;
}
return true; return true;
} }
@ -207,8 +217,9 @@ internal class PluginImageCache : IInternalDisposableService
{ {
try try
{ {
this.pluginIconMap[manifest.InternalName] = var texture = await this.DownloadPluginIconAsync(plugin, manifest, isThirdParty, requestedFrame);
await this.DownloadPluginIconAsync(plugin, manifest, isThirdParty, requestedFrame); if (texture != null)
this.pluginIconMap[manifest.InternalName] = new LoadedIcon(texture, DateTime.Now);
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -1814,23 +1814,27 @@ internal class PluginInstallerWindow : Window, IDisposable
if (ImGui.IsRectVisible(rectOffset + cursorBeforeImage, rectOffset + cursorBeforeImage + iconSize)) if (ImGui.IsRectVisible(rectOffset + cursorBeforeImage, rectOffset + cursorBeforeImage + iconSize))
{ {
var iconTex = this.imageCache.DefaultIcon; var iconTex = this.imageCache.DefaultIcon;
var hasIcon = this.imageCache.TryGetIcon(plugin, manifest, isThirdParty, out var cachedIconTex); var hasIcon = this.imageCache.TryGetIcon(plugin, manifest, isThirdParty, out var cachedIconTex, out var loadedSince);
if (hasIcon && cachedIconTex != null) if (hasIcon && cachedIconTex != null)
{ {
iconTex = cachedIconTex; iconTex = cachedIconTex;
} }
if (pluginDisabled || installableOutdated) const float fadeTime = 0.3f;
var iconAlpha = 1f;
if (loadedSince.HasValue)
{ {
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.4f); float EaseOutCubic(float t) => 1 - MathF.Pow(1 - t, 3);
var secondsSinceLoad = (float)DateTime.Now.Subtract(loadedSince.Value).TotalSeconds;
var fadeTo = pluginDisabled || installableOutdated ? 0.4f : 1f;
iconAlpha = Math.Clamp(EaseOutCubic(Math.Min(secondsSinceLoad, fadeTime) / fadeTime) * fadeTo, 0, 1);
} }
ImGui.PushStyleVar(ImGuiStyleVar.Alpha, iconAlpha);
ImGui.Image(iconTex.ImGuiHandle, iconSize); ImGui.Image(iconTex.ImGuiHandle, iconSize);
if (pluginDisabled || installableOutdated)
{
ImGui.PopStyleVar(); ImGui.PopStyleVar();
}
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetCursorPos(cursorBeforeImage); ImGui.SetCursorPos(cursorBeforeImage);
@ -2019,7 +2023,7 @@ internal class PluginInstallerWindow : Window, IDisposable
if (log is PluginChangelogEntry pluginLog) if (log is PluginChangelogEntry pluginLog)
{ {
icon = this.imageCache.DefaultIcon; icon = this.imageCache.DefaultIcon;
var hasIcon = this.imageCache.TryGetIcon(pluginLog.Plugin, pluginLog.Plugin.Manifest, pluginLog.Plugin.IsThirdParty, out var cachedIconTex); var hasIcon = this.imageCache.TryGetIcon(pluginLog.Plugin, pluginLog.Plugin.Manifest, pluginLog.Plugin.IsThirdParty, out var cachedIconTex, out _);
if (hasIcon && cachedIconTex != null) if (hasIcon && cachedIconTex != null)
{ {
icon = cachedIconTex; icon = cachedIconTex;

View file

@ -437,7 +437,7 @@ internal class ProfileManagerWidget
if (pmPlugin != null) if (pmPlugin != null)
{ {
var cursorBeforeIcon = ImGui.GetCursorPos(); var cursorBeforeIcon = ImGui.GetCursorPos();
pic.TryGetIcon(pmPlugin, pmPlugin.Manifest, pmPlugin.IsThirdParty, out var icon); pic.TryGetIcon(pmPlugin, pmPlugin.Manifest, pmPlugin.IsThirdParty, out var icon, out _);
icon ??= pic.DefaultIcon; icon ??= pic.DefaultIcon;
ImGui.Image(icon.ImGuiHandle, new Vector2(pluginLineHeight)); ImGui.Image(icon.ImGuiHandle, new Vector2(pluginLineHeight));