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.Manifest,
plugin.IsThirdParty,
out var texture) || texture is null)
out var texture, out _) || texture is null)
{
texture = dam.GetDalamudTextureWrap(DalamudAsset.DefaultIcon);
}

View file

@ -55,7 +55,9 @@ internal class PluginImageCache : IInternalDisposableService
private readonly Task downloadTask;
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 DalamudAssetManager dalamudAssetManager;
@ -153,7 +155,7 @@ internal class PluginImageCache : IInternalDisposableService
foreach (var icon in this.pluginIconMap.Values)
{
icon?.Dispose();
icon?.Texture.Dispose();
}
foreach (var images in this.pluginImagesMap.Values)
@ -185,10 +187,12 @@ internal class PluginImageCache : IInternalDisposableService
/// <param name="manifest">The plugin manifest.</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="loadedSince">The time the icon was successfully downloaded.</param>
/// <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;
loadedSince = null;
if (manifest == null || manifest.InternalName == null)
{
@ -198,7 +202,13 @@ internal class PluginImageCache : IInternalDisposableService
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;
}
@ -207,8 +217,9 @@ internal class PluginImageCache : IInternalDisposableService
{
try
{
this.pluginIconMap[manifest.InternalName] =
await this.DownloadPluginIconAsync(plugin, manifest, isThirdParty, requestedFrame);
var texture = await this.DownloadPluginIconAsync(plugin, manifest, isThirdParty, requestedFrame);
if (texture != null)
this.pluginIconMap[manifest.InternalName] = new LoadedIcon(texture, DateTime.Now);
}
catch (Exception ex)
{

View file

@ -1814,23 +1814,27 @@ internal class PluginInstallerWindow : Window, IDisposable
if (ImGui.IsRectVisible(rectOffset + cursorBeforeImage, rectOffset + cursorBeforeImage + iconSize))
{
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)
{
iconTex = cachedIconTex;
}
const float fadeTime = 0.3f;
var iconAlpha = 1f;
if (pluginDisabled || installableOutdated)
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);
if (pluginDisabled || installableOutdated)
{
ImGui.PopStyleVar();
}
ImGui.PopStyleVar();
ImGui.SameLine();
ImGui.SetCursorPos(cursorBeforeImage);
@ -2019,7 +2023,7 @@ internal class PluginInstallerWindow : Window, IDisposable
if (log is PluginChangelogEntry pluginLog)
{
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)
{
icon = cachedIconTex;

View file

@ -437,7 +437,7 @@ internal class ProfileManagerWidget
if (pmPlugin != null)
{
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;
ImGui.Image(icon.ImGuiHandle, new Vector2(pluginLineHeight));