Add events for certain style changes from within Dalamud. (#2277)

* Add events for certain style changes from within Dalamud.

* Capture reset changes in events too.

* Add non-static versions of events to IUiBuilder, add remarks about timing to events.

* Move statics to InterfaceManager members and make plugin events local.

---------

Co-authored-by: KazWolfe <KazWolfe@users.noreply.github.com>
This commit is contained in:
Ottermandias 2025-08-05 00:52:13 +02:00 committed by GitHub
parent bf5fcaaf00
commit d28a164d8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 134 additions and 29 deletions

View file

@ -140,6 +140,23 @@ internal partial class InterfaceManager : IInternalDisposableService
/// </summary>
public event Action? AfterBuildFonts;
/// <summary>
/// Invoked when the default global scale used by ImGui has been changed through Dalamud.
/// </summary>
/// <remarks> Fonts will generally not have finished rebuilding when this is invoked, so if you need to access the font you should subscribe to <seealso cref="DefaultFontHandle"/>.ImFontChanged instead.</remarks>
public event Action? DefaultGlobalScaleChanged;
/// <summary>
/// Invoked when the default font used by ImGui has been changed through Dalamud.
/// </summary>
/// <remarks> Fonts will generally not have finished rebuilding when this is invoked, so if you need to access the font you should subscribe to <seealso cref="DefaultFontHandle"/>.ImFontChanged instead.</remarks>
public event Action? DefaultFontChanged;
/// <summary>
/// Invoked when either the currently chosen style in Dalamud or a style or color variable within the currently chosen style has been changed through Dalamud.
/// </summary>
public event Action? DefaultStyleChanged;
/// <summary>
/// Gets the default ImGui font.<br />
/// <strong>Accessing this static property outside of the main thread is dangerous and not supported.</strong>
@ -499,6 +516,18 @@ internal partial class InterfaceManager : IInternalDisposableService
sizeof(uint)).ThrowOnFailure();
}
/// <summary> Safely invoke <seealso cref="DefaultGlobalScaleChanged"/>. </summary>
internal void InvokeGlobalScaleChanged()
=> DefaultGlobalScaleChanged.InvokeSafely();
/// <summary> Safely invoke <seealso cref="DefaultFontChanged"/>. </summary>
internal void InvokeFontChanged()
=> DefaultFontChanged.InvokeSafely();
/// <summary> Safely invoke <seealso cref="DefaultStyleChanged"/>. </summary>
internal void InvokeStyleChanged()
=> DefaultStyleChanged.InvokeSafely();
private static InterfaceManager WhenFontsReady()
{
var im = Service<InterfaceManager>.GetNullable();

View file

@ -100,19 +100,30 @@ internal class SettingsWindow : Window
var interfaceManager = Service<InterfaceManager>.Get();
var fontAtlasFactory = Service<FontAtlasFactory>.Get();
var scaleChanged = !Equals(ImGui.GetIO().FontGlobalScale, configuration.GlobalUiScale);
var rebuildFont = !Equals(fontAtlasFactory.DefaultFontSpec, configuration.DefaultFontSpec);
rebuildFont |= !Equals(ImGui.GetIO().FontGlobalScale, configuration.GlobalUiScale);
rebuildFont |= scaleChanged;
ImGui.GetIO().FontGlobalScale = configuration.GlobalUiScale;
if (scaleChanged)
{
Service<InterfaceManager>.Get().InvokeGlobalScaleChanged();
}
fontAtlasFactory.DefaultFontSpecOverride = null;
if (rebuildFont)
{
interfaceManager.RebuildFonts();
Service<InterfaceManager>.Get().InvokeFontChanged();
}
foreach (var settingsTab in this.tabs)
{
if (settingsTab.IsOpen)
{
settingsTab.OnClose();
}
settingsTab.IsOpen = false;
}

View file

@ -198,6 +198,7 @@ public class SettingsTabLook : SettingsTab
{
ImGui.GetIO().FontGlobalScale = this.globalUiScale = scale;
interfaceManager.RebuildFonts();
Service<InterfaceManager>.Get().InvokeGlobalScaleChanged();
}
}
@ -221,6 +222,7 @@ public class SettingsTabLook : SettingsTab
this.globalUiScale = globalUiScaleInPct / 100f;
ImGui.GetIO().FontGlobalScale = this.globalUiScale;
interfaceManager.RebuildFonts();
Service<InterfaceManager>.Get().InvokeGlobalScaleChanged();
}
ImGui.TextColoredWrapped(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingsGlobalUiScaleHint", "Scale text in all XIVLauncher UI elements - this is useful for 4K displays."));
@ -261,6 +263,7 @@ public class SettingsTabLook : SettingsTab
faf.DefaultFontSpecOverride = this.defaultFontSpec = r.Result;
interfaceManager.RebuildFonts();
Service<InterfaceManager>.Get().InvokeFontChanged();
}));
}
@ -275,6 +278,7 @@ public class SettingsTabLook : SettingsTab
this.defaultFontSpec =
new SingleFontSpec { FontId = new GameFontAndFamilyId(GameFontFamily.Axis) };
interfaceManager.RebuildFonts();
Service<InterfaceManager>.Get().InvokeFontChanged();
}
}

