mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge pull request #1618 from Soreepeong/fix/ifontatlas-compat-fix-2
IFontAtlas API9 compat: support reading GameFontHandle.ImFont during UiBuilder.After/BuildFonts
This commit is contained in:
commit
620f3999d2
10 changed files with 201 additions and 29 deletions
|
|
@ -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;
|
|||
/// <summary>
|
||||
/// ABI-compatible wrapper for <see cref="IFontHandle"/>.
|
||||
/// </summary>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public sealed class GameFontHandle : IFontHandle
|
||||
{
|
||||
private readonly IFontHandle.IInternal fontHandle;
|
||||
|
|
@ -53,8 +55,14 @@ public sealed class GameFontHandle : IFontHandle
|
|||
/// <inheritdoc />
|
||||
public void Dispose() => this.fontHandle.Dispose();
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <summary>
|
||||
/// Pushes the font.
|
||||
/// </summary>
|
||||
/// <returns>An <see cref="IDisposable"/> that can be used to pop the font on dispose.</returns>
|
||||
public IDisposable Push() => this.fontHandle.Push();
|
||||
|
||||
/// <inheritdoc/>
|
||||
IFontHandle.FontPopper IFontHandle.Push() => this.fontHandle.Push();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="GameFontLayoutPlan.Builder"/>.<br />
|
||||
|
|
|
|||
|
|
@ -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;
|
|||
/// </summary>
|
||||
public interface IFontAtlasBuildToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// Functionalities for compatibility behavior.<br />
|
||||
/// </summary>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
internal interface IApi9Compat : IFontAtlasBuildToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes <paramref name="action"/>, temporarily applying <see cref="IFontHandleSubstance"/>s.<br />
|
||||
/// </summary>
|
||||
/// <param name="action">The action to invoke.</param>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public void FromUiBuilderObsoleteEventHandlers(Action action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the font relevant to the call.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/// </summary>
|
||||
/// <returns>A disposable object that will call <see cref="ImGui.PopFont"/>(1) on dispose.</returns>
|
||||
IDisposable Push();
|
||||
/// <exception cref="InvalidOperationException">If called outside of the main thread.</exception>
|
||||
/// <remarks>
|
||||
/// Only intended for use with <c>using</c> keywords, such as <c>using (handle.Push())</c>.<br />
|
||||
/// Should you store or transfer the return value to somewhere else, use <see cref="IDisposable"/> as the type.
|
||||
/// </remarks>
|
||||
FontPopper Push();
|
||||
|
||||
/// <summary>
|
||||
/// The wrapper for popping fonts.
|
||||
/// </summary>
|
||||
public struct FontPopper : IDisposable
|
||||
{
|
||||
private int count;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FontPopper"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="fontPtr">The font to push.</param>
|
||||
/// <param name="push">Whether to push.</param>
|
||||
internal FontPopper(ImFontPtr fontPtr, bool push)
|
||||
{
|
||||
if (!push)
|
||||
return;
|
||||
|
||||
ThreadSafety.AssertMainThread();
|
||||
|
||||
this.count = 1;
|
||||
ImGui.PushFont(fontPtr);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
ThreadSafety.AssertMainThread();
|
||||
|
||||
while (this.count-- > 0)
|
||||
ImGui.PopFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IDisposable Push() => ImRaii.PushFont(this.ImFont, this.Available);
|
||||
public IFontHandle.FontPopper Push() => new(this.ImFont, this.Available);
|
||||
|
||||
/// <summary>
|
||||
/// Manager for <see cref="DelegateFontHandle"/>s.
|
||||
|
|
@ -144,6 +144,14 @@ internal class DelegateFontHandle : IFontHandle.IInternal
|
|||
/// <inheritdoc/>
|
||||
public IFontHandleManager Manager { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public IFontAtlasBuildToolkitPreBuild? PreBuildToolkitForApi9Compat { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public bool CreateFontOnAccess { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ internal sealed partial class FontAtlasFactory
|
|||
/// Implementations for <see cref="IFontAtlasBuildToolkitPreBuild"/> and
|
||||
/// <see cref="IFontAtlasBuildToolkitPostBuild"/>.
|
||||
/// </summary>
|
||||
private class BuildToolkit : IFontAtlasBuildToolkitPreBuild, IFontAtlasBuildToolkitPostBuild, IDisposable
|
||||
private class BuildToolkit : IFontAtlasBuildToolkit.IApi9Compat, IFontAtlasBuildToolkitPreBuild, IFontAtlasBuildToolkitPostBuild, IDisposable
|
||||
{
|
||||
private static readonly ushort FontAwesomeIconMin =
|
||||
(ushort)Enum.GetValues<FontAwesomeIcon>().Where(x => x > 0).Min();
|
||||
|
|
@ -107,6 +107,34 @@ internal sealed partial class FontAtlasFactory
|
|||
/// <inheritdoc/>
|
||||
public void DisposeWithAtlas(Action action) => this.data.Garbage.Add(action);
|
||||
|
||||
/// <inheritdoc/>
|
||||
[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ImFontPtr IgnoreGlobalScale(ImFontPtr fontPtr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IDisposable Push() => ImRaii.PushFont(this.ImFont, this.Available);
|
||||
public IFontHandle.FontPopper Push() => new(this.ImFont, this.Available);
|
||||
|
||||
/// <summary>
|
||||
/// Manager for <see cref="GamePrebakedFontHandle"/>s.
|
||||
|
|
@ -230,6 +229,14 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
|
|||
/// <inheritdoc/>
|
||||
public IFontHandleManager Manager => this.handleManager;
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public IFontAtlasBuildToolkitPreBuild? PreBuildToolkitForApi9Compat { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public bool CreateFontOnAccess { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
@ -285,11 +292,27 @@ internal class GamePrebakedFontHandle : IFontHandle.IInternal
|
|||
}
|
||||
}
|
||||
|
||||
// Use this on API 10.
|
||||
// /// <inheritdoc/>
|
||||
// public ImFontPtr GetFontPtr(IFontHandle handle) =>
|
||||
// handle is GamePrebakedFontHandle ggfh
|
||||
// ? this.fonts.GetValueOrDefault(ggfh.FontStyle)?.FullRangeFont ?? default
|
||||
// : default;
|
||||
|
||||
/// <inheritdoc/>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Exception? GetBuildException(IFontHandle handle) =>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using ImGuiNET;
|
||||
using Dalamud.Utility;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Dalamud.Interface.ManagedFontAtlas.Internals;
|
||||
|
||||
|
|
@ -12,6 +14,19 @@ internal interface IFontHandleSubstance : IDisposable
|
|||
/// </summary>
|
||||
IFontHandleManager Manager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relevant <see cref="IFontAtlasBuildToolkitPreBuild"/> for this.
|
||||
/// </summary>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
IFontAtlasBuildToolkitPreBuild? PreBuildToolkitForApi9Compat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to create a new instance of <see cref="ImGuiNET.ImFontPtr"/> on first
|
||||
/// access, for compatibility with API 9.
|
||||
/// </summary>
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
bool CreateFontOnAccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the font.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ public sealed class UiBuilder : IDisposable
|
|||
/// pointers inside this handler.
|
||||
/// </summary>
|
||||
[Obsolete($"Use {nameof(this.FontAtlas)} instead.", false)]
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public event Action? BuildFonts;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -113,6 +114,7 @@ public sealed class UiBuilder : IDisposable
|
|||
/// pointers inside this handler.
|
||||
/// </summary>
|
||||
[Obsolete($"Use {nameof(this.FontAtlas)} instead.", false)]
|
||||
[Api10ToDo(Api10ToDoAttribute.DeleteCompatBehavior)]
|
||||
public event Action? AfterBuildFonts;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -423,6 +425,7 @@ public sealed class UiBuilder : IDisposable
|
|||
/// <param name="style">Font to get.</param>
|
||||
/// <returns>Handle to the game font which may or may not be available for use yet.</returns>
|
||||
[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<FontAtlasFactory>.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()
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/// </remarks>
|
||||
[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
|
||||
|
|
|
|||
19
Dalamud/Utility/Api10ToDoAttribute.cs
Normal file
19
Dalamud/Utility/Api10ToDoAttribute.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
namespace Dalamud.Utility;
|
||||
|
||||
/// <summary>
|
||||
/// Utility class for marking something to be changed for API 10, for ease of lookup.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All, Inherited = false)]
|
||||
internal sealed class Api10ToDoAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks that this exists purely for making API 9 plugins work.
|
||||
/// </summary>
|
||||
public const string DeleteCompatBehavior = "Delete. This is for making API 9 plugins work.";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Api10ToDoAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="what">The explanation.</param>
|
||||
public Api10ToDoAttribute(string what) => _ = what;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue