From bb223ff093e55d332fce5e3194d44edcefa70db2 Mon Sep 17 00:00:00 2001 From: xrEugene Date: Thu, 6 Aug 2026 17:27:28 +0300 Subject: [PATCH 1/2] fix/interface-scale --- Source/Editor/Options/OptionsModule.cs | 7 +++++-- Source/Engine/Render2D/Font.cpp | 18 ++++++++++++++++++ Source/Engine/Render2D/Font.h | 12 ++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs index 49e30a53d..77fb116f9 100644 --- a/Source/Editor/Options/OptionsModule.cs +++ b/Source/Editor/Options/OptionsModule.cs @@ -129,10 +129,13 @@ namespace FlaxEditor.Options float prevInterfaceScale = Options.Interface.InterfaceScale; Options = options; - OnOptionsChanged(); - // Scale interface relative to the current value (eg. when using system-provided Dpi Scale) + // Scale interface relative to the current value (eg. when using system-provided Dpi Scale). + // Apply this before OnOptionsChanged so newly created fonts get rasterized at the target DPI scale (avoids blurry text). Platform.CustomDpiScale *= Options.Interface.InterfaceScale / prevInterfaceScale; + Font.SetGlobalScale(Platform.DpiScale); + + OnOptionsChanged(); } else { diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp index b2e6e8b75..ea098af2c 100644 --- a/Source/Engine/Render2D/Font.cpp +++ b/Source/Engine/Render2D/Font.cpp @@ -3,12 +3,30 @@ #include "Font.h" #include "FontAsset.h" #include "FontManager.h" +#include "Engine/Content/Content.h" #include "Engine/Core/Log.h" #include "Engine/Threading/Threading.h" #include "IncludeFreeType.h" Array, HeapAllocation> Font::FallbackFonts; +float Font::GetGlobalScale() +{ + return FontManager::FontScale; +} + +void Font::SetGlobalScale(float scale) +{ + if (scale <= 0.0f || Math::NearEqual(FontManager::FontScale, scale)) return; + FontManager::FontScale = scale; + + // Invalidate all loaded font assets so cached glyphs are re-rasterized and Font metrics are recomputed at the new scale + auto assets = Content::GetAssets(); + for (auto* asset : assets) if (asset) asset->Invalidate(); + + FontManager::Flush(); +} + Font::Font(FontAsset* parentAsset, float size) : ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer)) , _asset(parentAsset) diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h index fc40cc16c..b2365c0f8 100644 --- a/Source/Engine/Render2D/Font.h +++ b/Source/Engine/Render2D/Font.h @@ -261,6 +261,18 @@ public: /// API_FIELD() static Array, HeapAllocation> FallbackFonts; + /// + /// Gets the global font scaling factor used to rasterize font glyphs at higher resolutions (eg. for high-DPI displays or UI scaling). + /// + API_PROPERTY() static float GetGlobalScale(); + + /// + /// Sets the global font scaling factor used to rasterize font glyphs at higher resolutions (eg. for high-DPI displays or UI scaling). + /// Calling this rebuilds the cached glyphs and metrics of every loaded font so text rendered afterwards stays crisp at the new scale. + /// + /// The new font scale (must be greater than 0). + API_FUNCTION() static void SetGlobalScale(float scale); + /// /// Gets parent font asset that contains font family used by this font. /// From 67aaa3af5f29984131ac1fb1c5a7ecfe5159d0bd Mon Sep 17 00:00:00 2001 From: xrEugene Date: Thu, 6 Aug 2026 20:31:20 +0300 Subject: [PATCH 2/2] fix/tree-dropdown-animations --- Source/Editor/GUI/Tree/TreeNode.cs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs index b0ce8c251..4f00acd1a 100644 --- a/Source/Editor/GUI/Tree/TreeNode.cs +++ b/Source/Editor/GUI/Tree/TreeNode.cs @@ -508,9 +508,9 @@ namespace FlaxEditor.GUI.Tree /// True if event has been handled. protected virtual bool OnMouseDoubleClickHeader(ref Float2 location, MouseButton button) { - if (HasAnyVisibleChild) + if (HasAnyVisibleChild && _animationProgress >= 1.0f) { - // Toggle open state + // Toggle open state (ignored while an expand/collapse animation is running) if (_opened) Collapse(); else @@ -966,8 +966,8 @@ namespace FlaxEditor.GUI.Tree } } - // Check if mouse hits arrow - if (_mouseOverArrow && HasAnyVisibleChild) + // Check if mouse hits arrow (ignored while an expand/collapse animation is running) + if (_mouseOverArrow && HasAnyVisibleChild && _animationProgress >= 1.0f) { if (ParentTree.Root.GetKey(KeyboardKeys.Alt)) { @@ -1322,7 +1322,19 @@ namespace FlaxEditor.GUI.Tree // Skip full layout if it's fully collapsed if (_opened || _animationProgress < 1.0f) { - y -= _cachedHeight * (_opened ? 1.0f - _animationProgress : _animationProgress); + // Measure the total children height this frame instead of relying on the previously cached one. + // Using the stale _cachedHeight causes a visible 3-frame flicker on first expand (down -> up -> down). + // Frame 1 uses the collapsed cache (~header height) so children snap to fully-open. + // Frame 2 uses the just-refreshed full height so they snap behind the header. + // At the end subsequent frames slide back down. + float childrenHeight = 0.0f; + for (int i = 0; i < _children.Count; i++) + { + if (_children[i] is TreeNode node && node.Visible) + childrenHeight += node.Height + DefaultNodeOffsetY; + } + + y -= childrenHeight * (_opened ? 1.0f - _animationProgress : _animationProgress); for (int i = 0; i < _children.Count; i++) { if (_children[i] is TreeNode node && node.Visible)