Implement FontChooserDialog (#1637)

* Implement FontChooserDialog

* Minor fixes

* Fixes 2

* Add Reset default font button

* Add failsafe

* reduce uninteresting exception message

* Add remarks to use AttachExtraGlyphsForDalamudLanguage

* Support advanced font configuration options

* fixes

* Shift ui elements

* more fixes

* Add To(Localized)String for IFontSpec

* Untie GlobalFontScale from default font size

* Layout fixes

* Make UiBuilder.DefaultFontSize point to user configured value

* Update example for NewDelegateFontHandle

* Font interfaces: write notes on not intended for plugins to implement

* Update default gamma to 1.7 to match closer to prev behavior (1.4**2)

* Fix console window layout
This commit is contained in:
srkizer 2024-02-14 05:09:46 +09:00 committed by GitHub
parent 3b3823d4e6
commit 34daa73612
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 2478 additions and 81 deletions

View file

@ -5,7 +5,10 @@ using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Dalamud.Game;
using Dalamud.Interface.FontIdentifier;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.ImGuiFontChooserDialog;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
@ -24,6 +27,8 @@ internal class GamePrebakedFontsTestWidget : IDataWindowWidget, IDisposable
{
private ImVectorWrapper<byte> testStringBuffer;
private IFontAtlas? privateAtlas;
private SingleFontSpec fontSpec = new() { FontId = DalamudDefaultFontAndFamilyId.Instance };
private IFontHandle? fontDialogHandle;
private IReadOnlyDictionary<GameFontFamily, (GameFontStyle Size, Lazy<IFontHandle> Handle)[]>? fontHandles;
private bool useGlobalScale;
private bool useWordWrap;
@ -111,29 +116,32 @@ internal class GamePrebakedFontsTestWidget : IDataWindowWidget, IDisposable
if (ImGui.Button("Test Lock"))
Task.Run(this.TestLock);
fixed (byte* labelPtr = "Test Input"u8)
ImGui.SameLine();
if (ImGui.Button("Choose Editor Font"))
{
if (ImGuiNative.igInputTextMultiline(
labelPtr,
this.testStringBuffer.Data,
(uint)this.testStringBuffer.Capacity,
new(ImGui.GetContentRegionAvail().X, 32 * ImGuiHelpers.GlobalScale),
0,
null,
null) != 0)
{
var len = this.testStringBuffer.StorageSpan.IndexOf((byte)0);
if (len + 4 >= this.testStringBuffer.Capacity)
this.testStringBuffer.EnsureCapacityExponential(len + 4);
if (len < this.testStringBuffer.Capacity)
{
this.testStringBuffer.LengthUnsafe = len;
this.testStringBuffer.StorageSpan[len] = default;
}
var fcd = new SingleFontChooserDialog(
Service<FontAtlasFactory>.Get().CreateFontAtlas(
$"{nameof(GamePrebakedFontsTestWidget)}:EditorFont",
FontAtlasAutoRebuildMode.Async));
fcd.SelectedFont = this.fontSpec;
fcd.IgnorePreviewGlobalScale = !this.useGlobalScale;
Service<InterfaceManager>.Get().Draw += fcd.Draw;
fcd.ResultTask.ContinueWith(
r => Service<Framework>.Get().RunOnFrameworkThread(
() =>
{
Service<InterfaceManager>.Get().Draw -= fcd.Draw;
fcd.Dispose();
if (this.useMinimumBuild)
_ = this.privateAtlas?.BuildFontsAsync();
}
_ = r.Exception;
if (!r.IsCompletedSuccessfully)
return;
this.fontSpec = r.Result;
Log.Information("Selected font: {font}", this.fontSpec);
this.fontDialogHandle?.Dispose();
this.fontDialogHandle = null;
}));
}
this.privateAtlas ??=
@ -141,6 +149,41 @@ internal class GamePrebakedFontsTestWidget : IDataWindowWidget, IDisposable
nameof(GamePrebakedFontsTestWidget),
FontAtlasAutoRebuildMode.Async,
this.useGlobalScale);
this.fontDialogHandle ??= this.fontSpec.CreateFontHandle(this.privateAtlas);
fixed (byte* labelPtr = "Test Input"u8)
{
if (!this.useGlobalScale)
ImGuiNative.igSetWindowFontScale(1 / ImGuiHelpers.GlobalScale);
using (this.fontDialogHandle.Push())
{
if (ImGuiNative.igInputTextMultiline(
labelPtr,
this.testStringBuffer.Data,
(uint)this.testStringBuffer.Capacity,
new(ImGui.GetContentRegionAvail().X, ImGui.GetTextLineHeight() * 3),
0,
null,
null) != 0)
{
var len = this.testStringBuffer.StorageSpan.IndexOf((byte)0);
if (len + 4 >= this.testStringBuffer.Capacity)
this.testStringBuffer.EnsureCapacityExponential(len + 4);
if (len < this.testStringBuffer.Capacity)
{
this.testStringBuffer.LengthUnsafe = len;
this.testStringBuffer.StorageSpan[len] = default;
}
if (this.useMinimumBuild)
_ = this.privateAtlas?.BuildFontsAsync();
}
}
if (!this.useGlobalScale)
ImGuiNative.igSetWindowFontScale(1);
}
this.fontHandles ??=
Enum.GetValues<GameFontFamilyAndSize>()
.Where(x => x.GetAttribute<GameFontFamilyAndSizeAttribute>() is not null)
@ -227,6 +270,8 @@ internal class GamePrebakedFontsTestWidget : IDataWindowWidget, IDisposable
this.fontHandles?.Values.SelectMany(x => x.Where(y => y.Handle.IsValueCreated).Select(y => y.Handle.Value))
.AggregateToDisposable().Dispose();
this.fontHandles = null;
this.fontDialogHandle?.Dispose();
this.fontDialogHandle = null;
this.privateAtlas?.Dispose();
this.privateAtlas = null;
}