Add ability for plugins to add ImGui fonts at runtime, though we should discourage this as much as possible. Also sneak in an api-matching update to part of ImGuiScene, to make more things useable in SamplePlugin

This commit is contained in:
meli 2020-04-29 17:13:05 -07:00
parent 0800cc4e91
commit fcd98ee2bb
3 changed files with 81 additions and 26 deletions

View file

@ -54,11 +54,15 @@ namespace Dalamud.Interface
public ImGuiIOPtr LastImGuiIoPtr;
public Action OnBuildFonts;
private bool isRebuildingFonts = false;
/// <summary>
/// This event gets called by a plugin UiBuilder when read
/// </summary>
public event RawDX11Scene.BuildUIDelegate OnDraw;
public InterfaceManager(Dalamud dalamud, SigScanner scanner)
{
this.dalamud = dalamud;
@ -200,7 +204,18 @@ namespace Dalamud.Interface
return null;
}
private unsafe IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
// Sets up a deferred invocation of font rebuilding, before the next render frame
public void RebuildFonts()
{
// don't invoke this multiple times per frame, in case multiple plugins call it
if (!this.isRebuildingFonts)
{
this.isRebuildingFonts = true;
this.scene.OnNewRenderFrame += RebuildFontsInternal;
}
}
private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
{
if (this.scene == null)
{
@ -209,30 +224,7 @@ namespace Dalamud.Interface
this.scene.OnBuildUI += Display;
this.scene.OnNewInputFrame += OnNewInputFrame;
ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
fontConfig.MergeMode = true;
fontConfig.PixelSnapH = true;
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
var fontPathGame = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "gamesym.ttf");
Log.Verbose(fontPathGame);
var rangeHandle = GCHandle.Alloc(new ushort[]
{
0xE020,
0xE0DB,
0
}, GCHandleType.Pinned);
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, rangeHandle.AddrOfPinnedObject());
ImGui.GetIO().Fonts.Build();
fontConfig.Destroy();
rangeHandle.Free();
SetupFonts();
ImGui.GetStyle().GrabRounding = 3f;
ImGui.GetStyle().FrameRounding = 4f;
@ -268,6 +260,49 @@ namespace Dalamud.Interface
return this.presentHook.Original(swapChain, syncInterval, presentFlags);
}
private unsafe void SetupFonts()
{
ImGui.GetIO().Fonts.Clear();
ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
fontConfig.MergeMode = true;
fontConfig.PixelSnapH = true;
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
var fontPathGame = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "gamesym.ttf");
Log.Verbose(fontPathGame);
var rangeHandle = GCHandle.Alloc(new ushort[]
{
0xE020,
0xE0DB,
0
}, GCHandleType.Pinned);
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, rangeHandle.AddrOfPinnedObject());
OnBuildFonts?.Invoke();
ImGui.GetIO().Fonts.Build();
fontConfig.Destroy();
rangeHandle.Free();
}
// This is intended to only be called as a handler attached to scene.OnNewRenderFrame
private void RebuildFontsInternal()
{
SetupFonts();
this.scene.OnNewRenderFrame -= RebuildFontsInternal;
this.scene.InvalidateFonts();
this.isRebuildingFonts = false;
}
private IntPtr ResizeBuffersDetour(IntPtr swapChain, uint bufferCount, uint width, uint height, uint newFormat, uint swapChainFlags)
{
Log.Verbose($"Calling resizebuffers {bufferCount} {width} {height} {newFormat} {swapChainFlags}");

View file

@ -70,6 +70,26 @@ namespace Dalamud.Interface
public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) =>
this.interfaceManager.LoadImageRaw(imageData, width, height, numChannels);
/// <summary>
/// An event that is called any time ImGui fonts need to be rebuilt.<br/>
/// Any ImFontPtr objects that you store <strong>can be invalidated</strong> when fonts are rebuilt
/// (at any time), so you should both reload your custom fonts and restore those
/// pointers inside this handler.
/// </summary>
public Action OnBuildFonts
{
get { return this.interfaceManager.OnBuildFonts; }
set { this.interfaceManager.OnBuildFonts = value; }
}
/// <summary>
/// Call this to queue a rebuild of the font atlas.<br/>
/// This will invoke any <see cref="OnBuildFonts"/> handlers and ensure that any loaded fonts are
/// ready to be used on the next UI frame.
/// </summary>
public void RebuildFonts() =>
this.interfaceManager.RebuildFonts();
/// <summary>
/// Event that is fired when the plugin should open its configuration interface.
/// </summary>

@ -1 +1 @@
Subproject commit aaa037938d6fe835a15542a3451d12108e3f83b6
Subproject commit d5b9345dc1463d746b832843bd7c81b753d4e5b0