From 5eadfc1b4da13f3c8f909bdd0e6a9fe3e318dde5 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Thu, 22 Feb 2024 03:32:13 +0900 Subject: [PATCH] Add state fetchers --- .../Internal}/GameIconLookup.cs | 2 +- .../FileSystemSharableTexture.cs | 9 ++---- .../GamePathSharableTexture.cs | 9 ++---- .../SharableTextures/SharableTexture.cs | 23 ++++++++++---- Dalamud/Interface/Internal/TextureManager.cs | 30 +++++++++++++++++++ .../Plugin/Services/ITextureProvider.Api9.cs | 1 + Dalamud/Plugin/Services/ITextureProvider.cs | 18 +++++++++++ 7 files changed, 72 insertions(+), 20 deletions(-) rename Dalamud/{Plugin/Services => Interface/Internal}/GameIconLookup.cs (94%) diff --git a/Dalamud/Plugin/Services/GameIconLookup.cs b/Dalamud/Interface/Internal/GameIconLookup.cs similarity index 94% rename from Dalamud/Plugin/Services/GameIconLookup.cs rename to Dalamud/Interface/Internal/GameIconLookup.cs index 4ad710ab1..b34db9d59 100644 --- a/Dalamud/Plugin/Services/GameIconLookup.cs +++ b/Dalamud/Interface/Internal/GameIconLookup.cs @@ -1,6 +1,6 @@ using System.Diagnostics.CodeAnalysis; -namespace Dalamud.Plugin.Services; +namespace Dalamud.Interface.Internal; /// /// Represents a lookup for a game icon. diff --git a/Dalamud/Interface/Internal/SharableTextures/FileSystemSharableTexture.cs b/Dalamud/Interface/Internal/SharableTextures/FileSystemSharableTexture.cs index 0eea2a5f7..cae633a84 100644 --- a/Dalamud/Interface/Internal/SharableTextures/FileSystemSharableTexture.cs +++ b/Dalamud/Interface/Internal/SharableTextures/FileSystemSharableTexture.cs @@ -21,9 +21,6 @@ internal sealed class FileSystemSharableTexture : SharableTexture this.UnderlyingWrap = this.CreateTextureAsync(); } - /// - protected override Task UnderlyingWrap { get; set; } - /// public override string ToString() => $"{nameof(FileSystemSharableTexture)}#{this.InstanceIdForDebug}({this.path})"; @@ -32,10 +29,8 @@ internal sealed class FileSystemSharableTexture : SharableTexture protected override void FinalRelease() { this.DisposeSuppressingWrap = null; - _ = this.UnderlyingWrap.ToContentDisposedTask(true); - this.UnderlyingWrap = - Task.FromException(new ObjectDisposedException(nameof(GamePathSharableTexture))); - _ = this.UnderlyingWrap.Exception; + _ = this.UnderlyingWrap?.ToContentDisposedTask(true); + this.UnderlyingWrap = null; } /// diff --git a/Dalamud/Interface/Internal/SharableTextures/GamePathSharableTexture.cs b/Dalamud/Interface/Internal/SharableTextures/GamePathSharableTexture.cs index e2198b651..328377c1b 100644 --- a/Dalamud/Interface/Internal/SharableTextures/GamePathSharableTexture.cs +++ b/Dalamud/Interface/Internal/SharableTextures/GamePathSharableTexture.cs @@ -25,9 +25,6 @@ internal sealed class GamePathSharableTexture : SharableTexture this.UnderlyingWrap = this.CreateTextureAsync(); } - /// - protected override Task UnderlyingWrap { get; set; } - /// public override string ToString() => $"{nameof(GamePathSharableTexture)}#{this.InstanceIdForDebug}({this.path})"; @@ -35,10 +32,8 @@ internal sealed class GamePathSharableTexture : SharableTexture protected override void FinalRelease() { this.DisposeSuppressingWrap = null; - _ = this.UnderlyingWrap.ToContentDisposedTask(true); - this.UnderlyingWrap = - Task.FromException(new ObjectDisposedException(nameof(GamePathSharableTexture))); - _ = this.UnderlyingWrap.Exception; + _ = this.UnderlyingWrap?.ToContentDisposedTask(true); + this.UnderlyingWrap = null; } /// diff --git a/Dalamud/Interface/Internal/SharableTextures/SharableTexture.cs b/Dalamud/Interface/Internal/SharableTextures/SharableTexture.cs index b0c1a373a..9c4b43f66 100644 --- a/Dalamud/Interface/Internal/SharableTextures/SharableTexture.cs +++ b/Dalamud/Interface/Internal/SharableTextures/SharableTexture.cs @@ -66,7 +66,7 @@ internal abstract class SharableTexture : IRefCountable /// /// Gets or sets the underlying texture wrap. /// - protected abstract Task UnderlyingWrap { get; set; } + public Task? UnderlyingWrap { get; set; } /// /// Gets or sets the dispose-suppressing wrap for . @@ -185,8 +185,18 @@ internal abstract class SharableTexture : IRefCountable public Task CreateNewReference() { this.AddRef(); + if (this.UnderlyingWrap is null) + throw new InvalidOperationException("AddRef returned but UnderlyingWrap is null?"); + return this.UnderlyingWrap.ContinueWith( - r => (IDalamudTextureWrap)new RefCountableWrappingTextureWrap(r.Result, this)); + r => + { + if (r.IsCompletedSuccessfully) + return Task.FromResult((IDalamudTextureWrap)new RefCountableWrappingTextureWrap(r.Result, this)); + + this.Release(); + return r; + }).Unwrap(); } /// @@ -207,9 +217,12 @@ internal abstract class SharableTexture : IRefCountable if (this.RevivalPossibility?.TryGetTarget(out this.availableOnAccessWrapForApi9) is true) return this.availableOnAccessWrapForApi9; - this.UnderlyingWrap.Wait(); - if (this.UnderlyingWrap.Exception is not null) + var newRefTask = this.CreateNewReference(); + newRefTask.Wait(); + if (!newRefTask.IsCompletedSuccessfully) return null; + newRefTask.Result.Dispose(); + this.availableOnAccessWrapForApi9 = new AvailableOnAccessTextureWrap(this); this.RevivalPossibility = new(this.availableOnAccessWrapForApi9); } @@ -326,7 +339,7 @@ internal abstract class SharableTexture : IRefCountable if (this.inner.GetImmediate() is { } t) return t; - this.inner.UnderlyingWrap.Wait(); + this.inner.UnderlyingWrap?.Wait(); return this.inner.DisposeSuppressingWrap ?? Service.Get().Empty4X4; } } diff --git a/Dalamud/Interface/Internal/TextureManager.cs b/Dalamud/Interface/Internal/TextureManager.cs index cd0447b6b..9081cf14e 100644 --- a/Dalamud/Interface/Internal/TextureManager.cs +++ b/Dalamud/Interface/Internal/TextureManager.cs @@ -145,6 +145,36 @@ internal sealed class TextureManager : IServiceType, IDisposable, ITextureProvid this.fileSystemTextures.GetOrAdd(file.FullName, CreateFileSystemSharableTexture).GetAvailableOnAccessWrapForApi9(); #pragma warning restore CS0618 // Type or member is obsolete + /// + public bool ImmediateGetStateFromGameIcon(in GameIconLookup lookup, out Exception? exception) => + this.ImmediateGetStateFromGame(this.lookupToPath.GetOrAdd(lookup, this.GetIconPathByValue), out exception); + + /// + public bool ImmediateGetStateFromGame(string path, out Exception? exception) + { + if (!this.gamePathTextures.TryGetValue(path, out var texture)) + { + exception = null; + return false; + } + + exception = texture.UnderlyingWrap?.Exception; + return texture.UnderlyingWrap?.IsCompletedSuccessfully ?? false; + } + + /// + public bool ImmediateGetStateFromFile(string file, out Exception? exception) + { + if (!this.fileSystemTextures.TryGetValue(file, out var texture)) + { + exception = null; + return false; + } + + exception = texture.UnderlyingWrap?.Exception; + return texture.UnderlyingWrap?.IsCompletedSuccessfully ?? false; + } + /// public IDalamudTextureWrap ImmediateGetFromGameIcon(in GameIconLookup lookup) => this.ImmediateGetFromGame(this.lookupToPath.GetOrAdd(lookup, this.GetIconPathByValue)); diff --git a/Dalamud/Plugin/Services/ITextureProvider.Api9.cs b/Dalamud/Plugin/Services/ITextureProvider.Api9.cs index 9592da711..db033778e 100644 --- a/Dalamud/Plugin/Services/ITextureProvider.Api9.cs +++ b/Dalamud/Plugin/Services/ITextureProvider.Api9.cs @@ -1,5 +1,6 @@ using System.IO; +using Dalamud.Interface; using Dalamud.Interface.Internal; using Dalamud.Utility; diff --git a/Dalamud/Plugin/Services/ITextureProvider.cs b/Dalamud/Plugin/Services/ITextureProvider.cs index e004c8be7..52037a449 100644 --- a/Dalamud/Plugin/Services/ITextureProvider.cs +++ b/Dalamud/Plugin/Services/ITextureProvider.cs @@ -13,6 +13,24 @@ namespace Dalamud.Plugin.Services; /// public partial interface ITextureProvider { + /// Gets the state of the background load task for . + /// The icon specifier. + /// The exception, if failed. + /// true if loaded; false if not fully loaded or failed. + public bool ImmediateGetStateFromGameIcon(in GameIconLookup lookup, out Exception? exception); + + /// Gets the state of the background load task for . + /// The game-internal path to a .tex, .atex, or an image file such as .png. + /// The exception, if failed. + /// true if loaded; false if not fully loaded or failed. + public bool ImmediateGetStateFromGame(string path, out Exception? exception); + + /// Gets the state of the background load task for . + /// The filesystem path to a .tex, .atex, or an image file such as .png. + /// The exception, if failed. + /// true if loaded; false if not fully loaded or failed. + public bool ImmediateGetStateFromFile(string file, out Exception? exception); + /// Gets the corresponding game icon for use with the current frame. /// The icon specifier. /// An instance of that is guaranteed to be available for the current