View file

@ -26,6 +26,7 @@ public class StyleEditorWindow : Window
private int currentSel = 0;
private string initialStyle = string.Empty;
private bool didSave = false;
private bool anyChanges = false;
private string renameText = string.Empty;
private bool renameModalDrawing = false;
@ -65,6 +66,10 @@ public class StyleEditorWindow : Window
var config = Service<DalamudConfiguration>.Get();
var newStyle = config.SavedStyles.FirstOrDefault(x => x.Name == this.initialStyle);
newStyle?.Apply();
if (this.anyChanges)
{
Service<InterfaceManager>.Get().InvokeStyleChanged();
}
}
base.OnClose();
@ -88,6 +93,7 @@ public class StyleEditorWindow : Window
{
var newStyle = config.SavedStyles[this.currentSel];
newStyle.Apply();
this.Change();
appliedThisFrame = true;
}
@ -102,6 +108,7 @@ public class StyleEditorWindow : Window
this.currentSel = config.SavedStyles.Count - 1;
newStyle.Apply();
this.Change();
appliedThisFrame = true;
config.QueueSave();
@ -117,6 +124,7 @@ public class StyleEditorWindow : Window
this.currentSel--;
var newStyle = config.SavedStyles[this.currentSel];
newStyle.Apply();
this.Change();
appliedThisFrame = true;
config.SavedStyles.RemoveAt(this.currentSel + 1);
@ -181,6 +189,7 @@ public class StyleEditorWindow : Window
config.SavedStyles.Add(newStyle);
newStyle.Apply();
this.Change();
appliedThisFrame = true;
this.currentSel = config.SavedStyles.Count - 1;
@ -211,49 +220,52 @@ public class StyleEditorWindow : Window
else if (ImGui.BeginTabBar("StyleEditorTabs"u8))
{
var style = ImGui.GetStyle();
var changes = false;
if (ImGui.BeginTabItem(Loc.Localize("StyleEditorVariables", "Variables")))
{
if (ImGui.BeginChild($"ScrollingVars", ImGuiHelpers.ScaledVector2(0, -32), true, ImGuiWindowFlags.HorizontalScrollbar | ImGuiWindowFlags.NoBackground))
{
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - 5);
ImGui.SliderFloat2("WindowPadding", ref style.WindowPadding, 0.0f, 20.0f, "%.0f");
ImGui.SliderFloat2("FramePadding", ref style.FramePadding, 0.0f, 20.0f, "%.0f");
ImGui.SliderFloat2("CellPadding", ref style.CellPadding, 0.0f, 20.0f, "%.0f");
ImGui.SliderFloat2("ItemSpacing", ref style.ItemSpacing, 0.0f, 20.0f, "%.0f");
ImGui.SliderFloat2("ItemInnerSpacing", ref style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
ImGui.SliderFloat2("TouchExtraPadding", ref style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
ImGui.SliderFloat("IndentSpacing"u8, ref style.IndentSpacing, 0.0f, 30.0f, "%.0f"u8);
ImGui.SliderFloat("ScrollbarSize"u8, ref style.ScrollbarSize, 1.0f, 20.0f, "%.0f"u8);
ImGui.SliderFloat("GrabMinSize"u8, ref style.GrabMinSize, 1.0f, 20.0f, "%.0f"u8);
changes |= ImGui.SliderFloat2("WindowPadding", ref style.WindowPadding, 0.0f, 20.0f, "%.0f");
changes |= ImGui.SliderFloat2("FramePadding", ref style.FramePadding, 0.0f, 20.0f, "%.0f");
changes |= ImGui.SliderFloat2("CellPadding", ref style.CellPadding, 0.0f, 20.0f, "%.0f");
changes |= ImGui.SliderFloat2("ItemSpacing", ref style.ItemSpacing, 0.0f, 20.0f, "%.0f");
changes |= ImGui.SliderFloat2("ItemInnerSpacing", ref style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
changes |= ImGui.SliderFloat2("TouchExtraPadding", ref style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
changes |= ImGui.SliderFloat("IndentSpacing"u8, ref style.IndentSpacing, 0.0f, 30.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("ScrollbarSize"u8, ref style.ScrollbarSize, 1.0f, 20.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("GrabMinSize"u8, ref style.GrabMinSize, 1.0f, 20.0f, "%.0f"u8);
ImGui.Text("Borders"u8);
ImGui.SliderFloat("WindowBorderSize"u8, ref style.WindowBorderSize, 0.0f, 1.0f, "%.0f"u8);
ImGui.SliderFloat("ChildBorderSize"u8, ref style.ChildBorderSize, 0.0f, 1.0f, "%.0f"u8);
ImGui.SliderFloat("PopupBorderSize"u8, ref style.PopupBorderSize, 0.0f, 1.0f, "%.0f"u8);
ImGui.SliderFloat("FrameBorderSize"u8, ref style.FrameBorderSize, 0.0f, 1.0f, "%.0f"u8);
ImGui.SliderFloat("TabBorderSize"u8, ref style.TabBorderSize, 0.0f, 1.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("WindowBorderSize"u8, ref style.WindowBorderSize, 0.0f, 1.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("ChildBorderSize"u8, ref style.ChildBorderSize, 0.0f, 1.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("PopupBorderSize"u8, ref style.PopupBorderSize, 0.0f, 1.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("FrameBorderSize"u8, ref style.FrameBorderSize, 0.0f, 1.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("TabBorderSize"u8, ref style.TabBorderSize, 0.0f, 1.0f, "%.0f"u8);
ImGui.Text("Rounding"u8);
ImGui.SliderFloat("WindowRounding"u8, ref style.WindowRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("ChildRounding"u8, ref style.ChildRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("FrameRounding"u8, ref style.FrameRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("PopupRounding"u8, ref style.PopupRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("ScrollbarRounding"u8, ref style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("GrabRounding"u8, ref style.GrabRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("LogSliderDeadzone"u8, ref style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f"u8);
ImGui.SliderFloat("TabRounding"u8, ref style.TabRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("WindowRounding"u8, ref style.WindowRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("ChildRounding"u8, ref style.ChildRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("FrameRounding"u8, ref style.FrameRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("PopupRounding"u8, ref style.PopupRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("ScrollbarRounding"u8, ref style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("GrabRounding"u8, ref style.GrabRounding, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("LogSliderDeadzone"u8, ref style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f"u8);
changes |= ImGui.SliderFloat("TabRounding"u8, ref style.TabRounding, 0.0f, 12.0f, "%.0f"u8);
ImGui.Text("Alignment"u8);
ImGui.SliderFloat2("WindowTitleAlign", ref style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
changes |= ImGui.SliderFloat2("WindowTitleAlign", ref style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
var windowMenuButtonPosition = (int)style.WindowMenuButtonPosition + 1;
if (ImGui.Combo("WindowMenuButtonPosition"u8, ref windowMenuButtonPosition, ["None", "Left", "Right"]))
style.WindowMenuButtonPosition = (ImGuiDir)(windowMenuButtonPosition - 1);
ImGui.SliderFloat2("ButtonTextAlign", ref style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
changes = true;
}
changes |= ImGui.SliderFloat2("ButtonTextAlign", ref style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
ImGui.SameLine();
ImGuiComponents.HelpMarker("Alignment applies when a button is larger than its text content.");
ImGui.SliderFloat2("SelectableTextAlign", ref style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
changes |= ImGui.SliderFloat2("SelectableTextAlign", ref style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
ImGui.SameLine();
ImGuiComponents.HelpMarker("Alignment applies when a selectable is larger than its text content.");
ImGui.SliderFloat2("DisplaySafeAreaPadding", ref style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
changes |= ImGui.SliderFloat2("DisplaySafeAreaPadding", ref style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
ImGui.SameLine();
ImGuiComponents.HelpMarker(
"Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
@ -292,7 +304,7 @@ public class StyleEditorWindow : Window
ImGui.PushID(imGuiCol.ToString());
ImGui.ColorEdit4("##color", ref style.Colors[(int)imGuiCol], ImGuiColorEditFlags.AlphaBar | this.alphaFlags);
changes |= ImGui.ColorEdit4("##color", ref style.Colors[(int)imGuiCol], ImGuiColorEditFlags.AlphaBar | this.alphaFlags);
ImGui.SameLine(0.0f, style.ItemInnerSpacing.X);
ImGui.Text(imGuiCol.ToString());
@ -319,6 +331,7 @@ public class StyleEditorWindow : Window
{
property.SetValue(workStyle.BuiltInColors, color);
workStyle.BuiltInColors?.Apply();
changes = true;
}
ImGui.SameLine(0.0f, style.ItemInnerSpacing.X);
@ -333,6 +346,11 @@ public class StyleEditorWindow : Window
ImGui.EndTabItem();
}
if (changes)
{
this.Change();
}
ImGui.EndTabBar();
}
@ -395,4 +413,10 @@ public class StyleEditorWindow : Window
config.QueueSave();
}
private void Change()
{
this.anyChanges = true;
Service<InterfaceManager>.Get().InvokeStyleChanged();
}
}

View file

@ -12,6 +12,7 @@ using Dalamud.Interface.FontIdentifier;
using Dalamud.Interface.Internal;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.ManagedFontAtlas.Internals;
using Dalamud.Plugin;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility;
using Serilog;
@ -57,6 +58,15 @@ public interface IUiBuilder
/// </summary>
event Action? HideUi;
/// <inheritdoc cref="InterfaceManager.DefaultGlobalScaleChanged"/>
event Action? DefaultGlobalScaleChanged;
/// <inheritdoc cref="InterfaceManager.DefaultFontChanged"/>
event Action? DefaultFontChanged;
/// <inheritdoc cref="InterfaceManager.DefaultStyleChanged"/>
event Action? DefaultStyleChanged;
/// <summary>
/// Gets the handle to the default Dalamud font - supporting all game languages and icons.
/// </summary>
@ -287,6 +297,15 @@ public sealed class UiBuilder : IDisposable, IUiBuilder
this.interfaceManager.ResizeBuffers += this.OnResizeBuffers;
this.scopedFinalizer.Add(() => this.interfaceManager.ResizeBuffers -= this.OnResizeBuffers);
this.interfaceManager.DefaultStyleChanged += this.OnDefaultStyleChanged;
this.scopedFinalizer.Add(() => this.interfaceManager.DefaultStyleChanged -= this.OnDefaultStyleChanged);
this.interfaceManager.DefaultGlobalScaleChanged += this.OnDefaultGlobalScaleChanged;
this.scopedFinalizer.Add(() => this.interfaceManager.DefaultGlobalScaleChanged -= this.OnDefaultGlobalScaleChanged);
this.interfaceManager.DefaultFontChanged += this.OnDefaultFontChanged;
this.scopedFinalizer.Add(() => this.interfaceManager.DefaultFontChanged -= this.OnDefaultFontChanged);
this.FontAtlas =
this.scopedFinalizer
.Add(
@ -319,6 +338,15 @@ public sealed class UiBuilder : IDisposable, IUiBuilder
/// <inheritdoc/>
public event Action? HideUi;
/// <inheritdoc/>
public event Action? DefaultGlobalScaleChanged;
/// <inheritdoc/>
public event Action? DefaultFontChanged;
/// <inheritdoc/>
public event Action? DefaultStyleChanged;
/// <summary>
/// Gets the default Dalamud font size in points.
/// </summary>
@ -504,6 +532,15 @@ public sealed class UiBuilder : IDisposable, IUiBuilder
/// </summary>
public bool ShouldUseReducedMotion => Service<DalamudConfiguration>.Get().ReduceMotions ?? false;
private void OnDefaultStyleChanged()
=> this.DefaultStyleChanged.InvokeSafely();
private void OnDefaultGlobalScaleChanged()
=> this.DefaultGlobalScaleChanged.InvokeSafely();
private void OnDefaultFontChanged()
=> this.DefaultFontChanged.InvokeSafely();
/// <summary>
/// Gets or sets a value indicating whether statistics about UI draw time should be collected.
/// </summary>