From 57bd6bc1e38dc3e03fa5e9580965ec3bde0a65d5 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 10:53:56 +0200 Subject: [PATCH 01/33] feat: april fools 2022 --- .../Internal/DalamudConfiguration.cs | 2 + Dalamud/Dalamud.cs | 13 + Dalamud/Fools22.cs | 315 ++++++++++++++++++ .../Internal/Windows/SettingsWindow.cs | 12 + 4 files changed, 342 insertions(+) create mode 100644 Dalamud/Fools22.cs diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 6350da4aa..b2a11d774 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -290,6 +290,8 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; + public bool Fools22 { get; set; } = true; + /// /// Load a configuration from the provided path. /// diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 537ffa516..4ad19e5fa 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -53,6 +53,8 @@ namespace Dalamud #endregion + private Fools22? fools22; + /// /// Initializes a new instance of the class. /// @@ -270,6 +272,15 @@ namespace Dalamud Troubleshooting.LogTroubleshooting(); + try + { + this.fools22 = new Fools22(); + } + catch (Exception ex) + { + Log.Error(ex, "Fools22 load failed."); + } + Log.Information("Dalamud is ready."); } catch (Exception ex) @@ -360,6 +371,8 @@ namespace Dalamud this.processMonoHook?.Dispose(); + this.fools22?.Dispose(); + Log.Debug("Dalamud::Dispose() OK!"); } catch (Exception ex) diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs new file mode 100644 index 000000000..c384f3641 --- /dev/null +++ b/Dalamud/Fools22.cs @@ -0,0 +1,315 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Media; +using System.Numerics; + +using Dalamud.Configuration.Internal; +using Dalamud.Data; +using Dalamud.Game; +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.Gui; +using Dalamud.Game.Text; +using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Interface; +using Dalamud.Interface.Animation; +using Dalamud.Interface.Animation.EasingFunctions; +using Dalamud.Interface.Internal; +using Dalamud.Utility; +using ImGuiNET; +using ImGuiScene; +using Lumina.Excel.GeneratedSheets; +using Serilog; +using Condition = Dalamud.Game.ClientState.Conditions.Condition; + +namespace Dalamud; + +public class Fools22 : IDisposable +{ + private readonly TextureWrap erDeathBgTexture; + private readonly TextureWrap erNormalDeathTexture; + private readonly TextureWrap erCraftFailedTexture; + + private readonly string synthesisFailsMessage; + + private readonly Stopwatch time = new Stopwatch(); + private readonly SoundPlayer player; + + private bool assetsReady = false; + + private AnimationState currentState = AnimationState.NotPlaying; + private DeathType currentDeathType = DeathType.Death; + + private Easing alphaEasing; + private Easing scaleEasing; + + private bool lastFrameUnconscious = false; + + private int msFadeInTime = 1000; + private int msFadeOutTime = 2000; + private int msWaitTime = 1600; + + private TextureWrap TextTexture => this.currentDeathType switch + { + DeathType.Death => this.erNormalDeathTexture, + DeathType.CraftFailed => this.erCraftFailedTexture, + }; + + private enum AnimationState + { + NotPlaying, + FadeIn, + Wait, + FadeOut, + } + + private enum DeathType + { + Death, + CraftFailed, + } + + public Fools22() + { + var dalamud = Service.Get(); + var interfaceManager = Service.Get(); + var framework = Service.Get(); + var chatGui = Service.Get(); + var dataMgr = Service.Get(); + + this.erDeathBgTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_death_bg.png"))!; + this.erNormalDeathTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_normal_death.png"))!; + this.erCraftFailedTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_craft_failed.png"))!; + + var soundBytes = File.ReadAllBytes(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "snd_death_er.wav")); + this.player = new SoundPlayer(new MemoryStream(soundBytes)); + + if (this.erDeathBgTexture == null || this.erNormalDeathTexture == null || this.erCraftFailedTexture == null) + { + Log.Error("Fools22: Failed to load images"); + return; + } + + this.synthesisFailsMessage = dataMgr.GetExcelSheet()!.GetRow(1160)!.Text.ToDalamudString().TextValue; + + this.assetsReady = true; + + interfaceManager.Draw += this.Draw; + framework.Update += this.FrameworkOnUpdate; + chatGui.ChatMessage += this.ChatGuiOnChatMessage; + } + + private void ChatGuiOnChatMessage(XivChatType type, uint senderid, ref SeString sender, ref SeString message, ref bool ishandled) + { + if (message.TextValue.Contains(this.synthesisFailsMessage)) + { + this.PlayAnimation(DeathType.CraftFailed); + Log.Information("Fools22: Craft failed"); + } + } + + private void FrameworkOnUpdate(Framework framework) + { + var condition = Service.Get(); + var isUnconscious = condition[ConditionFlag.Unconscious]; + + if (isUnconscious && !this.lastFrameUnconscious) + { + this.PlayAnimation(DeathType.Death); + Log.Information("Fools22: Player died"); + } + + this.lastFrameUnconscious = isUnconscious; + } + + private void Draw() + { +#if DEBUG + if (ImGui.Begin("fools test")) + { + if (ImGui.Button("play death")) + { + this.PlayAnimation(DeathType.Death); + } + + if (ImGui.Button("play craft failed")) + { + this.PlayAnimation(DeathType.CraftFailed); + } + + ImGui.InputInt("fade in time", ref this.msFadeInTime); + ImGui.InputInt("fade out time", ref this.msFadeOutTime); + ImGui.InputInt("wait time", ref this.msWaitTime); + + ImGui.TextUnformatted("state: " + this.currentState); + ImGui.TextUnformatted("time: " + this.time.ElapsedMilliseconds); + + ImGui.TextUnformatted("scale: " + this.scaleEasing?.EasedPoint.X); + } + + ImGui.End(); +#endif + var vpSize = ImGuiHelpers.MainViewport.Size; + + ImGui.SetNextWindowPos(new Vector2(0, 0), ImGuiCond.Always); + ImGui.SetNextWindowSize(new Vector2(vpSize.X, vpSize.Y), ImGuiCond.Always); + ImGuiHelpers.ForceNextWindowMainViewport(); + + ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0); + ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 0); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0)); + ImGui.PushStyleColor(ImGuiCol.WindowBg, new Vector4(0, 0, 0, 0)); + ImGui.PushStyleColor(ImGuiCol.Border, new Vector4(0, 0, 0, 0)); + ImGui.PushStyleColor(ImGuiCol.BorderShadow, new Vector4(0, 0, 0, 0)); + + if (ImGui.Begin("fools22", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus + | ImGuiWindowFlags.NoMouseInputs | ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoScrollbar)) + { + if (this.currentState != AnimationState.NotPlaying) + { + this.alphaEasing?.Update(); + this.scaleEasing?.Update(); + } + + switch (this.currentState) + { + case AnimationState.FadeIn: + this.FadeIn(vpSize); + break; + case AnimationState.Wait: + this.Wait(vpSize); + break; + case AnimationState.FadeOut: + this.FadeOut(vpSize); + break; + } + } + + ImGui.End(); + + ImGui.PopStyleColor(3); + ImGui.PopStyleVar(3); + } + + private static void AdjustCursorAndDraw(Vector2 vpSize, TextureWrap tex, float scale = 1.0f) + { + var width = vpSize.X; + var height = tex.Height / (float)tex.Width * width; + + if (height < vpSize.Y) + { + height = vpSize.Y; + width = tex.Width / (float)tex.Height * height; + ImGui.SetCursorPosX((vpSize.X - width) / 2); + } + else + { + ImGui.SetCursorPosY((vpSize.Y - height) / 2); + } + + var scaledSize = new Vector2(width, height) * scale; + var difference = scaledSize - vpSize; + + var cursor = ImGui.GetCursorPos(); + ImGui.SetCursorPos(cursor - (difference / 2)); + + ImGui.Image(tex.ImGuiHandle, scaledSize); + } + + private void FadeIn(Vector2 vpSize) + { + if (this.time.ElapsedMilliseconds > this.msFadeInTime) + this.currentState = AnimationState.Wait; + + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, (float)this.alphaEasing.Value); + + AdjustCursorAndDraw(vpSize, this.erDeathBgTexture); + AdjustCursorAndDraw(vpSize, this.TextTexture, this.scaleEasing.EasedPoint.X); + + ImGui.PopStyleVar(); + } + + private void Wait(Vector2 vpSize) + { + if (this.time.ElapsedMilliseconds > this.msFadeInTime + this.msWaitTime) + { + this.currentState = AnimationState.FadeOut; + this.alphaEasing = new InOutCubic(TimeSpan.FromMilliseconds(this.msFadeOutTime)); + this.alphaEasing.Start(); + } + + AdjustCursorAndDraw(vpSize, this.erDeathBgTexture); + AdjustCursorAndDraw(vpSize, this.TextTexture, this.scaleEasing.EasedPoint.X); + } + + private void FadeOut(Vector2 vpSize) + { + if (this.time.ElapsedMilliseconds > this.msFadeInTime + this.msWaitTime + this.msFadeOutTime) + { + this.currentState = AnimationState.NotPlaying; + this.time.Stop(); + } + + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1 - (float)this.alphaEasing.Value); + + AdjustCursorAndDraw(vpSize, this.erDeathBgTexture); + AdjustCursorAndDraw(vpSize, this.TextTexture, this.scaleEasing.EasedPoint.X); + + ImGui.PopStyleVar(); + } + + private void PlayAnimation(DeathType type) + { + if (!this.CheckFoolsApplicable()) + return; + + if (this.currentState != AnimationState.NotPlaying) + return; + + this.currentDeathType = type; + + this.currentState = AnimationState.FadeIn; + this.alphaEasing = new InOutCubic(TimeSpan.FromMilliseconds(this.msFadeInTime)); + this.alphaEasing.Start(); + + this.scaleEasing = new OutCubic(TimeSpan.FromMilliseconds(this.msFadeInTime + this.msWaitTime + this.msFadeOutTime)) + { + Point1 = new Vector2(0.95f, 0.95f), + Point2 = new Vector2(1.05f, 1.05f), + }; + this.scaleEasing.Start(); + + this.time.Reset(); + this.time.Start(); + + this.player.Play(); + } + + private bool CheckFoolsApplicable() + { + var config = Service.Get(); + + if (!config.Fools22) + return false; + + if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) + return false; + + var timeZone = TimeZoneInfo.Local; + var offset = timeZone.GetUtcOffset(DateTime.UtcNow); + + Log.Information("Fools22: UTC offset: {0}", offset); + + return this.assetsReady; + } + + public void Dispose() + { + this.erDeathBgTexture.Dispose(); + this.erNormalDeathTexture.Dispose(); + this.erCraftFailedTexture.Dispose(); + + this.player.Dispose(); + } + +} diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 686839d0f..9ff94f42e 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -49,6 +49,8 @@ namespace Dalamud.Interface.Internal.Windows private bool doFocus; private bool doTsm; + private bool doFools22; + private List? dtrOrder; private List? dtrIgnore; private int dtrSpacing; @@ -104,6 +106,8 @@ namespace Dalamud.Interface.Internal.Windows this.doFocus = configuration.IsFocusManagementEnabled; this.doTsm = configuration.ShowTsm; + this.doFools22 = configuration.Fools22; + this.dtrSpacing = configuration.DtrSpacing; this.dtrSwapDirection = configuration.DtrSwapDirection; @@ -236,6 +240,12 @@ namespace Dalamud.Interface.Internal.Windows private void DrawGeneralTab() { + if (DateTime.Now.Month == 4 && DateTime.Now.Day == 1) + { + ImGui.Checkbox(Loc.Localize("Fools22", "Enable April Fools 2022"), ref this.doFools22); + ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("Fools22Hint", "Enables the April Fools 2022 funny joke. Turn this off if you don't think it's funny.")); + } + ImGui.Text(Loc.Localize("DalamudSettingsLanguage", "Language")); ImGui.Combo("##XlLangCombo", ref this.langIndex, this.locLanguages, this.locLanguages.Length); ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsLanguageHint", "Select the language Dalamud will be displayed in.")); @@ -843,6 +853,8 @@ namespace Dalamud.Interface.Internal.Windows configuration.IsFocusManagementEnabled = this.doFocus; configuration.ShowTsm = this.doTsm; + configuration.Fools22 = this.doFools22; + configuration.UseAxisFontsFromGame = this.doUseAxisFontsFromGame; configuration.FontGamma = this.fontGamma; From 9b811469b00f31f94622d704153901fad001f161 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 10:55:04 +0200 Subject: [PATCH 02/33] build: 6.3.0.8 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 3acb4edea..ef5e6f7f8 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.7 + 6.3.0.8 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From 804f5b767b9f25984b49b726e0f7c9df7d381327 Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 14:29:53 +0200 Subject: [PATCH 03/33] feat: more april fools work --- Dalamud/Dalamud.cs | 1 + Dalamud/Fools22.cs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 4ad19e5fa..691a541ef 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -274,6 +274,7 @@ namespace Dalamud try { + Log.Information("Loading fools22"); this.fools22 = new Fools22(); } catch (Exception ex) diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index c384f3641..2de81bc1a 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -3,12 +3,14 @@ using System.Diagnostics; using System.IO; using System.Media; using System.Numerics; +using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Data; using Dalamud.Game; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.Gui; +using Dalamud.Game.Network; using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface; @@ -20,6 +22,7 @@ using ImGuiNET; using ImGuiScene; using Lumina.Excel.GeneratedSheets; using Serilog; + using Condition = Dalamud.Game.ClientState.Conditions.Condition; namespace Dalamud; @@ -29,6 +32,7 @@ public class Fools22 : IDisposable private readonly TextureWrap erDeathBgTexture; private readonly TextureWrap erNormalDeathTexture; private readonly TextureWrap erCraftFailedTexture; + private readonly TextureWrap erEnemyFelledTexture; private readonly string synthesisFailsMessage; @@ -53,6 +57,7 @@ public class Fools22 : IDisposable { DeathType.Death => this.erNormalDeathTexture, DeathType.CraftFailed => this.erCraftFailedTexture, + DeathType.EnemyFelled => this.erEnemyFelledTexture, }; private enum AnimationState @@ -67,6 +72,7 @@ public class Fools22 : IDisposable { Death, CraftFailed, + EnemyFelled, } public Fools22() @@ -76,10 +82,12 @@ public class Fools22 : IDisposable var framework = Service.Get(); var chatGui = Service.Get(); var dataMgr = Service.Get(); + var gameNetwork = Service.Get(); this.erDeathBgTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_death_bg.png"))!; this.erNormalDeathTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_normal_death.png"))!; this.erCraftFailedTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_craft_failed.png"))!; + this.erEnemyFelledTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_enemy_felled.png"))!; var soundBytes = File.ReadAllBytes(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "snd_death_er.wav")); this.player = new SoundPlayer(new MemoryStream(soundBytes)); @@ -97,6 +105,24 @@ public class Fools22 : IDisposable interfaceManager.Draw += this.Draw; framework.Update += this.FrameworkOnUpdate; chatGui.ChatMessage += this.ChatGuiOnChatMessage; + gameNetwork.NetworkMessage += this.GameNetworkOnNetworkMessage; + } + + private unsafe void GameNetworkOnNetworkMessage(IntPtr dataptr, ushort opcode, uint sourceactorid, uint targetactorid, NetworkMessageDirection direction) + { + if (opcode != 0x301) + return; + + var cat = *(ushort*)(dataptr + 0x00); + var updateType = *(uint*)(dataptr + 0x08); + + if (cat == 0x6D && updateType == 0x40000003) + { + Task.Delay(1000).ContinueWith(t => + { + this.PlayAnimation(DeathType.EnemyFelled); + }); + } } private void ChatGuiOnChatMessage(XivChatType type, uint senderid, ref SeString sender, ref SeString message, ref bool ishandled) @@ -137,6 +163,14 @@ public class Fools22 : IDisposable this.PlayAnimation(DeathType.CraftFailed); } + if (ImGui.Button("play enemy felled")) + { + Task.Delay(1000).ContinueWith(t => + { + this.PlayAnimation(DeathType.EnemyFelled); + }); + } + ImGui.InputInt("fade in time", ref this.msFadeInTime); ImGui.InputInt("fade out time", ref this.msFadeOutTime); ImGui.InputInt("wait time", ref this.msWaitTime); From 0d5da42407bb270bcbbd96b7337861036cb99be0 Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 15:59:14 +0200 Subject: [PATCH 04/33] Revert "Keep glyph range handles alive until font is built" This reverts commit 5baccced15055ee21fd5b848ec386e3907d49c69. --- .../Interface/Internal/InterfaceManager.cs | 303 +++++++++--------- 1 file changed, 144 insertions(+), 159 deletions(-) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 8872fc45f..a58260c0a 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -611,189 +611,174 @@ namespace Dalamud.Interface.Internal ioFonts.Clear(); ioFonts.TexDesiredWidth = 4096; - ImFontConfigPtr fontConfig = null; - List garbageList = new(); + ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); + fontConfig.OversampleH = 1; + fontConfig.OversampleV = 1; + fontConfig.PixelSnapH = true; - try + var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); + if (!File.Exists(fontPathJp)) + ShowFontError(fontPathJp); + + // Default font { - fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); - fontConfig.OversampleH = 1; - fontConfig.OversampleV = 1; - fontConfig.PixelSnapH = true; + var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); + japaneseRangeHandle.Free(); + fontsToUnscale.Add(DefaultFont); + } - var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); - if (!File.Exists(fontPathJp)) - ShowFontError(fontPathJp); + // FontAwesome icon font + { + var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); + if (!File.Exists(fontPathIcon)) + ShowFontError(fontPathIcon); - // Default font + var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); + iconRangeHandle.Free(); + fontsToUnscale.Add(IconFont); + } + + // Monospace font + { + var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); + if (!File.Exists(fontPathMono)) + ShowFontError(fontPathMono); + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); + fontsToUnscale.Add(MonoFont); + } + + // Default font but in requested size for requested glyphs + { + Dictionary> extraFontRequests = new(); + foreach (var extraFontRequest in this.glyphRequests) { - var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); - garbageList.Add(japaneseRangeHandle); - - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); - fontsToUnscale.Add(DefaultFont); + if (!extraFontRequests.ContainsKey(extraFontRequest.Size)) + extraFontRequests[extraFontRequest.Size] = new(); + extraFontRequests[extraFontRequest.Size].Add(extraFontRequest); } - // FontAwesome icon font + foreach (var (fontSize, requests) in extraFontRequests) { - var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); - if (!File.Exists(fontPathIcon)) - ShowFontError(fontPathIcon); + List> codepointRanges = new(); + codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); + codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); - var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); - garbageList.Add(iconRangeHandle); + // ImGui default ellipsis characters + codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); + codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); - fontsToUnscale.Add(IconFont); - } - - // Monospace font - { - var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); - if (!File.Exists(fontPathMono)) - ShowFontError(fontPathMono); - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); - fontsToUnscale.Add(MonoFont); - } - - // Default font but in requested size for requested glyphs - { - Dictionary> extraFontRequests = new(); - foreach (var extraFontRequest in this.glyphRequests) + foreach (var request in requests) { - if (!extraFontRequests.ContainsKey(extraFontRequest.Size)) - extraFontRequests[extraFontRequest.Size] = new(); - extraFontRequests[extraFontRequest.Size].Add(extraFontRequest); + foreach (var range in request.CodepointRanges) + codepointRanges.Add(range); } - foreach (var (fontSize, requests) in extraFontRequests) + codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1))); + + List flattenedRanges = new(); + foreach (var range in codepointRanges) { - List> codepointRanges = new(); - codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); - codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); - - // ImGui default ellipsis characters - codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); - codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); - - foreach (var request in requests) + if (flattenedRanges.Any() && flattenedRanges[^1] >= range.Item1 - 1) { - foreach (var range in request.CodepointRanges) - codepointRanges.Add(range); + flattenedRanges[^1] = Math.Max(flattenedRanges[^1], range.Item2); } - - codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1))); - - List flattenedRanges = new(); - foreach (var range in codepointRanges) - { - if (flattenedRanges.Any() && flattenedRanges[^1] >= range.Item1 - 1) - { - flattenedRanges[^1] = Math.Max(flattenedRanges[^1], range.Item2); - } - else - { - flattenedRanges.Add(range.Item1); - flattenedRanges.Add(range.Item2); - } - } - - flattenedRanges.Add(0); - - var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); - garbageList.Add(rangeHandle); - - var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); - fontsToUnscale.Add(sizedFont); - - foreach (var request in requests) - request.FontInternal = sizedFont; - } - } - - var gameFontManager = Service.Get(); - gameFontManager.BuildFonts(); - - Log.Verbose("[FONT] Invoke OnBuildFonts"); - this.BuildFonts?.Invoke(); - Log.Verbose("[FONT] OnBuildFonts OK!"); - - for (var i = 0; i < ImGui.GetIO().Fonts.Fonts.Size; i++) - { - Log.Verbose("{0} - {1}", i, ImGui.GetIO().Fonts.Fonts[i].GetDebugName()); - } - - ioFonts.Build(); - - if (Math.Abs(fontGamma - 1.0f) >= 0.001) - { - // Gamma correction (stbtt/FreeType would output in linear space whereas most real world usages will apply 1.4 or 1.8 gamma; Windows/XIV prebaked uses 1.4) - ioFonts.GetTexDataAsRGBA32(out byte* texPixels, out var texWidth, out var texHeight); - for (int i = 3, i_ = texWidth * texHeight * 4; i < i_; i += 4) - texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); - } - - foreach (var font in fontsToUnscale) - GameFontManager.UnscaleFont(font, fontScale, false); - - gameFontManager.AfterBuildFonts(); - - foreach (var font in fontsToUnscale) - { - // Leave IconFont alone. - if (font.NativePtr == IconFont.NativePtr) - continue; - - // MonoFont will be filled later from DefaultFont. - if (font.NativePtr == MonoFont.NativePtr) - continue; - - var axisFont = this.axisFontHandles[^1]; - for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) - { - if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) - axisFont = this.axisFontHandles[i]; else - break; + { + flattenedRanges.Add(range.Item1); + flattenedRanges.Add(range.Item2); + } } - if (this.overwriteAllNotoGlyphsWithAxis) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); - else - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); + flattenedRanges.Add(0); - // Fill missing glyphs in DefaultFont from Axis - if (font.NativePtr == DefaultFont.NativePtr) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); + var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); + var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); + rangeHandle.Free(); + + fontsToUnscale.Add(sizedFont); + + foreach (var request in requests) + request.FontInternal = sizedFont; } - - // Fill missing glyphs in MonoFont from DefaultFont - GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); - - foreach (var font in fontsToUnscale) - { - font.FallbackChar = Fallback1Codepoint; - font.BuildLookupTable(); - } - - Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); - this.AfterBuildFonts?.Invoke(); - Log.Verbose("[FONT] OnAfterBuildFonts OK!"); - - Log.Verbose("[FONT] Fonts built!"); - - this.fontBuildSignal.Set(); - - this.FontsReady = true; } - finally + + var gameFontManager = Service.Get(); + gameFontManager.BuildFonts(); + + Log.Verbose("[FONT] Invoke OnBuildFonts"); + this.BuildFonts?.Invoke(); + Log.Verbose("[FONT] OnBuildFonts OK!"); + + for (var i = 0; i < ImGui.GetIO().Fonts.Fonts.Size; i++) { - if (fontConfig.NativePtr != null) - fontConfig.Destroy(); - - foreach (var garbage in garbageList) - garbage.Free(); + Log.Verbose("{0} - {1}", i, ImGui.GetIO().Fonts.Fonts[i].GetDebugName()); } + + ioFonts.Build(); + + if (Math.Abs(fontGamma - 1.0f) >= 0.001) + { + // Gamma correction (stbtt/FreeType would output in linear space whereas most real world usages will apply 1.4 or 1.8 gamma; Windows/XIV prebaked uses 1.4) + ioFonts.GetTexDataAsRGBA32(out byte* texPixels, out var texWidth, out var texHeight); + for (int i = 3, i_ = texWidth * texHeight * 4; i < i_; i += 4) + texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); + } + + foreach (var font in fontsToUnscale) + GameFontManager.UnscaleFont(font, fontScale, false); + + gameFontManager.AfterBuildFonts(); + + foreach (var font in fontsToUnscale) + { + // Leave IconFont alone. + if (font.NativePtr == IconFont.NativePtr) + continue; + + // MonoFont will be filled later from DefaultFont. + if (font.NativePtr == MonoFont.NativePtr) + continue; + + var axisFont = this.axisFontHandles[^1]; + for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) + { + if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) + axisFont = this.axisFontHandles[i]; + else + break; + } + + if (this.overwriteAllNotoGlyphsWithAxis) + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); + else + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); + + // Fill missing glyphs in DefaultFont from Axis + if (font.NativePtr == DefaultFont.NativePtr) + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); + } + + // Fill missing glyphs in MonoFont from DefaultFont + GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); + + foreach (var font in fontsToUnscale) + { + font.FallbackChar = Fallback1Codepoint; + font.BuildLookupTable(); + } + + Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); + this.AfterBuildFonts?.Invoke(); + Log.Verbose("[FONT] OnAfterBuildFonts OK!"); + + Log.Verbose("[FONT] Fonts built!"); + + fontConfig.Destroy(); + this.fontBuildSignal.Set(); + + this.FontsReady = true; } private void Disable() From c29360201be6afbc507de5c5338960d33be0702f Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 15:59:30 +0200 Subject: [PATCH 05/33] Revert "Always keep all AXIS fonts in memory" This reverts commit f5c75e4cd58b8bbed2e51fe22944b19043a6abaa. --- .../Interface/Internal/InterfaceManager.cs | 43 ++++++------------- .../Internal/Windows/TitleScreenMenuWindow.cs | 1 - 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index a58260c0a..e5c4cbdb4 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -64,7 +64,7 @@ namespace Dalamud.Interface.Internal private readonly SwapChainVtableResolver address; private RawDX11Scene? scene; - private GameFontHandle[] axisFontHandles; + private GameFontHandle? axisFontHandle; private bool overwriteAllNotoGlyphsWithAxis; // can't access imgui IO before first present call @@ -353,17 +353,16 @@ namespace Dalamud.Interface.Internal /// Requets handle. public SpecialGlyphRequest NewFontSizeRef(float size, List> ranges) { - var allContained = false; + var allContained = true; var fonts = ImGui.GetIO().Fonts.Fonts; ImFontPtr foundFont = null; unsafe { - for (int i = 0, i_ = fonts.Size; i < i_; i++) + for (int i = 0, i_ = fonts.Size; allContained && i < i_; i++) { if (!this.glyphRequests.Any(x => x.FontInternal.NativePtr == fonts[i].NativePtr)) continue; - allContained = true; foreach (var range in ranges) { if (!allContained) @@ -419,16 +418,12 @@ namespace Dalamud.Interface.Internal var configuration = Service.Get(); this.overwriteAllNotoGlyphsWithAxis = configuration.UseAxisFontsFromGame; - if (this.axisFontHandles == null) + var currentFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, this.axisFontHandle?.Style.Size ?? 0f); + var expectedFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, DefaultFontSizePt * ImGui.GetIO().FontGlobalScale); + if (currentFamilyAndSize != expectedFamilyAndSize) { - this.axisFontHandles = new GameFontHandle[] - { - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis96)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis12)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis14)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis18)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis36)), - }; + this.axisFontHandle?.Dispose(); + this.axisFontHandle = Service.Get().NewFontRef(new(expectedFamilyAndSize)); } } @@ -664,7 +659,7 @@ namespace Dalamud.Interface.Internal List> codepointRanges = new(); codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); - + // ImGui default ellipsis characters codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); @@ -741,25 +736,15 @@ namespace Dalamud.Interface.Internal if (font.NativePtr == MonoFont.NativePtr) continue; - var axisFont = this.axisFontHandles[^1]; - for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) - { - if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) - axisFont = this.axisFontHandles[i]; - else - break; - } - if (this.overwriteAllNotoGlyphsWithAxis) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false); else - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); - - // Fill missing glyphs in DefaultFont from Axis - if (font.NativePtr == DefaultFont.NativePtr) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false, 0xE020, 0xE0DB); } + // Fill missing glyphs in DefaultFont from Axis + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, DefaultFont, true, false); + // Fill missing glyphs in MonoFont from DefaultFont GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 40bb29672..7ea7b64dd 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -245,7 +245,6 @@ namespace Dalamud.Interface.Internal.Windows this.specialGlyphRequests[entry.Name] = fontHandle = Service.Get().NewFontSizeRef(TargetFontSizePx, entry.Name); ImGui.PushFont(fontHandle.Font); - ImGui.SetWindowFontScale(TargetFontSizePx / fontHandle.Size); var scale = ImGui.GetIO().FontGlobalScale; From a68d13f721acb219492558e12a219d62e3843f63 Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 15:59:40 +0200 Subject: [PATCH 06/33] Revert "A bit more of sensible defaults" This reverts commit 14dfbf7bcfe17c581331c50254fa1ea5dc9c2c66. --- Dalamud/Interface/GameFonts/GameFontManager.cs | 1 + Dalamud/Interface/Internal/InterfaceManager.cs | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index 83178acc9..6b00be2e7 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -292,6 +292,7 @@ namespace Dalamud.Interface.GameFonts fontConfig.PixelSnapH = true; var io = ImGui.GetIO(); + io.Fonts.TexDesiredWidth = 4096; this.glyphRectIds.Clear(); this.fonts.Clear(); diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index e5c4cbdb4..9c7d5b151 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -604,7 +604,6 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.Reset(); ioFonts.Clear(); - ioFonts.TexDesiredWidth = 4096; ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); fontConfig.OversampleH = 1; @@ -659,10 +658,6 @@ namespace Dalamud.Interface.Internal List> codepointRanges = new(); codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); - - // ImGui default ellipsis characters - codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); - codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); foreach (var request in requests) { From 64e931f9ef91c87aa379889f9878838d98d708b1 Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 15:59:50 +0200 Subject: [PATCH 07/33] Revert "Don't oversample fonts, and use geta mark to indicate unavailable glyph" This reverts commit e22b168c531b349a52e3577f2520c787e55efcd4. --- .../Interface/GameFonts/GameFontManager.cs | 62 ++++++++----------- .../Interface/Internal/InterfaceManager.cs | 32 ++-------- 2 files changed, 31 insertions(+), 63 deletions(-) diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index 6b00be2e7..b7e208af1 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -284,49 +284,39 @@ namespace Dalamud.Interface.GameFonts /// public void BuildFonts() { - unsafe + var io = ImGui.GetIO(); + io.Fonts.TexDesiredWidth = 4096; + + this.glyphRectIds.Clear(); + this.fonts.Clear(); + + foreach (var style in this.fontUseCounter.Keys) { - ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); - fontConfig.OversampleH = 1; - fontConfig.OversampleV = 1; - fontConfig.PixelSnapH = true; + var rectIds = this.glyphRectIds[style] = new(); - var io = ImGui.GetIO(); - io.Fonts.TexDesiredWidth = 4096; + var fdt = this.fdts[(int)style.FamilyAndSize]; + if (fdt == null) + continue; - this.glyphRectIds.Clear(); - this.fonts.Clear(); - - foreach (var style in this.fontUseCounter.Keys) + var font = io.Fonts.AddFontDefault(); + this.fonts[style] = font; + foreach (var glyph in fdt.Glyphs) { - var rectIds = this.glyphRectIds[style] = new(); - - var fdt = this.fdts[(int)style.FamilyAndSize]; - if (fdt == null) + var c = glyph.Char; + if (c < 32 || c >= 0xFFFF) continue; - var font = io.Fonts.AddFontDefault(fontConfig); - this.fonts[style] = font; - foreach (var glyph in fdt.Glyphs) - { - var c = glyph.Char; - if (c < 32 || c >= 0xFFFF) - continue; - - var widthAdjustment = style.CalculateWidthAdjustment(fdt, glyph); - rectIds[c] = Tuple.Create( - io.Fonts.AddCustomRectFontGlyph( - font, - c, - glyph.BoundingWidth + widthAdjustment + 1, - glyph.BoundingHeight + 1, - glyph.AdvanceWidth, - new Vector2(0, glyph.CurrentOffsetY)), - glyph); - } + var widthAdjustment = style.CalculateWidthAdjustment(fdt, glyph); + rectIds[c] = Tuple.Create( + io.Fonts.AddCustomRectFontGlyph( + font, + c, + glyph.BoundingWidth + widthAdjustment + 1, + glyph.BoundingHeight + 1, + glyph.AdvanceWidth, + new Vector2(0, glyph.CurrentOffsetY)), + glyph); } - - fontConfig.Destroy(); } } diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 9c7d5b151..6f5477463 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -49,8 +49,6 @@ namespace Dalamud.Interface.Internal { private const float DefaultFontSizePt = 12.0f; private const float DefaultFontSizePx = DefaultFontSizePt * 4.0f / 3.0f; - private const ushort Fallback1Codepoint = 0x3013; // Geta mark; FFXIV uses this to indicate that a glyph is missing. - private const ushort Fallback2Codepoint = '-'; // FFXIV uses dash if Geta mark is unavailable. private readonly string rtssPath; @@ -605,11 +603,6 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.Reset(); ioFonts.Clear(); - ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); - fontConfig.OversampleH = 1; - fontConfig.OversampleV = 1; - fontConfig.PixelSnapH = true; - var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); if (!File.Exists(fontPathJp)) ShowFontError(fontPathJp); @@ -617,7 +610,7 @@ namespace Dalamud.Interface.Internal // Default font { var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, null, japaneseRangeHandle.AddrOfPinnedObject()); japaneseRangeHandle.Free(); fontsToUnscale.Add(DefaultFont); } @@ -629,7 +622,7 @@ namespace Dalamud.Interface.Internal ShowFontError(fontPathIcon); var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, null, iconRangeHandle.AddrOfPinnedObject()); iconRangeHandle.Free(); fontsToUnscale.Add(IconFont); } @@ -639,7 +632,7 @@ namespace Dalamud.Interface.Internal var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); if (!File.Exists(fontPathMono)) ShowFontError(fontPathMono); - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale); fontsToUnscale.Add(MonoFont); } @@ -656,9 +649,6 @@ namespace Dalamud.Interface.Internal foreach (var (fontSize, requests) in extraFontRequests) { List> codepointRanges = new(); - codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); - codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); - foreach (var request in requests) { foreach (var range in request.CodepointRanges) @@ -684,7 +674,7 @@ namespace Dalamud.Interface.Internal flattenedRanges.Add(0); var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); - var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); + var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, null, rangeHandle.AddrOfPinnedObject()); rangeHandle.Free(); fontsToUnscale.Add(sizedFont); @@ -723,12 +713,7 @@ namespace Dalamud.Interface.Internal foreach (var font in fontsToUnscale) { - // Leave IconFont alone. - if (font.NativePtr == IconFont.NativePtr) - continue; - - // MonoFont will be filled later from DefaultFont. - if (font.NativePtr == MonoFont.NativePtr) + if (font.NativePtr == MonoFont.NativePtr || font.NativePtr == IconFont.NativePtr) continue; if (this.overwriteAllNotoGlyphsWithAxis) @@ -737,17 +722,11 @@ namespace Dalamud.Interface.Internal GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false, 0xE020, 0xE0DB); } - // Fill missing glyphs in DefaultFont from Axis - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, DefaultFont, true, false); - // Fill missing glyphs in MonoFont from DefaultFont GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); foreach (var font in fontsToUnscale) - { - font.FallbackChar = Fallback1Codepoint; font.BuildLookupTable(); - } Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); this.AfterBuildFonts?.Invoke(); @@ -755,7 +734,6 @@ namespace Dalamud.Interface.Internal Log.Verbose("[FONT] Fonts built!"); - fontConfig.Destroy(); this.fontBuildSignal.Set(); this.FontsReady = true; From 04ec131b15eadd32ebe6ba0803b74930d8d47ea5 Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 16:00:01 +0200 Subject: [PATCH 08/33] Revert "Show size appropriate fonts" This reverts commit be65907beb7c0ab9041f1e13d2d121a273a4ec52. --- .../Interface/GameFonts/GameFontManager.cs | 60 +--- .../Interface/Internal/InterfaceManager.cs | 280 ++++-------------- .../Internal/Windows/SettingsWindow.cs | 2 +- .../Internal/Windows/TitleScreenMenuWindow.cs | 75 ++--- 4 files changed, 97 insertions(+), 320 deletions(-) diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index b7e208af1..ba9253a9b 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -117,21 +117,18 @@ namespace Dalamud.Interface.GameFonts /// Target font. /// Whether to copy missing glyphs only. /// Whether to call target.BuildLookupTable(). - /// Low codepoint range to copy. - /// High codepoing range to copy. - public static void CopyGlyphsAcrossFonts(ImFontPtr? source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable, int rangeLow = 32, int rangeHigh = 0xFFFE) + public static void CopyGlyphsAcrossFonts(ImFontPtr? source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable) { if (!source.HasValue || !target.HasValue) return; - var scale = target.Value!.FontSize / source.Value!.FontSize; unsafe { var glyphs = (ImFontGlyphReal*)source.Value!.Glyphs.Data; for (int j = 0, j_ = source.Value!.Glyphs.Size; j < j_; j++) { var glyph = &glyphs[j]; - if (glyph->Codepoint < rangeLow || glyph->Codepoint > rangeHigh) + if (glyph->Codepoint < 32 || glyph->Codepoint >= 0xFFFF) continue; var prevGlyphPtr = (ImFontGlyphReal*)target.Value!.FindGlyphNoFallback((ushort)glyph->Codepoint).NativePtr; @@ -140,27 +137,27 @@ namespace Dalamud.Interface.GameFonts target.Value!.AddGlyph( target.Value!.ConfigData, (ushort)glyph->Codepoint, - glyph->X0 * scale, - glyph->Y0 * scale, - glyph->X1 * scale, - glyph->Y1 * scale, + glyph->X0, + glyph->Y0, + glyph->X0 + ((glyph->X1 - glyph->X0) * target.Value!.FontSize / source.Value!.FontSize), + glyph->Y0 + ((glyph->Y1 - glyph->Y0) * target.Value!.FontSize / source.Value!.FontSize), glyph->U0, glyph->V0, glyph->U1, glyph->V1, - glyph->AdvanceX * scale); + glyph->AdvanceX * target.Value!.FontSize / source.Value!.FontSize); } else if (!missingOnly) { - prevGlyphPtr->X0 = glyph->X0 * scale; - prevGlyphPtr->Y0 = glyph->Y0 * scale; - prevGlyphPtr->X1 = glyph->X1 * scale; - prevGlyphPtr->Y1 = glyph->Y1 * scale; + prevGlyphPtr->X0 = glyph->X0; + prevGlyphPtr->Y0 = glyph->Y0; + prevGlyphPtr->X1 = glyph->X0 + ((glyph->X1 - glyph->X0) * target.Value!.FontSize / source.Value!.FontSize); + prevGlyphPtr->Y1 = glyph->Y0 + ((glyph->Y1 - glyph->Y0) * target.Value!.FontSize / source.Value!.FontSize); prevGlyphPtr->U0 = glyph->U0; prevGlyphPtr->V0 = glyph->V0; prevGlyphPtr->U1 = glyph->U1; prevGlyphPtr->V1 = glyph->V1; - prevGlyphPtr->AdvanceX = glyph->AdvanceX * scale; + prevGlyphPtr->AdvanceX = glyph->AdvanceX * target.Value!.FontSize / source.Value!.FontSize; } } } @@ -169,39 +166,6 @@ namespace Dalamud.Interface.GameFonts target.Value!.BuildLookupTable(); } - /// - /// Unscales fonts after they have been rendered onto atlas. - /// - /// Font to unscale. - /// Scale factor. - /// Whether to call target.BuildLookupTable(). - public static void UnscaleFont(ImFontPtr fontPtr, float fontScale, bool rebuildLookupTable = true) - { - unsafe - { - var font = fontPtr.NativePtr; - for (int i = 0, i_ = font->IndexAdvanceX.Size; i < i_; ++i) - ((float*)font->IndexAdvanceX.Data)[i] /= fontScale; - font->FallbackAdvanceX /= fontScale; - font->FontSize /= fontScale; - font->Ascent /= fontScale; - font->Descent /= fontScale; - var glyphs = (ImFontGlyphReal*)font->Glyphs.Data; - for (int i = 0, i_ = font->Glyphs.Size; i < i_; i++) - { - var glyph = &glyphs[i]; - glyph->X0 /= fontScale; - glyph->X1 /= fontScale; - glyph->Y0 /= fontScale; - glyph->Y1 /= fontScale; - glyph->AdvanceX /= fontScale; - } - } - - if (rebuildLookupTable) - fontPtr.BuildLookupTable(); - } - /// public void Dispose() { diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 6f5477463..0c6d99efa 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -47,13 +47,8 @@ namespace Dalamud.Interface.Internal /// internal class InterfaceManager : IDisposable { - private const float DefaultFontSizePt = 12.0f; - private const float DefaultFontSizePx = DefaultFontSizePt * 4.0f / 3.0f; - private readonly string rtssPath; - private readonly HashSet glyphRequests = new(); - private readonly Hook presentHook; private readonly Hook resizeBuffersHook; private readonly Hook setCursorHook; @@ -63,7 +58,6 @@ namespace Dalamud.Interface.Internal private RawDX11Scene? scene; private GameFontHandle? axisFontHandle; - private bool overwriteAllNotoGlyphsWithAxis; // can't access imgui IO before first present call private bool lastWantCapture = false; @@ -343,69 +337,6 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.WaitOne(); } - /// - /// Requests a default font of specified size to exist. - /// - /// Font size in pixels. - /// Ranges of glyphs. - /// Requets handle. - public SpecialGlyphRequest NewFontSizeRef(float size, List> ranges) - { - var allContained = true; - var fonts = ImGui.GetIO().Fonts.Fonts; - ImFontPtr foundFont = null; - unsafe - { - for (int i = 0, i_ = fonts.Size; allContained && i < i_; i++) - { - if (!this.glyphRequests.Any(x => x.FontInternal.NativePtr == fonts[i].NativePtr)) - continue; - - foreach (var range in ranges) - { - if (!allContained) - break; - - for (var j = range.Item1; j <= range.Item2 && allContained; j++) - allContained &= fonts[i].FindGlyphNoFallback(j).NativePtr != null; - } - - if (allContained) - foundFont = fonts[i]; - - break; - } - } - - var req = new SpecialGlyphRequest(this, size, ranges); - req.FontInternal = foundFont; - - if (!allContained) - this.RebuildFonts(); - - return req; - } - - /// - /// Requests a default font of specified size to exist. - /// - /// Font size in pixels. - /// Text to calculate glyph ranges from. - /// Requets handle. - public SpecialGlyphRequest NewFontSizeRef(float size, string text) - { - List> ranges = new(); - foreach (var c in new SortedSet(text.ToHashSet())) - { - if (ranges.Any() && ranges[^1].Item2 + 1 == c) - ranges[^1] = Tuple.Create(ranges[^1].Item1, c); - else - ranges.Add(Tuple.Create(c, c)); - } - - return this.NewFontSizeRef(size, ranges); - } - private static void ShowFontError(string path) { Util.Fatal($"One or more files required by XIVLauncher were not found.\nPlease restart and report this error if it occurs again.\n\n{path}", "Error"); @@ -414,15 +345,21 @@ namespace Dalamud.Interface.Internal private void SetAxisFonts() { var configuration = Service.Get(); - this.overwriteAllNotoGlyphsWithAxis = configuration.UseAxisFontsFromGame; - - var currentFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, this.axisFontHandle?.Style.Size ?? 0f); - var expectedFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, DefaultFontSizePt * ImGui.GetIO().FontGlobalScale); - if (currentFamilyAndSize != expectedFamilyAndSize) + if (configuration.UseAxisFontsFromGame) { + var currentFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, this.axisFontHandle?.Style.Size ?? 0f); + var expectedFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, 12 * ImGui.GetIO().FontGlobalScale); + if (currentFamilyAndSize == expectedFamilyAndSize) + return; + this.axisFontHandle?.Dispose(); this.axisFontHandle = Service.Get().NewFontRef(new(expectedFamilyAndSize)); } + else + { + this.axisFontHandle?.Dispose(); + this.axisFontHandle = null; + } } /* @@ -594,95 +531,64 @@ namespace Dalamud.Interface.Internal private unsafe void SetupFonts() { var dalamud = Service.Get(); - var io = ImGui.GetIO(); - var ioFonts = io.Fonts; - var fontScale = io.FontGlobalScale; + var ioFonts = ImGui.GetIO().Fonts; var fontGamma = this.FontGamma; - List fontsToUnscale = new(); this.fontBuildSignal.Reset(); + ioFonts.Clear(); + ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); + fontConfig.PixelSnapH = true; + var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); + if (!File.Exists(fontPathJp)) ShowFontError(fontPathJp); - // Default font - { - var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, null, japaneseRangeHandle.AddrOfPinnedObject()); - japaneseRangeHandle.Free(); - fontsToUnscale.Add(DefaultFont); - } + var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); - // FontAwesome icon font - { - var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); - if (!File.Exists(fontPathIcon)) - ShowFontError(fontPathIcon); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, japaneseRangeHandle.AddrOfPinnedObject()); - var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, null, iconRangeHandle.AddrOfPinnedObject()); - iconRangeHandle.Free(); - fontsToUnscale.Add(IconFont); - } + var fontPathGame = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "gamesym.ttf"); - // Monospace font - { - var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); - if (!File.Exists(fontPathMono)) - ShowFontError(fontPathMono); - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale); - fontsToUnscale.Add(MonoFont); - } + if (!File.Exists(fontPathGame)) + ShowFontError(fontPathGame); - // Default font but in requested size for requested glyphs - { - Dictionary> extraFontRequests = new(); - foreach (var extraFontRequest in this.glyphRequests) + var gameRangeHandle = GCHandle.Alloc( + new ushort[] { - if (!extraFontRequests.ContainsKey(extraFontRequest.Size)) - extraFontRequests[extraFontRequest.Size] = new(); - extraFontRequests[extraFontRequest.Size].Add(extraFontRequest); - } + 0xE020, + 0xE0DB, + 0, + }, + GCHandleType.Pinned); - foreach (var (fontSize, requests) in extraFontRequests) + fontConfig.MergeMode = false; + ioFonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, gameRangeHandle.AddrOfPinnedObject()); + fontConfig.MergeMode = true; + + var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); + + if (!File.Exists(fontPathIcon)) + ShowFontError(fontPathIcon); + + var iconRangeHandle = GCHandle.Alloc( + new ushort[] { - List> codepointRanges = new(); - foreach (var request in requests) - { - foreach (var range in request.CodepointRanges) - codepointRanges.Add(range); - } + 0xE000, + 0xF8FF, + 0, + }, + GCHandleType.Pinned); + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, 17.0f, null, iconRangeHandle.AddrOfPinnedObject()); - codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1))); + var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); - List flattenedRanges = new(); - foreach (var range in codepointRanges) - { - if (flattenedRanges.Any() && flattenedRanges[^1] >= range.Item1 - 1) - { - flattenedRanges[^1] = Math.Max(flattenedRanges[^1], range.Item2); - } - else - { - flattenedRanges.Add(range.Item1); - flattenedRanges.Add(range.Item2); - } - } + if (!File.Exists(fontPathMono)) + ShowFontError(fontPathMono); - flattenedRanges.Add(0); - - var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); - var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, null, rangeHandle.AddrOfPinnedObject()); - rangeHandle.Free(); - - fontsToUnscale.Add(sizedFont); - - foreach (var request in requests) - request.FontInternal = sizedFont; - } - } + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, 16.0f); var gameFontManager = Service.Get(); gameFontManager.BuildFonts(); @@ -706,27 +612,8 @@ namespace Dalamud.Interface.Internal texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); } - foreach (var font in fontsToUnscale) - GameFontManager.UnscaleFont(font, fontScale, false); - gameFontManager.AfterBuildFonts(); - - foreach (var font in fontsToUnscale) - { - if (font.NativePtr == MonoFont.NativePtr || font.NativePtr == IconFont.NativePtr) - continue; - - if (this.overwriteAllNotoGlyphsWithAxis) - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false); - else - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false, 0xE020, 0xE0DB); - } - - // Fill missing glyphs in MonoFont from DefaultFont - GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); - - foreach (var font in fontsToUnscale) - font.BuildLookupTable(); + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, DefaultFont, false, true); Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); this.AfterBuildFonts?.Invoke(); @@ -736,6 +623,11 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.Set(); + fontConfig.Destroy(); + japaneseRangeHandle.Free(); + gameRangeHandle.Free(); + iconRangeHandle.Free(); + this.FontsReady = true; } @@ -873,65 +765,5 @@ namespace Dalamud.Interface.Internal Service.Get().Draw(); } - - /// - /// Represents a glyph request. - /// - public class SpecialGlyphRequest : IDisposable - { - /// - /// Initializes a new instance of the class. - /// - /// InterfaceManager to associate. - /// Font size in pixels. - /// Codepoint ranges. - internal SpecialGlyphRequest(InterfaceManager manager, float size, List> ranges) - { - this.Manager = manager; - this.Size = size; - this.CodepointRanges = ranges; - this.Manager.glyphRequests.Add(this); - } - - /// - /// Gets the font of specified size, or DefaultFont if it's not ready yet. - /// - public ImFontPtr Font - { - get - { - unsafe - { - return this.FontInternal.NativePtr == null ? DefaultFont : this.FontInternal; - } - } - } - - /// - /// Gets or sets the associated ImFont. - /// - internal ImFontPtr FontInternal { get; set; } - - /// - /// Gets associated InterfaceManager. - /// - internal InterfaceManager Manager { get; init; } - - /// - /// Gets font size. - /// - internal float Size { get; init; } - - /// - /// Gets codepoint ranges. - /// - internal List> CodepointRanges { get; init; } - - /// - public void Dispose() - { - this.Manager.glyphRequests.Remove(this); - } - } } } diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 9ff94f42e..48104ed6a 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -26,7 +26,7 @@ namespace Dalamud.Interface.Internal.Windows internal class SettingsWindow : Window { private const float MinScale = 0.3f; - private const float MaxScale = 3.0f; + private const float MaxScale = 2.0f; private readonly string[] languages; private readonly string[] locLanguages; diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 7ea7b64dd..b4c089fbe 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Numerics; using Dalamud.Configuration.Internal; @@ -21,18 +20,17 @@ namespace Dalamud.Interface.Internal.Windows /// internal class TitleScreenMenuWindow : Window, IDisposable { - private const float TargetFontSizePt = 18f; - private const float TargetFontSizePx = TargetFontSizePt * 4 / 3; - + private const float TargetFontSize = 16.2f; private readonly TextureWrap shadeTexture; private readonly Dictionary shadeEasings = new(); private readonly Dictionary moveEasings = new(); private readonly Dictionary logoEasings = new(); - private readonly Dictionary specialGlyphRequests = new(); private InOutCubic? fadeOutEasing; + private GameFontHandle? axisFontHandle; + private State state = State.Hide; /// @@ -73,14 +71,19 @@ namespace Dalamud.Interface.Internal.Windows /// public override void PreDraw() { + this.SetAxisFonts(); ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0)); + if (this.axisFontHandle?.Available ?? false) + ImGui.PushFont(this.axisFontHandle.ImFont); base.PreDraw(); } /// public override void PostDraw() { + if (this.axisFontHandle?.Available ?? false) + ImGui.PopFont(); ImGui.PopStyleVar(2); base.PostDraw(); } @@ -96,7 +99,7 @@ namespace Dalamud.Interface.Internal.Windows /// public override void Draw() { - var scale = ImGui.GetIO().FontGlobalScale; + ImGui.SetWindowFontScale(TargetFontSize / ImGui.GetFont().FontSize * 4 / 3); var tsm = Service.Get(); @@ -126,7 +129,7 @@ namespace Dalamud.Interface.Internal.Windows moveEasing.Update(); - var finalPos = (i + 1) * this.shadeTexture.Height * scale; + var finalPos = (i + 1) * this.shadeTexture.Height; var pos = moveEasing.Value * finalPos; // FIXME(goat): Sometimes, easings can overshoot and bring things out of alignment. @@ -177,7 +180,7 @@ namespace Dalamud.Interface.Internal.Windows { var entry = tsm.Entries[i]; - var finalPos = (i + 1) * this.shadeTexture.Height * scale; + var finalPos = (i + 1) * this.shadeTexture.Height; this.DrawEntry(entry, i != 0, true, i == 0, false); @@ -219,35 +222,26 @@ namespace Dalamud.Interface.Internal.Windows break; } } + } - var srcText = tsm.Entries.Select(e => e.Name).ToHashSet(); - var keys = this.specialGlyphRequests.Keys.ToHashSet(); - keys.RemoveWhere(x => srcText.Contains(x)); - foreach (var key in keys) + private void SetAxisFonts() + { + var configuration = Service.Get(); + if (configuration.UseAxisFontsFromGame) { - this.specialGlyphRequests[key].Dispose(); - this.specialGlyphRequests.Remove(key); + if (this.axisFontHandle == null) + this.axisFontHandle = Service.Get().NewFontRef(new(GameFontFamily.Axis, TargetFontSize)); + } + else + { + this.axisFontHandle?.Dispose(); + this.axisFontHandle = null; } } private bool DrawEntry( TitleScreenMenu.TitleScreenMenuEntry entry, bool inhibitFadeout, bool showText, bool isFirst, bool overrideAlpha) { - 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.Get().NewFontSizeRef(TargetFontSizePx, entry.Name); - - ImGui.PushFont(fontHandle.Font); - - var scale = ImGui.GetIO().FontGlobalScale; - if (!this.shadeEasings.TryGetValue(entry.Id, out var shadeEasing)) { shadeEasing = new InOutCubic(TimeSpan.FromMilliseconds(350)); @@ -257,7 +251,7 @@ namespace Dalamud.Interface.Internal.Windows var initialCursor = ImGui.GetCursorPos(); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, (float)shadeEasing.Value); - ImGui.Image(this.shadeTexture.ImGuiHandle, new Vector2(this.shadeTexture.Width * scale, this.shadeTexture.Height * scale)); + ImGui.Image(this.shadeTexture.ImGuiHandle, new Vector2(this.shadeTexture.Width, this.shadeTexture.Height)); ImGui.PopStyleVar(); var isHover = ImGui.IsItemHovered(); @@ -311,7 +305,7 @@ namespace Dalamud.Interface.Internal.Windows ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1f); } - ImGui.Image(entry.Texture.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale)); + ImGui.Image(entry.Texture.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize)); if (overrideAlpha || isFirst) { ImGui.PopStyleVar(); @@ -325,36 +319,23 @@ namespace Dalamud.Interface.Internal.Windows var textHeight = ImGui.GetTextLineHeightWithSpacing(); var cursor = ImGui.GetCursorPos(); - cursor.Y += (entry.Texture.Height * scale / 2) - (textHeight / 2); + cursor.Y += (entry.Texture.Height / 2) - (textHeight / 2); + ImGui.SetCursorPos(cursor); if (overrideAlpha) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, showText ? (float)logoEasing.Value : 0f); } - // Drop shadow - ImGui.PushStyleColor(ImGuiCol.Text, 0xFF000000); - for (int i = 0, i_ = (int)Math.Ceiling(1 * scale); i < i_; i++) - { - ImGui.SetCursorPos(new Vector2(cursor.X, cursor.Y + i)); - ImGui.Text(entry.Name); - } - - ImGui.PopStyleColor(); - - ImGui.SetCursorPos(cursor); ImGui.Text(entry.Name); - if (overrideAlpha) { ImGui.PopStyleVar(); } - initialCursor.Y += entry.Texture.Height * scale; + initialCursor.Y += entry.Texture.Height; ImGui.SetCursorPos(initialCursor); - ImGui.PopFont(); - return isHover; } From 0cd1c1b150edbc46ec6e8693a5b4be73eca36129 Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 16:08:11 +0200 Subject: [PATCH 09/33] build: 6.3.0.9 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index ef5e6f7f8..011750869 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.8 + 6.3.0.9 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From b2ff63a4cc6b0589a41c9170da5bd6c33bcf14c8 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Mon, 7 Mar 2022 13:47:37 +0900 Subject: [PATCH 10/33] Show size appropriate fonts (cherry picked from commit be65907beb7c0ab9041f1e13d2d121a273a4ec52) --- .../Interface/GameFonts/GameFontManager.cs | 60 +++- .../Interface/Internal/InterfaceManager.cs | 280 ++++++++++++++---- .../Internal/Windows/SettingsWindow.cs | 2 +- .../Internal/Windows/TitleScreenMenuWindow.cs | 75 +++-- 4 files changed, 320 insertions(+), 97 deletions(-) diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index ba9253a9b..b7e208af1 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -117,18 +117,21 @@ namespace Dalamud.Interface.GameFonts /// Target font. /// Whether to copy missing glyphs only. /// Whether to call target.BuildLookupTable(). - public static void CopyGlyphsAcrossFonts(ImFontPtr? source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable) + /// Low codepoint range to copy. + /// High codepoing range to copy. + public static void CopyGlyphsAcrossFonts(ImFontPtr? source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable, int rangeLow = 32, int rangeHigh = 0xFFFE) { if (!source.HasValue || !target.HasValue) return; + var scale = target.Value!.FontSize / source.Value!.FontSize; unsafe { var glyphs = (ImFontGlyphReal*)source.Value!.Glyphs.Data; for (int j = 0, j_ = source.Value!.Glyphs.Size; j < j_; j++) { var glyph = &glyphs[j]; - if (glyph->Codepoint < 32 || glyph->Codepoint >= 0xFFFF) + if (glyph->Codepoint < rangeLow || glyph->Codepoint > rangeHigh) continue; var prevGlyphPtr = (ImFontGlyphReal*)target.Value!.FindGlyphNoFallback((ushort)glyph->Codepoint).NativePtr; @@ -137,27 +140,27 @@ namespace Dalamud.Interface.GameFonts target.Value!.AddGlyph( target.Value!.ConfigData, (ushort)glyph->Codepoint, - glyph->X0, - glyph->Y0, - glyph->X0 + ((glyph->X1 - glyph->X0) * target.Value!.FontSize / source.Value!.FontSize), - glyph->Y0 + ((glyph->Y1 - glyph->Y0) * target.Value!.FontSize / source.Value!.FontSize), + glyph->X0 * scale, + glyph->Y0 * scale, + glyph->X1 * scale, + glyph->Y1 * scale, glyph->U0, glyph->V0, glyph->U1, glyph->V1, - glyph->AdvanceX * target.Value!.FontSize / source.Value!.FontSize); + glyph->AdvanceX * scale); } else if (!missingOnly) { - prevGlyphPtr->X0 = glyph->X0; - prevGlyphPtr->Y0 = glyph->Y0; - prevGlyphPtr->X1 = glyph->X0 + ((glyph->X1 - glyph->X0) * target.Value!.FontSize / source.Value!.FontSize); - prevGlyphPtr->Y1 = glyph->Y0 + ((glyph->Y1 - glyph->Y0) * target.Value!.FontSize / source.Value!.FontSize); + prevGlyphPtr->X0 = glyph->X0 * scale; + prevGlyphPtr->Y0 = glyph->Y0 * scale; + prevGlyphPtr->X1 = glyph->X1 * scale; + prevGlyphPtr->Y1 = glyph->Y1 * scale; prevGlyphPtr->U0 = glyph->U0; prevGlyphPtr->V0 = glyph->V0; prevGlyphPtr->U1 = glyph->U1; prevGlyphPtr->V1 = glyph->V1; - prevGlyphPtr->AdvanceX = glyph->AdvanceX * target.Value!.FontSize / source.Value!.FontSize; + prevGlyphPtr->AdvanceX = glyph->AdvanceX * scale; } } } @@ -166,6 +169,39 @@ namespace Dalamud.Interface.GameFonts target.Value!.BuildLookupTable(); } + /// + /// Unscales fonts after they have been rendered onto atlas. + /// + /// Font to unscale. + /// Scale factor. + /// Whether to call target.BuildLookupTable(). + public static void UnscaleFont(ImFontPtr fontPtr, float fontScale, bool rebuildLookupTable = true) + { + unsafe + { + var font = fontPtr.NativePtr; + for (int i = 0, i_ = font->IndexAdvanceX.Size; i < i_; ++i) + ((float*)font->IndexAdvanceX.Data)[i] /= fontScale; + font->FallbackAdvanceX /= fontScale; + font->FontSize /= fontScale; + font->Ascent /= fontScale; + font->Descent /= fontScale; + var glyphs = (ImFontGlyphReal*)font->Glyphs.Data; + for (int i = 0, i_ = font->Glyphs.Size; i < i_; i++) + { + var glyph = &glyphs[i]; + glyph->X0 /= fontScale; + glyph->X1 /= fontScale; + glyph->Y0 /= fontScale; + glyph->Y1 /= fontScale; + glyph->AdvanceX /= fontScale; + } + } + + if (rebuildLookupTable) + fontPtr.BuildLookupTable(); + } + /// public void Dispose() { diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 0c6d99efa..6f5477463 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -47,8 +47,13 @@ namespace Dalamud.Interface.Internal /// internal class InterfaceManager : IDisposable { + private const float DefaultFontSizePt = 12.0f; + private const float DefaultFontSizePx = DefaultFontSizePt * 4.0f / 3.0f; + private readonly string rtssPath; + private readonly HashSet glyphRequests = new(); + private readonly Hook presentHook; private readonly Hook resizeBuffersHook; private readonly Hook setCursorHook; @@ -58,6 +63,7 @@ namespace Dalamud.Interface.Internal private RawDX11Scene? scene; private GameFontHandle? axisFontHandle; + private bool overwriteAllNotoGlyphsWithAxis; // can't access imgui IO before first present call private bool lastWantCapture = false; @@ -337,6 +343,69 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.WaitOne(); } + /// + /// Requests a default font of specified size to exist. + /// + /// Font size in pixels. + /// Ranges of glyphs. + /// Requets handle. + public SpecialGlyphRequest NewFontSizeRef(float size, List> ranges) + { + var allContained = true; + var fonts = ImGui.GetIO().Fonts.Fonts; + ImFontPtr foundFont = null; + unsafe + { + for (int i = 0, i_ = fonts.Size; allContained && i < i_; i++) + { + if (!this.glyphRequests.Any(x => x.FontInternal.NativePtr == fonts[i].NativePtr)) + continue; + + foreach (var range in ranges) + { + if (!allContained) + break; + + for (var j = range.Item1; j <= range.Item2 && allContained; j++) + allContained &= fonts[i].FindGlyphNoFallback(j).NativePtr != null; + } + + if (allContained) + foundFont = fonts[i]; + + break; + } + } + + var req = new SpecialGlyphRequest(this, size, ranges); + req.FontInternal = foundFont; + + if (!allContained) + this.RebuildFonts(); + + return req; + } + + /// + /// Requests a default font of specified size to exist. + /// + /// Font size in pixels. + /// Text to calculate glyph ranges from. + /// Requets handle. + public SpecialGlyphRequest NewFontSizeRef(float size, string text) + { + List> ranges = new(); + foreach (var c in new SortedSet(text.ToHashSet())) + { + if (ranges.Any() && ranges[^1].Item2 + 1 == c) + ranges[^1] = Tuple.Create(ranges[^1].Item1, c); + else + ranges.Add(Tuple.Create(c, c)); + } + + return this.NewFontSizeRef(size, ranges); + } + private static void ShowFontError(string path) { Util.Fatal($"One or more files required by XIVLauncher were not found.\nPlease restart and report this error if it occurs again.\n\n{path}", "Error"); @@ -345,21 +414,15 @@ namespace Dalamud.Interface.Internal private void SetAxisFonts() { var configuration = Service.Get(); - if (configuration.UseAxisFontsFromGame) - { - var currentFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, this.axisFontHandle?.Style.Size ?? 0f); - var expectedFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, 12 * ImGui.GetIO().FontGlobalScale); - if (currentFamilyAndSize == expectedFamilyAndSize) - return; + this.overwriteAllNotoGlyphsWithAxis = configuration.UseAxisFontsFromGame; + var currentFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, this.axisFontHandle?.Style.Size ?? 0f); + var expectedFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, DefaultFontSizePt * ImGui.GetIO().FontGlobalScale); + if (currentFamilyAndSize != expectedFamilyAndSize) + { this.axisFontHandle?.Dispose(); this.axisFontHandle = Service.Get().NewFontRef(new(expectedFamilyAndSize)); } - else - { - this.axisFontHandle?.Dispose(); - this.axisFontHandle = null; - } } /* @@ -531,64 +594,95 @@ namespace Dalamud.Interface.Internal private unsafe void SetupFonts() { var dalamud = Service.Get(); - var ioFonts = ImGui.GetIO().Fonts; + var io = ImGui.GetIO(); + var ioFonts = io.Fonts; + var fontScale = io.FontGlobalScale; var fontGamma = this.FontGamma; + List fontsToUnscale = new(); this.fontBuildSignal.Reset(); - ioFonts.Clear(); - ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); - fontConfig.PixelSnapH = true; - var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); - if (!File.Exists(fontPathJp)) ShowFontError(fontPathJp); - var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); + // Default font + { + var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, null, japaneseRangeHandle.AddrOfPinnedObject()); + japaneseRangeHandle.Free(); + fontsToUnscale.Add(DefaultFont); + } - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, japaneseRangeHandle.AddrOfPinnedObject()); + // FontAwesome icon font + { + var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); + if (!File.Exists(fontPathIcon)) + ShowFontError(fontPathIcon); - var fontPathGame = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "gamesym.ttf"); + var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, null, iconRangeHandle.AddrOfPinnedObject()); + iconRangeHandle.Free(); + fontsToUnscale.Add(IconFont); + } - if (!File.Exists(fontPathGame)) - ShowFontError(fontPathGame); + // Monospace font + { + var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); + if (!File.Exists(fontPathMono)) + ShowFontError(fontPathMono); + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale); + fontsToUnscale.Add(MonoFont); + } - var gameRangeHandle = GCHandle.Alloc( - new ushort[] + // Default font but in requested size for requested glyphs + { + Dictionary> extraFontRequests = new(); + foreach (var extraFontRequest in this.glyphRequests) { - 0xE020, - 0xE0DB, - 0, - }, - GCHandleType.Pinned); + if (!extraFontRequests.ContainsKey(extraFontRequest.Size)) + extraFontRequests[extraFontRequest.Size] = new(); + extraFontRequests[extraFontRequest.Size].Add(extraFontRequest); + } - fontConfig.MergeMode = false; - ioFonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, gameRangeHandle.AddrOfPinnedObject()); - fontConfig.MergeMode = true; - - var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); - - if (!File.Exists(fontPathIcon)) - ShowFontError(fontPathIcon); - - var iconRangeHandle = GCHandle.Alloc( - new ushort[] + foreach (var (fontSize, requests) in extraFontRequests) { - 0xE000, - 0xF8FF, - 0, - }, - GCHandleType.Pinned); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, 17.0f, null, iconRangeHandle.AddrOfPinnedObject()); + List> codepointRanges = new(); + foreach (var request in requests) + { + foreach (var range in request.CodepointRanges) + codepointRanges.Add(range); + } - var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); + codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1))); - if (!File.Exists(fontPathMono)) - ShowFontError(fontPathMono); + List flattenedRanges = new(); + foreach (var range in codepointRanges) + { + if (flattenedRanges.Any() && flattenedRanges[^1] >= range.Item1 - 1) + { + flattenedRanges[^1] = Math.Max(flattenedRanges[^1], range.Item2); + } + else + { + flattenedRanges.Add(range.Item1); + flattenedRanges.Add(range.Item2); + } + } - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, 16.0f); + flattenedRanges.Add(0); + + var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); + var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, null, rangeHandle.AddrOfPinnedObject()); + rangeHandle.Free(); + + fontsToUnscale.Add(sizedFont); + + foreach (var request in requests) + request.FontInternal = sizedFont; + } + } var gameFontManager = Service.Get(); gameFontManager.BuildFonts(); @@ -612,8 +706,27 @@ namespace Dalamud.Interface.Internal texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); } + foreach (var font in fontsToUnscale) + GameFontManager.UnscaleFont(font, fontScale, false); + gameFontManager.AfterBuildFonts(); - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, DefaultFont, false, true); + + foreach (var font in fontsToUnscale) + { + if (font.NativePtr == MonoFont.NativePtr || font.NativePtr == IconFont.NativePtr) + continue; + + if (this.overwriteAllNotoGlyphsWithAxis) + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false); + else + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false, 0xE020, 0xE0DB); + } + + // Fill missing glyphs in MonoFont from DefaultFont + GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); + + foreach (var font in fontsToUnscale) + font.BuildLookupTable(); Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); this.AfterBuildFonts?.Invoke(); @@ -623,11 +736,6 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.Set(); - fontConfig.Destroy(); - japaneseRangeHandle.Free(); - gameRangeHandle.Free(); - iconRangeHandle.Free(); - this.FontsReady = true; } @@ -765,5 +873,65 @@ namespace Dalamud.Interface.Internal Service.Get().Draw(); } + + /// + /// Represents a glyph request. + /// + public class SpecialGlyphRequest : IDisposable + { + /// + /// Initializes a new instance of the class. + /// + /// InterfaceManager to associate. + /// Font size in pixels. + /// Codepoint ranges. + internal SpecialGlyphRequest(InterfaceManager manager, float size, List> ranges) + { + this.Manager = manager; + this.Size = size; + this.CodepointRanges = ranges; + this.Manager.glyphRequests.Add(this); + } + + /// + /// Gets the font of specified size, or DefaultFont if it's not ready yet. + /// + public ImFontPtr Font + { + get + { + unsafe + { + return this.FontInternal.NativePtr == null ? DefaultFont : this.FontInternal; + } + } + } + + /// + /// Gets or sets the associated ImFont. + /// + internal ImFontPtr FontInternal { get; set; } + + /// + /// Gets associated InterfaceManager. + /// + internal InterfaceManager Manager { get; init; } + + /// + /// Gets font size. + /// + internal float Size { get; init; } + + /// + /// Gets codepoint ranges. + /// + internal List> CodepointRanges { get; init; } + + /// + public void Dispose() + { + this.Manager.glyphRequests.Remove(this); + } + } } } diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 48104ed6a..9ff94f42e 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -26,7 +26,7 @@ namespace Dalamud.Interface.Internal.Windows internal class SettingsWindow : Window { private const float MinScale = 0.3f; - private const float MaxScale = 2.0f; + private const float MaxScale = 3.0f; private readonly string[] languages; private readonly string[] locLanguages; diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index b4c089fbe..7ea7b64dd 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Numerics; using Dalamud.Configuration.Internal; @@ -20,17 +21,18 @@ namespace Dalamud.Interface.Internal.Windows /// internal class TitleScreenMenuWindow : Window, IDisposable { - private const float TargetFontSize = 16.2f; + private const float TargetFontSizePt = 18f; + private const float TargetFontSizePx = TargetFontSizePt * 4 / 3; + private readonly TextureWrap shadeTexture; private readonly Dictionary shadeEasings = new(); private readonly Dictionary moveEasings = new(); private readonly Dictionary logoEasings = new(); + private readonly Dictionary specialGlyphRequests = new(); private InOutCubic? fadeOutEasing; - private GameFontHandle? axisFontHandle; - private State state = State.Hide; /// @@ -71,19 +73,14 @@ namespace Dalamud.Interface.Internal.Windows /// public override void PreDraw() { - this.SetAxisFonts(); ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0)); - if (this.axisFontHandle?.Available ?? false) - ImGui.PushFont(this.axisFontHandle.ImFont); base.PreDraw(); } /// public override void PostDraw() { - if (this.axisFontHandle?.Available ?? false) - ImGui.PopFont(); ImGui.PopStyleVar(2); base.PostDraw(); } @@ -99,7 +96,7 @@ namespace Dalamud.Interface.Internal.Windows /// public override void Draw() { - ImGui.SetWindowFontScale(TargetFontSize / ImGui.GetFont().FontSize * 4 / 3); + var scale = ImGui.GetIO().FontGlobalScale; var tsm = Service.Get(); @@ -129,7 +126,7 @@ namespace Dalamud.Interface.Internal.Windows moveEasing.Update(); - var finalPos = (i + 1) * this.shadeTexture.Height; + var finalPos = (i + 1) * this.shadeTexture.Height * scale; var pos = moveEasing.Value * finalPos; // FIXME(goat): Sometimes, easings can overshoot and bring things out of alignment. @@ -180,7 +177,7 @@ namespace Dalamud.Interface.Internal.Windows { var entry = tsm.Entries[i]; - var finalPos = (i + 1) * this.shadeTexture.Height; + var finalPos = (i + 1) * this.shadeTexture.Height * scale; this.DrawEntry(entry, i != 0, true, i == 0, false); @@ -222,26 +219,35 @@ namespace Dalamud.Interface.Internal.Windows break; } } - } - private void SetAxisFonts() - { - var configuration = Service.Get(); - if (configuration.UseAxisFontsFromGame) + var srcText = tsm.Entries.Select(e => e.Name).ToHashSet(); + var keys = this.specialGlyphRequests.Keys.ToHashSet(); + keys.RemoveWhere(x => srcText.Contains(x)); + foreach (var key in keys) { - if (this.axisFontHandle == null) - this.axisFontHandle = Service.Get().NewFontRef(new(GameFontFamily.Axis, TargetFontSize)); - } - else - { - this.axisFontHandle?.Dispose(); - this.axisFontHandle = null; + this.specialGlyphRequests[key].Dispose(); + this.specialGlyphRequests.Remove(key); } } private bool DrawEntry( TitleScreenMenu.TitleScreenMenuEntry entry, bool inhibitFadeout, bool showText, bool isFirst, bool overrideAlpha) { + 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.Get().NewFontSizeRef(TargetFontSizePx, entry.Name); + + ImGui.PushFont(fontHandle.Font); + + var scale = ImGui.GetIO().FontGlobalScale; + if (!this.shadeEasings.TryGetValue(entry.Id, out var shadeEasing)) { shadeEasing = new InOutCubic(TimeSpan.FromMilliseconds(350)); @@ -251,7 +257,7 @@ namespace Dalamud.Interface.Internal.Windows var initialCursor = ImGui.GetCursorPos(); ImGui.PushStyleVar(ImGuiStyleVar.Alpha, (float)shadeEasing.Value); - ImGui.Image(this.shadeTexture.ImGuiHandle, new Vector2(this.shadeTexture.Width, this.shadeTexture.Height)); + ImGui.Image(this.shadeTexture.ImGuiHandle, new Vector2(this.shadeTexture.Width * scale, this.shadeTexture.Height * scale)); ImGui.PopStyleVar(); var isHover = ImGui.IsItemHovered(); @@ -305,7 +311,7 @@ namespace Dalamud.Interface.Internal.Windows ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1f); } - ImGui.Image(entry.Texture.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize)); + ImGui.Image(entry.Texture.ImGuiHandle, new Vector2(TitleScreenMenu.TextureSize * scale)); if (overrideAlpha || isFirst) { ImGui.PopStyleVar(); @@ -319,23 +325,36 @@ namespace Dalamud.Interface.Internal.Windows var textHeight = ImGui.GetTextLineHeightWithSpacing(); var cursor = ImGui.GetCursorPos(); - cursor.Y += (entry.Texture.Height / 2) - (textHeight / 2); - ImGui.SetCursorPos(cursor); + cursor.Y += (entry.Texture.Height * scale / 2) - (textHeight / 2); if (overrideAlpha) { ImGui.PushStyleVar(ImGuiStyleVar.Alpha, showText ? (float)logoEasing.Value : 0f); } + // Drop shadow + ImGui.PushStyleColor(ImGuiCol.Text, 0xFF000000); + for (int i = 0, i_ = (int)Math.Ceiling(1 * scale); i < i_; i++) + { + ImGui.SetCursorPos(new Vector2(cursor.X, cursor.Y + i)); + ImGui.Text(entry.Name); + } + + ImGui.PopStyleColor(); + + ImGui.SetCursorPos(cursor); ImGui.Text(entry.Name); + if (overrideAlpha) { ImGui.PopStyleVar(); } - initialCursor.Y += entry.Texture.Height; + initialCursor.Y += entry.Texture.Height * scale; ImGui.SetCursorPos(initialCursor); + ImGui.PopFont(); + return isHover; } From 1f20b3c35af682e8cb69af27579e0db619895763 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Mon, 7 Mar 2022 14:05:20 +0900 Subject: [PATCH 11/33] Don't oversample fonts, and use geta mark to indicate unavailable glyph (cherry picked from commit e22b168c531b349a52e3577f2520c787e55efcd4) --- .../Interface/GameFonts/GameFontManager.cs | 62 +++++++++++-------- .../Interface/Internal/InterfaceManager.cs | 32 ++++++++-- 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index b7e208af1..6b00be2e7 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -284,39 +284,49 @@ namespace Dalamud.Interface.GameFonts /// public void BuildFonts() { - var io = ImGui.GetIO(); - io.Fonts.TexDesiredWidth = 4096; - - this.glyphRectIds.Clear(); - this.fonts.Clear(); - - foreach (var style in this.fontUseCounter.Keys) + unsafe { - var rectIds = this.glyphRectIds[style] = new(); + ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); + fontConfig.OversampleH = 1; + fontConfig.OversampleV = 1; + fontConfig.PixelSnapH = true; - var fdt = this.fdts[(int)style.FamilyAndSize]; - if (fdt == null) - continue; + var io = ImGui.GetIO(); + io.Fonts.TexDesiredWidth = 4096; - var font = io.Fonts.AddFontDefault(); - this.fonts[style] = font; - foreach (var glyph in fdt.Glyphs) + this.glyphRectIds.Clear(); + this.fonts.Clear(); + + foreach (var style in this.fontUseCounter.Keys) { - var c = glyph.Char; - if (c < 32 || c >= 0xFFFF) + var rectIds = this.glyphRectIds[style] = new(); + + var fdt = this.fdts[(int)style.FamilyAndSize]; + if (fdt == null) continue; - var widthAdjustment = style.CalculateWidthAdjustment(fdt, glyph); - rectIds[c] = Tuple.Create( - io.Fonts.AddCustomRectFontGlyph( - font, - c, - glyph.BoundingWidth + widthAdjustment + 1, - glyph.BoundingHeight + 1, - glyph.AdvanceWidth, - new Vector2(0, glyph.CurrentOffsetY)), - glyph); + var font = io.Fonts.AddFontDefault(fontConfig); + this.fonts[style] = font; + foreach (var glyph in fdt.Glyphs) + { + var c = glyph.Char; + if (c < 32 || c >= 0xFFFF) + continue; + + var widthAdjustment = style.CalculateWidthAdjustment(fdt, glyph); + rectIds[c] = Tuple.Create( + io.Fonts.AddCustomRectFontGlyph( + font, + c, + glyph.BoundingWidth + widthAdjustment + 1, + glyph.BoundingHeight + 1, + glyph.AdvanceWidth, + new Vector2(0, glyph.CurrentOffsetY)), + glyph); + } } + + fontConfig.Destroy(); } } diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 6f5477463..9c7d5b151 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -49,6 +49,8 @@ namespace Dalamud.Interface.Internal { private const float DefaultFontSizePt = 12.0f; private const float DefaultFontSizePx = DefaultFontSizePt * 4.0f / 3.0f; + private const ushort Fallback1Codepoint = 0x3013; // Geta mark; FFXIV uses this to indicate that a glyph is missing. + private const ushort Fallback2Codepoint = '-'; // FFXIV uses dash if Geta mark is unavailable. private readonly string rtssPath; @@ -603,6 +605,11 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.Reset(); ioFonts.Clear(); + ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); + fontConfig.OversampleH = 1; + fontConfig.OversampleV = 1; + fontConfig.PixelSnapH = true; + var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); if (!File.Exists(fontPathJp)) ShowFontError(fontPathJp); @@ -610,7 +617,7 @@ namespace Dalamud.Interface.Internal // Default font { var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, null, japaneseRangeHandle.AddrOfPinnedObject()); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); japaneseRangeHandle.Free(); fontsToUnscale.Add(DefaultFont); } @@ -622,7 +629,7 @@ namespace Dalamud.Interface.Internal ShowFontError(fontPathIcon); var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, null, iconRangeHandle.AddrOfPinnedObject()); + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); iconRangeHandle.Free(); fontsToUnscale.Add(IconFont); } @@ -632,7 +639,7 @@ namespace Dalamud.Interface.Internal var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); if (!File.Exists(fontPathMono)) ShowFontError(fontPathMono); - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale); + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); fontsToUnscale.Add(MonoFont); } @@ -649,6 +656,9 @@ namespace Dalamud.Interface.Internal foreach (var (fontSize, requests) in extraFontRequests) { List> codepointRanges = new(); + codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); + codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); + foreach (var request in requests) { foreach (var range in request.CodepointRanges) @@ -674,7 +684,7 @@ namespace Dalamud.Interface.Internal flattenedRanges.Add(0); var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); - var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, null, rangeHandle.AddrOfPinnedObject()); + var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); rangeHandle.Free(); fontsToUnscale.Add(sizedFont); @@ -713,7 +723,12 @@ namespace Dalamud.Interface.Internal foreach (var font in fontsToUnscale) { - if (font.NativePtr == MonoFont.NativePtr || font.NativePtr == IconFont.NativePtr) + // Leave IconFont alone. + if (font.NativePtr == IconFont.NativePtr) + continue; + + // MonoFont will be filled later from DefaultFont. + if (font.NativePtr == MonoFont.NativePtr) continue; if (this.overwriteAllNotoGlyphsWithAxis) @@ -722,11 +737,17 @@ namespace Dalamud.Interface.Internal GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false, 0xE020, 0xE0DB); } + // Fill missing glyphs in DefaultFont from Axis + GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, DefaultFont, true, false); + // Fill missing glyphs in MonoFont from DefaultFont GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); foreach (var font in fontsToUnscale) + { + font.FallbackChar = Fallback1Codepoint; font.BuildLookupTable(); + } Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); this.AfterBuildFonts?.Invoke(); @@ -734,6 +755,7 @@ namespace Dalamud.Interface.Internal Log.Verbose("[FONT] Fonts built!"); + fontConfig.Destroy(); this.fontBuildSignal.Set(); this.FontsReady = true; From cbc0896fade01f7011dd14abf98e3f25a05ac1f7 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Mon, 7 Mar 2022 14:14:30 +0900 Subject: [PATCH 12/33] A bit more of sensible defaults (cherry picked from commit 14dfbf7bcfe17c581331c50254fa1ea5dc9c2c66) --- Dalamud/Interface/GameFonts/GameFontManager.cs | 1 - Dalamud/Interface/Internal/InterfaceManager.cs | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index 6b00be2e7..83178acc9 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -292,7 +292,6 @@ namespace Dalamud.Interface.GameFonts fontConfig.PixelSnapH = true; var io = ImGui.GetIO(); - io.Fonts.TexDesiredWidth = 4096; this.glyphRectIds.Clear(); this.fonts.Clear(); diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 9c7d5b151..e5c4cbdb4 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -604,6 +604,7 @@ namespace Dalamud.Interface.Internal this.fontBuildSignal.Reset(); ioFonts.Clear(); + ioFonts.TexDesiredWidth = 4096; ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); fontConfig.OversampleH = 1; @@ -658,6 +659,10 @@ namespace Dalamud.Interface.Internal List> codepointRanges = new(); codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); + + // ImGui default ellipsis characters + codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); + codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); foreach (var request in requests) { From 267a4b0047a88e178affa9a69c70d752fe827b30 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Mon, 7 Mar 2022 14:41:55 +0900 Subject: [PATCH 13/33] Always keep all AXIS fonts in memory (cherry picked from commit f5c75e4cd58b8bbed2e51fe22944b19043a6abaa) --- .../Interface/Internal/InterfaceManager.cs | 47 ++++++++++++------- .../Internal/Windows/TitleScreenMenuWindow.cs | 1 + 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index e5c4cbdb4..a58260c0a 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -64,7 +64,7 @@ namespace Dalamud.Interface.Internal private readonly SwapChainVtableResolver address; private RawDX11Scene? scene; - private GameFontHandle? axisFontHandle; + private GameFontHandle[] axisFontHandles; private bool overwriteAllNotoGlyphsWithAxis; // can't access imgui IO before first present call @@ -353,16 +353,17 @@ namespace Dalamud.Interface.Internal /// Requets handle. public SpecialGlyphRequest NewFontSizeRef(float size, List> ranges) { - var allContained = true; + var allContained = false; var fonts = ImGui.GetIO().Fonts.Fonts; ImFontPtr foundFont = null; unsafe { - for (int i = 0, i_ = fonts.Size; allContained && i < i_; i++) + for (int i = 0, i_ = fonts.Size; i < i_; i++) { if (!this.glyphRequests.Any(x => x.FontInternal.NativePtr == fonts[i].NativePtr)) continue; + allContained = true; foreach (var range in ranges) { if (!allContained) @@ -418,12 +419,16 @@ namespace Dalamud.Interface.Internal var configuration = Service.Get(); this.overwriteAllNotoGlyphsWithAxis = configuration.UseAxisFontsFromGame; - var currentFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, this.axisFontHandle?.Style.Size ?? 0f); - var expectedFamilyAndSize = GameFontStyle.GetRecommendedFamilyAndSize(GameFontFamily.Axis, DefaultFontSizePt * ImGui.GetIO().FontGlobalScale); - if (currentFamilyAndSize != expectedFamilyAndSize) + if (this.axisFontHandles == null) { - this.axisFontHandle?.Dispose(); - this.axisFontHandle = Service.Get().NewFontRef(new(expectedFamilyAndSize)); + this.axisFontHandles = new GameFontHandle[] + { + Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis96)), + Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis12)), + Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis14)), + Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis18)), + Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis36)), + }; } } @@ -659,7 +664,7 @@ namespace Dalamud.Interface.Internal List> codepointRanges = new(); codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); - + // ImGui default ellipsis characters codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); @@ -736,14 +741,24 @@ namespace Dalamud.Interface.Internal if (font.NativePtr == MonoFont.NativePtr) continue; - if (this.overwriteAllNotoGlyphsWithAxis) - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false); - else - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, font, false, false, 0xE020, 0xE0DB); - } + var axisFont = this.axisFontHandles[^1]; + for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) + { + if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) + axisFont = this.axisFontHandles[i]; + else + break; + } - // Fill missing glyphs in DefaultFont from Axis - GameFontManager.CopyGlyphsAcrossFonts(this.axisFontHandle?.ImFont, DefaultFont, true, false); + if (this.overwriteAllNotoGlyphsWithAxis) + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); + else + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); + + // Fill missing glyphs in DefaultFont from Axis + if (font.NativePtr == DefaultFont.NativePtr) + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); + } // Fill missing glyphs in MonoFont from DefaultFont GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index 7ea7b64dd..40bb29672 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -245,6 +245,7 @@ namespace Dalamud.Interface.Internal.Windows this.specialGlyphRequests[entry.Name] = fontHandle = Service.Get().NewFontSizeRef(TargetFontSizePx, entry.Name); ImGui.PushFont(fontHandle.Font); + ImGui.SetWindowFontScale(TargetFontSizePx / fontHandle.Size); var scale = ImGui.GetIO().FontGlobalScale; From 0cf9b80172c3514bd48392c07c9777ddbc0064d6 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Wed, 9 Mar 2022 02:54:05 +0900 Subject: [PATCH 14/33] Keep glyph range handles alive until font is built (cherry picked from commit 5baccced15055ee21fd5b848ec386e3907d49c69) --- .../Interface/Internal/InterfaceManager.cs | 299 +++++++++--------- 1 file changed, 157 insertions(+), 142 deletions(-) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index a58260c0a..8872fc45f 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -611,174 +611,189 @@ namespace Dalamud.Interface.Internal ioFonts.Clear(); ioFonts.TexDesiredWidth = 4096; - ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); - fontConfig.OversampleH = 1; - fontConfig.OversampleV = 1; - fontConfig.PixelSnapH = true; + ImFontConfigPtr fontConfig = null; + List garbageList = new(); - var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); - if (!File.Exists(fontPathJp)) - ShowFontError(fontPathJp); - - // Default font + try { - var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); - japaneseRangeHandle.Free(); - fontsToUnscale.Add(DefaultFont); - } + fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); + fontConfig.OversampleH = 1; + fontConfig.OversampleV = 1; + fontConfig.PixelSnapH = true; - // FontAwesome icon font - { - var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); - if (!File.Exists(fontPathIcon)) - ShowFontError(fontPathIcon); + var fontPathJp = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "NotoSansCJKjp-Medium.otf"); + if (!File.Exists(fontPathJp)) + ShowFontError(fontPathJp); - var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); - iconRangeHandle.Free(); - fontsToUnscale.Add(IconFont); - } - - // Monospace font - { - var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); - if (!File.Exists(fontPathMono)) - ShowFontError(fontPathMono); - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); - fontsToUnscale.Add(MonoFont); - } - - // Default font but in requested size for requested glyphs - { - Dictionary> extraFontRequests = new(); - foreach (var extraFontRequest in this.glyphRequests) + // Default font { - if (!extraFontRequests.ContainsKey(extraFontRequest.Size)) - extraFontRequests[extraFontRequest.Size] = new(); - extraFontRequests[extraFontRequest.Size].Add(extraFontRequest); + var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); + garbageList.Add(japaneseRangeHandle); + + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); + fontsToUnscale.Add(DefaultFont); } - foreach (var (fontSize, requests) in extraFontRequests) + // FontAwesome icon font { - List> codepointRanges = new(); - codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); - codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); + var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); + if (!File.Exists(fontPathIcon)) + ShowFontError(fontPathIcon); - // ImGui default ellipsis characters - codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); - codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); + var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); + garbageList.Add(iconRangeHandle); - foreach (var request in requests) + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); + fontsToUnscale.Add(IconFont); + } + + // Monospace font + { + var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); + if (!File.Exists(fontPathMono)) + ShowFontError(fontPathMono); + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); + fontsToUnscale.Add(MonoFont); + } + + // Default font but in requested size for requested glyphs + { + Dictionary> extraFontRequests = new(); + foreach (var extraFontRequest in this.glyphRequests) { - foreach (var range in request.CodepointRanges) - codepointRanges.Add(range); + if (!extraFontRequests.ContainsKey(extraFontRequest.Size)) + extraFontRequests[extraFontRequest.Size] = new(); + extraFontRequests[extraFontRequest.Size].Add(extraFontRequest); } - codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1))); - - List flattenedRanges = new(); - foreach (var range in codepointRanges) + foreach (var (fontSize, requests) in extraFontRequests) { - if (flattenedRanges.Any() && flattenedRanges[^1] >= range.Item1 - 1) + List> codepointRanges = new(); + codepointRanges.Add(Tuple.Create(Fallback1Codepoint, Fallback1Codepoint)); + codepointRanges.Add(Tuple.Create(Fallback2Codepoint, Fallback2Codepoint)); + + // ImGui default ellipsis characters + codepointRanges.Add(Tuple.Create(0x2026, 0x2026)); + codepointRanges.Add(Tuple.Create(0x0085, 0x0085)); + + foreach (var request in requests) { - flattenedRanges[^1] = Math.Max(flattenedRanges[^1], range.Item2); + foreach (var range in request.CodepointRanges) + codepointRanges.Add(range); } + + codepointRanges.Sort((x, y) => (x.Item1 == y.Item1 ? (x.Item2 < y.Item2 ? -1 : (x.Item2 == y.Item2 ? 0 : 1)) : (x.Item1 < y.Item1 ? -1 : 1))); + + List flattenedRanges = new(); + foreach (var range in codepointRanges) + { + if (flattenedRanges.Any() && flattenedRanges[^1] >= range.Item1 - 1) + { + flattenedRanges[^1] = Math.Max(flattenedRanges[^1], range.Item2); + } + else + { + flattenedRanges.Add(range.Item1); + flattenedRanges.Add(range.Item2); + } + } + + flattenedRanges.Add(0); + + var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); + garbageList.Add(rangeHandle); + + var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); + fontsToUnscale.Add(sizedFont); + + foreach (var request in requests) + request.FontInternal = sizedFont; + } + } + + var gameFontManager = Service.Get(); + gameFontManager.BuildFonts(); + + Log.Verbose("[FONT] Invoke OnBuildFonts"); + this.BuildFonts?.Invoke(); + Log.Verbose("[FONT] OnBuildFonts OK!"); + + for (var i = 0; i < ImGui.GetIO().Fonts.Fonts.Size; i++) + { + Log.Verbose("{0} - {1}", i, ImGui.GetIO().Fonts.Fonts[i].GetDebugName()); + } + + ioFonts.Build(); + + if (Math.Abs(fontGamma - 1.0f) >= 0.001) + { + // Gamma correction (stbtt/FreeType would output in linear space whereas most real world usages will apply 1.4 or 1.8 gamma; Windows/XIV prebaked uses 1.4) + ioFonts.GetTexDataAsRGBA32(out byte* texPixels, out var texWidth, out var texHeight); + for (int i = 3, i_ = texWidth * texHeight * 4; i < i_; i += 4) + texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); + } + + foreach (var font in fontsToUnscale) + GameFontManager.UnscaleFont(font, fontScale, false); + + gameFontManager.AfterBuildFonts(); + + foreach (var font in fontsToUnscale) + { + // Leave IconFont alone. + if (font.NativePtr == IconFont.NativePtr) + continue; + + // MonoFont will be filled later from DefaultFont. + if (font.NativePtr == MonoFont.NativePtr) + continue; + + var axisFont = this.axisFontHandles[^1]; + for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) + { + if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) + axisFont = this.axisFontHandles[i]; else - { - flattenedRanges.Add(range.Item1); - flattenedRanges.Add(range.Item2); - } + break; } - flattenedRanges.Add(0); - - var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); - var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); - rangeHandle.Free(); - - fontsToUnscale.Add(sizedFont); - - foreach (var request in requests) - request.FontInternal = sizedFont; - } - } - - var gameFontManager = Service.Get(); - gameFontManager.BuildFonts(); - - Log.Verbose("[FONT] Invoke OnBuildFonts"); - this.BuildFonts?.Invoke(); - Log.Verbose("[FONT] OnBuildFonts OK!"); - - for (var i = 0; i < ImGui.GetIO().Fonts.Fonts.Size; i++) - { - Log.Verbose("{0} - {1}", i, ImGui.GetIO().Fonts.Fonts[i].GetDebugName()); - } - - ioFonts.Build(); - - if (Math.Abs(fontGamma - 1.0f) >= 0.001) - { - // Gamma correction (stbtt/FreeType would output in linear space whereas most real world usages will apply 1.4 or 1.8 gamma; Windows/XIV prebaked uses 1.4) - ioFonts.GetTexDataAsRGBA32(out byte* texPixels, out var texWidth, out var texHeight); - for (int i = 3, i_ = texWidth * texHeight * 4; i < i_; i += 4) - texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); - } - - foreach (var font in fontsToUnscale) - GameFontManager.UnscaleFont(font, fontScale, false); - - gameFontManager.AfterBuildFonts(); - - foreach (var font in fontsToUnscale) - { - // Leave IconFont alone. - if (font.NativePtr == IconFont.NativePtr) - continue; - - // MonoFont will be filled later from DefaultFont. - if (font.NativePtr == MonoFont.NativePtr) - continue; - - var axisFont = this.axisFontHandles[^1]; - for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) - { - if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) - axisFont = this.axisFontHandles[i]; + if (this.overwriteAllNotoGlyphsWithAxis) + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); else - break; + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); + + // Fill missing glyphs in DefaultFont from Axis + if (font.NativePtr == DefaultFont.NativePtr) + GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); } - if (this.overwriteAllNotoGlyphsWithAxis) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); - else - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); + // Fill missing glyphs in MonoFont from DefaultFont + GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); - // Fill missing glyphs in DefaultFont from Axis - if (font.NativePtr == DefaultFont.NativePtr) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); + foreach (var font in fontsToUnscale) + { + font.FallbackChar = Fallback1Codepoint; + font.BuildLookupTable(); + } + + Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); + this.AfterBuildFonts?.Invoke(); + Log.Verbose("[FONT] OnAfterBuildFonts OK!"); + + Log.Verbose("[FONT] Fonts built!"); + + this.fontBuildSignal.Set(); + + this.FontsReady = true; } - - // Fill missing glyphs in MonoFont from DefaultFont - GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false); - - foreach (var font in fontsToUnscale) + finally { - font.FallbackChar = Fallback1Codepoint; - font.BuildLookupTable(); + if (fontConfig.NativePtr != null) + fontConfig.Destroy(); + + foreach (var garbage in garbageList) + garbage.Free(); } - - Log.Verbose("[FONT] Invoke OnAfterBuildFonts"); - this.AfterBuildFonts?.Invoke(); - Log.Verbose("[FONT] OnAfterBuildFonts OK!"); - - Log.Verbose("[FONT] Fonts built!"); - - fontConfig.Destroy(); - this.fontBuildSignal.Set(); - - this.FontsReady = true; } private void Disable() From 6da762dc3c1ce6eab403d82fd0b0316ba03c918c Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Thu, 31 Mar 2022 23:29:37 +0900 Subject: [PATCH 15/33] Correct return types on boot --- lib/CoreCLR/CoreCLR.cpp | 4 ++-- lib/CoreCLR/CoreCLR.h | 4 ++-- lib/CoreCLR/boot.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/CoreCLR/CoreCLR.cpp b/lib/CoreCLR/CoreCLR.cpp index 6f4d337b8..265f1869e 100644 --- a/lib/CoreCLR/CoreCLR.cpp +++ b/lib/CoreCLR/CoreCLR.cpp @@ -37,12 +37,12 @@ int CoreCLR::load_hostfxr(const struct get_hostfxr_parameters* parameters) && m_hostfxr_close_fptr ? 0 : -1; } -bool CoreCLR::load_runtime(const std::wstring& runtime_config_path) +int CoreCLR::load_runtime(const std::wstring& runtime_config_path) { return CoreCLR::load_runtime(runtime_config_path, nullptr); } -bool CoreCLR::load_runtime(const std::wstring& runtime_config_path, const struct hostfxr_initialize_parameters* parameters) +int CoreCLR::load_runtime(const std::wstring& runtime_config_path, const struct hostfxr_initialize_parameters* parameters) { int result; diff --git a/lib/CoreCLR/CoreCLR.h b/lib/CoreCLR/CoreCLR.h index 235bf9923..71c62d90e 100644 --- a/lib/CoreCLR/CoreCLR.h +++ b/lib/CoreCLR/CoreCLR.h @@ -12,8 +12,8 @@ class CoreCLR { int load_hostfxr(); int load_hostfxr(const get_hostfxr_parameters* parameters); - bool load_runtime(const std::wstring& runtime_config_path); - bool load_runtime( + int load_runtime(const std::wstring& runtime_config_path); + int load_runtime( const std::wstring& runtime_config_path, const struct hostfxr_initialize_parameters* parameters); diff --git a/lib/CoreCLR/boot.cpp b/lib/CoreCLR/boot.cpp index 2fde7e221..63636e709 100644 --- a/lib/CoreCLR/boot.cpp +++ b/lib/CoreCLR/boot.cpp @@ -90,7 +90,7 @@ int InitializeClrAndGetEntryPoint( printf("Loading hostfxr... "); if ((result = g_clr->load_hostfxr(&init_parameters)) != 0) { - printf("\nError: Failed to load the `hostfxr` library (err=%d)\n", result); + printf("\nError: Failed to load the `hostfxr` library (err=0x%08x)\n", result); return result; } printf("Done!\n"); From f14bf171e48c4267678de505e82dfa51530848f9 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Fri, 1 Apr 2022 01:18:28 +0900 Subject: [PATCH 16/33] Add attempts to reduce font atlas size --- .../Internal/DalamudConfiguration.cs | 7 +- .../Interface/GameFonts/GameFontManager.cs | 13 +- .../Interface/Internal/InterfaceManager.cs | 179 ++++++++++++------ .../Internal/Windows/SettingsWindow.cs | 20 +- 4 files changed, 157 insertions(+), 62 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index b2a11d774..2ee31c4f7 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -141,7 +141,12 @@ namespace Dalamud.Configuration.Internal /// * ...TTF fonts loaded with stb or FreeType are in linear space. /// * ...the game's prebaked AXIS fonts are in gamma space with gamma value of 1.4. /// - public float FontGamma { get; set; } = 1.0f; + public float FontGamma { get; set; } = 1.4f; + + /// + /// Gets or sets a value indicating whether to allow big font atlas. + /// + public bool AllowBigFontAtlas { get; set; } = false; /// /// Gets or sets a value indicating whether or not plugin UI should be hidden. diff --git a/Dalamud/Interface/GameFonts/GameFontManager.cs b/Dalamud/Interface/GameFonts/GameFontManager.cs index 83178acc9..adbe6dfa4 100644 --- a/Dalamud/Interface/GameFonts/GameFontManager.cs +++ b/Dalamud/Interface/GameFonts/GameFontManager.cs @@ -141,9 +141,9 @@ namespace Dalamud.Interface.GameFonts target.Value!.ConfigData, (ushort)glyph->Codepoint, glyph->X0 * scale, - glyph->Y0 * scale, + ((glyph->Y0 - source.Value!.Ascent) * scale) + target.Value!.Ascent, glyph->X1 * scale, - glyph->Y1 * scale, + ((glyph->Y1 - source.Value!.Ascent) * scale) + target.Value!.Ascent, glyph->U0, glyph->V0, glyph->U1, @@ -153,9 +153,9 @@ namespace Dalamud.Interface.GameFonts else if (!missingOnly) { prevGlyphPtr->X0 = glyph->X0 * scale; - prevGlyphPtr->Y0 = glyph->Y0 * scale; + prevGlyphPtr->Y0 = ((glyph->Y0 - source.Value!.Ascent) * scale) + target.Value!.Ascent; prevGlyphPtr->X1 = glyph->X1 * scale; - prevGlyphPtr->Y1 = glyph->Y1 * scale; + prevGlyphPtr->Y1 = ((glyph->Y1 - source.Value!.Ascent) * scale) + target.Value!.Ascent; prevGlyphPtr->U0 = glyph->U0; prevGlyphPtr->V0 = glyph->V0; prevGlyphPtr->U1 = glyph->U1; @@ -343,7 +343,7 @@ namespace Dalamud.Interface.GameFonts { var fdt = this.fdts[(int)style.FamilyAndSize]; var fontPtr = font.NativePtr; - fontPtr->ConfigData->SizePixels = fontPtr->FontSize = fdt.FontHeader.LineHeight; + fontPtr->ConfigData->SizePixels = fontPtr->FontSize = fdt.FontHeader.Size * 4 / 3; fontPtr->Ascent = fdt.FontHeader.Ascent; fontPtr->Descent = fdt.FontHeader.Descent; fontPtr->EllipsisChar = '…'; @@ -444,6 +444,9 @@ namespace Dalamud.Interface.GameFonts { lock (this.syncRoot) { + if (!this.fontUseCounter.ContainsKey(style)) + return; + if ((this.fontUseCounter[style] -= 1) == 0) this.fontUseCounter.Remove(style); } diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 8872fc45f..50304e89c 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -55,6 +55,7 @@ namespace Dalamud.Interface.Internal private readonly string rtssPath; private readonly HashSet glyphRequests = new(); + private readonly List axisFontHandles = new(); private readonly Hook presentHook; private readonly Hook resizeBuffersHook; @@ -64,9 +65,6 @@ namespace Dalamud.Interface.Internal private readonly SwapChainVtableResolver address; private RawDX11Scene? scene; - private GameFontHandle[] axisFontHandles; - private bool overwriteAllNotoGlyphsWithAxis; - // can't access imgui IO before first present call private bool lastWantCapture = false; private bool isRebuildingFonts = false; @@ -197,6 +195,16 @@ namespace Dalamud.Interface.Internal /// public bool IsReady => this.scene != null; + /// + /// Gets or sets a value indicating whether to override configuration for UseAxis. + /// + public bool? UseAxisOverride { get; set; } = null; + + /// + /// Gets a value indicating whether to use AXIS fonts. + /// + public bool UseAxis => this.UseAxisOverride ?? Service.Get().UseAxisFontsFromGame; + /// /// Gets or sets the overrided font gamma value, instead of using the value from configuration. /// @@ -207,6 +215,16 @@ namespace Dalamud.Interface.Internal /// public float FontGamma => Math.Max(0.1f, this.FontGammaOverride.GetValueOrDefault(Service.Get().FontGamma)); + /// + /// Gets or sets a value indicating whether to override configuration for AllowBigFontAtlas. + /// + public bool? AllowBigFontAtlasOverride { get; set; } = null; + + /// + /// Gets a value indicating whether to allow big font atlas. + /// + public bool AllowBigFontAtlas => this.AllowBigFontAtlasOverride ?? Service.Get().AllowBigFontAtlas; + /// /// Enable this module. /// @@ -330,8 +348,6 @@ namespace Dalamud.Interface.Internal if (!this.isRebuildingFonts) { Log.Verbose("[FONT] RebuildFonts() trigger"); - this.SetAxisFonts(); - this.isRebuildingFonts = true; this.scene.OnNewRenderFrame += this.RebuildFontsInternal; } @@ -414,24 +430,6 @@ namespace Dalamud.Interface.Internal Util.Fatal($"One or more files required by XIVLauncher were not found.\nPlease restart and report this error if it occurs again.\n\n{path}", "Error"); } - private void SetAxisFonts() - { - var configuration = Service.Get(); - this.overwriteAllNotoGlyphsWithAxis = configuration.UseAxisFontsFromGame; - - if (this.axisFontHandles == null) - { - this.axisFontHandles = new GameFontHandle[] - { - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis96)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis12)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis14)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis18)), - Service.Get().NewFontRef(new(GameFontFamilyAndSize.Axis36)), - }; - } - } - /* * NOTE(goat): When hooking ReShade DXGISwapChain::runtime_present, this is missing the syncInterval arg. * Seems to work fine regardless, I guess, so whatever. @@ -493,8 +491,6 @@ namespace Dalamud.Interface.Internal this.scene.OnBuildUI += this.Display; this.scene.OnNewInputFrame += this.OnNewInputFrame; - this.SetAxisFonts(); - this.SetupFonts(); StyleModel.TransferOldModels(); @@ -600,22 +596,40 @@ namespace Dalamud.Interface.Internal private unsafe void SetupFonts() { + var gameFontManager = Service.Get(); var dalamud = Service.Get(); var io = ImGui.GetIO(); var ioFonts = io.Fonts; - var fontScale = io.FontGlobalScale; + var fontLoadScale = this.AllowBigFontAtlas ? io.FontGlobalScale : 1; var fontGamma = this.FontGamma; List fontsToUnscale = new(); + List fontsToOverwriteFromAxis = new(); + List fontsToReassignSizes = new(); this.fontBuildSignal.Reset(); ioFonts.Clear(); - ioFonts.TexDesiredWidth = 4096; + ioFonts.TexDesiredWidth = this.AllowBigFontAtlas ? 4096 : 2048; + + Log.Verbose("[FONT] SetupFonts - 1"); + + foreach (var v in this.axisFontHandles) + { + if (v != null) + v.Dispose(); + } + + this.axisFontHandles.Clear(); + + Log.Verbose("[FONT] SetupFonts - 2"); ImFontConfigPtr fontConfig = null; List garbageList = new(); try { + var dummyRangeHandle = GCHandle.Alloc(new ushort[] { '0', '0', 0 }, GCHandleType.Pinned); + garbageList.Add(dummyRangeHandle); + fontConfig = ImGuiNative.ImFontConfig_ImFontConfig(); fontConfig.OversampleH = 1; fontConfig.OversampleV = 1; @@ -626,15 +640,31 @@ namespace Dalamud.Interface.Internal ShowFontError(fontPathJp); // Default font + Log.Verbose("[FONT] SetupFonts - Default font"); + this.axisFontHandles.Add(gameFontManager.NewFontRef(this.AllowBigFontAtlas ? new(GameFontFamily.Axis, DefaultFontSizePt * fontLoadScale) : new(GameFontFamilyAndSize.Axis12))); + if (this.UseAxis) + { + fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); + fontConfig.SizePixels = DefaultFontSizePx * fontLoadScale; + DefaultFont = ioFonts.AddFontDefault(fontConfig); + fontsToUnscale.Add(DefaultFont); + fontsToOverwriteFromAxis.Add(true); + fontsToReassignSizes.Add(null); + } + else { var japaneseRangeHandle = GCHandle.Alloc(GlyphRangesJapanese.GlyphRanges, GCHandleType.Pinned); garbageList.Add(japaneseRangeHandle); - DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontScale, fontConfig, japaneseRangeHandle.AddrOfPinnedObject()); + fontConfig.GlyphRanges = japaneseRangeHandle.AddrOfPinnedObject(); + DefaultFont = ioFonts.AddFontFromFileTTF(fontPathJp, (DefaultFontSizePx + 1) * fontLoadScale, fontConfig); fontsToUnscale.Add(DefaultFont); + fontsToOverwriteFromAxis.Add(false); + fontsToReassignSizes.Add(null); } // FontAwesome icon font + Log.Verbose("[FONT] SetupFonts - FontAwesome icon font"); { var fontPathIcon = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "FontAwesome5FreeSolid.otf"); if (!File.Exists(fontPathIcon)) @@ -643,20 +673,31 @@ namespace Dalamud.Interface.Internal var iconRangeHandle = GCHandle.Alloc(new ushort[] { 0xE000, 0xF8FF, 0, }, GCHandleType.Pinned); garbageList.Add(iconRangeHandle); - IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontScale, fontConfig, iconRangeHandle.AddrOfPinnedObject()); + fontConfig.GlyphRanges = iconRangeHandle.AddrOfPinnedObject(); + IconFont = ioFonts.AddFontFromFileTTF(fontPathIcon, DefaultFontSizePx * fontLoadScale, fontConfig); fontsToUnscale.Add(IconFont); + this.axisFontHandles.Add(null); + fontsToOverwriteFromAxis.Add(false); + fontsToReassignSizes.Add(null); } // Monospace font + Log.Verbose("[FONT] SetupFonts - Monospace font"); { var fontPathMono = Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "Inconsolata-Regular.ttf"); if (!File.Exists(fontPathMono)) ShowFontError(fontPathMono); - MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontScale, fontConfig); + + fontConfig.GlyphRanges = IntPtr.Zero; + MonoFont = ioFonts.AddFontFromFileTTF(fontPathMono, DefaultFontSizePx * fontLoadScale, fontConfig); fontsToUnscale.Add(MonoFont); + this.axisFontHandles.Add(null); + fontsToOverwriteFromAxis.Add(false); + fontsToReassignSizes.Add(null); } // Default font but in requested size for requested glyphs + Log.Verbose("[FONT] SetupFonts - Default font but in requested size for requested glyphs"); { Dictionary> extraFontRequests = new(); foreach (var extraFontRequest in this.glyphRequests) @@ -700,18 +741,30 @@ namespace Dalamud.Interface.Internal flattenedRanges.Add(0); - var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); - garbageList.Add(rangeHandle); + ImFontPtr sizedFont; + this.axisFontHandles.Add(gameFontManager.NewFontRef(this.AllowBigFontAtlas ? new(GameFontFamily.Axis, fontSize * 3 / 4 * fontLoadScale) : new(GameFontFamilyAndSize.Axis12))); + if (this.UseAxis) + { + fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); + fontConfig.SizePixels = (this.AllowBigFontAtlas ? fontSize : DefaultFontSizePx) * fontLoadScale; + sizedFont = ioFonts.AddFontDefault(fontConfig); + } + else + { + var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); + garbageList.Add(rangeHandle); + sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, (this.AllowBigFontAtlas ? fontSize : DefaultFontSizePx) * fontLoadScale, fontConfig, rangeHandle.AddrOfPinnedObject()); + } - var sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, fontSize * fontScale, fontConfig, rangeHandle.AddrOfPinnedObject()); fontsToUnscale.Add(sizedFont); + fontsToOverwriteFromAxis.Add(true); + fontsToReassignSizes.Add(this.AllowBigFontAtlas ? null : fontSize); foreach (var request in requests) request.FontInternal = sizedFont; } } - var gameFontManager = Service.Get(); gameFontManager.BuildFonts(); Log.Verbose("[FONT] Invoke OnBuildFonts"); @@ -734,37 +787,53 @@ namespace Dalamud.Interface.Internal } foreach (var font in fontsToUnscale) - GameFontManager.UnscaleFont(font, fontScale, false); + GameFontManager.UnscaleFont(font, fontLoadScale, false); gameFontManager.AfterBuildFonts(); - foreach (var font in fontsToUnscale) + for (var i = 0; i < fontsToUnscale.Count; i++) { - // Leave IconFont alone. - if (font.NativePtr == IconFont.NativePtr) + var font = fontsToUnscale[i]; + var fontPtr = font.NativePtr; + var correspondingAxis = this.axisFontHandles[i]; + var overwrite = fontsToOverwriteFromAxis[i]; + var overwriteSize = fontsToReassignSizes[i]; + + if (correspondingAxis == null) continue; - // MonoFont will be filled later from DefaultFont. - if (font.NativePtr == MonoFont.NativePtr) - continue; - - var axisFont = this.axisFontHandles[^1]; - for (var i = this.axisFontHandles.Length - 2; i >= 0; i--) + if (overwrite) { - if (this.axisFontHandles[i].Style.Size >= (font.FontSize - 1) * fontScale * 3 / 4) - axisFont = this.axisFontHandles[i]; - else - break; + var srcPtr = correspondingAxis.ImFont.NativePtr; + var scale = fontPtr->ConfigData->SizePixels / srcPtr->ConfigData->SizePixels / fontLoadScale; + Log.Verbose("[FONT] Font {0}: scale {1}", i, scale); + fontPtr->FontSize = srcPtr->FontSize * scale; + fontPtr->Ascent = srcPtr->Ascent * scale; + fontPtr->Descent = srcPtr->Descent * scale; + fontPtr->FallbackChar = srcPtr->FallbackChar; + fontPtr->EllipsisChar = srcPtr->EllipsisChar; } - if (this.overwriteAllNotoGlyphsWithAxis) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false); - else - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, font, false, false, 0xE020, 0xE0DB); + if (overwriteSize != null) + { + var scale = overwriteSize.Value / fontPtr->ConfigData->SizePixels; + fontPtr->FontSize *= scale; + fontPtr->Ascent *= scale; + fontPtr->Descent *= scale; + } - // Fill missing glyphs in DefaultFont from Axis - if (font.NativePtr == DefaultFont.NativePtr) - GameFontManager.CopyGlyphsAcrossFonts(axisFont.ImFont, DefaultFont, true, false); + GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, !overwrite, false); + + if (!this.UseAxis && fontPtr == DefaultFont.NativePtr) + { + fontPtr->FontSize -= 1; + GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, true, false, 0xE020, 0xE0DB); + fontPtr->FontSize += 1; + } + else + { + GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, true, false, 0xE020, 0xE0DB); + } } // Fill missing glyphs in MonoFont from DefaultFont diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 9ff94f42e..493725d92 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -39,6 +39,7 @@ namespace Dalamud.Interface.Internal.Windows private float globalUiScale; private bool doUseAxisFontsFromGame; + private bool doAllowBigFontAtlas; private float fontGamma; private bool doToggleUiHide; private bool doToggleUiHideDuringCutscenes; @@ -96,6 +97,7 @@ namespace Dalamud.Interface.Internal.Windows this.globalUiScale = configuration.GlobalUiScale; this.fontGamma = configuration.FontGamma; this.doUseAxisFontsFromGame = configuration.UseAxisFontsFromGame; + this.doAllowBigFontAtlas = configuration.AllowBigFontAtlas; this.doToggleUiHide = configuration.ToggleUiHide; this.doToggleUiHideDuringCutscenes = configuration.ToggleUiHideDuringCutscenes; this.doToggleUiHideDuringGpose = configuration.ToggleUiHideDuringGpose; @@ -188,6 +190,8 @@ namespace Dalamud.Interface.Internal.Windows ImGui.GetIO().FontGlobalScale = configuration.GlobalUiScale; interfaceManager.FontGammaOverride = null; + interfaceManager.AllowBigFontAtlasOverride = null; + interfaceManager.UseAxisOverride = null; this.thirdRepoList = configuration.ThirdRepoList.Select(x => x.Clone()).ToList(); this.devPluginLocations = configuration.DevPluginLoadLocations.Select(x => x.Clone()).ToList(); @@ -325,9 +329,22 @@ namespace Dalamud.Interface.Internal.Windows ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiHideOptOutNote", "Plugins may independently opt out of the settings below.")); - ImGui.Checkbox(Loc.Localize("DalamudSettingToggleAxisFonts", "Use AXIS fonts as default Dalamud font"), ref this.doUseAxisFontsFromGame); + if (ImGui.Checkbox(Loc.Localize("DalamudSettingToggleAxisFonts", "Use AXIS fonts as default Dalamud font"), ref this.doUseAxisFontsFromGame)) + { + interfaceManager.UseAxisOverride = this.doUseAxisFontsFromGame; + interfaceManager.RebuildFonts(); + } + ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiAxisFontsHint", "Use AXIS fonts (the game's main UI fonts) as default Dalamud font.")); + if (ImGui.Checkbox(Loc.Localize("DalamudSettingAllowBigFontAtlas", "Allow big font atlas"), ref this.doAllowBigFontAtlas)) + { + interfaceManager.AllowBigFontAtlasOverride = this.doAllowBigFontAtlas; + interfaceManager.RebuildFonts(); + } + + ImGui.TextColored(ImGuiColors.DalamudGrey, string.Format(Loc.Localize("DalamudSettingAllowBigFontAtlas", "Displays text crisply, but may crash if your GPU does not support it.\nCurrent size: {0}px * {1}px"), ImGui.GetIO().Fonts.TexWidth, ImGui.GetIO().Fonts.TexHeight)); + ImGui.Checkbox(Loc.Localize("DalamudSettingToggleUiHide", "Hide plugin UI when the game UI is toggled off"), ref this.doToggleUiHide); ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingToggleUiHideHint", "Hide any open windows by plugins when toggling the game overlay.")); @@ -856,6 +873,7 @@ namespace Dalamud.Interface.Internal.Windows configuration.Fools22 = this.doFools22; configuration.UseAxisFontsFromGame = this.doUseAxisFontsFromGame; + configuration.AllowBigFontAtlas = this.doAllowBigFontAtlas; configuration.FontGamma = this.fontGamma; // This is applied every frame in InterfaceManager::CheckViewportState() From 216d205542d70eee7f9d49f5e03db5d13770b857 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Fri, 1 Apr 2022 01:52:58 +0900 Subject: [PATCH 17/33] Fix scaling problems --- .../Interface/Internal/InterfaceManager.cs | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 50304e89c..c19a32601 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -748,18 +748,20 @@ namespace Dalamud.Interface.Internal fontConfig.GlyphRanges = dummyRangeHandle.AddrOfPinnedObject(); fontConfig.SizePixels = (this.AllowBigFontAtlas ? fontSize : DefaultFontSizePx) * fontLoadScale; sizedFont = ioFonts.AddFontDefault(fontConfig); + fontsToUnscale.Add(sizedFont); + fontsToOverwriteFromAxis.Add(true); + fontsToReassignSizes.Add(this.AllowBigFontAtlas ? null : fontSize); } else { var rangeHandle = GCHandle.Alloc(flattenedRanges.ToArray(), GCHandleType.Pinned); garbageList.Add(rangeHandle); - sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, (this.AllowBigFontAtlas ? fontSize : DefaultFontSizePx) * fontLoadScale, fontConfig, rangeHandle.AddrOfPinnedObject()); + sizedFont = ioFonts.AddFontFromFileTTF(fontPathJp, (this.AllowBigFontAtlas ? fontSize : DefaultFontSizePx + 1) * fontLoadScale, fontConfig, rangeHandle.AddrOfPinnedObject()); + fontsToUnscale.Add(sizedFont); + fontsToOverwriteFromAxis.Add(false); + fontsToReassignSizes.Add(this.AllowBigFontAtlas ? null : fontSize); } - fontsToUnscale.Add(sizedFont); - fontsToOverwriteFromAxis.Add(true); - fontsToReassignSizes.Add(this.AllowBigFontAtlas ? null : fontSize); - foreach (var request in requests) request.FontInternal = sizedFont; } @@ -786,9 +788,6 @@ namespace Dalamud.Interface.Internal texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f); } - foreach (var font in fontsToUnscale) - GameFontManager.UnscaleFont(font, fontLoadScale, false); - gameFontManager.AfterBuildFonts(); for (var i = 0; i < fontsToUnscale.Count; i++) @@ -799,30 +798,34 @@ namespace Dalamud.Interface.Internal var overwrite = fontsToOverwriteFromAxis[i]; var overwriteSize = fontsToReassignSizes[i]; + GameFontManager.UnscaleFont(font, fontLoadScale, false); + if (correspondingAxis == null) continue; + var scale = 1f; + if (overwrite) { var srcPtr = correspondingAxis.ImFont.NativePtr; - var scale = fontPtr->ConfigData->SizePixels / srcPtr->ConfigData->SizePixels / fontLoadScale; - Log.Verbose("[FONT] Font {0}: scale {1}", i, scale); + scale = fontPtr->ConfigData->SizePixels / srcPtr->ConfigData->SizePixels / fontLoadScale; fontPtr->FontSize = srcPtr->FontSize * scale; fontPtr->Ascent = srcPtr->Ascent * scale; fontPtr->Descent = srcPtr->Descent * scale; fontPtr->FallbackChar = srcPtr->FallbackChar; fontPtr->EllipsisChar = srcPtr->EllipsisChar; + GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, false, false); + + scale = 1f; } if (overwriteSize != null) - { - var scale = overwriteSize.Value / fontPtr->ConfigData->SizePixels; - fontPtr->FontSize *= scale; - fontPtr->Ascent *= scale; - fontPtr->Descent *= scale; - } + scale *= overwriteSize.Value / fontPtr->ConfigData->SizePixels; - GameFontManager.CopyGlyphsAcrossFonts(correspondingAxis.ImFont, font, !overwrite, false); + if (scale != 1f) + GameFontManager.UnscaleFont(font, 1 / scale, false); + + Log.Verbose("[FONT] Font {0}: result size {1}", i, fontPtr->FontSize); if (!this.UseAxis && fontPtr == DefaultFont.NativePtr) { From a33aef5c45441920ec62e614c9df3d04cdd1b23e Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 20:24:23 +0200 Subject: [PATCH 18/33] feat: add timezone check --- Dalamud/Configuration/Internal/DalamudConfiguration.cs | 2 +- Dalamud/Dalamud.cs | 7 +++++++ Dalamud/Fools22.cs | 7 +------ Dalamud/Interface/Internal/Windows/SettingsWindow.cs | 6 +++--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index b2a11d774..e33df668e 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -290,7 +290,7 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; - public bool Fools22 { get; set; } = true; + public bool? Fools22New { get; set; } = true; /// /// Load a configuration from the provided path. diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 691a541ef..b07bf2594 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -275,6 +275,13 @@ namespace Dalamud try { Log.Information("Loading fools22"); + var timeZone = TimeZoneInfo.Local; + var offset = timeZone.GetUtcOffset(DateTime.UtcNow); + + var config = Service.Get(); + config.Fools22New = offset.Hours < 1; + config.Save(); + this.fools22 = new Fools22(); } catch (Exception ex) diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index 2de81bc1a..380fde208 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -323,17 +323,12 @@ public class Fools22 : IDisposable { var config = Service.Get(); - if (!config.Fools22) + if (!(config.Fools22New ?? true)) return false; if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) return false; - var timeZone = TimeZoneInfo.Local; - var offset = timeZone.GetUtcOffset(DateTime.UtcNow); - - Log.Information("Fools22: UTC offset: {0}", offset); - return this.assetsReady; } diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 48104ed6a..909b5fe69 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -106,8 +106,6 @@ namespace Dalamud.Interface.Internal.Windows this.doFocus = configuration.IsFocusManagementEnabled; this.doTsm = configuration.ShowTsm; - this.doFools22 = configuration.Fools22; - this.dtrSpacing = configuration.DtrSpacing; this.dtrSwapDirection = configuration.DtrSwapDirection; @@ -176,6 +174,8 @@ namespace Dalamud.Interface.Internal.Windows var configuration = Service.Get(); this.dtrOrder = configuration.DtrOrder; this.dtrIgnore = configuration.DtrIgnore; + + this.doFools22 = configuration.Fools22New ?? true; } /// @@ -853,7 +853,7 @@ namespace Dalamud.Interface.Internal.Windows configuration.IsFocusManagementEnabled = this.doFocus; configuration.ShowTsm = this.doTsm; - configuration.Fools22 = this.doFools22; + configuration.Fools22New = this.doFools22; configuration.UseAxisFontsFromGame = this.doUseAxisFontsFromGame; configuration.FontGamma = this.fontGamma; From e59004b052354a496042410f62f43eced29ec7ad Mon Sep 17 00:00:00 2001 From: goaaats Date: Thu, 31 Mar 2022 20:24:57 +0200 Subject: [PATCH 19/33] build: 6.3.0.10 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 011750869..1aa86b569 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.9 + 6.3.0.10 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From 77b0a1f4e5c94e277a2ad90a2280c370661b02f3 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 02:42:18 +0200 Subject: [PATCH 20/33] fix: correct visuals for all screen resolutions --- Dalamud/Fools22.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index 380fde208..c25a1746f 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -227,6 +227,8 @@ public class Fools22 : IDisposable private static void AdjustCursorAndDraw(Vector2 vpSize, TextureWrap tex, float scale = 1.0f) { + ImGui.SetCursorPos(new Vector2(0, 0)); + var width = vpSize.X; var height = tex.Height / (float)tex.Width * width; @@ -234,11 +236,6 @@ public class Fools22 : IDisposable { height = vpSize.Y; width = tex.Width / (float)tex.Height * height; - ImGui.SetCursorPosX((vpSize.X - width) / 2); - } - else - { - ImGui.SetCursorPosY((vpSize.Y - height) / 2); } var scaledSize = new Vector2(width, height) * scale; @@ -340,5 +337,4 @@ public class Fools22 : IDisposable this.player.Dispose(); } - } From 691c256d6049f2fe28e5fee304ce0de405ca5b77 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 03:03:59 +0200 Subject: [PATCH 21/33] feat: respect game sound mixer settings for sfx --- Dalamud/Dalamud.cs | 2 +- Dalamud/Fools22.cs | 51 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index b07bf2594..953637240 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -279,7 +279,7 @@ namespace Dalamud var offset = timeZone.GetUtcOffset(DateTime.UtcNow); var config = Service.Get(); - config.Fools22New = offset.Hours < 1; + config.Fools22New ??= offset.Hours < 1; config.Save(); this.fools22 = new Fools22(); diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index c25a1746f..b222c8e5b 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -17,6 +17,7 @@ using Dalamud.Interface; using Dalamud.Interface.Animation; using Dalamud.Interface.Animation.EasingFunctions; using Dalamud.Interface.Internal; +using Dalamud.Memory; using Dalamud.Utility; using ImGuiNET; using ImGuiScene; @@ -313,7 +314,10 @@ public class Fools22 : IDisposable this.time.Reset(); this.time.Start(); - this.player.Play(); + if (this.CheckIsSfxEnabled()) + { + this.player.Play(); + } } private bool CheckFoolsApplicable() @@ -329,6 +333,51 @@ public class Fools22 : IDisposable return this.assetsReady; } + private unsafe bool CheckIsSfxEnabled() + { + try + { + var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance(); + var configBase = framework->SystemConfig.CommonSystemConfig.ConfigBase; + + var seEnabled = false; + var masterEnabled = false; + + for (var i = 0; i < configBase.ConfigCount; i++) + { + var entry = configBase.ConfigEntry[i]; + + if (entry.Name != null) + { + var name = MemoryHelper.ReadStringNullTerminated(new IntPtr(entry.Name)); + + if (name == "IsSndSe") + { + var value = entry.Value.UInt; + Log.Information("Fools21: {Name} - {Type} - {Value}", name, entry.Type, value); + + seEnabled = value == 0; + } + + if (name == "IsSndMaster") + { + var value = entry.Value.UInt; + Log.Information("Fools21: {Name} - {Type} - {Value}", name, entry.Type, value); + + masterEnabled = value == 0; + } + } + } + + return seEnabled && masterEnabled; + } + catch (Exception ex) + { + Log.Error(ex, "Fools21: Error checking if sfx is enabled"); + return true; + } + } + public void Dispose() { this.erDeathBgTexture.Dispose(); From 4aa32efd5574995a093b51f9dc819f58407725f0 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 03:04:25 +0200 Subject: [PATCH 22/33] build: 6.3.0.11 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 1aa86b569..647acef04 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.10 + 6.3.0.11 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From a7a4633f2e49b9a0c3eac472fdd7dfe2eb2b54f5 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 05:03:41 +0200 Subject: [PATCH 23/33] chore: remove defaults --- Dalamud/Configuration/Internal/DalamudConfiguration.cs | 2 +- Dalamud/Dalamud.cs | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index e33df668e..e7cc9607c 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -290,7 +290,7 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; - public bool? Fools22New { get; set; } = true; + public bool? Fools22New { get; set; } = false; /// /// Load a configuration from the provided path. diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 953637240..691a541ef 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -275,13 +275,6 @@ namespace Dalamud try { Log.Information("Loading fools22"); - var timeZone = TimeZoneInfo.Local; - var offset = timeZone.GetUtcOffset(DateTime.UtcNow); - - var config = Service.Get(); - config.Fools22New ??= offset.Hours < 1; - config.Save(); - this.fools22 = new Fools22(); } catch (Exception ex) From b8de19c7e9aae721818c4b76be036b8b788c0f98 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 05:04:15 +0200 Subject: [PATCH 24/33] build: 6.3.0.12 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 647acef04..cccedf2a1 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.11 + 6.3.0.12 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From 92455c4c642442d11d43235044815ad84ab49d22 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 05:53:03 +0200 Subject: [PATCH 25/33] chore: change settings key again --- Dalamud/Configuration/Internal/DalamudConfiguration.cs | 2 +- Dalamud/Fools22.cs | 2 +- Dalamud/Interface/Internal/Windows/SettingsWindow.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index e7cc9607c..df7e2f179 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -290,7 +290,7 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; - public bool? Fools22New { get; set; } = false; + public bool? Fools22Newer { get; set; } = false; /// /// Load a configuration from the provided path. diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index b222c8e5b..0b04ce8a6 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -324,7 +324,7 @@ public class Fools22 : IDisposable { var config = Service.Get(); - if (!(config.Fools22New ?? true)) + if (!(config.Fools22Newer ?? true)) return false; if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 909b5fe69..67cca1eb2 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -175,7 +175,7 @@ namespace Dalamud.Interface.Internal.Windows this.dtrOrder = configuration.DtrOrder; this.dtrIgnore = configuration.DtrIgnore; - this.doFools22 = configuration.Fools22New ?? true; + this.doFools22 = configuration.Fools22Newer ?? true; } /// @@ -853,7 +853,7 @@ namespace Dalamud.Interface.Internal.Windows configuration.IsFocusManagementEnabled = this.doFocus; configuration.ShowTsm = this.doTsm; - configuration.Fools22New = this.doFools22; + configuration.Fools22Newer = this.doFools22; configuration.UseAxisFontsFromGame = this.doUseAxisFontsFromGame; configuration.FontGamma = this.fontGamma; From f128e3122b6dcc9666bcc1a851d96794fe35c27f Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 05:53:26 +0200 Subject: [PATCH 26/33] build: 6.3.0.13 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index cccedf2a1..125c78438 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.12 + 6.3.0.13 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From d0907df5d2744bd988636c43554a8a17d2706eae Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 20:33:45 +0200 Subject: [PATCH 27/33] feat: use NAudio, master volume for sound effect --- Dalamud/Dalamud.csproj | 1 + Dalamud/Fools22.cs | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 125c78438..151a707e9 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -69,6 +69,7 @@ + diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index 0b04ce8a6..1ea68e613 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -22,6 +22,7 @@ using Dalamud.Utility; using ImGuiNET; using ImGuiScene; using Lumina.Excel.GeneratedSheets; +using NAudio.Wave; using Serilog; using Condition = Dalamud.Game.ClientState.Conditions.Condition; @@ -35,10 +36,11 @@ public class Fools22 : IDisposable private readonly TextureWrap erCraftFailedTexture; private readonly TextureWrap erEnemyFelledTexture; + private readonly byte[] soundBytes; + private readonly string synthesisFailsMessage; private readonly Stopwatch time = new Stopwatch(); - private readonly SoundPlayer player; private bool assetsReady = false; @@ -90,8 +92,7 @@ public class Fools22 : IDisposable this.erCraftFailedTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_craft_failed.png"))!; this.erEnemyFelledTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_enemy_felled.png"))!; - var soundBytes = File.ReadAllBytes(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "snd_death_er.wav")); - this.player = new SoundPlayer(new MemoryStream(soundBytes)); + this.soundBytes = File.ReadAllBytes(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "snd_death_er.wav")); if (this.erDeathBgTexture == null || this.erNormalDeathTexture == null || this.erCraftFailedTexture == null) { @@ -314,9 +315,16 @@ public class Fools22 : IDisposable this.time.Reset(); this.time.Start(); - if (this.CheckIsSfxEnabled()) + var volume = this.GetSfxVolume(); + if (volume > 0) { - this.player.Play(); + var waveStream = new WaveFileReader(new MemoryStream(this.soundBytes)); + var volumeStream = new WaveChannel32(waveStream); + var player = new WaveOutEvent(); + + player.Volume = volume; + player.Init(volumeStream); + player.Play(); } } @@ -333,7 +341,7 @@ public class Fools22 : IDisposable return this.assetsReady; } - private unsafe bool CheckIsSfxEnabled() + private unsafe float GetSfxVolume() { try { @@ -342,6 +350,7 @@ public class Fools22 : IDisposable var seEnabled = false; var masterEnabled = false; + var masterVolume = 0u; for (var i = 0; i < configBase.ConfigCount; i++) { @@ -366,15 +375,26 @@ public class Fools22 : IDisposable masterEnabled = value == 0; } + + if (name == "SoundMaster") + { + var value = entry.Value.UInt; + Log.Information("Fools21: {Name} - {Type} - {Value}", name, entry.Type, value); + + masterVolume = value; + } } } - return seEnabled && masterEnabled; + if (!(seEnabled && masterEnabled)) + return 0; + + return masterVolume / 100F; } catch (Exception ex) { Log.Error(ex, "Fools21: Error checking if sfx is enabled"); - return true; + return 0; } } @@ -383,7 +403,5 @@ public class Fools22 : IDisposable this.erDeathBgTexture.Dispose(); this.erNormalDeathTexture.Dispose(); this.erCraftFailedTexture.Dispose(); - - this.player.Dispose(); } } From 4ae45492e69b98282c0ff2ea55be594e419de4cc Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 20:51:43 +0200 Subject: [PATCH 28/33] feat: add update window --- .../Internal/DalamudConfiguration.cs | 4 +- Dalamud/Fools22.cs | 23 +++- .../Interface/Internal/DalamudInterface.cs | 5 + .../Internal/Windows/FoolsAskWindow.cs | 100 ++++++++++++++++++ .../Internal/Windows/SettingsWindow.cs | 2 +- 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index df7e2f179..fe2fc97a6 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -290,7 +290,9 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; - public bool? Fools22Newer { get; set; } = false; + public bool AskedFools22 { get; set; } = false; + + public bool Fools22Newer { get; set; } = false; /// /// Load a configuration from the provided path. diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index 1ea68e613..256ed08dd 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -1,13 +1,13 @@ using System; using System.Diagnostics; using System.IO; -using System.Media; using System.Numerics; using System.Threading.Tasks; using Dalamud.Configuration.Internal; using Dalamud.Data; using Dalamud.Game; +using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.Gui; using Dalamud.Game.Network; @@ -86,6 +86,7 @@ public class Fools22 : IDisposable var chatGui = Service.Get(); var dataMgr = Service.Get(); var gameNetwork = Service.Get(); + var clientState = Service.Get(); this.erDeathBgTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_death_bg.png"))!; this.erNormalDeathTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_normal_death.png"))!; @@ -108,6 +109,21 @@ public class Fools22 : IDisposable framework.Update += this.FrameworkOnUpdate; chatGui.ChatMessage += this.ChatGuiOnChatMessage; gameNetwork.NetworkMessage += this.GameNetworkOnNetworkMessage; + clientState.Login += ClientStateOnLogin; + } + + private void ClientStateOnLogin(object? sender, EventArgs e) + { + var config = Service.Get(); + + if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) + return; + + if (config.AskedFools22) + return; + + var di = Service.Get(); + di.OpenFaWindow(); } private unsafe void GameNetworkOnNetworkMessage(IntPtr dataptr, ushort opcode, uint sourceactorid, uint targetactorid, NetworkMessageDirection direction) @@ -332,7 +348,7 @@ public class Fools22 : IDisposable { var config = Service.Get(); - if (!(config.Fools22Newer ?? true)) + if (!config.Fools22Newer) return false; if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) @@ -389,7 +405,8 @@ public class Fools22 : IDisposable if (!(seEnabled && masterEnabled)) return 0; - return masterVolume / 100F; + var vol = masterVolume / 100F; + return Math.Clamp(vol, 0f, 1f); } catch (Exception ex) { diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index ee56e749f..e924774d9 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -53,6 +53,7 @@ namespace Dalamud.Interface.Internal private readonly SelfTestWindow selfTestWindow; private readonly StyleEditorWindow styleEditorWindow; private readonly TitleScreenMenuWindow titleScreenMenuWindow; + private readonly FoolsAskWindow faWindow; private readonly TextureWrap logoTexture; private readonly TextureWrap tsmLogoTexture; @@ -91,6 +92,7 @@ namespace Dalamud.Interface.Internal this.selfTestWindow = new SelfTestWindow() { IsOpen = false }; this.styleEditorWindow = new StyleEditorWindow() { IsOpen = false }; this.titleScreenMenuWindow = new TitleScreenMenuWindow() { IsOpen = false }; + this.faWindow = new FoolsAskWindow() { IsOpen = false }; this.WindowSystem.AddWindow(this.changelogWindow); this.WindowSystem.AddWindow(this.colorDemoWindow); @@ -106,6 +108,7 @@ namespace Dalamud.Interface.Internal this.WindowSystem.AddWindow(this.selfTestWindow); this.WindowSystem.AddWindow(this.styleEditorWindow); this.WindowSystem.AddWindow(this.titleScreenMenuWindow); + this.WindowSystem.AddWindow(this.faWindow); ImGuiManagedAsserts.AssertsEnabled = configuration.AssertsEnabledAtStartup; @@ -247,6 +250,8 @@ namespace Dalamud.Interface.Internal /// public void OpenStyleEditor() => this.styleEditorWindow.IsOpen = true; + public void OpenFaWindow() => this.faWindow.IsOpen = true; + #endregion #region Close diff --git a/Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs b/Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs new file mode 100644 index 000000000..20bedfbc6 --- /dev/null +++ b/Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs @@ -0,0 +1,100 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Numerics; +using Dalamud.Configuration.Internal; +using Dalamud.Interface.Colors; +using Dalamud.Interface.Windowing; +using Dalamud.Utility; +using ImGuiNET; +using ImGuiScene; + +namespace Dalamud.Interface.Internal.Windows +{ + /// + /// For major updates, an in-game Changelog window. + /// + internal sealed class FoolsAskWindow : Window, IDisposable + { + private readonly string assemblyVersion = Util.AssemblyVersion; + + private readonly TextureWrap logoTexture; + + /// + /// Initializes a new instance of the class. + /// + public FoolsAskWindow() + : base("New in Dalamud!", ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse) + { + this.Namespace = "DalamudChangelogWindow"; + + var interfaceManager = Service.Get(); + var dalamud = Service.Get(); + + this.logoTexture = + interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png"))!; + } + + /// + public override void Draw() + { + this.Size = new Vector2(885, 250); + this.SizeCondition = ImGuiCond.Always; + this.Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse; + + ImGui.TextWrapped("Today, we are proud to announce \"Dalamud: Prepare To Die Edition\".\nIt's a new initiative intended to improve your immersion when playing FFXIV, featuring all new and unintrusive visual and sound effects.\nIt's only available today, so join while you can."); + + ImGuiHelpers.ScaledDummy(10); + + ImGui.TextWrapped("You can choose to opt-in here - thank you for your support!"); + + ImGui.SameLine(); + ImGuiHelpers.ScaledDummy(0); + var imgCursor = ImGui.GetCursorPos(); + + ImGuiHelpers.ScaledDummy(40); + + ImGuiHelpers.ScaledDummy(240); + + ImGui.SameLine(); + + var btnSize = new Vector2(140, 40); + + var config = Service.Get(); + + if (ImGui.Button("No, don't ask again", btnSize)) + { + config.AskedFools22 = true; + config.Fools22Newer = false; + config.Save(); + + this.IsOpen = false; + } + + ImGui.SameLine(); + + if (ImGui.Button("Yes!", btnSize)) + { + config.AskedFools22 = true; + config.Fools22Newer = true; + config.Save(); + + this.IsOpen = false; + } + + imgCursor.X += 750; + imgCursor.Y -= 30; + ImGui.SetCursorPos(imgCursor); + + ImGui.Image(this.logoTexture.ImGuiHandle, new Vector2(100)); + } + + /// + /// Dispose this window. + /// + public void Dispose() + { + this.logoTexture.Dispose(); + } + } +} diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 67cca1eb2..a3adb3780 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -175,7 +175,7 @@ namespace Dalamud.Interface.Internal.Windows this.dtrOrder = configuration.DtrOrder; this.dtrIgnore = configuration.DtrIgnore; - this.doFools22 = configuration.Fools22Newer ?? true; + this.doFools22 = configuration.Fools22Newer; } /// From 741f7261233ff65f9d1b239daefeeb6a87956734 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 20:53:50 +0200 Subject: [PATCH 29/33] build: 6.3.0.14 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 151a707e9..1b54b92c2 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.13 + 6.3.0.14 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From acd16ad9a48d36056642268ff4ca6dc2939e7051 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 21:59:39 +0200 Subject: [PATCH 30/33] fix: set volume on WaveChannel instead --- Dalamud/Fools22.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs index 256ed08dd..8cd5f354b 100644 --- a/Dalamud/Fools22.cs +++ b/Dalamud/Fools22.cs @@ -334,11 +334,13 @@ public class Fools22 : IDisposable var volume = this.GetSfxVolume(); if (volume > 0) { + Log.Information("Fools22: Vol {Volume}", volume); + var waveStream = new WaveFileReader(new MemoryStream(this.soundBytes)); var volumeStream = new WaveChannel32(waveStream); + volumeStream.Volume = volume; var player = new WaveOutEvent(); - player.Volume = volume; player.Init(volumeStream); player.Play(); } From 4f0b8104c5185d157c7797fdb9528d98d286ae55 Mon Sep 17 00:00:00 2001 From: goaaats Date: Fri, 1 Apr 2022 22:00:01 +0200 Subject: [PATCH 31/33] build: 6.3.0.15 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 1b54b92c2..0712a0c52 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 6.3.0.14 + 6.3.0.15 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion) From 76b2129a93a5f592e76b25b4d8e06b98a03e1bfd Mon Sep 17 00:00:00 2001 From: goaaats Date: Sun, 3 Apr 2022 03:02:31 +0200 Subject: [PATCH 32/33] chore: purge april fools 2022 code --- .../Internal/DalamudConfiguration.cs | 4 - Dalamud/Dalamud.cs | 14 - Dalamud/Fools22.cs | 426 ------------------ .../Interface/Internal/DalamudInterface.cs | 5 - .../Internal/Windows/FoolsAskWindow.cs | 100 ---- .../Internal/Windows/SettingsWindow.cs | 12 - 6 files changed, 561 deletions(-) delete mode 100644 Dalamud/Fools22.cs delete mode 100644 Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 7dd5c2ac8..41eeb5b03 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -295,10 +295,6 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; - public bool AskedFools22 { get; set; } = false; - - public bool Fools22Newer { get; set; } = false; - /// /// Load a configuration from the provided path. /// diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 691a541ef..537ffa516 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -53,8 +53,6 @@ namespace Dalamud #endregion - private Fools22? fools22; - /// /// Initializes a new instance of the class. /// @@ -272,16 +270,6 @@ namespace Dalamud Troubleshooting.LogTroubleshooting(); - try - { - Log.Information("Loading fools22"); - this.fools22 = new Fools22(); - } - catch (Exception ex) - { - Log.Error(ex, "Fools22 load failed."); - } - Log.Information("Dalamud is ready."); } catch (Exception ex) @@ -372,8 +360,6 @@ namespace Dalamud this.processMonoHook?.Dispose(); - this.fools22?.Dispose(); - Log.Debug("Dalamud::Dispose() OK!"); } catch (Exception ex) diff --git a/Dalamud/Fools22.cs b/Dalamud/Fools22.cs deleted file mode 100644 index 8cd5f354b..000000000 --- a/Dalamud/Fools22.cs +++ /dev/null @@ -1,426 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Numerics; -using System.Threading.Tasks; - -using Dalamud.Configuration.Internal; -using Dalamud.Data; -using Dalamud.Game; -using Dalamud.Game.ClientState; -using Dalamud.Game.ClientState.Conditions; -using Dalamud.Game.Gui; -using Dalamud.Game.Network; -using Dalamud.Game.Text; -using Dalamud.Game.Text.SeStringHandling; -using Dalamud.Interface; -using Dalamud.Interface.Animation; -using Dalamud.Interface.Animation.EasingFunctions; -using Dalamud.Interface.Internal; -using Dalamud.Memory; -using Dalamud.Utility; -using ImGuiNET; -using ImGuiScene; -using Lumina.Excel.GeneratedSheets; -using NAudio.Wave; -using Serilog; - -using Condition = Dalamud.Game.ClientState.Conditions.Condition; - -namespace Dalamud; - -public class Fools22 : IDisposable -{ - private readonly TextureWrap erDeathBgTexture; - private readonly TextureWrap erNormalDeathTexture; - private readonly TextureWrap erCraftFailedTexture; - private readonly TextureWrap erEnemyFelledTexture; - - private readonly byte[] soundBytes; - - private readonly string synthesisFailsMessage; - - private readonly Stopwatch time = new Stopwatch(); - - private bool assetsReady = false; - - private AnimationState currentState = AnimationState.NotPlaying; - private DeathType currentDeathType = DeathType.Death; - - private Easing alphaEasing; - private Easing scaleEasing; - - private bool lastFrameUnconscious = false; - - private int msFadeInTime = 1000; - private int msFadeOutTime = 2000; - private int msWaitTime = 1600; - - private TextureWrap TextTexture => this.currentDeathType switch - { - DeathType.Death => this.erNormalDeathTexture, - DeathType.CraftFailed => this.erCraftFailedTexture, - DeathType.EnemyFelled => this.erEnemyFelledTexture, - }; - - private enum AnimationState - { - NotPlaying, - FadeIn, - Wait, - FadeOut, - } - - private enum DeathType - { - Death, - CraftFailed, - EnemyFelled, - } - - public Fools22() - { - var dalamud = Service.Get(); - var interfaceManager = Service.Get(); - var framework = Service.Get(); - var chatGui = Service.Get(); - var dataMgr = Service.Get(); - var gameNetwork = Service.Get(); - var clientState = Service.Get(); - - this.erDeathBgTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_death_bg.png"))!; - this.erNormalDeathTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_normal_death.png"))!; - this.erCraftFailedTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_craft_failed.png"))!; - this.erEnemyFelledTexture = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "er_enemy_felled.png"))!; - - this.soundBytes = File.ReadAllBytes(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "fools22", "snd_death_er.wav")); - - if (this.erDeathBgTexture == null || this.erNormalDeathTexture == null || this.erCraftFailedTexture == null) - { - Log.Error("Fools22: Failed to load images"); - return; - } - - this.synthesisFailsMessage = dataMgr.GetExcelSheet()!.GetRow(1160)!.Text.ToDalamudString().TextValue; - - this.assetsReady = true; - - interfaceManager.Draw += this.Draw; - framework.Update += this.FrameworkOnUpdate; - chatGui.ChatMessage += this.ChatGuiOnChatMessage; - gameNetwork.NetworkMessage += this.GameNetworkOnNetworkMessage; - clientState.Login += ClientStateOnLogin; - } - - private void ClientStateOnLogin(object? sender, EventArgs e) - { - var config = Service.Get(); - - if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) - return; - - if (config.AskedFools22) - return; - - var di = Service.Get(); - di.OpenFaWindow(); - } - - private unsafe void GameNetworkOnNetworkMessage(IntPtr dataptr, ushort opcode, uint sourceactorid, uint targetactorid, NetworkMessageDirection direction) - { - if (opcode != 0x301) - return; - - var cat = *(ushort*)(dataptr + 0x00); - var updateType = *(uint*)(dataptr + 0x08); - - if (cat == 0x6D && updateType == 0x40000003) - { - Task.Delay(1000).ContinueWith(t => - { - this.PlayAnimation(DeathType.EnemyFelled); - }); - } - } - - private void ChatGuiOnChatMessage(XivChatType type, uint senderid, ref SeString sender, ref SeString message, ref bool ishandled) - { - if (message.TextValue.Contains(this.synthesisFailsMessage)) - { - this.PlayAnimation(DeathType.CraftFailed); - Log.Information("Fools22: Craft failed"); - } - } - - private void FrameworkOnUpdate(Framework framework) - { - var condition = Service.Get(); - var isUnconscious = condition[ConditionFlag.Unconscious]; - - if (isUnconscious && !this.lastFrameUnconscious) - { - this.PlayAnimation(DeathType.Death); - Log.Information("Fools22: Player died"); - } - - this.lastFrameUnconscious = isUnconscious; - } - - private void Draw() - { -#if DEBUG - if (ImGui.Begin("fools test")) - { - if (ImGui.Button("play death")) - { - this.PlayAnimation(DeathType.Death); - } - - if (ImGui.Button("play craft failed")) - { - this.PlayAnimation(DeathType.CraftFailed); - } - - if (ImGui.Button("play enemy felled")) - { - Task.Delay(1000).ContinueWith(t => - { - this.PlayAnimation(DeathType.EnemyFelled); - }); - } - - ImGui.InputInt("fade in time", ref this.msFadeInTime); - ImGui.InputInt("fade out time", ref this.msFadeOutTime); - ImGui.InputInt("wait time", ref this.msWaitTime); - - ImGui.TextUnformatted("state: " + this.currentState); - ImGui.TextUnformatted("time: " + this.time.ElapsedMilliseconds); - - ImGui.TextUnformatted("scale: " + this.scaleEasing?.EasedPoint.X); - } - - ImGui.End(); -#endif - var vpSize = ImGuiHelpers.MainViewport.Size; - - ImGui.SetNextWindowPos(new Vector2(0, 0), ImGuiCond.Always); - ImGui.SetNextWindowSize(new Vector2(vpSize.X, vpSize.Y), ImGuiCond.Always); - ImGuiHelpers.ForceNextWindowMainViewport(); - - ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0); - ImGui.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 0); - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0)); - ImGui.PushStyleColor(ImGuiCol.WindowBg, new Vector4(0, 0, 0, 0)); - ImGui.PushStyleColor(ImGuiCol.Border, new Vector4(0, 0, 0, 0)); - ImGui.PushStyleColor(ImGuiCol.BorderShadow, new Vector4(0, 0, 0, 0)); - - if (ImGui.Begin("fools22", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus - | ImGuiWindowFlags.NoMouseInputs | ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoDocking | ImGuiWindowFlags.NoScrollbar)) - { - if (this.currentState != AnimationState.NotPlaying) - { - this.alphaEasing?.Update(); - this.scaleEasing?.Update(); - } - - switch (this.currentState) - { - case AnimationState.FadeIn: - this.FadeIn(vpSize); - break; - case AnimationState.Wait: - this.Wait(vpSize); - break; - case AnimationState.FadeOut: - this.FadeOut(vpSize); - break; - } - } - - ImGui.End(); - - ImGui.PopStyleColor(3); - ImGui.PopStyleVar(3); - } - - private static void AdjustCursorAndDraw(Vector2 vpSize, TextureWrap tex, float scale = 1.0f) - { - ImGui.SetCursorPos(new Vector2(0, 0)); - - var width = vpSize.X; - var height = tex.Height / (float)tex.Width * width; - - if (height < vpSize.Y) - { - height = vpSize.Y; - width = tex.Width / (float)tex.Height * height; - } - - var scaledSize = new Vector2(width, height) * scale; - var difference = scaledSize - vpSize; - - var cursor = ImGui.GetCursorPos(); - ImGui.SetCursorPos(cursor - (difference / 2)); - - ImGui.Image(tex.ImGuiHandle, scaledSize); - } - - private void FadeIn(Vector2 vpSize) - { - if (this.time.ElapsedMilliseconds > this.msFadeInTime) - this.currentState = AnimationState.Wait; - - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, (float)this.alphaEasing.Value); - - AdjustCursorAndDraw(vpSize, this.erDeathBgTexture); - AdjustCursorAndDraw(vpSize, this.TextTexture, this.scaleEasing.EasedPoint.X); - - ImGui.PopStyleVar(); - } - - private void Wait(Vector2 vpSize) - { - if (this.time.ElapsedMilliseconds > this.msFadeInTime + this.msWaitTime) - { - this.currentState = AnimationState.FadeOut; - this.alphaEasing = new InOutCubic(TimeSpan.FromMilliseconds(this.msFadeOutTime)); - this.alphaEasing.Start(); - } - - AdjustCursorAndDraw(vpSize, this.erDeathBgTexture); - AdjustCursorAndDraw(vpSize, this.TextTexture, this.scaleEasing.EasedPoint.X); - } - - private void FadeOut(Vector2 vpSize) - { - if (this.time.ElapsedMilliseconds > this.msFadeInTime + this.msWaitTime + this.msFadeOutTime) - { - this.currentState = AnimationState.NotPlaying; - this.time.Stop(); - } - - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1 - (float)this.alphaEasing.Value); - - AdjustCursorAndDraw(vpSize, this.erDeathBgTexture); - AdjustCursorAndDraw(vpSize, this.TextTexture, this.scaleEasing.EasedPoint.X); - - ImGui.PopStyleVar(); - } - - private void PlayAnimation(DeathType type) - { - if (!this.CheckFoolsApplicable()) - return; - - if (this.currentState != AnimationState.NotPlaying) - return; - - this.currentDeathType = type; - - this.currentState = AnimationState.FadeIn; - this.alphaEasing = new InOutCubic(TimeSpan.FromMilliseconds(this.msFadeInTime)); - this.alphaEasing.Start(); - - this.scaleEasing = new OutCubic(TimeSpan.FromMilliseconds(this.msFadeInTime + this.msWaitTime + this.msFadeOutTime)) - { - Point1 = new Vector2(0.95f, 0.95f), - Point2 = new Vector2(1.05f, 1.05f), - }; - this.scaleEasing.Start(); - - this.time.Reset(); - this.time.Start(); - - var volume = this.GetSfxVolume(); - if (volume > 0) - { - Log.Information("Fools22: Vol {Volume}", volume); - - var waveStream = new WaveFileReader(new MemoryStream(this.soundBytes)); - var volumeStream = new WaveChannel32(waveStream); - volumeStream.Volume = volume; - var player = new WaveOutEvent(); - - player.Init(volumeStream); - player.Play(); - } - } - - private bool CheckFoolsApplicable() - { - var config = Service.Get(); - - if (!config.Fools22Newer) - return false; - - if (!(DateTime.Now.Month == 4 && DateTime.Now.Day == 1)) - return false; - - return this.assetsReady; - } - - private unsafe float GetSfxVolume() - { - try - { - var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance(); - var configBase = framework->SystemConfig.CommonSystemConfig.ConfigBase; - - var seEnabled = false; - var masterEnabled = false; - var masterVolume = 0u; - - for (var i = 0; i < configBase.ConfigCount; i++) - { - var entry = configBase.ConfigEntry[i]; - - if (entry.Name != null) - { - var name = MemoryHelper.ReadStringNullTerminated(new IntPtr(entry.Name)); - - if (name == "IsSndSe") - { - var value = entry.Value.UInt; - Log.Information("Fools21: {Name} - {Type} - {Value}", name, entry.Type, value); - - seEnabled = value == 0; - } - - if (name == "IsSndMaster") - { - var value = entry.Value.UInt; - Log.Information("Fools21: {Name} - {Type} - {Value}", name, entry.Type, value); - - masterEnabled = value == 0; - } - - if (name == "SoundMaster") - { - var value = entry.Value.UInt; - Log.Information("Fools21: {Name} - {Type} - {Value}", name, entry.Type, value); - - masterVolume = value; - } - } - } - - if (!(seEnabled && masterEnabled)) - return 0; - - var vol = masterVolume / 100F; - return Math.Clamp(vol, 0f, 1f); - } - catch (Exception ex) - { - Log.Error(ex, "Fools21: Error checking if sfx is enabled"); - return 0; - } - } - - public void Dispose() - { - this.erDeathBgTexture.Dispose(); - this.erNormalDeathTexture.Dispose(); - this.erCraftFailedTexture.Dispose(); - } -} diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index e924774d9..ee56e749f 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -53,7 +53,6 @@ namespace Dalamud.Interface.Internal private readonly SelfTestWindow selfTestWindow; private readonly StyleEditorWindow styleEditorWindow; private readonly TitleScreenMenuWindow titleScreenMenuWindow; - private readonly FoolsAskWindow faWindow; private readonly TextureWrap logoTexture; private readonly TextureWrap tsmLogoTexture; @@ -92,7 +91,6 @@ namespace Dalamud.Interface.Internal this.selfTestWindow = new SelfTestWindow() { IsOpen = false }; this.styleEditorWindow = new StyleEditorWindow() { IsOpen = false }; this.titleScreenMenuWindow = new TitleScreenMenuWindow() { IsOpen = false }; - this.faWindow = new FoolsAskWindow() { IsOpen = false }; this.WindowSystem.AddWindow(this.changelogWindow); this.WindowSystem.AddWindow(this.colorDemoWindow); @@ -108,7 +106,6 @@ namespace Dalamud.Interface.Internal this.WindowSystem.AddWindow(this.selfTestWindow); this.WindowSystem.AddWindow(this.styleEditorWindow); this.WindowSystem.AddWindow(this.titleScreenMenuWindow); - this.WindowSystem.AddWindow(this.faWindow); ImGuiManagedAsserts.AssertsEnabled = configuration.AssertsEnabledAtStartup; @@ -250,8 +247,6 @@ namespace Dalamud.Interface.Internal /// public void OpenStyleEditor() => this.styleEditorWindow.IsOpen = true; - public void OpenFaWindow() => this.faWindow.IsOpen = true; - #endregion #region Close diff --git a/Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs b/Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs deleted file mode 100644 index 20bedfbc6..000000000 --- a/Dalamud/Interface/Internal/Windows/FoolsAskWindow.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Numerics; -using Dalamud.Configuration.Internal; -using Dalamud.Interface.Colors; -using Dalamud.Interface.Windowing; -using Dalamud.Utility; -using ImGuiNET; -using ImGuiScene; - -namespace Dalamud.Interface.Internal.Windows -{ - /// - /// For major updates, an in-game Changelog window. - /// - internal sealed class FoolsAskWindow : Window, IDisposable - { - private readonly string assemblyVersion = Util.AssemblyVersion; - - private readonly TextureWrap logoTexture; - - /// - /// Initializes a new instance of the class. - /// - public FoolsAskWindow() - : base("New in Dalamud!", ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse) - { - this.Namespace = "DalamudChangelogWindow"; - - var interfaceManager = Service.Get(); - var dalamud = Service.Get(); - - this.logoTexture = - interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "logo.png"))!; - } - - /// - public override void Draw() - { - this.Size = new Vector2(885, 250); - this.SizeCondition = ImGuiCond.Always; - this.Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse; - - ImGui.TextWrapped("Today, we are proud to announce \"Dalamud: Prepare To Die Edition\".\nIt's a new initiative intended to improve your immersion when playing FFXIV, featuring all new and unintrusive visual and sound effects.\nIt's only available today, so join while you can."); - - ImGuiHelpers.ScaledDummy(10); - - ImGui.TextWrapped("You can choose to opt-in here - thank you for your support!"); - - ImGui.SameLine(); - ImGuiHelpers.ScaledDummy(0); - var imgCursor = ImGui.GetCursorPos(); - - ImGuiHelpers.ScaledDummy(40); - - ImGuiHelpers.ScaledDummy(240); - - ImGui.SameLine(); - - var btnSize = new Vector2(140, 40); - - var config = Service.Get(); - - if (ImGui.Button("No, don't ask again", btnSize)) - { - config.AskedFools22 = true; - config.Fools22Newer = false; - config.Save(); - - this.IsOpen = false; - } - - ImGui.SameLine(); - - if (ImGui.Button("Yes!", btnSize)) - { - config.AskedFools22 = true; - config.Fools22Newer = true; - config.Save(); - - this.IsOpen = false; - } - - imgCursor.X += 750; - imgCursor.Y -= 30; - ImGui.SetCursorPos(imgCursor); - - ImGui.Image(this.logoTexture.ImGuiHandle, new Vector2(100)); - } - - /// - /// Dispose this window. - /// - public void Dispose() - { - this.logoTexture.Dispose(); - } - } -} diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index e94d7890b..6edff8e66 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -50,8 +50,6 @@ namespace Dalamud.Interface.Internal.Windows private bool doFocus; private bool doTsm; - private bool doFools22; - private List? dtrOrder; private List? dtrIgnore; private int dtrSpacing; @@ -176,8 +174,6 @@ namespace Dalamud.Interface.Internal.Windows var configuration = Service.Get(); this.dtrOrder = configuration.DtrOrder; this.dtrIgnore = configuration.DtrIgnore; - - this.doFools22 = configuration.Fools22Newer; } /// @@ -244,12 +240,6 @@ namespace Dalamud.Interface.Internal.Windows private void DrawGeneralTab() { - if (DateTime.Now.Month == 4 && DateTime.Now.Day == 1) - { - ImGui.Checkbox(Loc.Localize("Fools22", "Enable April Fools 2022"), ref this.doFools22); - ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("Fools22Hint", "Enables the April Fools 2022 funny joke. Turn this off if you don't think it's funny.")); - } - ImGui.Text(Loc.Localize("DalamudSettingsLanguage", "Language")); ImGui.Combo("##XlLangCombo", ref this.langIndex, this.locLanguages, this.locLanguages.Length); ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsLanguageHint", "Select the language Dalamud will be displayed in.")); @@ -870,8 +860,6 @@ namespace Dalamud.Interface.Internal.Windows configuration.IsFocusManagementEnabled = this.doFocus; configuration.ShowTsm = this.doTsm; - configuration.Fools22Newer = this.doFools22; - configuration.UseAxisFontsFromGame = this.doUseAxisFontsFromGame; configuration.AllowBigFontAtlas = this.doAllowBigFontAtlas; configuration.FontGamma = this.fontGamma; From 0c9fd9547812e8bceb7d9e4cfc69466cc7dbb7cf Mon Sep 17 00:00:00 2001 From: goaaats Date: Sun, 3 Apr 2022 03:07:28 +0200 Subject: [PATCH 33/33] feat: add mb collect checkbox to general settings --- Dalamud.Injector/EntryPoint.cs | 4 +--- Dalamud/Configuration/Internal/DalamudConfiguration.cs | 5 +++++ Dalamud/DalamudStartInfo.cs | 5 ----- Dalamud/Game/Network/Internal/NetworkHandlers.cs | 7 ++----- Dalamud/Interface/Internal/Windows/SettingsWindow.cs | 6 ++++++ 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs index 92a0861d4..829a15429 100644 --- a/Dalamud.Injector/EntryPoint.cs +++ b/Dalamud.Injector/EntryPoint.cs @@ -281,7 +281,6 @@ namespace Dalamud.Injector AssetDirectory = Path.Combine(xivlauncherDir, "dalamudAssets", "dev"), GameVersion = gameVer, Language = ClientLanguage.English, - OptOutMbCollection = false, }; Log.Debug( @@ -292,8 +291,7 @@ namespace Dalamud.Injector $" DefaultPluginDirectory: {startInfo.DefaultPluginDirectory}\n" + $" AssetDirectory: {startInfo.AssetDirectory}\n" + $" GameVersion: {startInfo.GameVersion}\n" + - $" Language: {startInfo.Language}\n" + - $" OptOutMbCollection: {startInfo.OptOutMbCollection}"); + $" Language: {startInfo.Language}\n"); Log.Information("A Dalamud start info was not found in the program arguments. One has been generated for you."); Log.Information("Copy the following contents into the program arguments:"); diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs index 41eeb5b03..e9209e2d0 100644 --- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs +++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs @@ -295,6 +295,11 @@ namespace Dalamud.Configuration.Internal /// public bool ShowTsm { get; set; } = true; + /// + /// Gets or sets a value indicating whether or not market board data should be uploaded. + /// + public bool DoMbCollect { get; set; } = false; + /// /// Load a configuration from the provided path. /// diff --git a/Dalamud/DalamudStartInfo.cs b/Dalamud/DalamudStartInfo.cs index 891a57dca..767ee5000 100644 --- a/Dalamud/DalamudStartInfo.cs +++ b/Dalamud/DalamudStartInfo.cs @@ -47,11 +47,6 @@ namespace Dalamud [JsonConverter(typeof(GameVersionConverter))] public GameVersion GameVersion { get; init; } - /// - /// Gets a value indicating whether or not market board information should be uploaded by default. - /// - public bool OptOutMbCollection { get; init; } - /// /// Gets a value that specifies how much to wait before a new Dalamud session. /// diff --git a/Dalamud/Game/Network/Internal/NetworkHandlers.cs b/Dalamud/Game/Network/Internal/NetworkHandlers.cs index 3958f3f3b..8220a1473 100644 --- a/Dalamud/Game/Network/Internal/NetworkHandlers.cs +++ b/Dalamud/Game/Network/Internal/NetworkHandlers.cs @@ -25,7 +25,6 @@ namespace Dalamud.Game.Network.Internal { private readonly List marketBoardRequests = new(); - private readonly bool optOutMbUploads; private readonly IMarketBoardUploader uploader; private MarketBoardPurchaseHandler marketBoardPurchaseHandler; @@ -35,8 +34,6 @@ namespace Dalamud.Game.Network.Internal /// public NetworkHandlers() { - this.optOutMbUploads = Service.Get().OptOutMbCollection; - this.uploader = new UniversalisMarketBoardUploader(); Service.Get().NetworkMessage += this.OnNetworkMessage; @@ -58,7 +55,7 @@ namespace Dalamud.Game.Network.Internal if (direction == NetworkMessageDirection.ZoneUp) { - if (!this.optOutMbUploads) + if (configuration.DoMbCollect) { if (opCode == dataManager.ClientOpCodes["MarketBoardPurchaseHandler"]) { @@ -76,7 +73,7 @@ namespace Dalamud.Game.Network.Internal return; } - if (!this.optOutMbUploads) + if (configuration.DoMbCollect) { if (opCode == dataManager.ServerOpCodes["MarketBoardItemRequestStart"]) { diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs index 6edff8e66..b1f212d49 100644 --- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs +++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs @@ -36,6 +36,7 @@ namespace Dalamud.Interface.Internal.Windows private bool doCfTaskBarFlash; private bool doCfChatMessage; + private bool doMbCollect; private float globalUiScale; private bool doUseAxisFontsFromGame; @@ -91,6 +92,7 @@ namespace Dalamud.Interface.Internal.Windows this.doCfTaskBarFlash = configuration.DutyFinderTaskbarFlash; this.doCfChatMessage = configuration.DutyFinderChatMessage; + this.doMbCollect = configuration.DoMbCollect; this.globalUiScale = configuration.GlobalUiScale; this.fontGamma = configuration.FontGamma; @@ -281,6 +283,9 @@ namespace Dalamud.Interface.Internal.Windows ImGui.Checkbox(Loc.Localize("DalamudSettingsDisableRmtFiltering", "Disable RMT Filtering"), ref this.disableRmtFiltering); ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsDisableRmtFilteringMsgHint", "Disable dalamud's built-in RMT ad filtering.")); + + ImGui.Checkbox(Loc.Localize("DalamudSettingDoMbCollect", "Anonymously upload market board data"), ref this.doMbCollect); + ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingDoMbCollectHint", "Anonymously provide data about in-game economics to Universalis when browsing the market board. This data can't be tied to you in any way and everyone benefits!")); } private void DrawLookAndFeelTab() @@ -849,6 +854,7 @@ namespace Dalamud.Interface.Internal.Windows configuration.DutyFinderTaskbarFlash = this.doCfTaskBarFlash; configuration.DutyFinderChatMessage = this.doCfChatMessage; + configuration.DoMbCollect = this.doMbCollect; configuration.GlobalUiScale = this.globalUiScale; configuration.ToggleUiHide = this.doToggleUiHide;