Revert "IFontAtlas: font atlas per plugin"

This commit is contained in:
goat 2024-01-18 21:37:05 +01:00 committed by KazWolfe
parent 14c5ad1605
commit b5696afe94
44 changed files with 1499 additions and 7943 deletions

View file

@ -1,3 +1,4 @@
using System.IO;
using System.Linq;
using System.Numerics;
@ -6,8 +7,6 @@ using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Interface.Windowing;
@ -32,14 +31,8 @@ internal sealed class ChangelogWindow : Window, IDisposable
Plugins can now add tooltips and interaction to the server info bar
The Dalamud/plugin installer UI has been refreshed
";
private readonly TitleScreenMenuWindow tsmWindow;
private readonly DisposeSafety.ScopedFinalizer scopedFinalizer = new();
private readonly IFontAtlas privateAtlas;
private readonly Lazy<IFontHandle> bannerFont;
private readonly Lazy<IDalamudTextureWrap> apiBumpExplainerTexture;
private readonly Lazy<IDalamudTextureWrap> logoTexture;
private readonly InOutCubic windowFade = new(TimeSpan.FromSeconds(2.5f))
{
@ -53,36 +46,27 @@ internal sealed class ChangelogWindow : Window, IDisposable
Point2 = Vector2.One,
};
private IDalamudTextureWrap? apiBumpExplainerTexture;
private IDalamudTextureWrap? logoTexture;
private GameFontHandle? bannerFont;
private State state = State.WindowFadeIn;
private bool needFadeRestart = false;
/// <summary>
/// Initializes a new instance of the <see cref="ChangelogWindow"/> class.
/// </summary>
/// <param name="tsmWindow">TSM window.</param>
/// <param name="fontAtlasFactory">An instance of <see cref="FontAtlasFactory"/>.</param>
/// <param name="assets">An instance of <see cref="DalamudAssetManager"/>.</param>
public ChangelogWindow(
TitleScreenMenuWindow tsmWindow,
FontAtlasFactory fontAtlasFactory,
DalamudAssetManager assets)
public ChangelogWindow(TitleScreenMenuWindow tsmWindow)
: base("What's new in Dalamud?##ChangelogWindow", ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse, true)
{
this.tsmWindow = tsmWindow;
this.Namespace = "DalamudChangelogWindow";
this.privateAtlas = this.scopedFinalizer.Add(
fontAtlasFactory.CreateFontAtlas(this.Namespace, FontAtlasAutoRebuildMode.Async));
this.bannerFont = new(
() => this.scopedFinalizer.Add(
this.privateAtlas.NewGameFontHandle(new(GameFontFamilyAndSize.MiedingerMid18))));
this.apiBumpExplainerTexture = new(() => assets.GetDalamudTextureWrap(DalamudAsset.ChangelogApiBumpIcon));
this.logoTexture = new(() => assets.GetDalamudTextureWrap(DalamudAsset.Logo));
// If we are going to show a changelog, make sure we have the font ready, otherwise it will hitch
if (WarrantsChangelog())
_ = this.bannerFont.Value;
Service<GameFontManager>.GetAsync().ContinueWith(t => this.MakeFont(t.Result));
}
private enum State
@ -113,12 +97,20 @@ internal sealed class ChangelogWindow : Window, IDisposable
Service<DalamudInterface>.Get().SetCreditsDarkeningAnimation(true);
this.tsmWindow.AllowDrawing = false;
_ = this.bannerFont;
this.MakeFont(Service<GameFontManager>.Get());
this.state = State.WindowFadeIn;
this.windowFade.Reset();
this.bodyFade.Reset();
this.needFadeRestart = true;
if (this.apiBumpExplainerTexture == null)
{
var dalamud = Service<Dalamud>.Get();
var tm = Service<TextureManager>.Get();
this.apiBumpExplainerTexture = tm.GetTextureFromFile(new FileInfo(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "changelogApiBump.png")))
?? throw new Exception("Could not load api bump explainer.");
}
base.OnOpen();
}
@ -194,7 +186,10 @@ internal sealed class ChangelogWindow : Window, IDisposable
ImGui.SetCursorPos(new Vector2(logoContainerSize.X / 2 - logoSize.X / 2, logoContainerSize.Y / 2 - logoSize.Y / 2));
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, Math.Clamp(this.windowFade.EasedPoint.X - 0.5f, 0f, 1f)))
ImGui.Image(this.logoTexture.Value.ImGuiHandle, logoSize);
{
this.logoTexture ??= Service<DalamudAssetManager>.Get().GetDalamudTextureWrap(DalamudAsset.Logo);
ImGui.Image(this.logoTexture.ImGuiHandle, logoSize);
}
}
ImGui.SameLine();
@ -210,7 +205,7 @@ internal sealed class ChangelogWindow : Window, IDisposable
using (ImRaii.PushStyle(ImGuiStyleVar.Alpha, Math.Clamp(this.windowFade.EasedPoint.X - 1f, 0f, 1f)))
{
using var font = this.bannerFont.Value.Push();
using var font = ImRaii.PushFont(this.bannerFont!.ImFont);
switch (this.state)
{
@ -280,11 +275,9 @@ internal sealed class ChangelogWindow : Window, IDisposable
ImGui.TextWrapped("If some plugins are displayed with a red cross in the 'Installed Plugins' tab, they may not yet be available.");
ImGuiHelpers.ScaledDummy(15);
ImGuiHelpers.CenterCursorFor(this.apiBumpExplainerTexture.Value.Width);
ImGui.Image(
this.apiBumpExplainerTexture.Value.ImGuiHandle,
this.apiBumpExplainerTexture.Value.Size);
ImGuiHelpers.CenterCursorFor(this.apiBumpExplainerTexture!.Width);
ImGui.Image(this.apiBumpExplainerTexture.ImGuiHandle, this.apiBumpExplainerTexture.Size);
DrawNextButton(State.Links);
break;
@ -384,4 +377,7 @@ internal sealed class ChangelogWindow : Window, IDisposable
public void Dispose()
{
}
private void MakeFont(GameFontManager gfm) =>
this.bannerFont ??= gfm.NewFontRef(new GameFontStyle(GameFontFamilyAndSize.MiedingerMid18));
}

View file

@ -6,8 +6,6 @@ using Dalamud.Interface.Components;
using Dalamud.Interface.Internal.Windows.Data.Widgets;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Windowing;
using Dalamud.Utility;
using ImGuiNET;
using Serilog;
@ -16,7 +14,7 @@ namespace Dalamud.Interface.Internal.Windows.Data;
/// <summary>
/// Class responsible for drawing the data/debug window.
/// </summary>
internal class DataWindow : Window, IDisposable
internal class DataWindow : Window
{
private readonly IDataWindowWidget[] modules =
{
@ -36,7 +34,6 @@ internal class DataWindow : Window, IDisposable
new FlyTextWidget(),
new FontAwesomeTestWidget(),
new GameInventoryTestWidget(),
new GamePrebakedFontsTestWidget(),
new GamepadWidget(),
new GaugeWidget(),
new HookWidget(),
@ -79,9 +76,6 @@ internal class DataWindow : Window, IDisposable
this.Load();
}
/// <inheritdoc/>
public void Dispose() => this.modules.OfType<IDisposable>().AggregateToDisposable().Dispose();
/// <inheritdoc/>
public override void OnOpen()
{

View file

@ -1,213 +0,0 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
using Dalamud.Utility;
using ImGuiNET;
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
/// <summary>
/// Widget for testing game prebaked fonts.
/// </summary>
internal class GamePrebakedFontsTestWidget : IDataWindowWidget, IDisposable
{
private ImVectorWrapper<byte> testStringBuffer;
private IFontAtlas? privateAtlas;
private IReadOnlyDictionary<GameFontFamily, (GameFontStyle Size, Lazy<IFontHandle> Handle)[]>? fontHandles;
private bool useGlobalScale;
private bool useWordWrap;
private bool useItalic;
private bool useBold;
private bool useMinimumBuild;
/// <inheritdoc/>
public string[]? CommandShortcuts { get; init; }
/// <inheritdoc/>
public string DisplayName { get; init; } = "Game Prebaked Fonts";
/// <inheritdoc/>
public bool Ready { get; set; }
/// <inheritdoc/>
public void Load() => this.Ready = true;
/// <inheritdoc/>
public unsafe void Draw()
{
ImGui.AlignTextToFramePadding();
fixed (byte* labelPtr = "Global Scale"u8)
{
var v = (byte)(this.useGlobalScale ? 1 : 0);
if (ImGuiNative.igCheckbox(labelPtr, &v) != 0)
{
this.useGlobalScale = v != 0;
this.ClearAtlas();
}
}
ImGui.SameLine();
fixed (byte* labelPtr = "Word Wrap"u8)
{
var v = (byte)(this.useWordWrap ? 1 : 0);
if (ImGuiNative.igCheckbox(labelPtr, &v) != 0)
this.useWordWrap = v != 0;
}
ImGui.SameLine();
fixed (byte* labelPtr = "Italic"u8)
{
var v = (byte)(this.useItalic ? 1 : 0);
if (ImGuiNative.igCheckbox(labelPtr, &v) != 0)
{
this.useItalic = v != 0;
this.ClearAtlas();
}
}
ImGui.SameLine();
fixed (byte* labelPtr = "Bold"u8)
{
var v = (byte)(this.useBold ? 1 : 0);
if (ImGuiNative.igCheckbox(labelPtr, &v) != 0)
{
this.useBold = v != 0;
this.ClearAtlas();
}
}
ImGui.SameLine();
fixed (byte* labelPtr = "Minimum Range"u8)
{
var v = (byte)(this.useMinimumBuild ? 1 : 0);
if (ImGuiNative.igCheckbox(labelPtr, &v) != 0)
{
this.useMinimumBuild = v != 0;
this.ClearAtlas();
}
}
ImGui.SameLine();
if (ImGui.Button("Reset Text") || this.testStringBuffer.IsDisposed)
{
this.testStringBuffer.Dispose();
this.testStringBuffer = ImVectorWrapper.CreateFromSpan(
"(Game)-[Font] {Test}. 0123456789!! <氣気气きキ기>。"u8,
minCapacity: 1024);
}
fixed (byte* labelPtr = "Test Input"u8)
{
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;
}
if (this.useMinimumBuild)
_ = this.privateAtlas?.BuildFontsAsync();
}
}
this.privateAtlas ??=
Service<FontAtlasFactory>.Get().CreateFontAtlas(
nameof(GamePrebakedFontsTestWidget),
FontAtlasAutoRebuildMode.Async,
this.useGlobalScale);
this.fontHandles ??=
Enum.GetValues<GameFontFamilyAndSize>()
.Where(x => x.GetAttribute<GameFontFamilyAndSizeAttribute>() is not null)
.Select(x => new GameFontStyle(x) { Italic = this.useItalic, Bold = this.useBold })
.GroupBy(x => x.Family)
.ToImmutableDictionary(
x => x.Key,
x => x.Select(
y => (y, new Lazy<IFontHandle>(
() => this.useMinimumBuild
? this.privateAtlas.NewDelegateFontHandle(
e =>
e.OnPreBuild(
tk => tk.AddGameGlyphs(
y,
Encoding.UTF8.GetString(
this.testStringBuffer.DataSpan).ToGlyphRange(),
default)))
: this.privateAtlas.NewGameFontHandle(y))))
.ToArray());
var offsetX = ImGui.CalcTextSize("99.9pt").X + (ImGui.GetStyle().FramePadding.X * 2);
foreach (var (family, items) in this.fontHandles)
{
if (!ImGui.CollapsingHeader($"{family} Family"))
continue;
foreach (var (gfs, handle) in items)
{
ImGui.TextUnformatted($"{gfs.SizePt}pt");
ImGui.SameLine(offsetX);
ImGuiNative.igPushTextWrapPos(this.useWordWrap ? 0f : -1f);
try
{
if (handle.Value.LoadException is { } exc)
{
ImGui.TextUnformatted(exc.ToString());
}
else if (!handle.Value.Available)
{
fixed (byte* labelPtr = "Loading..."u8)
ImGuiNative.igTextUnformatted(labelPtr, labelPtr + 8 + ((Environment.TickCount / 200) % 3));
}
else
{
if (!this.useGlobalScale)
ImGuiNative.igSetWindowFontScale(1 / ImGuiHelpers.GlobalScale);
using var pushPop = handle.Value.Push();
ImGuiNative.igTextUnformatted(
this.testStringBuffer.Data,
this.testStringBuffer.Data + this.testStringBuffer.Length);
}
}
finally
{
ImGuiNative.igPopTextWrapPos();
ImGuiNative.igSetWindowFontScale(1);
}
}
}
}
/// <inheritdoc/>
public void Dispose()
{
this.ClearAtlas();
this.testStringBuffer.Dispose();
}
private void ClearAtlas()
{
this.fontHandles?.Values.SelectMany(x => x.Where(y => y.Handle.IsValueCreated).Select(y => y.Handle.Value))
.AggregateToDisposable().Dispose();
this.fontHandles = null;
this.privateAtlas?.Dispose();
this.privateAtlas = null;
}
}

View file

@ -5,10 +5,10 @@ using CheapLoc;
using Dalamud.Configuration.Internal;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Internal.Windows.Settings.Tabs;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using ImGuiNET;
@ -19,7 +19,14 @@ namespace Dalamud.Interface.Internal.Windows.Settings;
/// </summary>
internal class SettingsWindow : Window
{
private SettingsTab[]? tabs;
private readonly SettingsTab[] tabs =
{
new SettingsTabGeneral(),
new SettingsTabLook(),
new SettingsTabDtr(),
new SettingsTabExperimental(),
new SettingsTabAbout(),
};
private string searchInput = string.Empty;
@ -42,15 +49,6 @@ internal class SettingsWindow : Window
/// <inheritdoc/>
public override void OnOpen()
{
this.tabs ??= new SettingsTab[]
{
new SettingsTabGeneral(),
new SettingsTabLook(),
new SettingsTabDtr(),
new SettingsTabExperimental(),
new SettingsTabAbout(),
};
foreach (var settingsTab in this.tabs)
{
settingsTab.Load();
@ -66,12 +64,15 @@ internal class SettingsWindow : Window
{
var configuration = Service<DalamudConfiguration>.Get();
var interfaceManager = Service<InterfaceManager>.Get();
var fontAtlasFactory = Service<FontAtlasFactory>.Get();
var rebuildFont = fontAtlasFactory.UseAxis != configuration.UseAxisFontsFromGame;
var rebuildFont =
ImGui.GetIO().FontGlobalScale != configuration.GlobalUiScale ||
interfaceManager.FontGamma != configuration.FontGammaLevel ||
interfaceManager.UseAxis != configuration.UseAxisFontsFromGame;
ImGui.GetIO().FontGlobalScale = configuration.GlobalUiScale;
fontAtlasFactory.UseAxisOverride = null;
interfaceManager.FontGammaOverride = null;
interfaceManager.UseAxisOverride = null;
if (rebuildFont)
interfaceManager.RebuildFonts();

View file

@ -1,13 +1,13 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Numerics;
using CheapLoc;
using Dalamud.Game.Gui;
using Dalamud.Interface.GameFonts;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Internal;
@ -15,6 +15,7 @@ using Dalamud.Storage.Assets;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.Game.UI;
using ImGuiNET;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.Settings.Tabs;
@ -172,21 +173,16 @@ Contribute at: https://github.com/goatcorp/Dalamud
";
private readonly Stopwatch creditsThrottler;
private readonly IFontAtlas privateAtlas;
private string creditsText;
private bool resetNow = false;
private IDalamudTextureWrap? logoTexture;
private IFontHandle? thankYouFont;
private GameFontHandle? thankYouFont;
public SettingsTabAbout()
{
this.creditsThrottler = new();
this.privateAtlas = Service<FontAtlasFactory>
.Get()
.CreateFontAtlas(nameof(SettingsTabAbout), FontAtlasAutoRebuildMode.Async);
}
public override SettingsEntry[] Entries { get; } = { };
@ -211,7 +207,11 @@ Contribute at: https://github.com/goatcorp/Dalamud
this.creditsThrottler.Restart();
this.thankYouFont ??= this.privateAtlas.NewGameFontHandle(new(GameFontFamilyAndSize.TrumpGothic34));
if (this.thankYouFont == null)
{
var gfm = Service<GameFontManager>.Get();
this.thankYouFont = gfm.NewFontRef(new GameFontStyle(GameFontFamilyAndSize.TrumpGothic34));
}
this.resetNow = true;
@ -269,12 +269,14 @@ Contribute at: https://github.com/goatcorp/Dalamud
if (this.thankYouFont != null)
{
using var fontPush = this.thankYouFont.Push();
ImGui.PushFont(this.thankYouFont.ImFont);
var thankYouLenX = ImGui.CalcTextSize(ThankYouText).X;
ImGui.Dummy(new Vector2((windowX / 2) - (thankYouLenX / 2), 0f));
ImGui.SameLine();
ImGui.TextUnformatted(ThankYouText);
ImGui.PopFont();
}
ImGuiHelpers.ScaledDummy(0, windowSize.Y + 50f);
@ -303,5 +305,9 @@ Contribute at: https://github.com/goatcorp/Dalamud
/// <summary>
/// Disposes of managed and unmanaged resources.
/// </summary>
public override void Dispose() => this.privateAtlas.Dispose();
public override void Dispose()
{
this.logoTexture?.Dispose();
this.thankYouFont?.Dispose();
}
}

View file

@ -1,14 +1,12 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using System.Text;
using CheapLoc;
using Dalamud.Configuration.Internal;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Internal.Windows.PluginInstaller;
using Dalamud.Interface.Internal.Windows.Settings.Widgets;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
using Dalamud.Utility;
using ImGuiNET;
@ -30,6 +28,7 @@ public class SettingsTabLook : SettingsTab
};
private float globalUiScale;
private float fontGamma;
public override SettingsEntry[] Entries { get; } =
{
@ -42,8 +41,9 @@ public class SettingsTabLook : SettingsTab
(v, c) => c.UseAxisFontsFromGame = v,
v =>
{
Service<FontAtlasFactory>.Get().UseAxisOverride = v;
Service<InterfaceManager>.Get().RebuildFonts();
var im = Service<InterfaceManager>.Get();
im.UseAxisOverride = v;
im.RebuildFonts();
}),
new GapSettingsEntry(5, true),
@ -145,7 +145,6 @@ public class SettingsTabLook : SettingsTab
public override void Draw()
{
var interfaceManager = Service<InterfaceManager>.Get();
var fontBuildTask = interfaceManager.FontBuildTask;
ImGui.AlignTextToFramePadding();
ImGui.Text(Loc.Localize("DalamudSettingsGlobalUiScale", "Global Font Scale"));
@ -165,19 +164,6 @@ public class SettingsTabLook : SettingsTab
}
}
if (!fontBuildTask.IsCompleted)
{
ImGui.SameLine();
var buildingFonts = Loc.Localize("DalamudSettingsFontBuildInProgressWithEndingThreeDots", "Building fonts...");
unsafe
{
var len = Encoding.UTF8.GetByteCount(buildingFonts);
var p = stackalloc byte[len];
Encoding.UTF8.GetBytes(buildingFonts, new(p, len));
ImGuiNative.igTextUnformatted(p, (p + len + ((Environment.TickCount / 200) % 3)) - 2);
}
}
var globalUiScaleInPt = 12f * this.globalUiScale;
if (ImGui.DragFloat("##DalamudSettingsGlobalUiScaleDrag", ref globalUiScaleInPt, 0.1f, 9.6f, 36f, "%.1fpt", ImGuiSliderFlags.AlwaysClamp))
{
@ -188,25 +174,33 @@ public class SettingsTabLook : SettingsTab
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsGlobalUiScaleHint", "Scale text in all XIVLauncher UI elements - this is useful for 4K displays."));
if (fontBuildTask.IsFaulted || fontBuildTask.IsCanceled)
ImGuiHelpers.ScaledDummy(5);
ImGui.AlignTextToFramePadding();
ImGui.Text(Loc.Localize("DalamudSettingsFontGamma", "Font Gamma"));
ImGui.SameLine();
if (ImGui.Button(Loc.Localize("DalamudSettingsIndividualConfigResetToDefaultValue", "Reset") + "##DalamudSettingsFontGammaReset"))
{
ImGui.TextColored(
ImGuiColors.DalamudRed,
Loc.Localize("DalamudSettingsFontBuildFaulted", "Failed to load fonts as requested."));
if (fontBuildTask.Exception is not null
&& ImGui.CollapsingHeader("##DalamudSetingsFontBuildFaultReason"))
{
foreach (var e in fontBuildTask.Exception.InnerExceptions)
ImGui.TextUnformatted(e.ToString());
}
this.fontGamma = 1.4f;
interfaceManager.FontGammaOverride = this.fontGamma;
interfaceManager.RebuildFonts();
}
if (ImGui.DragFloat("##DalamudSettingsFontGammaDrag", ref this.fontGamma, 0.005f, 0.3f, 3f, "%.2f", ImGuiSliderFlags.AlwaysClamp))
{
interfaceManager.FontGammaOverride = this.fontGamma;
interfaceManager.RebuildFonts();
}
ImGuiHelpers.SafeTextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsFontGammaHint", "Changes the thickness of text."));
base.Draw();
}
public override void Load()
{
this.globalUiScale = Service<DalamudConfiguration>.Get().GlobalUiScale;
this.fontGamma = Service<DalamudConfiguration>.Get().FontGammaLevel;
base.Load();
}

View file

@ -7,14 +7,11 @@ using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.Gui;
using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin.Services;
using Dalamud.Storage.Assets;
using Dalamud.Utility;
using ImGuiNET;
@ -30,17 +27,16 @@ internal class TitleScreenMenuWindow : Window, IDisposable
private readonly ClientState clientState;
private readonly DalamudConfiguration configuration;
private readonly Framework framework;
private readonly GameGui gameGui;
private readonly TitleScreenMenu titleScreenMenu;
private readonly DisposeSafety.ScopedFinalizer scopedFinalizer = new();
private readonly IFontAtlas privateAtlas;
private readonly Lazy<IFontHandle> myFontHandle;
private readonly Lazy<IDalamudTextureWrap> shadeTexture;
private readonly Dictionary<Guid, InOutCubic> shadeEasings = new();
private readonly Dictionary<Guid, InOutQuint> moveEasings = new();
private readonly Dictionary<Guid, InOutCubic> logoEasings = new();
private readonly Dictionary<string, InterfaceManager.SpecialGlyphRequest> specialGlyphRequests = new();
private InOutCubic? fadeOutEasing;
@ -52,7 +48,6 @@ internal class TitleScreenMenuWindow : Window, IDisposable
/// <param name="clientState">An instance of <see cref="ClientState"/>.</param>
/// <param name="configuration">An instance of <see cref="DalamudConfiguration"/>.</param>
/// <param name="dalamudAssetManager">An instance of <see cref="DalamudAssetManager"/>.</param>
/// <param name="fontAtlasFactory">An instance of <see cref="FontAtlasFactory"/>.</param>
/// <param name="framework">An instance of <see cref="Framework"/>.</param>
/// <param name="titleScreenMenu">An instance of <see cref="TitleScreenMenu"/>.</param>
/// <param name="gameGui">An instance of <see cref="gameGui"/>.</param>
@ -60,7 +55,6 @@ internal class TitleScreenMenuWindow : Window, IDisposable
ClientState clientState,
DalamudConfiguration configuration,
DalamudAssetManager dalamudAssetManager,
FontAtlasFactory fontAtlasFactory,
Framework framework,
GameGui gameGui,
TitleScreenMenu titleScreenMenu)
@ -71,6 +65,7 @@ internal class TitleScreenMenuWindow : Window, IDisposable
{
this.clientState = clientState;
this.configuration = configuration;
this.framework = framework;
this.gameGui = gameGui;
this.titleScreenMenu = titleScreenMenu;
@ -82,25 +77,9 @@ internal class TitleScreenMenuWindow : Window, IDisposable
this.PositionCondition = ImGuiCond.Always;
this.RespectCloseHotkey = false;
this.shadeTexture = new(() => dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.TitleScreenMenuShade));
this.privateAtlas = fontAtlasFactory.CreateFontAtlas(this.WindowName, FontAtlasAutoRebuildMode.Async);
this.scopedFinalizer.Add(this.privateAtlas);
this.myFontHandle = new(
() => this.scopedFinalizer.Add(
this.privateAtlas.NewDelegateFontHandle(
e => e.OnPreBuild(
toolkit => toolkit.AddDalamudDefaultFont(
TargetFontSizePx,
titleScreenMenu.Entries.SelectMany(x => x.Name).ToGlyphRange())))));
titleScreenMenu.EntryListChange += this.TitleScreenMenuEntryListChange;
this.scopedFinalizer.Add(() => titleScreenMenu.EntryListChange -= this.TitleScreenMenuEntryListChange);
this.shadeTexture = new(() => dalamudAssetManager.GetDalamudTextureWrap(DalamudAsset.TitleScreenMenuShade));
framework.Update += this.FrameworkOnUpdate;
this.scopedFinalizer.Add(() => framework.Update -= this.FrameworkOnUpdate);
}
private enum State
@ -115,9 +94,6 @@ internal class TitleScreenMenuWindow : Window, IDisposable
/// </summary>
public bool AllowDrawing { get; set; } = true;
/// <inheritdoc/>
public void Dispose() => this.scopedFinalizer.Dispose();
/// <inheritdoc/>
public override void PreDraw()
{
@ -133,6 +109,12 @@ internal class TitleScreenMenuWindow : Window, IDisposable
base.PostDraw();
}
/// <inheritdoc/>
public void Dispose()
{
this.framework.Update -= this.FrameworkOnUpdate;
}
/// <inheritdoc/>
public override void Draw()
{
@ -264,12 +246,33 @@ internal class TitleScreenMenuWindow : Window, IDisposable
break;
}
}
var srcText = entries.Select(e => e.Name).ToHashSet();
var keys = this.specialGlyphRequests.Keys.ToHashSet();
keys.RemoveWhere(x => srcText.Contains(x));
foreach (var key in keys)
{
this.specialGlyphRequests[key].Dispose();
this.specialGlyphRequests.Remove(key);
}
}
private bool DrawEntry(
TitleScreenMenuEntry entry, bool inhibitFadeout, bool showText, bool isFirst, bool overrideAlpha, bool interactable)
{
using var fontScopeDispose = this.myFontHandle.Value.Push();
InterfaceManager.SpecialGlyphRequest fontHandle;
if (this.specialGlyphRequests.TryGetValue(entry.Name, out fontHandle) && fontHandle.Size != TargetFontSizePx)
{
fontHandle.Dispose();
this.specialGlyphRequests.Remove(entry.Name);
fontHandle = null;
}
if (fontHandle == null)
this.specialGlyphRequests[entry.Name] = fontHandle = Service<InterfaceManager>.Get().NewFontSizeRef(TargetFontSizePx, entry.Name);
ImGui.PushFont(fontHandle.Font);
ImGui.SetWindowFontScale(TargetFontSizePx / fontHandle.Size);
var scale = ImGui.GetIO().FontGlobalScale;
@ -380,6 +383,8 @@ internal class TitleScreenMenuWindow : Window, IDisposable
initialCursor.Y += entry.Texture.Height * scale;
ImGui.SetCursorPos(initialCursor);
ImGui.PopFont();
return isHover;
}
@ -396,6 +401,4 @@ internal class TitleScreenMenuWindow : Window, IDisposable
if (charaMake != IntPtr.Zero || charaSelect != IntPtr.Zero || titleDcWorldMap != IntPtr.Zero)
this.IsOpen = false;
}
private void TitleScreenMenuEntryListChange() => this.privateAtlas.BuildFontsAsync();
}