diff --git a/Dalamud/Interface/GameFonts/GameFontHandle.cs b/Dalamud/Interface/GameFonts/GameFontHandle.cs
index 77461aa0a..d11414517 100644
--- a/Dalamud/Interface/GameFonts/GameFontHandle.cs
+++ b/Dalamud/Interface/GameFonts/GameFontHandle.cs
@@ -2,6 +2,7 @@ using System.Numerics;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
+using Dalamud.Utility;
using ImGuiNET;
@@ -10,6 +11,7 @@ namespace Dalamud.Interface.GameFonts;
///
/// ABI-compatible wrapper for .
///
+[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
public sealed class GameFontHandle : IFontHandle
{
private readonly IFontHandle.IInternal fontHandle;
@@ -53,8 +55,14 @@ public sealed class GameFontHandle : IFontHandle
///
public void Dispose() => this.fontHandle.Dispose();
- ///
+ ///
+ /// Pushes the font.
+ ///
+ /// An that can be used to pop the font on dispose.
public IDisposable Push() => this.fontHandle.Push();
+
+ ///
+ IFontHandle.FontPopper IFontHandle.Push() => this.fontHandle.Push();
///
/// Creates a new .
diff --git a/Dalamud/Interface/ManagedFontAtlas/IFontAtlasBuildToolkit.cs b/Dalamud/Interface/ManagedFontAtlas/IFontAtlasBuildToolkit.cs
index 4b016bbb2..a997c48c1 100644
--- a/Dalamud/Interface/ManagedFontAtlas/IFontAtlasBuildToolkit.cs
+++ b/Dalamud/Interface/ManagedFontAtlas/IFontAtlasBuildToolkit.cs
@@ -1,6 +1,8 @@
using System.Runtime.InteropServices;
+using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
+using Dalamud.Utility;
using ImGuiNET;
@@ -11,6 +13,20 @@ namespace Dalamud.Interface.ManagedFontAtlas;
///
public interface IFontAtlasBuildToolkit
{
+ ///
+ /// Functionalities for compatibility behavior.
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ internal interface IApi9Compat : IFontAtlasBuildToolkit
+ {
+ ///
+ /// Invokes , temporarily applying s.
+ ///
+ /// The action to invoke.
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public void FromUiBuilderObsoleteEventHandlers(Action action);
+ }
+
///
/// Gets or sets the font relevant to the call.
///
diff --git a/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs b/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs
index 854594663..460fd53a0 100644
--- a/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs
+++ b/Dalamud/Interface/ManagedFontAtlas/IFontHandle.cs
@@ -1,4 +1,6 @@
-using ImGuiNET;
+using Dalamud.Utility;
+
+using ImGuiNET;
namespace Dalamud.Interface.ManagedFontAtlas;
@@ -38,5 +40,43 @@ public interface IFontHandle : IDisposable
/// You may not access the font once you dispose this object.
///
/// A disposable object that will call (1) on dispose.
- IDisposable Push();
+ /// If called outside of the main thread.
+ ///
+ /// Only intended for use with using keywords, such as using (handle.Push()).
+ /// Should you store or transfer the return value to somewhere else, use as the type.
+ ///
+ FontPopper Push();
+
+ ///
+ /// The wrapper for popping fonts.
+ ///
+ public struct FontPopper : IDisposable
+ {
+ private int count;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The font to push.
+ /// Whether to push.
+ internal FontPopper(ImFontPtr fontPtr, bool push)
+ {
+ if (!push)
+ return;
+
+ ThreadSafety.AssertMainThread();
+
+ this.count = 1;
+ ImGui.PushFont(fontPtr);
+ }
+
+ ///
+ public void Dispose()
+ {
+ ThreadSafety.AssertMainThread();
+
+ while (this.count-- > 0)
+ ImGui.PopFont();
+ }
+ }
}
diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/DelegateFontHandle.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/DelegateFontHandle.cs
index f0ed09155..bde349736 100644
--- a/Dalamud/Interface/ManagedFontAtlas/Internals/DelegateFontHandle.cs
+++ b/Dalamud/Interface/ManagedFontAtlas/Internals/DelegateFontHandle.cs
@@ -2,8 +2,8 @@
using System.Linq;
using Dalamud.Interface.Utility;
-using Dalamud.Interface.Utility.Raii;
using Dalamud.Logging.Internal;
+using Dalamud.Utility;
using ImGuiNET;
@@ -52,7 +52,7 @@ internal class DelegateFontHandle : IFontHandle.IInternal
}
///
- public IDisposable Push() => ImRaii.PushFont(this.ImFont, this.Available);
+ public IFontHandle.FontPopper Push() => new(this.ImFont, this.Available);
///
/// Manager for s.
@@ -144,6 +144,14 @@ internal class DelegateFontHandle : IFontHandle.IInternal
///
public IFontHandleManager Manager { get; }
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public IFontAtlasBuildToolkitPreBuild? PreBuildToolkitForApi9Compat { get; set; }
+
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public bool CreateFontOnAccess { get; set; }
+
///
public void Dispose()
{
diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs
index e73ea7548..fde115c9e 100644
--- a/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs
+++ b/Dalamud/Interface/ManagedFontAtlas/Internals/FontAtlasFactory.BuildToolkit.cs
@@ -30,7 +30,7 @@ internal sealed partial class FontAtlasFactory
/// Implementations for and
/// .
///
- private class BuildToolkit : IFontAtlasBuildToolkitPreBuild, IFontAtlasBuildToolkitPostBuild, IDisposable
+ private class BuildToolkit : IFontAtlasBuildToolkit.IApi9Compat, IFontAtlasBuildToolkitPreBuild, IFontAtlasBuildToolkitPostBuild, IDisposable
{
private static readonly ushort FontAwesomeIconMin =
(ushort)Enum.GetValues().Where(x => x > 0).Min();
@@ -107,6 +107,34 @@ internal sealed partial class FontAtlasFactory
///
public void DisposeWithAtlas(Action action) => this.data.Garbage.Add(action);
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public void FromUiBuilderObsoleteEventHandlers(Action action)
+ {
+ var previousSubstances = new IFontHandleSubstance[this.data.Substances.Count];
+ for (var i = 0; i < previousSubstances.Length; i++)
+ {
+ previousSubstances[i] = this.data.Substances[i].Manager.Substance;
+ this.data.Substances[i].Manager.Substance = this.data.Substances[i];
+ this.data.Substances[i].CreateFontOnAccess = true;
+ this.data.Substances[i].PreBuildToolkitForApi9Compat = this;
+ }
+
+ try
+ {
+ action();
+ }
+ finally
+ {
+ for (var i = 0; i < previousSubstances.Length; i++)
+ {
+ this.data.Substances[i].Manager.Substance = previousSubstances[i];
+ this.data.Substances[i].CreateFontOnAccess = false;
+ this.data.Substances[i].PreBuildToolkitForApi9Compat = null;
+ }
+ }
+ }
+
///
public ImFontPtr IgnoreGlobalScale(ImFontPtr fontPtr)
{
diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs
index 99c817a91..feda47a8a 100644
--- a/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs
+++ b/Dalamud/Interface/ManagedFontAtlas/Internals/GamePrebakedFontHandle.cs
@@ -9,7 +9,6 @@ using Dalamud.Game.Text;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility;
-using Dalamud.Interface.Utility.Raii;
using Dalamud.Utility;
using ImGuiNET;
@@ -117,7 +116,7 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
}
///
- public IDisposable Push() => ImRaii.PushFont(this.ImFont, this.Available);
+ public IFontHandle.FontPopper Push() => new(this.ImFont, this.Available);
///
/// Manager for s.
@@ -230,6 +229,14 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
///
public IFontHandleManager Manager => this.handleManager;
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public IFontAtlasBuildToolkitPreBuild? PreBuildToolkitForApi9Compat { get; set; }
+
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public bool CreateFontOnAccess { get; set; }
+
///
public void Dispose()
{
@@ -285,11 +292,27 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
}
}
+ // Use this on API 10.
+ // ///
+ // public ImFontPtr GetFontPtr(IFontHandle handle) =>
+ // handle is GamePrebakedFontHandle ggfh
+ // ? this.fonts.GetValueOrDefault(ggfh.FontStyle)?.FullRangeFont ?? default
+ // : default;
+
///
- public ImFontPtr GetFontPtr(IFontHandle handle) =>
- handle is GamePrebakedFontHandle ggfh
- ? this.fonts.GetValueOrDefault(ggfh.FontStyle)?.FullRangeFont ?? default
- : default;
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ public ImFontPtr GetFontPtr(IFontHandle handle)
+ {
+ if (handle is not GamePrebakedFontHandle ggfh)
+ return default;
+ if (this.fonts.GetValueOrDefault(ggfh.FontStyle)?.FullRangeFont is { } font)
+ return font;
+ if (!this.CreateFontOnAccess)
+ return default;
+ if (this.PreBuildToolkitForApi9Compat is not { } tk)
+ return default;
+ return this.GetOrCreateFont(ggfh.FontStyle, tk);
+ }
///
public Exception? GetBuildException(IFontHandle handle) =>
diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/IFontHandleSubstance.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/IFontHandleSubstance.cs
index f6c5c6591..c800c30ac 100644
--- a/Dalamud/Interface/ManagedFontAtlas/Internals/IFontHandleSubstance.cs
+++ b/Dalamud/Interface/ManagedFontAtlas/Internals/IFontHandleSubstance.cs
@@ -1,4 +1,6 @@
-using ImGuiNET;
+using Dalamud.Utility;
+
+using ImGuiNET;
namespace Dalamud.Interface.ManagedFontAtlas.Internals;
@@ -12,6 +14,19 @@ internal interface IFontHandleSubstance : IDisposable
///
IFontHandleManager Manager { get; }
+ ///
+ /// Gets or sets the relevant for this.
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ IFontAtlasBuildToolkitPreBuild? PreBuildToolkitForApi9Compat { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to create a new instance of on first
+ /// access, for compatibility with API 9.
+ ///
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
+ bool CreateFontOnAccess { get; set; }
+
///
/// Gets the font.
///
diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs
index a477ec09e..87e3b9032 100644
--- a/Dalamud/Interface/UiBuilder.cs
+++ b/Dalamud/Interface/UiBuilder.cs
@@ -104,6 +104,7 @@ public sealed class UiBuilder : IDisposable
/// pointers inside this handler.
///
[Obsolete($"Use {nameof(this.FontAtlas)} instead.", false)]
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
public event Action? BuildFonts;
///
@@ -113,6 +114,7 @@ public sealed class UiBuilder : IDisposable
/// pointers inside this handler.
///
[Obsolete($"Use {nameof(this.FontAtlas)} instead.", false)]
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
public event Action? AfterBuildFonts;
///
@@ -423,6 +425,7 @@ public sealed class UiBuilder : IDisposable
/// Font to get.
/// Handle to the game font which may or may not be available for use yet.
[Obsolete($"Use {nameof(this.FontAtlas)}.{nameof(IFontAtlas.NewGameFontHandle)} instead.", false)]
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
public GameFontHandle GetGameFontHandle(GameFontStyle style) => new(
(IFontHandle.IInternal)this.FontAtlas.NewGameFontHandle(style),
Service.Get());
@@ -620,28 +623,37 @@ public sealed class UiBuilder : IDisposable
this.hitchDetector.Stop();
}
+ [Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
private unsafe void PrivateAtlasOnBuildStepChange(IFontAtlasBuildToolkit e)
{
if (e.IsAsyncBuildOperation)
return;
- e.OnPreBuild(
- _ =>
- {
- var prev = ImGui.GetIO().NativePtr->Fonts;
- ImGui.GetIO().NativePtr->Fonts = e.NewImAtlas.NativePtr;
- this.BuildFonts?.InvokeSafely();
- ImGui.GetIO().NativePtr->Fonts = prev;
- });
+ if (this.BuildFonts is not null)
+ {
+ e.OnPreBuild(
+ _ =>
+ {
+ var prev = ImGui.GetIO().NativePtr->Fonts;
+ ImGui.GetIO().NativePtr->Fonts = e.NewImAtlas.NativePtr;
+ ((IFontAtlasBuildToolkit.IApi9Compat)e)
+ .FromUiBuilderObsoleteEventHandlers(() => this.BuildFonts?.InvokeSafely());
+ ImGui.GetIO().NativePtr->Fonts = prev;
+ });
+ }
- e.OnPostBuild(
- _ =>
- {
- var prev = ImGui.GetIO().NativePtr->Fonts;
- ImGui.GetIO().NativePtr->Fonts = e.NewImAtlas.NativePtr;
- this.AfterBuildFonts?.InvokeSafely();
- ImGui.GetIO().NativePtr->Fonts = prev;
- });
+ if (this.AfterBuildFonts is not null)
+ {
+ e.OnPostBuild(
+ _ =>
+ {
+ var prev = ImGui.GetIO().NativePtr->Fonts;
+ ImGui.GetIO().NativePtr->Fonts = e.NewImAtlas.NativePtr;
+ ((IFontAtlasBuildToolkit.IApi9Compat)e)
+ .FromUiBuilderObsoleteEventHandlers(() => this.AfterBuildFonts?.InvokeSafely());
+ ImGui.GetIO().NativePtr->Fonts = prev;
+ });
+ }
}
private void OnResizeBuffers()
diff --git a/Dalamud/Logging/PluginLog.cs b/Dalamud/Logging/PluginLog.cs
index decf10b4c..e3744c617 100644
--- a/Dalamud/Logging/PluginLog.cs
+++ b/Dalamud/Logging/PluginLog.cs
@@ -1,6 +1,8 @@
using System.Reflection;
using Dalamud.Plugin.Services;
+using Dalamud.Utility;
+
using Serilog;
using Serilog.Events;
@@ -14,6 +16,7 @@ namespace Dalamud.Logging;
/// move over as soon as reasonably possible for performance reasons.
///
[Obsolete("Static PluginLog will be removed in API 10. Developers should use IPluginLog.")]
+[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
public static class PluginLog
{
#region "Log" prefixed Serilog style methods
diff --git a/Dalamud/Utility/Api10ToDoAttribute.cs b/Dalamud/Utility/Api10ToDoAttribute.cs
new file mode 100644
index 000000000..f397f8f0c
--- /dev/null
+++ b/Dalamud/Utility/Api10ToDoAttribute.cs
@@ -0,0 +1,19 @@
+namespace Dalamud.Utility;
+
+///
+/// Utility class for marking something to be changed for API 10, for ease of lookup.
+///
+[AttributeUsage(AttributeTargets.All, Inherited = false)]
+internal sealed class Api10ToDoAttribute : Attribute
+{
+ ///
+ /// Marks that this exists purely for making API 9 plugins work.
+ ///
+ public const string DeleteCompatBehavior = "Delete. This is for making API 9 plugins work.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The explanation.
+ public Api10ToDoAttribute(string what) => _ = what;
+}