From 47a25c7828cb6351f660ca2a6d282957458b8b6d Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Tue, 28 Nov 2023 07:17:46 +0800
Subject: [PATCH 01/16] Add font fallback
Note: All the `First()` in the code are temperary workarounds to make it work and require refractoring
---
Source/Editor/Content/Tree/ContentTreeNode.cs | 5 +-
.../CustomEditors/Dedicated/ScriptsEditor.cs | 3 +-
.../Dedicated/UIControlEditor.cs | 4 +-
.../Editors/ActorTransformEditor.cs | 3 +-
.../Editor/CustomEditors/Editors/TagEditor.cs | 2 +-
Source/Editor/EditorAssets.cs | 2 +
Source/Editor/GUI/ComboBox.cs | 2 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 7 +-
Source/Editor/GUI/CurveEditor.cs | 2 +-
Source/Editor/GUI/Docking/DockWindow.cs | 3 +-
Source/Editor/GUI/ItemsListContextMenu.cs | 5 +-
Source/Editor/GUI/MainMenuButton.cs | 5 +-
Source/Editor/GUI/NavigationButton.cs | 5 +-
Source/Editor/GUI/Row.cs | 5 +-
Source/Editor/GUI/Table.cs | 3 +-
.../Editor/GUI/Timeline/Tracks/MemberTrack.cs | 2 +-
Source/Editor/GUI/ToolStripButton.cs | 5 +-
Source/Editor/GUI/Tree/TreeNode.cs | 3 +-
Source/Editor/Options/InterfaceOptions.cs | 6 +
Source/Editor/Options/OptionsModule.cs | 9 +-
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 4 +-
.../Editor/Surface/Archetypes/BehaviorTree.cs | 3 +-
.../Surface/ContextMenu/VisjectCMItem.cs | 14 +-
Source/Editor/Surface/Elements/InputBox.cs | 4 +-
Source/Editor/Surface/SurfaceNode.cs | 5 +-
Source/Editor/Tools/Foliage/FoliageTab.cs | 3 +-
Source/Editor/Tools/Terrain/CarveTab.cs | 3 +-
Source/Editor/Viewport/EditorViewport.cs | 6 +-
.../Viewport/Widgets/ViewportWidgetButton.cs | 5 +-
Source/Editor/Windows/AboutDialog.cs | 3 +-
Source/Editor/Windows/Profiler/Timeline.cs | 5 +-
Source/Editor/Windows/ToolboxWindow.cs | 5 +-
Source/Engine/Render2D/Font.cpp | 205 +++++++++++
Source/Engine/Render2D/Font.h | 35 ++
Source/Engine/Render2D/FontManager.cpp | 3 +
Source/Engine/Render2D/Render2D.cpp | 332 +++++++++++++++++-
Source/Engine/Render2D/Render2D.cs | 53 +++
Source/Engine/Render2D/Render2D.h | 45 ++-
Source/Engine/Scripting/Scripting.cs | 5 +-
Source/Engine/UI/GUI/Common/Button.cs | 3 +-
Source/Engine/UI/GUI/Common/Dropdown.cs | 3 +-
Source/Engine/UI/GUI/Common/Label.cs | 8 +-
Source/Engine/UI/GUI/Common/RichTextBox.cs | 3 +-
Source/Engine/UI/GUI/Common/TextBox.cs | 4 +-
Source/Engine/UI/GUI/Panels/DropPanel.cs | 3 +-
Source/Engine/UI/GUI/Style.cs | 26 +-
Source/Engine/UI/GUI/Tooltip.cs | 5 +-
47 files changed, 787 insertions(+), 87 deletions(-)
diff --git a/Source/Editor/Content/Tree/ContentTreeNode.cs b/Source/Editor/Content/Tree/ContentTreeNode.cs
index 0c0fc6a51..47159c6c9 100644
--- a/Source/Editor/Content/Tree/ContentTreeNode.cs
+++ b/Source/Editor/Content/Tree/ContentTreeNode.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
@@ -140,8 +141,8 @@ namespace FlaxEditor.Content
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(text, ranges[i].StartIndex);
- var end = font.GetCharPosition(text, ranges[i].EndIndex);
+ var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.First().GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index d7bfbbad7..1f69074ce 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.Content;
using FlaxEditor.GUI;
@@ -42,7 +43,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Add script button
var buttonText = "Add script";
- var textSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
float addScriptButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
_addScriptsButton = new Button
diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index 296560507..5b5c2f90d 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -247,7 +247,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Info
var info = new Label(0, title.Bottom, DialogWidth, InfoHeight)
{
- Font = new FontReference(style.FontSmall),
+ Font = new FontReference(style.FontSmall.First()),
Text = "Shift: also set bounds\nControl: also set pivot",
Parent = this
};
@@ -423,7 +423,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Set control type button
var space = layout.Space(20);
var buttonText = "Set Type";
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.First().MeasureText(buttonText);
float setTypeButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var setTypeButton = new Button
{
diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
index 4c153e759..d7059f712 100644
--- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
@@ -2,6 +2,7 @@
using FlaxEngine;
using FlaxEngine.GUI;
+using System.Linq;
namespace FlaxEditor.CustomEditors.Editors
{
@@ -100,7 +101,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.Clicked += ToggleLink;
ToggleEnabled();
SetLinkStyle();
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(LinkedLabel.Text.Value);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.First().MeasureText(LinkedLabel.Text.Value);
_linkButton.LocalX += textSize.X + 10;
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
{
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index dbd5d124c..a174d02e4 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -631,7 +631,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Edit...",
Parent = _label,
};
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.First().MeasureText(buttonText);
if (textSize.Y > button.Width)
button.Width = textSize.Y + 2;
diff --git a/Source/Editor/EditorAssets.cs b/Source/Editor/EditorAssets.cs
index eb2f21356..237908a0c 100644
--- a/Source/Editor/EditorAssets.cs
+++ b/Source/Editor/EditorAssets.cs
@@ -54,6 +54,8 @@ namespace FlaxEditor
///
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
+ public static string CJKFont = "Editor/Fonts/NotoSansSC-Medium";
+
///
/// The Inconsolata Regular font.
///
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index 0417cc7e3..7dc407698 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -273,7 +273,7 @@ namespace FlaxEditor.GUI
MaximumItemsInViewCount = 20;
var style = Style.Current;
- Font = new FontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium.First());
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BackgroundColorHighlighted = BackgroundColor;
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index e371f7c4b..872700a9b 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -233,11 +234,11 @@ namespace FlaxEditor.GUI.ContextMenu
{
var style = Style.Current;
float width = 20;
- if (style.FontMedium)
+ if (style.FontMedium.First())
{
- width += style.FontMedium.MeasureText(Text).X;
+ width += style.FontMedium.First().MeasureText(Text).X;
if (!string.IsNullOrEmpty(ShortKeys))
- width += 40 + style.FontMedium.MeasureText(ShortKeys).X;
+ width += 40 + style.FontMedium.First().MeasureText(ShortKeys).X;
}
return Mathf.Max(width, base.MinimumWidth);
diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs
index 22deec120..f71409b20 100644
--- a/Source/Editor/GUI/CurveEditor.cs
+++ b/Source/Editor/GUI/CurveEditor.cs
@@ -437,7 +437,7 @@ namespace FlaxEditor.GUI
_contentsColor = style.Background.RGBMultiplied(0.7f);
_linesColor = style.ForegroundDisabled.RGBMultiplied(0.7f);
_labelsColor = style.ForegroundDisabled;
- _labelsFont = style.FontSmall;
+ _labelsFont = style.FontSmall.First();
_mainPanel = new Panel(ScrollBars.Both)
{
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index dd4e39ce2..8601b9c53 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -6,6 +6,7 @@ using FlaxEngine;
using FlaxEngine.Assertions;
using FlaxEngine.GUI;
using FlaxEditor.Options;
+using System.Linq;
namespace FlaxEditor.GUI.Docking
{
@@ -488,7 +489,7 @@ namespace FlaxEditor.GUI.Docking
{
var style = Style.Current;
if (style?.FontMedium != null)
- _titleSize = style.FontMedium.MeasureText(_title);
+ _titleSize = style.FontMedium.First().MeasureText(_title);
}
base.PerformLayoutBeforeChildren();
diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs
index 42d236991..ce69f3544 100644
--- a/Source/Editor/GUI/ItemsListContextMenu.cs
+++ b/Source/Editor/GUI/ItemsListContextMenu.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Input;
using FlaxEditor.Utilities;
@@ -86,8 +87,8 @@ namespace FlaxEditor.GUI
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(Name, ranges[i].StartIndex);
- var end = font.GetCharPosition(Name, ranges[i].EndIndex);
+ var start = font.First().GetCharPosition(Name, ranges[i].StartIndex);
+ var end = font.First().GetCharPosition(Name, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
}
Visible = true;
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 117922361..76687f8b9 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -2,6 +2,7 @@
using FlaxEngine;
using FlaxEngine.GUI;
+using System.Linq;
namespace FlaxEditor.GUI
{
@@ -101,8 +102,8 @@ namespace FlaxEditor.GUI
var style = Style.Current;
float width = 18;
- if (style.FontMedium)
- width += style.FontMedium.MeasureText(Text).X;
+ if (style.FontMedium.First())
+ width += style.FontMedium.First().MeasureText(Text).X;
Width = width;
}
diff --git a/Source/Editor/GUI/NavigationButton.cs b/Source/Editor/GUI/NavigationButton.cs
index 18e862304..77f8a7656 100644
--- a/Source/Editor/GUI/NavigationButton.cs
+++ b/Source/Editor/GUI/NavigationButton.cs
@@ -2,6 +2,7 @@
using FlaxEngine;
using FlaxEngine.GUI;
+using System.Linq;
namespace FlaxEditor.GUI
{
@@ -65,9 +66,9 @@ namespace FlaxEditor.GUI
{
var style = Style.Current;
- if (style.FontMedium)
+ if (style.FontMedium.First())
{
- Width = style.FontMedium.MeasureText(Text).X + 2 * DefaultMargin;
+ Width = style.FontMedium.First().MeasureText(Text).X + 2 * DefaultMargin;
}
}
}
diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs
index f6bd5b02a..458138aea 100644
--- a/Source/Editor/GUI/Row.cs
+++ b/Source/Editor/GUI/Row.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -38,8 +39,8 @@ namespace FlaxEditor.GUI
{
Depth = -1;
- if (Height < Style.Current.FontMedium.Height)
- Height = Style.Current.FontMedium.Height + 4;
+ if (Height < Style.Current.FontMedium.First().Height)
+ Height = Style.Current.FontMedium.First().Height + 4;
}
///
diff --git a/Source/Editor/GUI/Table.cs b/Source/Editor/GUI/Table.cs
index 1d22ddb15..fed33a336 100644
--- a/Source/Editor/GUI/Table.cs
+++ b/Source/Editor/GUI/Table.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using System.Runtime.CompilerServices;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -129,7 +130,7 @@ namespace FlaxEditor.GUI
Render2D.FillRectangle(rect, column.TitleBackgroundColor);
var style = Style.Current;
- var font = column.TitleFont ?? style.FontMedium;
+ var font = column.TitleFont ?? style.FontMedium.First();
Render2D.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
if (columnIndex < _columns.Length - 1)
diff --git a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
index 63787df2c..928129917 100644
--- a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
@@ -345,7 +345,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (_previewValue != null)
{
// Based on Track.Draw for track text placement
- var left = _xOffset + 16 + Style.Current.FontSmall.MeasureText(Title ?? Name).X;
+ var left = _xOffset + 16 + Style.Current.FontSmall.First().MeasureText(Title ?? Name).X;
if (Icon.IsValid)
left += 18;
if (IsExpanded)
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index e839a7356..b74c7c19f 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -150,8 +151,8 @@ namespace FlaxEditor.GUI
if (hasSprite)
width += iconSize;
- if (!string.IsNullOrEmpty(_text) && style.FontMedium)
- width += style.FontMedium.MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
+ if (!string.IsNullOrEmpty(_text) && style.FontMedium.First())
+ width += style.FontMedium.First().MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
Width = width;
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index 703079469..f26929993 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -317,7 +318,7 @@ namespace FlaxEditor.GUI.Tree
BackgroundColorSelected = style.BackgroundSelected;
BackgroundColorHighlighted = style.BackgroundHighlighted;
BackgroundColorSelectedUnfocused = style.LightBackground;
- TextFont = new FontReference(style.FontSmall);
+ TextFont = new FontReference(style.FontSmall.First());
}
///
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index 95a273f19..c96a52fb1 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -237,12 +237,18 @@ namespace FlaxEditor.Options
public int NumberOfGameClientsToLaunch = 1;
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont);
+ private static FontAsset _cjkFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CJKFont);
private FontReference _titleFont = new FontReference(DefaultFont, 18);
private FontReference _largeFont = new FontReference(DefaultFont, 14);
private FontReference _mediumFont = new FontReference(DefaultFont, 9);
private FontReference _smallFont = new FontReference(DefaultFont, 9);
private FontReference _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont), 10);
+ public FontReference CJKFont
+ {
+ get => new FontReference(_cjkFont, 9);
+ }
+
///
/// Gets or sets the title font for editor UI.
///
diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs
index 1137e4c37..15059bd56 100644
--- a/Source/Editor/Options/OptionsModule.cs
+++ b/Source/Editor/Options/OptionsModule.cs
@@ -261,8 +261,9 @@ namespace FlaxEditor.Options
// Fonts
FontTitle = options.Interface.TitleFont.GetFont(),
FontLarge = options.Interface.LargeFont.GetFont(),
- FontMedium = options.Interface.MediumFont.GetFont(),
- FontSmall = options.Interface.SmallFont.GetFont(),
+ FontMedium = new Font[] { options.Interface.MediumFont.GetFont(), options.Interface.CJKFont.GetFont() },
+ FontSmall = new Font[] { options.Interface.SmallFont.GetFont(), options.Interface.CJKFont.GetFont() },
+ FontCJK = options.Interface.CJKFont.GetFont(),
// Icons
ArrowDown = Editor.Icons.ArrowDown12,
@@ -314,8 +315,8 @@ namespace FlaxEditor.Options
// Fonts
FontTitle = options.Interface.TitleFont.GetFont(),
FontLarge = options.Interface.LargeFont.GetFont(),
- FontMedium = options.Interface.MediumFont.GetFont(),
- FontSmall = options.Interface.SmallFont.GetFont(),
+ FontMedium = new Font[] { options.Interface.MediumFont.GetFont(), options.Interface.CJKFont.GetFont() },
+ FontSmall = new Font[] { options.Interface.SmallFont.GetFont(), options.Interface.CJKFont.GetFont() },
// Icons
ArrowDown = Editor.Icons.ArrowDown12,
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index f64e46385..9a6fe4fd2 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -142,8 +142,8 @@ namespace FlaxEditor.SceneGraph.GUI
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(text, ranges[i].StartIndex);
- var end = font.GetCharPosition(text, ranges[i].EndIndex);
+ var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.First().GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
index f8cd7bb5a..38dd28e62 100644
--- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs
+++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.CustomEditors.Dedicated;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Drag;
@@ -100,7 +101,7 @@ namespace FlaxEditor.Surface.Archetypes
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
if (!string.IsNullOrEmpty(_debugInfo))
- _debugInfoSize = Style.Current.FontSmall.MeasureText(_debugInfo);
+ _debugInfoSize = Style.Current.FontSmall.First().MeasureText(_debugInfo);
}
}
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index 207875a92..812bec5d2 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -200,8 +200,8 @@ namespace FlaxEditor.Surface.ContextMenu
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
- var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
+ var start = font.First().GetCharPosition(_archetype.Title, ranges[i].StartIndex);
+ var end = font.First().GetCharPosition(_archetype.Title, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
if (ranges[i].StartIndex <= 0)
@@ -222,8 +222,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = font.GetCharPosition(_archetype.Title, 0);
- var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
+ var start = font.First().GetCharPosition(_archetype.Title, 0);
+ var end = font.First().GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
_isFullMatch = true;
Visible = true;
@@ -237,8 +237,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = font.GetCharPosition(_archetype.Title, 0);
- var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
+ var start = font.First().GetCharPosition(_archetype.Title, 0);
+ var end = font.First().GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
Visible = true;
@@ -286,7 +286,7 @@ namespace FlaxEditor.Surface.ContextMenu
Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
if (_archetype.SubTitle != null)
{
- var titleLength = style.FontSmall.MeasureText(_archetype.Title).X;
+ var titleLength = style.FontSmall.First().MeasureText(_archetype.Title).X;
var subTitleRect = new Rectangle(textRect.X + titleLength, textRect.Y, textRect.Width - titleLength, textRect.Height);
Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs
index 2047bcd1a..611160611 100644
--- a/Source/Editor/Surface/Elements/InputBox.cs
+++ b/Source/Editor/Surface/Elements/InputBox.cs
@@ -1428,7 +1428,7 @@ namespace FlaxEditor.Surface.Elements
if (_defaultValueEditor != null)
{
- _defaultValueEditor.Location = new Float2(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y);
+ _defaultValueEditor.Location = new Float2(X + Width + 8 + Style.Current.FontSmall.First().MeasureText(Text).X, Y);
}
}
@@ -1635,7 +1635,7 @@ namespace FlaxEditor.Surface.Elements
{
if (DefaultValueEditors[i].CanUse(this, ref _currentType))
{
- var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y, 90, Height);
+ var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.First().MeasureText(Text).X, Y, 90, Height);
_editor = DefaultValueEditors[i];
try
{
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index 780ef81f0..82a9ab2bd 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
@@ -199,7 +200,7 @@ namespace FlaxEditor.Surface
continue;
if (child is InputBox inputBox)
{
- var boxWidth = boxLabelFont.MeasureText(inputBox.Text).X + 20;
+ var boxWidth = boxLabelFont.First().MeasureText(inputBox.Text).X + 20;
if (inputBox.DefaultValueEditor != null)
boxWidth += inputBox.DefaultValueEditor.Width + 4;
leftWidth = Mathf.Max(leftWidth, boxWidth);
@@ -207,7 +208,7 @@ namespace FlaxEditor.Surface
}
else if (child is OutputBox outputBox)
{
- rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 20);
+ rightWidth = Mathf.Max(rightWidth, boxLabelFont.First().MeasureText(outputBox.Text).X + 20);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
}
else if (child is Control control)
diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs
index 1b46a42be..e88972b5c 100644
--- a/Source/Editor/Tools/Foliage/FoliageTab.cs
+++ b/Source/Editor/Tools/Foliage/FoliageTab.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
@@ -147,7 +148,7 @@ namespace FlaxEditor.Tools.Foliage
Parent = _noFoliagePanel,
Enabled = false
};
- var textSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
if (_createNewFoliage.Width < textSize.X)
{
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CarveTab.cs b/Source/Editor/Tools/Terrain/CarveTab.cs
index d51915acf..0a43cd2d2 100644
--- a/Source/Editor/Tools/Terrain/CarveTab.cs
+++ b/Source/Editor/Tools/Terrain/CarveTab.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
@@ -105,7 +106,7 @@ namespace FlaxEditor.Tools.Terrain
Parent = _noTerrainPanel,
Enabled = false
};
- var textSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
if (_createTerrainButton.Width < textSize.X)
{
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index c49392d01..f4ebfb51b 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -548,9 +548,9 @@ namespace FlaxEditor.Viewport
#region Camera settings widget
var largestText = "Relative Panning";
- var textSize = Style.Current.FontMedium.MeasureText(largestText);
+ var textSize = Style.Current.FontMedium.First().MeasureText(largestText);
var xLocationForExtras = textSize.X + 5;
- var cameraSpeedTextWidth = Style.Current.FontMedium.MeasureText("0.00").X;
+ var cameraSpeedTextWidth = Style.Current.FontMedium.First().MeasureText("0.00").X;
// Camera Settings Widget
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
@@ -801,7 +801,7 @@ namespace FlaxEditor.Viewport
#region View mode widget
largestText = "Brightness";
- textSize = Style.Current.FontMedium.MeasureText(largestText);
+ textSize = Style.Current.FontMedium.First().MeasureText(largestText);
xLocationForExtras = textSize.X + 5;
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
index 77e94ae53..a58350ded 100644
--- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
+++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
using FlaxEditor.GUI.ContextMenu;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -162,8 +163,8 @@ namespace FlaxEditor.Viewport.Widgets
{
var style = Style.Current;
- if (style != null && style.FontMedium)
- Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.MeasureText(_text).X, Icon.IsValid);
+ if (style != null && style.FontMedium.First())
+ Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.First().MeasureText(_text).X, Icon.IsValid);
}
}
}
diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs
index b059dadcb..63ad44f29 100644
--- a/Source/Editor/Windows/AboutDialog.cs
+++ b/Source/Editor/Windows/AboutDialog.cs
@@ -2,6 +2,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.GUI.Dialogs;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -53,7 +54,7 @@ namespace FlaxEditor.Windows
Parent = this
};
var buttonText = "Copy version info";
- var fontSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var fontSize = Style.Current.FontMedium.First().MeasureText(buttonText);
var copyVersionButton = new Button(Width - fontSize.X - 8, 6, fontSize.X + 4, 20)
{
Text = buttonText,
diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs
index 59a7a0e26..88019b329 100644
--- a/Source/Editor/Windows/Profiler/Timeline.cs
+++ b/Source/Editor/Windows/Profiler/Timeline.cs
@@ -2,6 +2,7 @@
using FlaxEngine;
using FlaxEngine.GUI;
+using System.Linq;
namespace FlaxEditor.Windows.Profiler
{
@@ -84,8 +85,8 @@ namespace FlaxEditor.Windows.Profiler
Render2D.FillRectangle(bounds, color);
Render2D.DrawRectangle(bounds, color * 0.5f);
- if (_nameLength < 0 && style.FontMedium)
- _nameLength = style.FontMedium.MeasureText(_name).X;
+ if (_nameLength < 0 && style.FontMedium.First())
+ _nameLength = style.FontMedium.First().MeasureText(_name).X;
if (_nameLength < bounds.Width + 4)
{
diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs
index e2b04669b..e8fc1d56c 100644
--- a/Source/Editor/Windows/ToolboxWindow.cs
+++ b/Source/Editor/Windows/ToolboxWindow.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using FlaxEditor.GUI.Input;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.GUI.Tree;
@@ -272,8 +273,8 @@ namespace FlaxEditor.Windows
var textRect = item.TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(text, ranges[i].StartIndex);
- var end = font.GetCharPosition(text, ranges[i].EndIndex);
+ var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.First().GetCharPosition(text, ranges[i].EndIndex);
highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
item.SetHighlights(highlights);
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index 90423f5ce..13b17197c 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -283,6 +283,206 @@ void Font::ProcessText(const StringView& text, Array& outputLines
}
}
+void Font::ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
+{
+ float cursorX = 0;
+ int32 kerning;
+ FontLineCache tmpLine;
+ FontCharacterEntry entry;
+ FontCharacterEntry previous;
+ int32 textLength = text.Length();
+ float scale = layout.Scale / FontManager::FontScale;
+ float boundsWidth = layout.Bounds.GetWidth();
+ float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
+ tmpLine.Location = Float2::Zero;
+ tmpLine.Size = Float2::Zero;
+ tmpLine.FirstCharIndex = 0;
+ tmpLine.LastCharIndex = -1;
+
+ int32 lastWrapCharIndex = INVALID_INDEX;
+ float lastWrapCharX = 0;
+ bool lastMoveLine = false;
+
+ int32 previousFontIndex = -1;
+ // The maximum font height of the current line
+ float maxHeight = 0;
+ // Process each character to split text into single lines
+ for (int32 currentIndex = 0; currentIndex < textLength;)
+ {
+ bool moveLine = false;
+ float xAdvance = 0;
+ int32 nextCharIndex = currentIndex + 1;
+
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Check if character can wrap words
+ const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar);
+ if (isWrapChar && currentIndex != 0)
+ {
+ lastWrapCharIndex = currentIndex;
+ lastWrapCharX = cursorX;
+ }
+
+ // Check if it's a newline character
+ if (currentChar == '\n')
+ {
+ // Break line
+ moveLine = true;
+ currentIndex++;
+ tmpLine.LastCharIndex++;
+ }
+ else
+ {
+ // Get character entry
+ int32 fontIndex = 0;
+ while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(currentChar))
+ {
+ fontIndex++;
+ }
+
+ // If no font can match the char, then use the first font
+ if (fontIndex == fonts.Count()) {
+ fontIndex = 0;
+ }
+ // Get character entry
+ fonts[fontIndex]->GetCharacter(currentChar, entry);
+ maxHeight = Math::Max(maxHeight, static_cast(fonts[fontIndex]->GetHeight()));
+
+ // Get kerning, only when the font hasn't changed
+ if (!isWhitespace && previous.IsValid && previousFontIndex == fontIndex)
+ {
+ kerning = fonts[fontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ else
+ {
+ kerning = 0;
+ }
+ previous = entry;
+ previousFontIndex = fontIndex;
+ xAdvance = (kerning + entry.AdvanceX) * scale;
+
+ // Check if character fits the line or skip wrapping
+ if (cursorX + xAdvance <= boundsWidth || layout.TextWrapping == TextWrapping::NoWrap)
+ {
+ // Move character
+ cursorX += xAdvance;
+ tmpLine.LastCharIndex++;
+ }
+ else if (layout.TextWrapping == TextWrapping::WrapWords)
+ {
+ if (lastWrapCharIndex != INVALID_INDEX)
+ {
+ // Skip moving twice for the same character
+ int32 lastLineLasCharIndex = outputLines.HasItems() ? outputLines.Last().LastCharIndex : -10000;
+ if (lastLineLasCharIndex == lastWrapCharIndex || lastLineLasCharIndex == lastWrapCharIndex - 1 || lastLineLasCharIndex == lastWrapCharIndex - 2)
+ {
+ currentIndex = nextCharIndex;
+ lastMoveLine = moveLine;
+ continue;
+ }
+
+ // Move line
+ const Char wrapChar = text[lastWrapCharIndex];
+ moveLine = true;
+ cursorX = lastWrapCharX;
+ if (StringUtils::IsWhitespace(wrapChar))
+ {
+ // Skip whitespaces
+ tmpLine.LastCharIndex = lastWrapCharIndex - 1;
+ nextCharIndex = currentIndex = lastWrapCharIndex + 1;
+ }
+ else
+ {
+ tmpLine.LastCharIndex = lastWrapCharIndex - 1;
+ nextCharIndex = currentIndex = lastWrapCharIndex;
+ }
+ }
+ }
+ else if (layout.TextWrapping == TextWrapping::WrapChars)
+ {
+ // Move line
+ moveLine = true;
+ nextCharIndex = currentIndex;
+
+ // Skip moving twice for the same character
+ if (lastMoveLine)
+ break;
+ }
+ }
+
+ // Check if move to another line
+ if (moveLine)
+ {
+ // Add line
+ tmpLine.Size.X = cursorX;
+ tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
+ tmpLine.LastCharIndex = Math::Max(tmpLine.LastCharIndex, tmpLine.FirstCharIndex);
+ outputLines.Add(tmpLine);
+
+ // Reset line
+ tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
+ tmpLine.FirstCharIndex = currentIndex;
+ tmpLine.LastCharIndex = currentIndex - 1;
+ cursorX = 0;
+ lastWrapCharIndex = INVALID_INDEX;
+ lastWrapCharX = 0;
+ previous.IsValid = false;
+
+ // Reset max font height
+ maxHeight = 0;
+ }
+
+ currentIndex = nextCharIndex;
+ lastMoveLine = moveLine;
+ }
+
+ if (textLength != 0 && (tmpLine.LastCharIndex >= tmpLine.FirstCharIndex || text[textLength - 1] == '\n'))
+ {
+ // Add line
+ tmpLine.Size.X = cursorX;
+ tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
+ tmpLine.LastCharIndex = textLength - 1;
+ outputLines.Add(tmpLine);
+
+ tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
+ }
+
+ // Check amount of lines
+ if (outputLines.IsEmpty())
+ return;
+
+ float totalHeight = tmpLine.Location.Y;
+
+ Float2 offset = Float2::Zero;
+ if (layout.VerticalAlignment == TextAlignment::Center)
+ {
+ offset.Y += (layout.Bounds.GetHeight() - totalHeight) * 0.5f;
+ }
+ else if (layout.VerticalAlignment == TextAlignment::Far)
+ {
+ offset.Y += layout.Bounds.GetHeight() - totalHeight;
+ }
+ for (int32 i = 0; i < outputLines.Count(); i++)
+ {
+ FontLineCache& line = outputLines[i];
+ Float2 rootPos = line.Location + offset;
+
+ // Fix upper left line corner to match desire text alignment
+ if (layout.HorizontalAlignment == TextAlignment::Center)
+ {
+ rootPos.X += (layout.Bounds.GetWidth() - line.Size.X) * 0.5f;
+ }
+ else if (layout.HorizontalAlignment == TextAlignment::Far)
+ {
+ rootPos.X += layout.Bounds.GetWidth() - line.Size.X;
+ }
+
+ line.Location = rootPos;
+ }
+}
+
Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
@@ -432,6 +632,11 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
return rootOffset + Float2(lines.Last().Size.X, static_cast((lines.Count() - 1) * baseLinesDistance));
}
+bool Font::ContainsChar(Char c)
+{
+ return FT_Get_Char_Index(GetAsset()->GetFTFace(), c) > 0;
+}
+
void Font::FlushFaceSize() const
{
// Set the character size
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index 90f723cd8..d8ac1b708 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -339,6 +339,15 @@ public:
/// The output lines list.
void ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The font list.
+ /// The input text.
+ /// The layout properties.
+ /// The output lines list.
+ static void ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
+
///
/// Processes text to get cached lines for rendering.
///
@@ -395,6 +404,15 @@ public:
/// The minimum size for that text and fot to render properly.
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text.
+ ///
+ /// The fonts to render with.
+ /// The input text to test.
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() static Float2 MeasureText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+
///
/// Measures minimum size of the rectangle that will be needed to draw given text.
///
@@ -482,6 +500,16 @@ public:
/// The character position (upper left corner which can be used for a caret position).
API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+ ///
+ /// Calculates character position for given text and character index.
+ ///
+ /// The fonts to use.
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() static Float2 GetCharPosition(const Array& fonts, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+
///
/// Calculates character position for given text and character index.
///
@@ -518,6 +546,13 @@ public:
return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
}
+ ///
+ /// Check if the font contains the glyph of a char
+ ///
+ /// The char to test.
+ /// True if the font contains the glyph of the char, otherwise false.
+ API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c);
+
///
/// Flushes the size of the face with the Free Type library backend.
///
diff --git a/Source/Engine/Render2D/FontManager.cpp b/Source/Engine/Render2D/FontManager.cpp
index bb7edf974..5b08c1d87 100644
--- a/Source/Engine/Render2D/FontManager.cpp
+++ b/Source/Engine/Render2D/FontManager.cpp
@@ -155,6 +155,9 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
// Get the index to the glyph in the font face
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
+ if (glyphIndex == 0) {
+ LOG(Warning, "Font `{}` doesn't contain character `\\u{:x}`, consider choosing another font. ", String(face->family_name), c);
+ }
// Load the glyph
const FT_Error error = FT_Load_Glyph(face, glyphIndex, glyphFlags);
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index b56c3e1a2..eedfbeffe 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -27,11 +27,11 @@
#if USE_EDITOR
#define RENDER2D_CHECK_RENDERING_STATE \
- if (!Render2D::IsRendering()) \
- { \
- LOG(Error, "Calling Render2D is only valid during rendering."); \
- return; \
- }
+ if (!Render2D::IsRendering()) \
+ { \
+ LOG(Error, "Calling Render2D is only valid during rendering."); \
+ return; \
+ }
#else
#define RENDER2D_CHECK_RENDERING_STATE
#endif
@@ -54,7 +54,7 @@ const bool DownsampleForBlur = false;
PACK_STRUCT(struct Data {
Matrix ViewProjection;
- });
+});
PACK_STRUCT(struct BlurData {
Float2 InvBufferSize;
@@ -62,7 +62,7 @@ PACK_STRUCT(struct BlurData {
float Dummy0;
Float4 Bounds;
Float4 WeightAndOffsets[RENDER2D_BLUR_MAX_SAMPLES / 2];
- });
+});
enum class DrawCallType : byte
{
@@ -1174,7 +1174,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
drawCall.AsChar.Mat = nullptr;
}
Float2 pointer = location;
- for (int32 currentIndex = 0; currentIndex <= text.Length(); currentIndex++)
+ for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
{
// Cache current character
const Char currentChar = text[currentIndex];
@@ -1368,6 +1368,318 @@ void Render2D::DrawText(Font* font, const StringView& text, const TextRange& tex
DrawText(font, textRange.Substring(text), color, layout, customMaterial);
}
+void Render2D::DrawText(const Array& fonts, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
+{
+ RENDER2D_CHECK_RENDERING_STATE;
+
+ // Check if there is no need to do anything
+ if (fonts.IsEmpty() || text.Length() < 0)
+ return;
+
+ // Temporary data
+ uint32 fontAtlasIndex = 0;
+ FontTextureAtlas* fontAtlas = nullptr;
+ Float2 invAtlasSize = Float2::One;
+ FontCharacterEntry previous;
+ int32 kerning;
+ float scale = 1.0f / FontManager::FontScale;
+
+ // Render all characters
+ FontCharacterEntry entry;
+ Render2DDrawCall drawCall;
+ if (customMaterial)
+ {
+ drawCall.Type = DrawCallType::DrawCharMaterial;
+ drawCall.AsChar.Mat = customMaterial;
+ }
+ else
+ {
+ drawCall.Type = DrawCallType::DrawChar;
+ drawCall.AsChar.Mat = nullptr;
+ }
+
+ // The following code cut the text into segments, according to the font used to render
+ Float2 pointer = location;
+ // The starting index of the current segment
+ int32 startIndex = 0;
+ // The index of the font used by the current segment
+ int32 segmentFontIndex = 0;
+ // The maximum font height of the current line
+ float maxHeight = 0;
+ for (int32 currentIndex = 0; currentIndex <= text.Length(); currentIndex++)
+ {
+ // Cache current character
+ const Char currentChar = currentIndex < text.Length() ? text[currentIndex] : 0;
+
+ // Check if it isn't a newline character
+ if (currentChar != '\n')
+ {
+ int32 fontIndex = 0;
+ if (currentIndex < text.Length()) {
+ while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(currentChar))
+ {
+ fontIndex++;
+ }
+
+ // If no font can match the char, then use the segment font
+ if (fontIndex == fonts.Count()) {
+ fontIndex = segmentFontIndex;
+ }
+
+ // Do nothing if the char still belongs to the current segment
+ if (fontIndex == segmentFontIndex) {
+ continue;
+ }
+ }
+
+ // Render the pending segment before beginning the new segment
+ renderText:auto fontHeight = fonts[segmentFontIndex]->GetHeight();
+ maxHeight = Math::Max(maxHeight, static_cast(fontHeight));
+ auto fontDescender = fonts[segmentFontIndex]->GetDescender();
+ for (int32 renderIndex = startIndex; renderIndex < currentIndex; renderIndex++)
+ {
+ // Get character entry
+ fonts[segmentFontIndex]->GetCharacter(text[renderIndex], entry);
+
+ // Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
+ if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
+ {
+ // Get texture atlas that contains current character
+ fontAtlasIndex = entry.TextureIndex;
+ fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
+ if (fontAtlas)
+ {
+ fontAtlas->EnsureTextureCreated();
+ drawCall.AsChar.Tex = fontAtlas->GetTexture();
+ invAtlasSize = 1.0f / fontAtlas->GetSize();
+ }
+ else
+ {
+ drawCall.AsChar.Tex = nullptr;
+ invAtlasSize = 1.0f;
+ }
+ }
+
+ // Check if character is a whitespace
+ const bool isWhitespace = StringUtils::IsWhitespace(text[renderIndex]);
+
+ // Get kerning
+ if (!isWhitespace && previous.IsValid)
+ {
+ kerning = fonts[segmentFontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ else
+ {
+ kerning = 0;
+ }
+ pointer.X += kerning * scale;
+ previous = entry;
+
+ // Omit whitespace characters
+ if (!isWhitespace)
+ {
+ // Calculate character size and atlas coordinates
+ const float x = pointer.X + entry.OffsetX * scale;
+ const float y = pointer.Y + (fontHeight + fontDescender - entry.OffsetY) * scale;
+
+ Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
+
+ Float2 upperLeftUV = entry.UV * invAtlasSize;
+ Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
+
+ // Add draw call
+ drawCall.StartIB = IBIndex;
+ drawCall.CountIB = 6;
+ DrawCalls.Add(drawCall);
+ WriteRect(charRect, color, upperLeftUV, rightBottomUV);
+ }
+
+ // Move
+ pointer.X += entry.AdvanceX * scale;
+ }
+
+ // Start new segment
+ startIndex = currentIndex;
+ segmentFontIndex = fontIndex;
+
+ if (currentIndex == text.Length() - 1) {
+ currentIndex++;
+ goto renderText;
+ }
+ }
+ else
+ {
+ // Move
+ pointer.X = location.X;
+ pointer.Y += maxHeight * scale;
+ // Clear max height
+ maxHeight = 0;
+ }
+ }
+}
+
+void Render2D::DrawText(const Array& fonts, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
+{
+ DrawText(fonts, textRange.Substring(text), color, location, customMaterial);
+}
+
+void Render2D::DrawText(const Array& fonts, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+{
+ RENDER2D_CHECK_RENDERING_STATE;
+
+ // Check if there is no need to do anything
+ if (fonts.IsEmpty() || text.IsEmpty() || layout.Scale <= ZeroTolerance)
+ return;
+
+ // Temporary data
+ uint32 fontAtlasIndex = 0;
+ FontTextureAtlas* fontAtlas = nullptr;
+ Float2 invAtlasSize = Float2::One;
+ FontCharacterEntry previous;
+ int32 kerning;
+ float scale = layout.Scale / FontManager::FontScale;
+
+ // Process text to get lines
+ Lines.Clear();
+ Font::ProcessText(fonts, text, Lines, layout);
+
+ // Render all lines
+ FontCharacterEntry entry;
+ Render2DDrawCall drawCall;
+ if (customMaterial)
+ {
+ drawCall.Type = DrawCallType::DrawCharMaterial;
+ drawCall.AsChar.Mat = customMaterial;
+ }
+ else
+ {
+ drawCall.Type = DrawCallType::DrawChar;
+ drawCall.AsChar.Mat = nullptr;
+ }
+
+ for (int32 lineIndex = 0; lineIndex < Lines.Count(); lineIndex++)
+ {
+ const FontLineCache& line = Lines[lineIndex];
+
+ // The following code cut the text into segments, according to the font used to render
+ Float2 pointer = line.Location;
+ // The starting index of the current segment
+ int32 startIndex = line.FirstCharIndex;
+ // The index of the font used by the current segment
+ int32 segmentFontIndex = 0;
+ // The maximum font height of the current line
+ float maxHeight = 0;
+
+ // Partition and render all characters from the line
+ for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex + 1; charIndex++)
+ {
+ const Char c = charIndex <= line.LastCharIndex ? text[charIndex] : 0;
+
+ if (c != '\n')
+ {
+ int32 fontIndex = 0;
+ if (charIndex <= line.LastCharIndex) {
+ while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(c))
+ {
+ fontIndex++;
+ }
+
+ // If no font can match the char, then use the segment font
+ if (fontIndex == fonts.Count()) {
+ fontIndex = segmentFontIndex;
+ }
+
+
+ // Do nothing if the char still belongs to the current segment
+ if (fontIndex == segmentFontIndex) {
+ continue;
+ }
+ }
+
+
+ // Render the pending segment before beginning the new segment
+ auto fontHeight = fonts[segmentFontIndex]->GetHeight();
+ maxHeight = Math::Max(maxHeight, static_cast(fontHeight));
+ auto fontDescender = fonts[segmentFontIndex]->GetDescender();
+
+ const Char* pred = L"Type";
+ if (text.Substring(0, Math::Min(4, text.Length())) == pred) {
+ // __debugbreak();
+ }
+ for (int32 renderIndex = startIndex; renderIndex < charIndex; renderIndex++)
+ {
+ // Get character entry
+ fonts[segmentFontIndex]->GetCharacter(text[renderIndex], entry);
+
+ // Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
+ if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
+ {
+ // Get texture atlas that contains current character
+ fontAtlasIndex = entry.TextureIndex;
+ fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
+ if (fontAtlas)
+ {
+ fontAtlas->EnsureTextureCreated();
+ invAtlasSize = 1.0f / fontAtlas->GetSize();
+ drawCall.AsChar.Tex = fontAtlas->GetTexture();
+ }
+ else
+ {
+ invAtlasSize = 1.0f;
+ drawCall.AsChar.Tex = nullptr;
+ }
+ }
+
+ // Get kerning
+ const bool isWhitespace = StringUtils::IsWhitespace(text[renderIndex]);
+ if (!isWhitespace && previous.IsValid)
+ {
+ kerning = fonts[segmentFontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ else
+ {
+ kerning = 0;
+ }
+ pointer.X += (float)kerning * scale;
+ previous = entry;
+
+ // Omit whitespace characters
+ if (!isWhitespace)
+ {
+ // Calculate character size and atlas coordinates
+ const float x = pointer.X + entry.OffsetX * scale;
+ const float y = pointer.Y - entry.OffsetY * scale + Math::Ceil((fontHeight + fontDescender) * scale);
+
+ Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
+ charRect.Offset(layout.Bounds.Location);
+
+ Float2 upperLeftUV = entry.UV * invAtlasSize;
+ Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
+
+ // Add draw call
+ drawCall.StartIB = IBIndex;
+ drawCall.CountIB = 6;
+ DrawCalls.Add(drawCall);
+ WriteRect(charRect, color, upperLeftUV, rightBottomUV);
+ }
+
+ // Move
+ pointer.X += entry.AdvanceX * scale;
+ }
+
+ // Start new segment
+ startIndex = charIndex;
+ segmentFontIndex = fontIndex;
+ }
+ }
+ }
+}
+
+void Render2D::DrawText(const Array& fonts, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+{
+ DrawText(fonts, textRange.Substring(text), color, layout, customMaterial);
+}
+
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
{
return (color.A * TintLayersStack.Peek().A) < 1.0f;
@@ -1931,7 +2243,7 @@ void Render2D::DrawBlur(const Rectangle& rect, float blurStrength)
void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span& vertices, const Span& uvs)
{
RENDER2D_CHECK_RENDERING_STATE;
- CHECK(vertices.Length() == uvs.Length())
+ CHECK(vertices.Length() == uvs.Length());
Render2DDrawCall& drawCall = DrawCalls.AddOne();
drawCall.Type = DrawCallType::FillTexture;
@@ -1977,7 +2289,7 @@ void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span& indices,
drawCall.StartIB = IBIndex;
drawCall.CountIB = indices.Length();
drawCall.AsTexture.Ptr = t;
-
+
for (int32 i = 0; i < indices.Length();)
{
const uint16 i0 = indices.Get()[i++];
diff --git a/Source/Engine/Render2D/Render2D.cs b/Source/Engine/Render2D/Render2D.cs
index c4d9e81b4..a73556f7b 100644
--- a/Source/Engine/Render2D/Render2D.cs
+++ b/Source/Engine/Render2D/Render2D.cs
@@ -152,6 +152,59 @@ namespace FlaxEngine
DrawText(font, text, color, ref layout, customMaterial);
}
+ ///
+ /// Draws a text.
+ ///
+ /// The fonts to use, ordered by priority.
+ /// The text to render.
+ /// The size and position of the area in which the text is drawn.
+ /// The text color.
+ /// The horizontal alignment of the text in a layout rectangle.
+ /// The vertical alignment of the text in a layout rectangle.
+ /// Describes how wrap text inside a layout rectangle.
+ /// The scale for distance one baseline from another. Default is 1.
+ /// The text drawing scale. Default is 1.
+ public static void DrawText(Font[] fonts, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+ DrawText(fonts, text, color, ref layout);
+ }
+
+ ///
+ /// Draws a text using a custom material shader. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling).
+ ///
+ /// The fonts to use, ordered by priority.
+ /// Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ /// The text to render.
+ /// The size and position of the area in which the text is drawn.
+ /// The text color.
+ /// The horizontal alignment of the text in a layout rectangle.
+ /// The vertical alignment of the text in a layout rectangle.
+ /// Describes how wrap text inside a layout rectangle.
+ /// The scale for distance one baseline from another. Default is 1.
+ /// The text drawing scale. Default is 1.
+ public static void DrawText(Font[] fonts, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+ DrawText(fonts, text, color, ref layout, customMaterial);
+ }
+
///
/// Calls drawing GUI to the texture.
///
diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h
index 2b890ced9..0ec88edc0 100644
--- a/Source/Engine/Render2D/Render2D.h
+++ b/Source/Engine/Render2D/Render2D.h
@@ -33,7 +33,7 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
///
/// The rendering features and options flags.
///
- API_ENUM(Attributes="Flags") enum class RenderingFeatures
+ API_ENUM(Attributes = "Flags") enum class RenderingFeatures
{
///
/// The none.
@@ -215,6 +215,49 @@ public:
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
API_FUNCTION() static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ ///
+ /// Draws a text.
+ ///
+ /// The fonts to use, ordered by priority.
+ /// The text to render.
+ /// The input text range (substring range of the input text parameter).
+ /// The text color.
+ /// The text location.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+
+ ///
+ /// Draws a text with formatting.
+ ///
+ /// The fonts to use, ordered by priority.
+ /// The text to render.
+ /// The text color.
+ /// The text layout properties.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+
+ ///
+ /// Draws a text with formatting.
+ ///
+ /// The fonts to use, ordered by priority.
+ /// The text to render.
+ /// The input text range (substring range of the input text parameter).
+ /// The text color.
+ /// The text layout properties.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+
+ ///
+ /// Draws a text with formatting.
+ ///
+ /// The fonts to use, ordered by priority.
+ /// The text to render.
+ /// The input text range (substring range of the input text parameter).
+ /// The text color.
+ /// The text layout properties.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+
///
/// Fills a rectangle area.
///
diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs
index 188333ff1..8e71c9f31 100644
--- a/Source/Engine/Scripting/Scripting.cs
+++ b/Source/Engine/Scripting/Scripting.cs
@@ -295,12 +295,13 @@ namespace FlaxEngine
// Use optionally bundled default font (matches Editor)
var defaultFont = Content.LoadAsyncInternal("Editor/Fonts/Roboto-Regular");
+ var cjkFont = Content.LoadAsyncInternal("NotoSansSC-Medium");
if (defaultFont)
{
style.FontTitle = defaultFont.CreateFont(18);
style.FontLarge = defaultFont.CreateFont(14);
- style.FontMedium = defaultFont.CreateFont(9);
- style.FontSmall = defaultFont.CreateFont(9);
+ style.FontMedium = new Font[] { defaultFont.CreateFont(9), cjkFont.CreateFont(9) };
+ style.FontSmall = new Font[] { defaultFont.CreateFont(9), cjkFont.CreateFont(9) };
}
Style.Current = style;
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index 02337411b..1b965b8d1 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -155,7 +156,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
if (style != null)
{
- _font = new FontReference(style.FontMedium);
+ _font = new FontReference(style.FontMedium.First());
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BorderColor = style.BorderNormal;
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index ecca2978f..21ca9cbea 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -358,7 +359,7 @@ namespace FlaxEngine.GUI
: base(0, 0, 120, 18.0f)
{
var style = Style.Current;
- Font = new FontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium.First());
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BackgroundColorHighlighted = BackgroundColor;
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index 3c7c04fb2..b92e762e1 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -1,6 +1,8 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using FlaxEditor.Options;
using System.ComponentModel;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -190,7 +192,7 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
- Font = new FontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium.First());
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
@@ -201,7 +203,7 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
- Font = new FontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium.First());
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
@@ -233,7 +235,7 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ Render2D.DrawText(new Font[] { _font.GetFont(), Style.Current.FontCJK }, Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
Render2D.PopClip();
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.cs b/Source/Engine/UI/GUI/Common/RichTextBox.cs
index ab922d93d..e6a82c986 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -45,7 +46,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
_textStyle = new TextBlockStyle
{
- Font = new FontReference(style.FontMedium),
+ Font = new FontReference(style.FontMedium.First()),
Color = style.Foreground,
BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected),
};
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index ee4f744a6..967617649 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -1,5 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using System.Linq;
+
namespace FlaxEngine.GUI
{
///
@@ -88,7 +90,7 @@ namespace FlaxEngine.GUI
_layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
var style = Style.Current;
- Font = new FontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium.First());
TextColor = style.Foreground;
WatermarkTextColor = style.ForegroundDisabled;
SelectionColor = style.BackgroundSelected;
diff --git a/Source/Engine/UI/GUI/Panels/DropPanel.cs b/Source/Engine/UI/GUI/Panels/DropPanel.cs
index 66e7413eb..33c2e1605 100644
--- a/Source/Engine/UI/GUI/Panels/DropPanel.cs
+++ b/Source/Engine/UI/GUI/Panels/DropPanel.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -237,7 +238,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
HeaderColor = style.BackgroundNormal;
HeaderColorMouseOver = style.BackgroundHighlighted;
- HeaderTextFont = new FontReference(style.FontMedium);
+ HeaderTextFont = new FontReference(style.FontMedium.First());
HeaderTextColor = style.Foreground;
ArrowImageOpened = new SpriteBrush(style.ArrowDown);
ArrowImageClosed = new SpriteBrush(style.ArrowRight);
diff --git a/Source/Engine/UI/GUI/Style.cs b/Source/Engine/UI/GUI/Style.cs
index 22b8f52af..d3375a670 100644
--- a/Source/Engine/UI/GUI/Style.cs
+++ b/Source/Engine/UI/GUI/Style.cs
@@ -1,5 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using System.Linq;
+
namespace FlaxEngine.GUI
{
///
@@ -12,6 +14,14 @@ namespace FlaxEngine.GUI
///
public static Style Current { get; set; }
+ public Font FontCJK
+ {
+ get => _fontCJK?.GetFont();
+ set => _fontCJK = new FontReference(value);
+ }
+
+ private FontReference _fontCJK;
+
[Serialize]
private FontReference _fontTitle;
@@ -41,31 +51,31 @@ namespace FlaxEngine.GUI
}
[Serialize]
- private FontReference _fontMedium;
+ private FontReference[] _fontMedium;
///
/// The font medium.
///
[NoSerialize]
[EditorOrder(30)]
- public Font FontMedium
+ public Font[] FontMedium
{
- get => _fontMedium?.GetFont();
- set => _fontMedium = new FontReference(value);
+ get => _fontMedium?.Select((x)=>x.GetFont()).ToArray();
+ set => _fontMedium = value.Select((x)=>new FontReference(x)).ToArray();
}
[Serialize]
- private FontReference _fontSmall;
+ private FontReference[] _fontSmall;
///
/// The font small.
///
[NoSerialize]
[EditorOrder(40)]
- public Font FontSmall
+ public Font[] FontSmall
{
- get => _fontSmall?.GetFont();
- set => _fontSmall = new FontReference(value);
+ get => _fontSmall?.Select((x) => x.GetFont()).ToArray();
+ set => _fontSmall = value.Select((x) => new FontReference(x)).ToArray();
}
///
diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs
index 734fb078f..e17b754c4 100644
--- a/Source/Engine/UI/GUI/Tooltip.cs
+++ b/Source/Engine/UI/GUI/Tooltip.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -255,14 +256,14 @@ namespace FlaxEngine.GUI
// Calculate size of the tooltip
var size = Float2.Zero;
- if (style != null && style.FontMedium && !string.IsNullOrEmpty(_currentText))
+ if (style != null && style.FontMedium.First() && !string.IsNullOrEmpty(_currentText))
{
var layout = TextLayoutOptions.Default;
layout.Bounds = new Rectangle(0, 0, MaxWidth, 10000000);
layout.HorizontalAlignment = TextAlignment.Center;
layout.VerticalAlignment = TextAlignment.Center;
layout.TextWrapping = TextWrapping.WrapWords;
- var items = style.FontMedium.ProcessText(_currentText, ref layout);
+ var items = style.FontMedium.First().ProcessText(_currentText, ref layout);
for (int i = 0; i < items.Length; i++)
{
ref var item = ref items[i];
From a3bc394e4e0279c51b3acb133a6ad8ef5a2f27bf Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Wed, 29 Nov 2023 15:04:29 +0800
Subject: [PATCH 02/16] Fix a bunch of rendering bugs
---
.gitignore | 1 +
Source/Editor/EditorAssets.cs | 2 +-
Source/Engine/Render2D/Font.cpp | 133 ++++++++++----
Source/Engine/Render2D/Font.h | 39 +++-
Source/Engine/Render2D/MultiFont.cpp | 1 +
Source/Engine/Render2D/MultiFont.h | 77 ++++++++
Source/Engine/Render2D/Render2D.cpp | 266 +++++++++++++--------------
Source/Engine/UI/GUI/Common/Label.cs | 2 +-
8 files changed, 332 insertions(+), 189 deletions(-)
create mode 100644 Source/Engine/Render2D/MultiFont.cpp
create mode 100644 Source/Engine/Render2D/MultiFont.h
diff --git a/.gitignore b/.gitignore
index b7e11e554..b653b7f77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -157,3 +157,4 @@ obj/
.idea/
*.code-workspace
omnisharp.json
+Content/Editor/Fonts/NotoSansSC-Regular.flax
diff --git a/Source/Editor/EditorAssets.cs b/Source/Editor/EditorAssets.cs
index 237908a0c..0fe5ee47e 100644
--- a/Source/Editor/EditorAssets.cs
+++ b/Source/Editor/EditorAssets.cs
@@ -54,7 +54,7 @@ namespace FlaxEditor
///
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
- public static string CJKFont = "Editor/Fonts/NotoSansSC-Medium";
+ public static string CJKFont = "Editor/Fonts/NotoSansSC-Regular";
///
/// The Inconsolata Regular font.
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index 13b17197c..277ad8ddd 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -6,6 +6,7 @@
#include "Engine/Core/Log.h"
#include "Engine/Threading/Threading.h"
#include "IncludeFreeType.h"
+#include "MultiFont.h"
Font::Font(FontAsset* parentAsset, float size)
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer))
@@ -118,6 +119,10 @@ void Font::ProcessText(const StringView& text, Array& outputLines
tmpLine.FirstCharIndex = 0;
tmpLine.LastCharIndex = -1;
+ if (textLength == 0) {
+ return;
+ }
+
int32 lastWrapCharIndex = INVALID_INDEX;
float lastWrapCharX = 0;
bool lastMoveLine = false;
@@ -129,6 +134,11 @@ void Font::ProcessText(const StringView& text, Array& outputLines
float xAdvance = 0;
int32 nextCharIndex = currentIndex + 1;
+ // Submit line if text ends
+ if (nextCharIndex == textLength) {
+ moveLine = true;
+ }
+
// Cache current character
const Char currentChar = text[currentIndex];
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
@@ -146,7 +156,6 @@ void Font::ProcessText(const StringView& text, Array& outputLines
{
// Break line
moveLine = true;
- currentIndex++;
tmpLine.LastCharIndex++;
}
else
@@ -178,8 +187,8 @@ void Font::ProcessText(const StringView& text, Array& outputLines
if (lastWrapCharIndex != INVALID_INDEX)
{
// Skip moving twice for the same character
- int32 lastLineLasCharIndex = outputLines.HasItems() ? outputLines.Last().LastCharIndex : -10000;
- if (lastLineLasCharIndex == lastWrapCharIndex || lastLineLasCharIndex == lastWrapCharIndex - 1 || lastLineLasCharIndex == lastWrapCharIndex - 2)
+ int32 lastLineLastCharIndex = outputLines.HasItems() ? outputLines.Last().LastCharIndex : -10000;
+ if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
{
currentIndex = nextCharIndex;
lastMoveLine = moveLine;
@@ -226,8 +235,8 @@ void Font::ProcessText(const StringView& text, Array& outputLines
// Reset line
tmpLine.Location.Y += baseLinesDistance;
- tmpLine.FirstCharIndex = currentIndex;
- tmpLine.LastCharIndex = currentIndex - 1;
+ tmpLine.FirstCharIndex = nextCharIndex;
+ tmpLine.LastCharIndex = nextCharIndex - 1;
cursorX = 0;
lastWrapCharIndex = INVALID_INDEX;
lastWrapCharX = 0;
@@ -238,7 +247,8 @@ void Font::ProcessText(const StringView& text, Array& outputLines
lastMoveLine = moveLine;
}
- if (textLength != 0 && (tmpLine.LastCharIndex >= tmpLine.FirstCharIndex || text[textLength - 1] == '\n'))
+ // Check if an additional line should be created
+ if (text[textLength - 1] == '\n')
{
// Add line
tmpLine.Size.X = cursorX;
@@ -283,84 +293,101 @@ void Font::ProcessText(const StringView& text, Array& outputLines
}
}
-void Font::ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
+void Font::ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
{
float cursorX = 0;
int32 kerning;
- FontLineCache tmpLine;
+ MultiFontLineCache tmpLine;
+ MultiFontSegmentCache tmpSegment;
FontCharacterEntry entry;
FontCharacterEntry previous;
int32 textLength = text.Length();
float scale = layout.Scale / FontManager::FontScale;
float boundsWidth = layout.Bounds.GetWidth();
float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
+
+ tmpSegment.Location = Float2::Zero;
+ tmpSegment.Height = 0;
+ tmpSegment.FirstCharIndex = 0;
+ tmpSegment.LastCharIndex = -1;
+
tmpLine.Location = Float2::Zero;
tmpLine.Size = Float2::Zero;
- tmpLine.FirstCharIndex = 0;
- tmpLine.LastCharIndex = -1;
+ tmpLine.Segments = Array();
+
+ if (textLength == 0) {
+ return;
+ }
int32 lastWrapCharIndex = INVALID_INDEX;
float lastWrapCharX = 0;
bool lastMoveLine = false;
-
- int32 previousFontIndex = -1;
+ // The index of the font used by the current segment
+ int32 currentFontIndex = GetCharFontIndex(fonts, text[0], 0);
// The maximum font height of the current line
float maxHeight = 0;
+ float maxAscender = 0;
+
// Process each character to split text into single lines
for (int32 currentIndex = 0; currentIndex < textLength;)
{
bool moveLine = false;
+ bool moveSegment = false;
float xAdvance = 0;
int32 nextCharIndex = currentIndex + 1;
+ // Submit line and segment if text ends
+ if (nextCharIndex == textLength) {
+ moveLine = moveSegment = true;
+ }
+
// Cache current character
const Char currentChar = text[currentIndex];
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
// Check if character can wrap words
- const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar);
+ const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar) || (currentChar >= 0x3040 && currentChar <= 0x9FFF);
if (isWrapChar && currentIndex != 0)
{
lastWrapCharIndex = currentIndex;
lastWrapCharX = cursorX;
}
+ int32 nextFontIndex = currentFontIndex;
// Check if it's a newline character
if (currentChar == '\n')
{
// Break line
- moveLine = true;
- currentIndex++;
- tmpLine.LastCharIndex++;
+ moveLine = moveSegment = true;
+ tmpSegment.LastCharIndex++;
}
else
{
// Get character entry
- int32 fontIndex = 0;
- while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(currentChar))
- {
- fontIndex++;
+ if (nextCharIndex < textLength) {
+ nextFontIndex = GetCharFontIndex(fonts, text[nextCharIndex], currentFontIndex);
}
- // If no font can match the char, then use the first font
- if (fontIndex == fonts.Count()) {
- fontIndex = 0;
- }
// Get character entry
- fonts[fontIndex]->GetCharacter(currentChar, entry);
- maxHeight = Math::Max(maxHeight, static_cast(fonts[fontIndex]->GetHeight()));
+ fonts[currentFontIndex]->GetCharacter(currentChar, entry);
+ maxHeight = Math::Max(maxHeight, static_cast(fonts[currentFontIndex]->GetHeight()));
+ maxAscender = Math::Max(maxAscender, static_cast(fonts[currentFontIndex]->GetAscender()));
+
+ // Move segment if the font changes or text ends
+ if (nextFontIndex != currentFontIndex || nextCharIndex == textLength) {
+ moveSegment = true;
+ }
// Get kerning, only when the font hasn't changed
- if (!isWhitespace && previous.IsValid && previousFontIndex == fontIndex)
+ if (!isWhitespace && previous.IsValid && !moveSegment)
{
- kerning = fonts[fontIndex]->GetKerning(previous.Character, entry.Character);
+ kerning = fonts[currentFontIndex]->GetKerning(previous.Character, entry.Character);
}
else
{
kerning = 0;
}
previous = entry;
- previousFontIndex = fontIndex;
xAdvance = (kerning + entry.AdvanceX) * scale;
// Check if character fits the line or skip wrapping
@@ -368,15 +395,15 @@ void Font::ProcessText(const Array& fonts, const StringView& text, Array<
{
// Move character
cursorX += xAdvance;
- tmpLine.LastCharIndex++;
+ tmpSegment.LastCharIndex++;
}
else if (layout.TextWrapping == TextWrapping::WrapWords)
{
if (lastWrapCharIndex != INVALID_INDEX)
{
// Skip moving twice for the same character
- int32 lastLineLasCharIndex = outputLines.HasItems() ? outputLines.Last().LastCharIndex : -10000;
- if (lastLineLasCharIndex == lastWrapCharIndex || lastLineLasCharIndex == lastWrapCharIndex - 1 || lastLineLasCharIndex == lastWrapCharIndex - 2)
+ int32 lastLineLastCharIndex = outputLines.HasItems() && outputLines.Last().Segments.HasItems() ? outputLines.Last().Segments.Last().LastCharIndex : -10000;
+ if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
{
currentIndex = nextCharIndex;
lastMoveLine = moveLine;
@@ -386,16 +413,18 @@ void Font::ProcessText(const Array& fonts, const StringView& text, Array<
// Move line
const Char wrapChar = text[lastWrapCharIndex];
moveLine = true;
+ moveSegment = tmpSegment.FirstCharIndex < lastWrapCharIndex;
+
cursorX = lastWrapCharX;
if (StringUtils::IsWhitespace(wrapChar))
{
// Skip whitespaces
- tmpLine.LastCharIndex = lastWrapCharIndex - 1;
+ tmpSegment.LastCharIndex = lastWrapCharIndex - 1;
nextCharIndex = currentIndex = lastWrapCharIndex + 1;
}
else
{
- tmpLine.LastCharIndex = lastWrapCharIndex - 1;
+ tmpSegment.LastCharIndex = lastWrapCharIndex - 1;
nextCharIndex = currentIndex = lastWrapCharIndex;
}
}
@@ -404,6 +433,7 @@ void Font::ProcessText(const Array& fonts, const StringView& text, Array<
{
// Move line
moveLine = true;
+ moveSegment = tmpSegment.FirstCharIndex < currentChar;
nextCharIndex = currentIndex;
// Skip moving twice for the same character
@@ -412,38 +442,54 @@ void Font::ProcessText(const Array& fonts, const StringView& text, Array<
}
}
+ if (moveSegment) {
+ // Add segment
+ tmpSegment.Height = baseLinesDistanceScale * fonts[currentFontIndex]->GetHeight();
+ tmpSegment.LastCharIndex = Math::Max(tmpSegment.LastCharIndex, tmpSegment.FirstCharIndex);
+ tmpSegment.FontIndex = currentFontIndex;
+ tmpLine.Segments.Add(tmpSegment);
+
+ // Reset segment
+ tmpSegment.Location.X = cursorX;
+ tmpSegment.FirstCharIndex = nextCharIndex;
+ tmpSegment.LastCharIndex = nextCharIndex - 1;
+
+ currentFontIndex = nextFontIndex;
+ }
+
// Check if move to another line
if (moveLine)
{
// Add line
tmpLine.Size.X = cursorX;
tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
- tmpLine.LastCharIndex = Math::Max(tmpLine.LastCharIndex, tmpLine.FirstCharIndex);
+ tmpLine.MaxAscender = maxAscender;
outputLines.Add(tmpLine);
// Reset line
+ tmpLine.Segments.Clear();
tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
- tmpLine.FirstCharIndex = currentIndex;
- tmpLine.LastCharIndex = currentIndex - 1;
cursorX = 0;
+ tmpSegment.Location.X = cursorX;
lastWrapCharIndex = INVALID_INDEX;
lastWrapCharX = 0;
previous.IsValid = false;
// Reset max font height
maxHeight = 0;
+ maxAscender = 0;
}
currentIndex = nextCharIndex;
lastMoveLine = moveLine;
}
- if (textLength != 0 && (tmpLine.LastCharIndex >= tmpLine.FirstCharIndex || text[textLength - 1] == '\n'))
+ // Check if an additional line should be created
+ if (text[textLength - 1] == '\n')
{
// Add line
tmpLine.Size.X = cursorX;
tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
- tmpLine.LastCharIndex = textLength - 1;
outputLines.Add(tmpLine);
tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
@@ -466,7 +512,7 @@ void Font::ProcessText(const Array& fonts, const StringView& text, Array<
}
for (int32 i = 0; i < outputLines.Count(); i++)
{
- FontLineCache& line = outputLines[i];
+ MultiFontLineCache& line = outputLines[i];
Float2 rootPos = line.Location + offset;
// Fix upper left line corner to match desire text alignment
@@ -480,6 +526,13 @@ void Font::ProcessText(const Array& fonts, const StringView& text, Array<
}
line.Location = rootPos;
+
+ // Align all segments to center in case they have different heights
+ for (int32 j = 0; j < line.Segments.Count(); j++)
+ {
+ MultiFontSegmentCache& segment = line.Segments[j];
+ segment.Location.Y += (line.MaxAscender - fonts[segment.FontIndex]->GetAscender()) / 2;
+ }
}
}
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index d8ac1b708..0425f2bc5 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -8,9 +8,11 @@
#include "Engine/Content/AssetReference.h"
#include "Engine/Scripting/ScriptingObject.h"
#include "TextLayoutOptions.h"
+#include "MultiFont.h"
class FontAsset;
struct FontTextureAtlasSlot;
+struct MultiFontLineCache;
// The default DPI that engine is using
#define DefaultDPI 96
@@ -20,7 +22,7 @@ struct FontTextureAtlasSlot;
///
API_STRUCT(NoDefault) struct TextRange
{
-DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
+ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
///
/// The start index (inclusive).
@@ -90,7 +92,7 @@ struct TIsPODType
///
API_STRUCT(NoDefault) struct FontLineCache
{
-DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache);
+ DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache);
///
/// The root position of the line (upper left corner).
@@ -108,7 +110,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache);
API_FIELD() int32 FirstCharIndex;
///
- /// The last character index (from the input text).
+ /// The last character index (from the input text), inclusive.
///
API_FIELD() int32 LastCharIndex;
};
@@ -154,7 +156,7 @@ struct TIsPODType
///
API_STRUCT(NoDefault) struct FontCharacterEntry
{
-DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry);
+ DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry);
///
/// The character represented by this entry.
@@ -223,7 +225,7 @@ struct TIsPODType
///
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API Font : public ManagedScriptingObject
{
-DECLARE_SCRIPTING_TYPE_NO_SPAWN(Font);
+ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Font);
friend FontAsset;
private:
@@ -346,7 +348,7 @@ public:
/// The input text.
/// The layout properties.
/// The output lines list.
- static void ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
+ static void ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
///
/// Processes text to get cached lines for rendering.
@@ -404,6 +406,7 @@ public:
/// The minimum size for that text and fot to render properly.
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+ /*
///
/// Measures minimum size of the rectangle that will be needed to draw given text.
///
@@ -412,6 +415,7 @@ public:
/// The layout properties.
/// The minimum size for that text and fot to render properly.
API_FUNCTION() static Float2 MeasureText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+ */
///
/// Measures minimum size of the rectangle that will be needed to draw given text.
@@ -500,6 +504,7 @@ public:
/// The character position (upper left corner which can be used for a caret position).
API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+ /*
///
/// Calculates character position for given text and character index.
///
@@ -509,6 +514,7 @@ public:
/// The text layout properties.
/// The character position (upper left corner which can be used for a caret position).
API_FUNCTION() static Float2 GetCharPosition(const Array& fonts, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+ */
///
/// Calculates character position for given text and character index.
@@ -553,6 +559,27 @@ public:
/// True if the font contains the glyph of the char, otherwise false.
API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c);
+ ///
+ /// Gets the index of the font that should be used to render the char
+ ///
+ /// The font list.
+ /// The char.
+ /// Number to return if char cannot be found.
+ ///
+ API_FUNCTION() FORCE_INLINE static int32 GetCharFontIndex(const Array& fonts, Char c, int32 missing = -1) {
+ int32 fontIndex = 0;
+ while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(c))
+ {
+ fontIndex++;
+ }
+
+ if (fontIndex == fonts.Count()) {
+ return missing;
+ }
+
+ return fontIndex;
+ }
+
///
/// Flushes the size of the face with the Free Type library backend.
///
diff --git a/Source/Engine/Render2D/MultiFont.cpp b/Source/Engine/Render2D/MultiFont.cpp
new file mode 100644
index 000000000..9844c12e0
--- /dev/null
+++ b/Source/Engine/Render2D/MultiFont.cpp
@@ -0,0 +1 @@
+#include "MultiFont.h"
diff --git a/Source/Engine/Render2D/MultiFont.h b/Source/Engine/Render2D/MultiFont.h
new file mode 100644
index 000000000..b1da832d5
--- /dev/null
+++ b/Source/Engine/Render2D/MultiFont.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include "Engine/Core/Collections/Array.h"
+#include "Engine/Core/Collections/Dictionary.h"
+#include "Font.h"
+
+///
+/// The font segment info generated during text processing.
+///
+API_STRUCT(NoDefault) struct MultiFontSegmentCache
+{
+ DECLARE_SCRIPTING_TYPE_MINIMAL(MultiFontSegmentCache);
+
+ ///
+ /// The root position of the segment (upper left corner), relative to line.
+ ///
+ API_FIELD() Float2 Location;
+
+ ///
+ /// The height of the current segment
+ ///
+ API_FIELD() float Height;
+
+ ///
+ /// The first character index (from the input text).
+ ///
+ API_FIELD() int32 FirstCharIndex;
+
+ ///
+ /// The last character index (from the input text), inclusive.
+ ///
+ API_FIELD() int32 LastCharIndex;
+
+ ///
+ /// The index of the font to render with
+ ///
+ API_FIELD() int32 FontIndex;
+};
+
+template<>
+struct TIsPODType
+{
+ enum { Value = true };
+};
+
+///
+/// Line of font segments info generated during text processing.
+///
+API_STRUCT(NoDefault) struct MultiFontLineCache
+{
+ DECLARE_SCRIPTING_TYPE_MINIMAL(MultiFontLineCache);
+
+ ///
+ /// The root position of the line (upper left corner).
+ ///
+ API_FIELD() Float2 Location;
+
+ ///
+ /// The line bounds (width and height).
+ ///
+ API_FIELD() Float2 Size;
+
+ ///
+ /// The maximum ascendent of the line.
+ ///
+ API_FIELD() float MaxAscender;
+
+ ///
+ /// The index of the font to render with
+ ///
+ API_FIELD() Array Segments;
+};
+
+API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API MultiFont : public ManagedScriptingObject
+{
+ DECLARE_SCRIPTING_TYPE_NO_SPAWN(MultiFont);
+};
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index eedfbeffe..8a39d29be 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -3,6 +3,7 @@
#include "Render2D.h"
#include "Font.h"
#include "FontManager.h"
+#include "MultiFont.h"
#include "FontTextureAtlas.h"
#include "RotatedRectangle.h"
#include "SpriteAtlas.h"
@@ -194,6 +195,7 @@ namespace
// Drawing
Array DrawCalls;
Array Lines;
+ Array MultiFontLines;
Array Lines2;
bool IsScissorsRectEmpty;
bool IsScissorsRectEnabled;
@@ -1384,6 +1386,9 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
int32 kerning;
float scale = 1.0f / FontManager::FontScale;
+ // Process text to get lines
+ Array maxAscenders;
+
// Render all characters
FontCharacterEntry entry;
Render2DDrawCall drawCall;
@@ -1398,48 +1403,70 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
drawCall.AsChar.Mat = nullptr;
}
+ int32 lineIndex = 0;
+ maxAscenders.Add(0);
+ for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
+ {
+ if (text[currentIndex] != '\n') {
+ int32 fontIndex = Font::GetCharFontIndex(fonts, text[currentIndex], 0);
+ maxAscenders[lineIndex] = Math::Max(maxAscenders[lineIndex], static_cast(fonts[fontIndex]->GetAscender()));
+ }
+ else {
+ lineIndex++;
+ maxAscenders.Add(0);
+ }
+ }
+
+ lineIndex = 0;
// The following code cut the text into segments, according to the font used to render
Float2 pointer = location;
// The starting index of the current segment
int32 startIndex = 0;
// The index of the font used by the current segment
- int32 segmentFontIndex = 0;
+ int32 currentFontIndex = Font::GetCharFontIndex(fonts, text[0], 0);
// The maximum font height of the current line
float maxHeight = 0;
- for (int32 currentIndex = 0; currentIndex <= text.Length(); currentIndex++)
+ for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
{
// Cache current character
- const Char currentChar = currentIndex < text.Length() ? text[currentIndex] : 0;
+ const Char currentChar = text[currentIndex];
+ int32 nextCharIndex = currentIndex + 1;
+ bool moveSegment = false;
+ bool moveLine = false;
+ int32 nextFontIndex = currentFontIndex;
+
+ // Submit segment if text ends
+ if (nextCharIndex == text.Length()) {
+ moveSegment = true;
+ }
// Check if it isn't a newline character
if (currentChar != '\n')
{
- int32 fontIndex = 0;
- if (currentIndex < text.Length()) {
- while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(currentChar))
- {
- fontIndex++;
- }
-
- // If no font can match the char, then use the segment font
- if (fontIndex == fonts.Count()) {
- fontIndex = segmentFontIndex;
- }
-
- // Do nothing if the char still belongs to the current segment
- if (fontIndex == segmentFontIndex) {
- continue;
- }
+ // Get character entry
+ if (nextCharIndex < text.Length()) {
+ nextFontIndex = Font::GetCharFontIndex(fonts, text[nextCharIndex], currentFontIndex);
}
+ if (nextFontIndex != currentFontIndex) {
+ moveSegment = true;
+ }
+ }
+ else
+ {
+ // Move
+ moveLine = moveSegment = true;
+ }
+
+ if (moveSegment) {
// Render the pending segment before beginning the new segment
- renderText:auto fontHeight = fonts[segmentFontIndex]->GetHeight();
+ auto fontHeight = fonts[currentFontIndex]->GetHeight();
maxHeight = Math::Max(maxHeight, static_cast(fontHeight));
- auto fontDescender = fonts[segmentFontIndex]->GetDescender();
- for (int32 renderIndex = startIndex; renderIndex < currentIndex; renderIndex++)
+ auto fontDescender = fonts[currentFontIndex]->GetDescender();
+ for (int32 renderIndex = startIndex; renderIndex <= currentIndex; renderIndex++)
{
// Get character entry
- fonts[segmentFontIndex]->GetCharacter(text[renderIndex], entry);
+ fonts[currentFontIndex]->GetCharacter(text[renderIndex], entry);
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
@@ -1466,7 +1493,7 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
// Get kerning
if (!isWhitespace && previous.IsValid)
{
- kerning = fonts[segmentFontIndex]->GetKerning(previous.Character, entry.Character);
+ kerning = fonts[currentFontIndex]->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -1482,7 +1509,7 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
const float x = pointer.X + entry.OffsetX * scale;
const float y = pointer.Y + (fontHeight + fontDescender - entry.OffsetY) * scale;
- Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
+ Rectangle charRect(x, y + (maxAscenders[lineIndex] - fonts[currentFontIndex]->GetAscender()) / 2, entry.UVSize.X * scale, entry.UVSize.Y * scale);
Float2 upperLeftUV = entry.UV * invAtlasSize;
Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
@@ -1498,22 +1525,17 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
pointer.X += entry.AdvanceX * scale;
}
- // Start new segment
- startIndex = currentIndex;
- segmentFontIndex = fontIndex;
-
- if (currentIndex == text.Length() - 1) {
- currentIndex++;
- goto renderText;
+ if (moveLine) {
+ pointer.X = location.X;
+ pointer.Y += maxHeight * scale;
+ // Clear max height
+ maxHeight = 0;
+ lineIndex++;
}
- }
- else
- {
- // Move
- pointer.X = location.X;
- pointer.Y += maxHeight * scale;
- // Clear max height
- maxHeight = 0;
+
+ // Start new segment
+ startIndex = nextCharIndex;
+ currentFontIndex = nextFontIndex;
}
}
}
@@ -1540,8 +1562,8 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
float scale = layout.Scale / FontManager::FontScale;
// Process text to get lines
- Lines.Clear();
- Font::ProcessText(fonts, text, Lines, layout);
+ MultiFontLines.Clear();
+ Font::ProcessText(fonts, text, MultiFontLines, layout);
// Render all lines
FontCharacterEntry entry;
@@ -1557,119 +1579,81 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
drawCall.AsChar.Mat = nullptr;
}
- for (int32 lineIndex = 0; lineIndex < Lines.Count(); lineIndex++)
+ for (int32 lineIndex = 0; lineIndex < MultiFontLines.Count(); lineIndex++)
{
- const FontLineCache& line = Lines[lineIndex];
-
- // The following code cut the text into segments, according to the font used to render
- Float2 pointer = line.Location;
- // The starting index of the current segment
- int32 startIndex = line.FirstCharIndex;
- // The index of the font used by the current segment
- int32 segmentFontIndex = 0;
- // The maximum font height of the current line
- float maxHeight = 0;
-
- // Partition and render all characters from the line
- for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex + 1; charIndex++)
+ const MultiFontLineCache& line = MultiFontLines[lineIndex];
+ for (int32 segmentIndex = 0; segmentIndex < line.Segments.Count(); segmentIndex++)
{
- const Char c = charIndex <= line.LastCharIndex ? text[charIndex] : 0;
+ const MultiFontSegmentCache& segment = MultiFontLines[lineIndex].Segments[segmentIndex];
+ auto fontHeight = fonts[segment.FontIndex]->GetHeight();
+ auto fontDescender = fonts[segment.FontIndex]->GetDescender();
+ Float2 pointer = line.Location + segment.Location;
- if (c != '\n')
+ for (int32 charIndex = segment.FirstCharIndex; charIndex <= segment.LastCharIndex; charIndex++)
{
- int32 fontIndex = 0;
- if (charIndex <= line.LastCharIndex) {
- while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(c))
- {
- fontIndex++;
- }
-
- // If no font can match the char, then use the segment font
- if (fontIndex == fonts.Count()) {
- fontIndex = segmentFontIndex;
- }
-
-
- // Do nothing if the char still belongs to the current segment
- if (fontIndex == segmentFontIndex) {
- continue;
- }
- }
-
-
- // Render the pending segment before beginning the new segment
- auto fontHeight = fonts[segmentFontIndex]->GetHeight();
- maxHeight = Math::Max(maxHeight, static_cast(fontHeight));
- auto fontDescender = fonts[segmentFontIndex]->GetDescender();
-
- const Char* pred = L"Type";
- if (text.Substring(0, Math::Min(4, text.Length())) == pred) {
- // __debugbreak();
- }
- for (int32 renderIndex = startIndex; renderIndex < charIndex; renderIndex++)
+ Char c = text[charIndex];
+ if (c == '\n')
{
- // Get character entry
- fonts[segmentFontIndex]->GetCharacter(text[renderIndex], entry);
+ continue;
+ }
- // Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
- if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
- {
- // Get texture atlas that contains current character
- fontAtlasIndex = entry.TextureIndex;
- fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
- if (fontAtlas)
- {
- fontAtlas->EnsureTextureCreated();
- invAtlasSize = 1.0f / fontAtlas->GetSize();
- drawCall.AsChar.Tex = fontAtlas->GetTexture();
- }
- else
- {
- invAtlasSize = 1.0f;
- drawCall.AsChar.Tex = nullptr;
- }
- }
+ // Get character entry
+ fonts[segment.FontIndex]->GetCharacter(c, entry);
- // Get kerning
- const bool isWhitespace = StringUtils::IsWhitespace(text[renderIndex]);
- if (!isWhitespace && previous.IsValid)
+ // Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
+ if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
+ {
+ // Get texture atlas that contains current character
+ fontAtlasIndex = entry.TextureIndex;
+ fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
+ if (fontAtlas)
{
- kerning = fonts[segmentFontIndex]->GetKerning(previous.Character, entry.Character);
+ fontAtlas->EnsureTextureCreated();
+ invAtlasSize = 1.0f / fontAtlas->GetSize();
+ drawCall.AsChar.Tex = fontAtlas->GetTexture();
}
else
{
- kerning = 0;
+ invAtlasSize = 1.0f;
+ drawCall.AsChar.Tex = nullptr;
}
- pointer.X += (float)kerning * scale;
- previous = entry;
-
- // Omit whitespace characters
- if (!isWhitespace)
- {
- // Calculate character size and atlas coordinates
- const float x = pointer.X + entry.OffsetX * scale;
- const float y = pointer.Y - entry.OffsetY * scale + Math::Ceil((fontHeight + fontDescender) * scale);
-
- Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
- charRect.Offset(layout.Bounds.Location);
-
- Float2 upperLeftUV = entry.UV * invAtlasSize;
- Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
-
- // Add draw call
- drawCall.StartIB = IBIndex;
- drawCall.CountIB = 6;
- DrawCalls.Add(drawCall);
- WriteRect(charRect, color, upperLeftUV, rightBottomUV);
- }
-
- // Move
- pointer.X += entry.AdvanceX * scale;
}
- // Start new segment
- startIndex = charIndex;
- segmentFontIndex = fontIndex;
+ // Get kerning
+ const bool isWhitespace = StringUtils::IsWhitespace(c);
+ if (!isWhitespace && previous.IsValid)
+ {
+ kerning = fonts[segment.FontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ else
+ {
+ kerning = 0;
+ }
+ pointer.X += (float)kerning * scale;
+ previous = entry;
+
+ // Omit whitespace characters
+ if (!isWhitespace)
+ {
+ // Calculate character size and atlas coordinates
+ const float x = pointer.X + entry.OffsetX * scale;
+ const float y = pointer.Y - entry.OffsetY * scale + Math::Ceil((fontHeight + fontDescender) * scale);
+
+ Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
+ charRect.Offset(layout.Bounds.Location);
+
+ Float2 upperLeftUV = entry.UV * invAtlasSize;
+ Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
+
+ // Add draw call
+ drawCall.StartIB = IBIndex;
+ drawCall.CountIB = 6;
+ DrawCalls.Add(drawCall);
+ WriteRect(charRect, color, upperLeftUV, rightBottomUV);
+ }
+
+ // Move
+ pointer.X += entry.AdvanceX * scale;
}
}
}
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index b92e762e1..5fa8ad21d 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -235,7 +235,7 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText(new Font[] { _font.GetFont(), Style.Current.FontCJK }, Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ Render2D.DrawText([_font.GetFont(), Style.Current.FontCJK], Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
Render2D.PopClip();
From 41bbce56f6935d9066579a6b1d1e5d1b03c7fcc6 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Thu, 30 Nov 2023 13:41:45 +0800
Subject: [PATCH 03/16] Add multifont rendering to editor
---
.../Content/Create/CreateFilesDialog.cs | 2 +-
.../Content/Import/ImportFilesDialog.cs | 2 +-
Source/Editor/Content/Tree/ContentTreeNode.cs | 4 +-
.../CustomEditors/Dedicated/RagdollEditor.cs | 2 +-
.../CustomEditors/Dedicated/ScriptsEditor.cs | 2 +-
.../Dedicated/UIControlEditor.cs | 6 +-
.../Editors/ActorTransformEditor.cs | 2 +-
.../Editor/CustomEditors/Editors/TagEditor.cs | 2 +-
.../CustomEditors/LayoutElementsContainer.cs | 4 +-
Source/Editor/EditorAssets.cs | 2 +-
Source/Editor/GUI/ColumnDefinition.cs | 2 +-
Source/Editor/GUI/ComboBox.cs | 6 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 6 +-
Source/Editor/GUI/CurveEditor.cs | 4 +-
Source/Editor/GUI/Docking/DockWindow.cs | 2 +-
Source/Editor/GUI/ItemsListContextMenu.cs | 4 +-
Source/Editor/GUI/MainMenu.cs | 8 +-
Source/Editor/GUI/MainMenuButton.cs | 4 +-
Source/Editor/GUI/NavigationButton.cs | 4 +-
Source/Editor/GUI/Row.cs | 4 +-
Source/Editor/GUI/Table.cs | 2 +-
.../Editor/GUI/Timeline/GUI/PositionHandle.cs | 21 +-
.../Editor/GUI/Timeline/Tracks/MemberTrack.cs | 2 +-
Source/Editor/GUI/ToolStripButton.cs | 4 +-
Source/Editor/GUI/Tree/TreeNode.cs | 8 +-
Source/Editor/Options/InterfaceOptions.cs | 63 ++-
Source/Editor/Options/OptionsModule.cs | 17 +-
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 4 +-
.../Archetypes/Animation.TransitionEditor.cs | 2 +-
.../Editor/Surface/Archetypes/BehaviorTree.cs | 2 +-
Source/Editor/Surface/Archetypes/Function.cs | 2 +-
Source/Editor/Surface/AttributesEditor.cs | 2 +-
.../Editor/Surface/ContextMenu/VisjectCM.cs | 2 +-
.../Surface/ContextMenu/VisjectCMItem.cs | 14 +-
Source/Editor/Surface/Elements/InputBox.cs | 4 +-
Source/Editor/Surface/SurfaceNode.cs | 4 +-
Source/Editor/Tools/Foliage/FoliageTab.cs | 2 +-
Source/Editor/Tools/Terrain/CarveTab.cs | 2 +-
.../Tools/Terrain/CreateTerrainDialog.cs | 2 +-
Source/Editor/Viewport/EditorViewport.cs | 6 +-
.../Viewport/Widgets/ViewportWidgetButton.cs | 4 +-
Source/Editor/Windows/AboutDialog.cs | 4 +-
Source/Editor/Windows/Assets/FontWindow.cs | 2 +-
Source/Editor/Windows/ContentWindow.Search.cs | 2 +-
Source/Editor/Windows/OutputLogWindow.cs | 74 +--
Source/Editor/Windows/PluginsWindow.cs | 9 +-
Source/Editor/Windows/Profiler/Timeline.cs | 4 +-
Source/Editor/Windows/ToolboxWindow.cs | 4 +-
Source/Engine/Render2D/Font.cpp | 249 +---------
Source/Engine/Render2D/Font.h | 56 +--
Source/Engine/Render2D/MultiFont.cpp | 430 ++++++++++++++++++
Source/Engine/Render2D/MultiFont.h | 296 +++++++++++-
Source/Engine/Render2D/MultiFontReference.cs | 74 +++
Source/Engine/Render2D/Render2D.cpp | 72 +--
Source/Engine/Render2D/Render2D.cs | 7 +-
Source/Engine/Render2D/Render2D.h | 9 +-
Source/Engine/Scripting/Scripting.cs | 15 +-
Source/Engine/UI/GUI/Common/Button.cs | 8 +-
Source/Engine/UI/GUI/Common/Dropdown.cs | 6 +-
Source/Engine/UI/GUI/Common/Label.cs | 12 +-
.../UI/GUI/Common/RichTextBox.Parsing.cs | 34 +-
.../Engine/UI/GUI/Common/RichTextBox.Tags.cs | 72 +--
Source/Engine/UI/GUI/Common/RichTextBox.cs | 2 +-
.../Engine/UI/GUI/Common/RichTextBoxBase.cs | 28 +-
Source/Engine/UI/GUI/Common/TextBox.cs | 16 +-
Source/Engine/UI/GUI/Panels/DropPanel.cs | 6 +-
Source/Engine/UI/GUI/Style.cs | 40 +-
Source/Engine/UI/GUI/TextBlockStyle.cs | 2 +-
Source/Engine/UI/GUI/Tooltip.cs | 5 +-
69 files changed, 1132 insertions(+), 647 deletions(-)
create mode 100644 Source/Engine/Render2D/MultiFontReference.cs
diff --git a/Source/Editor/Content/Create/CreateFilesDialog.cs b/Source/Editor/Content/Create/CreateFilesDialog.cs
index d48e878bc..48e4920bb 100644
--- a/Source/Editor/Content/Create/CreateFilesDialog.cs
+++ b/Source/Editor/Content/Create/CreateFilesDialog.cs
@@ -39,7 +39,7 @@ namespace FlaxEditor.Content.Create
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, 0, 40),
Parent = this,
- Font = new FontReference(Style.Current.FontTitle)
+ Font = new MultiFontReference(Style.Current.FontTitle)
};
var infoLabel = new Label
{
diff --git a/Source/Editor/Content/Import/ImportFilesDialog.cs b/Source/Editor/Content/Import/ImportFilesDialog.cs
index 967583cf6..5a142d0f6 100644
--- a/Source/Editor/Content/Import/ImportFilesDialog.cs
+++ b/Source/Editor/Content/Import/ImportFilesDialog.cs
@@ -60,7 +60,7 @@ namespace FlaxEditor.Content.Import
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, 0, 40),
Parent = this,
- Font = new FontReference(Style.Current.FontTitle)
+ Font = new MultiFontReference(Style.Current.FontTitle)
};
var infoLabel = new Label
{
diff --git a/Source/Editor/Content/Tree/ContentTreeNode.cs b/Source/Editor/Content/Tree/ContentTreeNode.cs
index 37c4e8dbb..ee9b463f7 100644
--- a/Source/Editor/Content/Tree/ContentTreeNode.cs
+++ b/Source/Editor/Content/Tree/ContentTreeNode.cs
@@ -151,8 +151,8 @@ namespace FlaxEditor.Content
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
- var end = font.First().GetCharPosition(text, ranges[i].EndIndex);
+ var start = font.GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs b/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs
index c4b334b3a..b6d14d81e 100644
--- a/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs
@@ -81,7 +81,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new FontReference(FlaxEngine.GUI.Style.Current.FontLarge),
+ Font = new MultiFontReference(FlaxEngine.GUI.Style.Current.FontLarge),
Text = "Ragdoll Options",
Parent = this
};
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index 1f69074ce..fd56422cb 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -43,7 +43,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Add script button
var buttonText = "Add script";
- var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
+ var textSize = Style.Current.FontMedium.MeasureText(buttonText);
float addScriptButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
_addScriptsButton = new Button
diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index 5b5c2f90d..9627edfd8 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -239,7 +239,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Title
var title = new Label(2, 2, DialogWidth - 4, TitleHeight)
{
- Font = new FontReference(style.FontLarge),
+ Font = new MultiFontReference(style.FontLarge),
Text = "Anchor Presets",
Parent = this
};
@@ -247,7 +247,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Info
var info = new Label(0, title.Bottom, DialogWidth, InfoHeight)
{
- Font = new FontReference(style.FontSmall.First()),
+ Font = new MultiFontReference(style.FontSmall),
Text = "Shift: also set bounds\nControl: also set pivot",
Parent = this
};
@@ -423,7 +423,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Set control type button
var space = layout.Space(20);
var buttonText = "Set Type";
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.First().MeasureText(buttonText);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
float setTypeButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var setTypeButton = new Button
{
diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
index d7059f712..0cad200fd 100644
--- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
@@ -101,7 +101,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.Clicked += ToggleLink;
ToggleEnabled();
SetLinkStyle();
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.First().MeasureText(LinkedLabel.Text.Value);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(LinkedLabel.Text.Value);
_linkButton.LocalX += textSize.X + 10;
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
{
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index a174d02e4..dbd5d124c 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -631,7 +631,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Edit...",
Parent = _label,
};
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.First().MeasureText(buttonText);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
if (textSize.Y > button.Width)
button.Width = textSize.Y + 2;
diff --git a/Source/Editor/CustomEditors/LayoutElementsContainer.cs b/Source/Editor/CustomEditors/LayoutElementsContainer.cs
index 936851b15..1584e88de 100644
--- a/Source/Editor/CustomEditors/LayoutElementsContainer.cs
+++ b/Source/Editor/CustomEditors/LayoutElementsContainer.cs
@@ -276,7 +276,7 @@ namespace FlaxEditor.CustomEditors
public LabelElement Header(string text)
{
var element = Label(text);
- element.Label.Font = new FontReference(Style.Current.FontLarge);
+ element.Label.Font = new MultiFontReference(Style.Current.FontLarge);
return element;
}
@@ -284,7 +284,7 @@ namespace FlaxEditor.CustomEditors
{
var element = Header(header.Text);
if (header.FontSize != -1)
- element.Label.Font = new FontReference(element.Label.Font.Font, header.FontSize);
+ element.Label.Font = new MultiFontReference(element.Label.Font, header.FontSize);
if (header.Color != 0)
element.Label.TextColor = Color.FromRGBA(header.Color);
return element;
diff --git a/Source/Editor/EditorAssets.cs b/Source/Editor/EditorAssets.cs
index 0fe5ee47e..c894abe6b 100644
--- a/Source/Editor/EditorAssets.cs
+++ b/Source/Editor/EditorAssets.cs
@@ -54,7 +54,7 @@ namespace FlaxEditor
///
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
- public static string CJKFont = "Editor/Fonts/NotoSansSC-Regular";
+ public static string CjkFont = "Editor/Fonts/NotoSansSC-Regular";
///
/// The Inconsolata Regular font.
diff --git a/Source/Editor/GUI/ColumnDefinition.cs b/Source/Editor/GUI/ColumnDefinition.cs
index aff1817c3..c6e8f2889 100644
--- a/Source/Editor/GUI/ColumnDefinition.cs
+++ b/Source/Editor/GUI/ColumnDefinition.cs
@@ -35,7 +35,7 @@ namespace FlaxEditor.GUI
///
/// The title font.
///
- public Font TitleFont;
+ public MultiFont TitleFont;
///
/// The column title text color.
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index 7dc407698..8e6cf39a0 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -191,7 +191,7 @@ namespace FlaxEditor.GUI
/// Gets or sets the font used to draw text.
///
[EditorDisplay("Style"), EditorOrder(2000)]
- public FontReference Font { get; set; }
+ public MultiFontReference Font { get; set; }
///
/// Gets or sets the color of the text.
@@ -273,7 +273,7 @@ namespace FlaxEditor.GUI
MaximumItemsInViewCount = 20;
var style = Style.Current;
- Font = new FontReference(style.FontMedium.First());
+ Font = new MultiFontReference(style.FontMedium);
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BackgroundColorHighlighted = BackgroundColor;
@@ -554,7 +554,7 @@ namespace FlaxEditor.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ Render2D.DrawText(Font.GetMultiFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
}
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index 872700a9b..ba3326412 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -234,11 +234,11 @@ namespace FlaxEditor.GUI.ContextMenu
{
var style = Style.Current;
float width = 20;
- if (style.FontMedium.First())
+ if (style.FontMedium)
{
- width += style.FontMedium.First().MeasureText(Text).X;
+ width += style.FontMedium.MeasureText(Text).X;
if (!string.IsNullOrEmpty(ShortKeys))
- width += 40 + style.FontMedium.First().MeasureText(ShortKeys).X;
+ width += 40 + style.FontMedium.MeasureText(ShortKeys).X;
}
return Mathf.Max(width, base.MinimumWidth);
diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs
index f71409b20..ff14cdb24 100644
--- a/Source/Editor/GUI/CurveEditor.cs
+++ b/Source/Editor/GUI/CurveEditor.cs
@@ -317,7 +317,7 @@ namespace FlaxEditor.GUI
private Color _contentsColor;
private Color _linesColor;
private Color _labelsColor;
- private Font _labelsFont;
+ private MultiFont _labelsFont;
///
/// The keyframe UI points.
@@ -437,7 +437,7 @@ namespace FlaxEditor.GUI
_contentsColor = style.Background.RGBMultiplied(0.7f);
_linesColor = style.ForegroundDisabled.RGBMultiplied(0.7f);
_labelsColor = style.ForegroundDisabled;
- _labelsFont = style.FontSmall.First();
+ _labelsFont = style.FontSmall;
_mainPanel = new Panel(ScrollBars.Both)
{
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index 8601b9c53..374885f01 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -489,7 +489,7 @@ namespace FlaxEditor.GUI.Docking
{
var style = Style.Current;
if (style?.FontMedium != null)
- _titleSize = style.FontMedium.First().MeasureText(_title);
+ _titleSize = style.FontMedium.MeasureText(_title);
}
base.PerformLayoutBeforeChildren();
diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs
index ce69f3544..b823cc907 100644
--- a/Source/Editor/GUI/ItemsListContextMenu.cs
+++ b/Source/Editor/GUI/ItemsListContextMenu.cs
@@ -87,8 +87,8 @@ namespace FlaxEditor.GUI
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.First().GetCharPosition(Name, ranges[i].StartIndex);
- var end = font.First().GetCharPosition(Name, ranges[i].EndIndex);
+ var start = font.GetCharPosition(Name, ranges[i].StartIndex);
+ var end = font.GetCharPosition(Name, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
}
Visible = true;
diff --git a/Source/Editor/GUI/MainMenu.cs b/Source/Editor/GUI/MainMenu.cs
index b313fed9f..aadfbf0a7 100644
--- a/Source/Editor/GUI/MainMenu.cs
+++ b/Source/Editor/GUI/MainMenu.cs
@@ -76,7 +76,7 @@ namespace FlaxEditor.GUI
var windowIcon = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIcon);
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIconsFont);
- Font iconFont = windowIconsFont?.CreateFont(9);
+ MultiFont iconFont = new MultiFontReference([windowIconsFont], 9).GetMultiFont();
_window = mainWindow.RootWindow.Window;
_window.HitTest += OnHitTest;
@@ -108,7 +108,7 @@ namespace FlaxEditor.GUI
_closeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
- Font = new FontReference(iconFont),
+ Font = new MultiFontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
@@ -124,7 +124,7 @@ namespace FlaxEditor.GUI
_minimizeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
- Font = new FontReference(iconFont),
+ Font = new MultiFontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
@@ -139,7 +139,7 @@ namespace FlaxEditor.GUI
_maximizeButton = new Button
{
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
- Font = new FontReference(iconFont),
+ Font = new MultiFontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 76687f8b9..3bc57479c 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -102,8 +102,8 @@ namespace FlaxEditor.GUI
var style = Style.Current;
float width = 18;
- if (style.FontMedium.First())
- width += style.FontMedium.First().MeasureText(Text).X;
+ if (style.FontMedium)
+ width += style.FontMedium.MeasureText(Text).X;
Width = width;
}
diff --git a/Source/Editor/GUI/NavigationButton.cs b/Source/Editor/GUI/NavigationButton.cs
index 77f8a7656..6fd17332c 100644
--- a/Source/Editor/GUI/NavigationButton.cs
+++ b/Source/Editor/GUI/NavigationButton.cs
@@ -66,9 +66,9 @@ namespace FlaxEditor.GUI
{
var style = Style.Current;
- if (style.FontMedium.First())
+ if (style.FontMedium)
{
- Width = style.FontMedium.First().MeasureText(Text).X + 2 * DefaultMargin;
+ Width = style.FontMedium.MeasureText(Text).X + 2 * DefaultMargin;
}
}
}
diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs
index 458138aea..7533dfb17 100644
--- a/Source/Editor/GUI/Row.cs
+++ b/Source/Editor/GUI/Row.cs
@@ -39,8 +39,8 @@ namespace FlaxEditor.GUI
{
Depth = -1;
- if (Height < Style.Current.FontMedium.First().Height)
- Height = Style.Current.FontMedium.First().Height + 4;
+ if (Height < Style.Current.FontMedium.MaxHeight)
+ Height = Style.Current.FontMedium.MaxHeight + 4;
}
///
diff --git a/Source/Editor/GUI/Table.cs b/Source/Editor/GUI/Table.cs
index fed33a336..54656a6c2 100644
--- a/Source/Editor/GUI/Table.cs
+++ b/Source/Editor/GUI/Table.cs
@@ -130,7 +130,7 @@ namespace FlaxEditor.GUI
Render2D.FillRectangle(rect, column.TitleBackgroundColor);
var style = Style.Current;
- var font = column.TitleFont ?? style.FontMedium.First();
+ var font = column.TitleFont ?? style.FontMedium;
Render2D.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
if (columnIndex < _columns.Length - 1)
diff --git a/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs b/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs
index bedb61a5e..791fb7133 100644
--- a/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs
+++ b/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs
@@ -2,6 +2,7 @@
using System;
using System.Globalization;
+using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -36,16 +37,16 @@ namespace FlaxEditor.GUI.Timeline.GUI
string labelText;
switch (_timeline.TimeShowMode)
{
- case Timeline.TimeShowModes.Frames:
- labelText = _timeline.CurrentFrame.ToString("###0", CultureInfo.InvariantCulture);
- break;
- case Timeline.TimeShowModes.Seconds:
- labelText = _timeline.CurrentTime.ToString("###0.##'s'", CultureInfo.InvariantCulture);
- break;
- case Timeline.TimeShowModes.Time:
- labelText = TimeSpan.FromSeconds(_timeline.CurrentTime).ToString("g");
- break;
- default: throw new ArgumentOutOfRangeException();
+ case Timeline.TimeShowModes.Frames:
+ labelText = _timeline.CurrentFrame.ToString("###0", CultureInfo.InvariantCulture);
+ break;
+ case Timeline.TimeShowModes.Seconds:
+ labelText = _timeline.CurrentTime.ToString("###0.##'s'", CultureInfo.InvariantCulture);
+ break;
+ case Timeline.TimeShowModes.Time:
+ labelText = TimeSpan.FromSeconds(_timeline.CurrentTime).ToString("g");
+ break;
+ default: throw new ArgumentOutOfRangeException();
}
var color = (_timeline.IsMovingPositionHandle ? style.ProgressNormal : style.Foreground).AlphaMultiplied(0.6f);
Matrix3x3.RotationZ(Mathf.PiOverTwo, out var m1);
diff --git a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
index 928129917..63787df2c 100644
--- a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
@@ -345,7 +345,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (_previewValue != null)
{
// Based on Track.Draw for track text placement
- var left = _xOffset + 16 + Style.Current.FontSmall.First().MeasureText(Title ?? Name).X;
+ var left = _xOffset + 16 + Style.Current.FontSmall.MeasureText(Title ?? Name).X;
if (Icon.IsValid)
left += 18;
if (IsExpanded)
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index b74c7c19f..d21fd5689 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -151,8 +151,8 @@ namespace FlaxEditor.GUI
if (hasSprite)
width += iconSize;
- if (!string.IsNullOrEmpty(_text) && style.FontMedium.First())
- width += style.FontMedium.First().MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
+ if (!string.IsNullOrEmpty(_text) && style.FontMedium)
+ width += style.FontMedium.MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
Width = width;
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index f26929993..acb67ea8f 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -115,7 +115,7 @@ namespace FlaxEditor.GUI.Tree
/// Gets or sets the font used to render text.
///
[EditorDisplay("Style"), EditorOrder(2000)]
- public FontReference TextFont { get; set; }
+ public MultiFontReference TextFont { get; set; }
///
/// Gets or sets the color of the background when tree node is selected.
@@ -318,7 +318,7 @@ namespace FlaxEditor.GUI.Tree
BackgroundColorSelected = style.BackgroundSelected;
BackgroundColorHighlighted = style.BackgroundHighlighted;
BackgroundColorSelectedUnfocused = style.LightBackground;
- TextFont = new FontReference(style.FontSmall.First());
+ TextFont = new MultiFontReference(style.FontSmall);
}
///
@@ -573,7 +573,7 @@ namespace FlaxEditor.GUI.Tree
{
if (_textChanged)
{
- var font = TextFont.GetFont();
+ var font = TextFont.GetMultiFont();
if (font)
{
_textWidth = font.MeasureText(_text).X;
@@ -657,7 +657,7 @@ namespace FlaxEditor.GUI.Tree
}
// Draw text
- Render2D.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(TextFont.GetMultiFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
// Draw drag and drop effect
if (IsDragOver && _tree.DraggedOverNode == this)
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index c96a52fb1..e43751fd1 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -166,15 +166,13 @@ namespace FlaxEditor.Options
/// Gets or sets the output log text font.
///
[EditorDisplay("Output Log", "Text Font"), EditorOrder(320), Tooltip("The output log text font.")]
- public FontReference OutputLogTextFont
+ public MultiFontReference OutputLogTextFont
{
get => _outputLogFont;
set
{
- if (value == null)
- _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont), 10);
- else if (!value.Font)
- _outputLogFont.Font = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont);
+ if (value == null || !value.Verify())
+ _outputLogFont = new MultiFontReference(ConsoleFonts, 10);
else
_outputLogFont = value;
}
@@ -236,32 +234,31 @@ namespace FlaxEditor.Options
[EditorDisplay("Cook & Run"), EditorOrder(500)]
public int NumberOfGameClientsToLaunch = 1;
- private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont);
- private static FontAsset _cjkFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CJKFont);
- private FontReference _titleFont = new FontReference(DefaultFont, 18);
- private FontReference _largeFont = new FontReference(DefaultFont, 14);
- private FontReference _mediumFont = new FontReference(DefaultFont, 9);
- private FontReference _smallFont = new FontReference(DefaultFont, 9);
- private FontReference _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont), 10);
+ private static FontAsset[] DefaultFonts =>
+ [FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont),
+ FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CjkFont)];
+
+ private static FontAsset[] ConsoleFonts => [FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont),
+ FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CjkFont)];
+
+ private MultiFontReference _titleFont = new MultiFontReference(DefaultFonts, 18);
+ private MultiFontReference _largeFont = new MultiFontReference(DefaultFonts, 14);
+ private MultiFontReference _mediumFont = new MultiFontReference(DefaultFonts, 9);
+ private MultiFontReference _smallFont = new MultiFontReference(DefaultFonts, 9);
+ private MultiFontReference _outputLogFont = new MultiFontReference(ConsoleFonts, 10);
- public FontReference CJKFont
- {
- get => new FontReference(_cjkFont, 9);
- }
///
/// Gets or sets the title font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(600), Tooltip("The title font for editor UI.")]
- public FontReference TitleFont
+ public MultiFontReference TitleFont
{
get => _titleFont;
set
{
- if (value == null)
- _titleFont = new FontReference(DefaultFont, 18);
- else if (!value.Font)
- _titleFont.Font = DefaultFont;
+ if (value == null || !value.Verify())
+ _titleFont = new MultiFontReference(DefaultFonts, 18);
else
_titleFont = value;
}
@@ -271,15 +268,13 @@ namespace FlaxEditor.Options
/// Gets or sets the large font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(610), Tooltip("The large font for editor UI.")]
- public FontReference LargeFont
+ public MultiFontReference LargeFont
{
get => _largeFont;
set
{
- if (value == null)
- _largeFont = new FontReference(DefaultFont, 14);
- else if (!value.Font)
- _largeFont.Font = DefaultFont;
+ if (value == null || !value.Verify())
+ _largeFont = new MultiFontReference(DefaultFonts, 14);
else
_largeFont = value;
}
@@ -289,15 +284,13 @@ namespace FlaxEditor.Options
/// Gets or sets the medium font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(620), Tooltip("The medium font for editor UI.")]
- public FontReference MediumFont
+ public MultiFontReference MediumFont
{
get => _mediumFont;
set
{
- if (value == null)
- _mediumFont = new FontReference(DefaultFont, 9);
- else if (!value.Font)
- _mediumFont.Font = DefaultFont;
+ if (value == null || !value.Verify())
+ _mediumFont = new MultiFontReference(DefaultFonts, 9);
else
_mediumFont = value;
}
@@ -307,15 +300,13 @@ namespace FlaxEditor.Options
/// Gets or sets the small font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(630), Tooltip("The small font for editor UI.")]
- public FontReference SmallFont
+ public MultiFontReference SmallFont
{
get => _smallFont;
set
{
- if (value == null)
- _smallFont = new FontReference(DefaultFont, 9);
- else if (!value.Font)
- _smallFont.Font = DefaultFont;
+ if (value == null || !value.Verify())
+ _smallFont = new MultiFontReference(DefaultFonts, 9);
else
_smallFont = value;
}
diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs
index 15059bd56..d138d7d0d 100644
--- a/Source/Editor/Options/OptionsModule.cs
+++ b/Source/Editor/Options/OptionsModule.cs
@@ -259,11 +259,10 @@ namespace FlaxEditor.Options
},
// Fonts
- FontTitle = options.Interface.TitleFont.GetFont(),
- FontLarge = options.Interface.LargeFont.GetFont(),
- FontMedium = new Font[] { options.Interface.MediumFont.GetFont(), options.Interface.CJKFont.GetFont() },
- FontSmall = new Font[] { options.Interface.SmallFont.GetFont(), options.Interface.CJKFont.GetFont() },
- FontCJK = options.Interface.CJKFont.GetFont(),
+ FontTitle = options.Interface.TitleFont.GetMultiFont(),
+ FontLarge = options.Interface.LargeFont.GetMultiFont(),
+ FontMedium = options.Interface.MediumFont.GetMultiFont(),
+ FontSmall = options.Interface.SmallFont.GetMultiFont(),
// Icons
ArrowDown = Editor.Icons.ArrowDown12,
@@ -313,10 +312,10 @@ namespace FlaxEditor.Options
ProgressNormal = new Color(0.03f, 0.65f, 0.12f, 1f),
// Fonts
- FontTitle = options.Interface.TitleFont.GetFont(),
- FontLarge = options.Interface.LargeFont.GetFont(),
- FontMedium = new Font[] { options.Interface.MediumFont.GetFont(), options.Interface.CJKFont.GetFont() },
- FontSmall = new Font[] { options.Interface.SmallFont.GetFont(), options.Interface.CJKFont.GetFont() },
+ FontTitle = options.Interface.TitleFont.GetMultiFont(),
+ FontLarge = options.Interface.LargeFont.GetMultiFont(),
+ FontMedium = options.Interface.MediumFont.GetMultiFont(),
+ FontSmall = options.Interface.SmallFont.GetMultiFont(),
// Icons
ArrowDown = Editor.Icons.ArrowDown12,
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index 9a6fe4fd2..f64e46385 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -142,8 +142,8 @@ namespace FlaxEditor.SceneGraph.GUI
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
- var end = font.First().GetCharPosition(text, ranges[i].EndIndex);
+ var start = font.GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs b/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs
index 84c2144b2..e1fdb0a42 100644
--- a/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs
@@ -39,7 +39,7 @@ namespace FlaxEditor.Surface.Archetypes
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new FontReference(Style.Current.FontLarge),
+ Font = new MultiFontReference(Style.Current.FontLarge),
Text = transition.SurfaceName,
Parent = this
};
diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
index 38dd28e62..cca6856ae 100644
--- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs
+++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
@@ -101,7 +101,7 @@ namespace FlaxEditor.Surface.Archetypes
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
if (!string.IsNullOrEmpty(_debugInfo))
- _debugInfoSize = Style.Current.FontSmall.First().MeasureText(_debugInfo);
+ _debugInfoSize = Style.Current.FontSmall.MeasureText(_debugInfo);
}
}
diff --git a/Source/Editor/Surface/Archetypes/Function.cs b/Source/Editor/Surface/Archetypes/Function.cs
index 53950dad2..bc982a510 100644
--- a/Source/Editor/Surface/Archetypes/Function.cs
+++ b/Source/Editor/Surface/Archetypes/Function.cs
@@ -1407,7 +1407,7 @@ namespace FlaxEditor.Surface.Archetypes
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new FontReference(Style.Current.FontLarge),
+ Font = new MultiFontReference(Style.Current.FontLarge),
Text = "Edit function signature",
Parent = this
};
diff --git a/Source/Editor/Surface/AttributesEditor.cs b/Source/Editor/Surface/AttributesEditor.cs
index 81b11bb68..c9e32e23a 100644
--- a/Source/Editor/Surface/AttributesEditor.cs
+++ b/Source/Editor/Surface/AttributesEditor.cs
@@ -83,7 +83,7 @@ namespace FlaxEditor.Surface
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new FontReference(Style.Current.FontLarge),
+ Font = new MultiFontReference(Style.Current.FontLarge),
Text = "Edit attributes",
Parent = this
};
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
index 930741807..0624d44b3 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
@@ -141,7 +141,7 @@ namespace FlaxEditor.Surface.ContextMenu
};
// Title bar
- var titleFontReference = new FontReference(Style.Current.FontLarge.Asset, 10);
+ var titleFontReference = new MultiFontReference(Style.Current.FontLarge);
var titleLabel = new Label
{
Width = Width * 0.5f - 8f,
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index 812bec5d2..207875a92 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -200,8 +200,8 @@ namespace FlaxEditor.Surface.ContextMenu
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.First().GetCharPosition(_archetype.Title, ranges[i].StartIndex);
- var end = font.First().GetCharPosition(_archetype.Title, ranges[i].EndIndex);
+ var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
+ var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
if (ranges[i].StartIndex <= 0)
@@ -222,8 +222,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = font.First().GetCharPosition(_archetype.Title, 0);
- var end = font.First().GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
+ var start = font.GetCharPosition(_archetype.Title, 0);
+ var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
_isFullMatch = true;
Visible = true;
@@ -237,8 +237,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = font.First().GetCharPosition(_archetype.Title, 0);
- var end = font.First().GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
+ var start = font.GetCharPosition(_archetype.Title, 0);
+ var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
Visible = true;
@@ -286,7 +286,7 @@ namespace FlaxEditor.Surface.ContextMenu
Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
if (_archetype.SubTitle != null)
{
- var titleLength = style.FontSmall.First().MeasureText(_archetype.Title).X;
+ var titleLength = style.FontSmall.MeasureText(_archetype.Title).X;
var subTitleRect = new Rectangle(textRect.X + titleLength, textRect.Y, textRect.Width - titleLength, textRect.Height);
Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs
index 611160611..2047bcd1a 100644
--- a/Source/Editor/Surface/Elements/InputBox.cs
+++ b/Source/Editor/Surface/Elements/InputBox.cs
@@ -1428,7 +1428,7 @@ namespace FlaxEditor.Surface.Elements
if (_defaultValueEditor != null)
{
- _defaultValueEditor.Location = new Float2(X + Width + 8 + Style.Current.FontSmall.First().MeasureText(Text).X, Y);
+ _defaultValueEditor.Location = new Float2(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y);
}
}
@@ -1635,7 +1635,7 @@ namespace FlaxEditor.Surface.Elements
{
if (DefaultValueEditors[i].CanUse(this, ref _currentType))
{
- var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.First().MeasureText(Text).X, Y, 90, Height);
+ var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y, 90, Height);
_editor = DefaultValueEditors[i];
try
{
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index 82a9ab2bd..b6436e542 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -200,7 +200,7 @@ namespace FlaxEditor.Surface
continue;
if (child is InputBox inputBox)
{
- var boxWidth = boxLabelFont.First().MeasureText(inputBox.Text).X + 20;
+ var boxWidth = boxLabelFont.MeasureText(inputBox.Text).X + 20;
if (inputBox.DefaultValueEditor != null)
boxWidth += inputBox.DefaultValueEditor.Width + 4;
leftWidth = Mathf.Max(leftWidth, boxWidth);
@@ -208,7 +208,7 @@ namespace FlaxEditor.Surface
}
else if (child is OutputBox outputBox)
{
- rightWidth = Mathf.Max(rightWidth, boxLabelFont.First().MeasureText(outputBox.Text).X + 20);
+ rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 20);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
}
else if (child is Control control)
diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs
index e88972b5c..1badb8c0c 100644
--- a/Source/Editor/Tools/Foliage/FoliageTab.cs
+++ b/Source/Editor/Tools/Foliage/FoliageTab.cs
@@ -148,7 +148,7 @@ namespace FlaxEditor.Tools.Foliage
Parent = _noFoliagePanel,
Enabled = false
};
- var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
+ var textSize = Style.Current.FontMedium.MeasureText(buttonText);
if (_createNewFoliage.Width < textSize.X)
{
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CarveTab.cs b/Source/Editor/Tools/Terrain/CarveTab.cs
index 0a43cd2d2..4ff85ca23 100644
--- a/Source/Editor/Tools/Terrain/CarveTab.cs
+++ b/Source/Editor/Tools/Terrain/CarveTab.cs
@@ -106,7 +106,7 @@ namespace FlaxEditor.Tools.Terrain
Parent = _noTerrainPanel,
Enabled = false
};
- var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
+ var textSize = Style.Current.FontMedium.MeasureText(buttonText);
if (_createTerrainButton.Width < textSize.X)
{
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs
index 252891d44..cba52283d 100644
--- a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs
+++ b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs
@@ -96,7 +96,7 @@ namespace FlaxEditor.Tools.Terrain
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, 0, 40),
Parent = this,
- Font = new FontReference(Style.Current.FontTitle)
+ Font = new MultiFontReference(Style.Current.FontTitle)
};
var infoLabel = new Label
{
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index f4ebfb51b..c49392d01 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -548,9 +548,9 @@ namespace FlaxEditor.Viewport
#region Camera settings widget
var largestText = "Relative Panning";
- var textSize = Style.Current.FontMedium.First().MeasureText(largestText);
+ var textSize = Style.Current.FontMedium.MeasureText(largestText);
var xLocationForExtras = textSize.X + 5;
- var cameraSpeedTextWidth = Style.Current.FontMedium.First().MeasureText("0.00").X;
+ var cameraSpeedTextWidth = Style.Current.FontMedium.MeasureText("0.00").X;
// Camera Settings Widget
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
@@ -801,7 +801,7 @@ namespace FlaxEditor.Viewport
#region View mode widget
largestText = "Brightness";
- textSize = Style.Current.FontMedium.First().MeasureText(largestText);
+ textSize = Style.Current.FontMedium.MeasureText(largestText);
xLocationForExtras = textSize.X + 5;
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
index a58350ded..fe73048fd 100644
--- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
+++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
@@ -163,8 +163,8 @@ namespace FlaxEditor.Viewport.Widgets
{
var style = Style.Current;
- if (style != null && style.FontMedium.First())
- Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.First().MeasureText(_text).X, Icon.IsValid);
+ if (style != null && style.FontMedium)
+ Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.MeasureText(_text).X, Icon.IsValid);
}
}
}
diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs
index 63ad44f29..1a81a9421 100644
--- a/Source/Editor/Windows/AboutDialog.cs
+++ b/Source/Editor/Windows/AboutDialog.cs
@@ -41,7 +41,7 @@ namespace FlaxEditor.Windows
var nameLabel = new Label(icon.Right + 10, icon.Top, 200, 34)
{
Text = "Flax Engine",
- Font = new FontReference(Style.Current.FontTitle),
+ Font = new MultiFontReference(Style.Current.FontTitle),
HorizontalAlignment = TextAlignment.Near,
VerticalAlignment = TextAlignment.Center,
Parent = this
@@ -54,7 +54,7 @@ namespace FlaxEditor.Windows
Parent = this
};
var buttonText = "Copy version info";
- var fontSize = Style.Current.FontMedium.First().MeasureText(buttonText);
+ var fontSize = Style.Current.FontMedium.MeasureText(buttonText);
var copyVersionButton = new Button(Width - fontSize.X - 8, 6, fontSize.X + 4, 20)
{
Text = buttonText,
diff --git a/Source/Editor/Windows/Assets/FontWindow.cs b/Source/Editor/Windows/Assets/FontWindow.cs
index ff4135165..2e2e14d99 100644
--- a/Source/Editor/Windows/Assets/FontWindow.cs
+++ b/Source/Editor/Windows/Assets/FontWindow.cs
@@ -144,7 +144,7 @@ namespace FlaxEditor.Windows.Assets
protected override void OnAssetLinked()
{
Asset.WaitForLoaded();
- _textPreview.Font = new FontReference(Asset.CreateFont(30));
+ _textPreview.Font = new MultiFontReference([Asset], 30);
_inputText.Text = string.Format("This is a sample text using font {0}.", Asset.FamilyName);
var options = Asset.Options;
_proxy.Set(ref options);
diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs
index a1072d158..f29dc0bd6 100644
--- a/Source/Editor/Windows/ContentWindow.Search.cs
+++ b/Source/Editor/Windows/ContentWindow.Search.cs
@@ -57,7 +57,7 @@ namespace FlaxEditor.Windows
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ Render2D.DrawText(Font.GetMultiFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
// Arrow
diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs
index 6526d7c8a..ac4fea5ba 100644
--- a/Source/Editor/Windows/OutputLogWindow.cs
+++ b/Source/Editor/Windows/OutputLogWindow.cs
@@ -470,9 +470,9 @@ namespace FlaxEditor.Windows
var wasEmpty = _output.TextLength == 0;
// Cache fonts
- _output.DefaultStyle.Font.GetFont();
- _output.WarningStyle.Font.GetFont();
- _output.ErrorStyle.Font.GetFont();
+ _output.DefaultStyle.Font.GetMultiFont();
+ _output.WarningStyle.Font.GetMultiFont();
+ _output.ErrorStyle.Font.GetMultiFont();
// Generate the output log
Span entries = CollectionsMarshal.AsSpan(_entries);
@@ -536,7 +536,7 @@ namespace FlaxEditor.Windows
}
var prevBlockBottom = _textBlocks.Count == 0 ? 0.0f : _textBlocks[_textBlocks.Count - 1].Bounds.Bottom;
var entryText = _textBuffer.ToString(startIndex, endIndex - startIndex);
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
continue;
var style = textBlock.Style;
@@ -544,46 +544,52 @@ namespace FlaxEditor.Windows
for (int j = 0; j < lines.Length; j++)
{
ref var line = ref lines[j];
- textBlock.Range.StartIndex = startIndex + line.FirstCharIndex;
- textBlock.Range.EndIndex = startIndex + line.LastCharIndex + 1;
- textBlock.Bounds = new Rectangle(new Float2(0.0f, prevBlockBottom), line.Size);
-
- if (textBlock.Range.Length > 0)
+ for (int k = 0; k < line.Blocks.Length; k++)
{
- // Parse compilation error/warning
- var regexStart = line.FirstCharIndex;
- if (j == 0)
- regexStart += prefixLength;
- var regexLength = line.LastCharIndex + 1 - regexStart;
- if (regexLength > 0)
+ ref var block = ref line.Blocks[k];
+
+ textBlock.Range.StartIndex = startIndex + block.FirstCharIndex;
+ textBlock.Range.EndIndex = startIndex + block.LastCharIndex + 1;
+ textBlock.Bounds = new Rectangle(new Float2(block.Location.X, prevBlockBottom), block.Size);
+
+ if (textBlock.Range.Length > 0)
{
- var match = _compileRegex.Match(entryText, regexStart, regexLength);
- if (match.Success)
+ // Parse compilation error/warning
+ var regexStart = block.FirstCharIndex;
+ if (j == 0)
+ regexStart += prefixLength;
+ var regexLength = block.LastCharIndex + 1 - regexStart;
+ if (regexLength > 0)
{
- switch (match.Groups["level"].Value)
+ var match = _compileRegex.Match(entryText, regexStart, regexLength);
+ if (match.Success)
{
- case "error":
- textBlock.Style = _output.ErrorStyle;
- break;
- case "warning":
- textBlock.Style = _output.WarningStyle;
- break;
+ switch (match.Groups["level"].Value)
+ {
+ case "error":
+ textBlock.Style = _output.ErrorStyle;
+ break;
+ case "warning":
+ textBlock.Style = _output.WarningStyle;
+ break;
+ }
+ textBlock.Tag = new TextBlockTag
+ {
+ Type = TextBlockTag.Types.CodeLocation,
+ Url = match.Groups["path"].Value,
+ Line = int.Parse(match.Groups["line"].Value),
+ };
}
- textBlock.Tag = new TextBlockTag
- {
- Type = TextBlockTag.Types.CodeLocation,
- Url = match.Groups["path"].Value,
- Line = int.Parse(match.Groups["line"].Value),
- };
+ // TODO: parsing hyperlinks with link
+ // TODO: parsing file paths with link
}
- // TODO: parsing hyperlinks with link
- // TODO: parsing file paths with link
}
+
+ _textBlocks.Add(textBlock);
+ textBlock.Style = style;
}
prevBlockBottom += line.Size.Y;
- _textBlocks.Add(textBlock);
- textBlock.Style = style;
}
}
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index 372505795..d6c14f4e4 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -14,6 +14,7 @@ using FlaxEditor.GUI.Tabs;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
+using FlaxEngine.Utilities;
namespace FlaxEditor.Windows
{
@@ -78,7 +79,7 @@ namespace FlaxEditor.Windows
HorizontalAlignment = TextAlignment.Near,
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Text = desc.Name,
- Font = new FontReference(Style.Current.FontLarge),
+ Font = new MultiFontReference(Style.Current.FontLarge),
Parent = this,
Bounds = new Rectangle(tmp1, margin, Width - tmp1 - margin, 28),
};
@@ -119,8 +120,8 @@ namespace FlaxEditor.Windows
url = desc.HomepageUrl;
else if (!string.IsNullOrEmpty(desc.RepositoryUrl))
url = desc.RepositoryUrl;
- versionLabel.Font.Font.WaitForLoaded();
- var font = versionLabel.Font.GetFont();
+ versionLabel.Font.ForEach(x => x.Font.WaitForLoaded());
+ var font = versionLabel.Font.GetMultiFont();
var authorWidth = font.MeasureText(desc.Author).X + 8;
var authorLabel = new ClickableLabel
{
@@ -391,7 +392,7 @@ namespace FlaxEditor.Windows
}
Editor.Log("Plugin project has been cloned.");
-
+
try
{
// Start git submodule clone
diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs
index 88019b329..917647f23 100644
--- a/Source/Editor/Windows/Profiler/Timeline.cs
+++ b/Source/Editor/Windows/Profiler/Timeline.cs
@@ -85,8 +85,8 @@ namespace FlaxEditor.Windows.Profiler
Render2D.FillRectangle(bounds, color);
Render2D.DrawRectangle(bounds, color * 0.5f);
- if (_nameLength < 0 && style.FontMedium.First())
- _nameLength = style.FontMedium.First().MeasureText(_name).X;
+ if (_nameLength < 0 && style.FontMedium)
+ _nameLength = style.FontMedium.MeasureText(_name).X;
if (_nameLength < bounds.Width + 4)
{
diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs
index e8fc1d56c..16b9165e1 100644
--- a/Source/Editor/Windows/ToolboxWindow.cs
+++ b/Source/Editor/Windows/ToolboxWindow.cs
@@ -273,8 +273,8 @@ namespace FlaxEditor.Windows
var textRect = item.TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
- var end = font.First().GetCharPosition(text, ranges[i].EndIndex);
+ var start = font.GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.GetCharPosition(text, ranges[i].EndIndex);
highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
item.SetHighlights(highlights);
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index 277ad8ddd..b33b10899 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -293,249 +293,6 @@ void Font::ProcessText(const StringView& text, Array& outputLines
}
}
-void Font::ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
-{
- float cursorX = 0;
- int32 kerning;
- MultiFontLineCache tmpLine;
- MultiFontSegmentCache tmpSegment;
- FontCharacterEntry entry;
- FontCharacterEntry previous;
- int32 textLength = text.Length();
- float scale = layout.Scale / FontManager::FontScale;
- float boundsWidth = layout.Bounds.GetWidth();
- float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
-
- tmpSegment.Location = Float2::Zero;
- tmpSegment.Height = 0;
- tmpSegment.FirstCharIndex = 0;
- tmpSegment.LastCharIndex = -1;
-
- tmpLine.Location = Float2::Zero;
- tmpLine.Size = Float2::Zero;
- tmpLine.Segments = Array();
-
- if (textLength == 0) {
- return;
- }
-
- int32 lastWrapCharIndex = INVALID_INDEX;
- float lastWrapCharX = 0;
- bool lastMoveLine = false;
- // The index of the font used by the current segment
- int32 currentFontIndex = GetCharFontIndex(fonts, text[0], 0);
- // The maximum font height of the current line
- float maxHeight = 0;
- float maxAscender = 0;
-
- // Process each character to split text into single lines
- for (int32 currentIndex = 0; currentIndex < textLength;)
- {
- bool moveLine = false;
- bool moveSegment = false;
- float xAdvance = 0;
- int32 nextCharIndex = currentIndex + 1;
-
- // Submit line and segment if text ends
- if (nextCharIndex == textLength) {
- moveLine = moveSegment = true;
- }
-
- // Cache current character
- const Char currentChar = text[currentIndex];
- const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
-
- // Check if character can wrap words
- const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar) || (currentChar >= 0x3040 && currentChar <= 0x9FFF);
- if (isWrapChar && currentIndex != 0)
- {
- lastWrapCharIndex = currentIndex;
- lastWrapCharX = cursorX;
- }
-
- int32 nextFontIndex = currentFontIndex;
- // Check if it's a newline character
- if (currentChar == '\n')
- {
- // Break line
- moveLine = moveSegment = true;
- tmpSegment.LastCharIndex++;
- }
- else
- {
- // Get character entry
- if (nextCharIndex < textLength) {
- nextFontIndex = GetCharFontIndex(fonts, text[nextCharIndex], currentFontIndex);
- }
-
- // Get character entry
- fonts[currentFontIndex]->GetCharacter(currentChar, entry);
- maxHeight = Math::Max(maxHeight, static_cast(fonts[currentFontIndex]->GetHeight()));
- maxAscender = Math::Max(maxAscender, static_cast(fonts[currentFontIndex]->GetAscender()));
-
- // Move segment if the font changes or text ends
- if (nextFontIndex != currentFontIndex || nextCharIndex == textLength) {
- moveSegment = true;
- }
-
- // Get kerning, only when the font hasn't changed
- if (!isWhitespace && previous.IsValid && !moveSegment)
- {
- kerning = fonts[currentFontIndex]->GetKerning(previous.Character, entry.Character);
- }
- else
- {
- kerning = 0;
- }
- previous = entry;
- xAdvance = (kerning + entry.AdvanceX) * scale;
-
- // Check if character fits the line or skip wrapping
- if (cursorX + xAdvance <= boundsWidth || layout.TextWrapping == TextWrapping::NoWrap)
- {
- // Move character
- cursorX += xAdvance;
- tmpSegment.LastCharIndex++;
- }
- else if (layout.TextWrapping == TextWrapping::WrapWords)
- {
- if (lastWrapCharIndex != INVALID_INDEX)
- {
- // Skip moving twice for the same character
- int32 lastLineLastCharIndex = outputLines.HasItems() && outputLines.Last().Segments.HasItems() ? outputLines.Last().Segments.Last().LastCharIndex : -10000;
- if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
- {
- currentIndex = nextCharIndex;
- lastMoveLine = moveLine;
- continue;
- }
-
- // Move line
- const Char wrapChar = text[lastWrapCharIndex];
- moveLine = true;
- moveSegment = tmpSegment.FirstCharIndex < lastWrapCharIndex;
-
- cursorX = lastWrapCharX;
- if (StringUtils::IsWhitespace(wrapChar))
- {
- // Skip whitespaces
- tmpSegment.LastCharIndex = lastWrapCharIndex - 1;
- nextCharIndex = currentIndex = lastWrapCharIndex + 1;
- }
- else
- {
- tmpSegment.LastCharIndex = lastWrapCharIndex - 1;
- nextCharIndex = currentIndex = lastWrapCharIndex;
- }
- }
- }
- else if (layout.TextWrapping == TextWrapping::WrapChars)
- {
- // Move line
- moveLine = true;
- moveSegment = tmpSegment.FirstCharIndex < currentChar;
- nextCharIndex = currentIndex;
-
- // Skip moving twice for the same character
- if (lastMoveLine)
- break;
- }
- }
-
- if (moveSegment) {
- // Add segment
- tmpSegment.Height = baseLinesDistanceScale * fonts[currentFontIndex]->GetHeight();
- tmpSegment.LastCharIndex = Math::Max(tmpSegment.LastCharIndex, tmpSegment.FirstCharIndex);
- tmpSegment.FontIndex = currentFontIndex;
- tmpLine.Segments.Add(tmpSegment);
-
- // Reset segment
- tmpSegment.Location.X = cursorX;
- tmpSegment.FirstCharIndex = nextCharIndex;
- tmpSegment.LastCharIndex = nextCharIndex - 1;
-
- currentFontIndex = nextFontIndex;
- }
-
- // Check if move to another line
- if (moveLine)
- {
- // Add line
- tmpLine.Size.X = cursorX;
- tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
- tmpLine.MaxAscender = maxAscender;
- outputLines.Add(tmpLine);
-
- // Reset line
- tmpLine.Segments.Clear();
- tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
- cursorX = 0;
- tmpSegment.Location.X = cursorX;
- lastWrapCharIndex = INVALID_INDEX;
- lastWrapCharX = 0;
- previous.IsValid = false;
-
- // Reset max font height
- maxHeight = 0;
- maxAscender = 0;
- }
-
- currentIndex = nextCharIndex;
- lastMoveLine = moveLine;
- }
-
- // Check if an additional line should be created
- if (text[textLength - 1] == '\n')
- {
- // Add line
- tmpLine.Size.X = cursorX;
- tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
- outputLines.Add(tmpLine);
-
- tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
- }
-
- // Check amount of lines
- if (outputLines.IsEmpty())
- return;
-
- float totalHeight = tmpLine.Location.Y;
-
- Float2 offset = Float2::Zero;
- if (layout.VerticalAlignment == TextAlignment::Center)
- {
- offset.Y += (layout.Bounds.GetHeight() - totalHeight) * 0.5f;
- }
- else if (layout.VerticalAlignment == TextAlignment::Far)
- {
- offset.Y += layout.Bounds.GetHeight() - totalHeight;
- }
- for (int32 i = 0; i < outputLines.Count(); i++)
- {
- MultiFontLineCache& line = outputLines[i];
- Float2 rootPos = line.Location + offset;
-
- // Fix upper left line corner to match desire text alignment
- if (layout.HorizontalAlignment == TextAlignment::Center)
- {
- rootPos.X += (layout.Bounds.GetWidth() - line.Size.X) * 0.5f;
- }
- else if (layout.HorizontalAlignment == TextAlignment::Far)
- {
- rootPos.X += layout.Bounds.GetWidth() - line.Size.X;
- }
-
- line.Location = rootPos;
-
- // Align all segments to center in case they have different heights
- for (int32 j = 0; j < line.Segments.Count(); j++)
- {
- MultiFontSegmentCache& segment = line.Segments[j];
- segment.Location.Y += (line.MaxAscender - fonts[segment.FontIndex]->GetAscender()) / 2;
- }
- }
-}
-
Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
@@ -643,7 +400,7 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
ASSERT(lines.HasItems());
float scale = layout.Scale / FontManager::FontScale;
float baseLinesDistance = static_cast(_height) * layout.BaseLinesGapScale * scale;
- Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
+ Float2 rootOffset = layout.Bounds.Location;
// Find line with that position
FontCharacterEntry previous;
@@ -682,10 +439,10 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
}
// Position after last character in the last line
- return rootOffset + Float2(lines.Last().Size.X, static_cast((lines.Count() - 1) * baseLinesDistance));
+ return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, static_cast((lines.Count() - 1) * baseLinesDistance));
}
-bool Font::ContainsChar(Char c)
+bool Font::ContainsChar(Char c) const
{
return FT_Get_Char_Index(GetAsset()->GetFTFace(), c) > 0;
}
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index 0425f2bc5..453872582 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -8,7 +8,6 @@
#include "Engine/Content/AssetReference.h"
#include "Engine/Scripting/ScriptingObject.h"
#include "TextLayoutOptions.h"
-#include "MultiFont.h"
class FontAsset;
struct FontTextureAtlasSlot;
@@ -341,15 +340,6 @@ public:
/// The output lines list.
void ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
- ///
- /// Processes text to get cached lines for rendering.
- ///
- /// The font list.
- /// The input text.
- /// The layout properties.
- /// The output lines list.
- static void ProcessText(const Array& fonts, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
-
///
/// Processes text to get cached lines for rendering.
///
@@ -406,17 +396,6 @@ public:
/// The minimum size for that text and fot to render properly.
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
- /*
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
- ///
- /// The fonts to render with.
- /// The input text to test.
- /// The layout properties.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() static Float2 MeasureText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
- */
-
///
/// Measures minimum size of the rectangle that will be needed to draw given text.
///
@@ -504,18 +483,6 @@ public:
/// The character position (upper left corner which can be used for a caret position).
API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
- /*
- ///
- /// Calculates character position for given text and character index.
- ///
- /// The fonts to use.
- /// The input text to test.
- /// The text position to get coordinates of.
- /// The text layout properties.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() static Float2 GetCharPosition(const Array& fonts, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
- */
-
///
/// Calculates character position for given text and character index.
///
@@ -557,28 +524,7 @@ public:
///
/// The char to test.
/// True if the font contains the glyph of the char, otherwise false.
- API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c);
-
- ///
- /// Gets the index of the font that should be used to render the char
- ///
- /// The font list.
- /// The char.
- /// Number to return if char cannot be found.
- ///
- API_FUNCTION() FORCE_INLINE static int32 GetCharFontIndex(const Array& fonts, Char c, int32 missing = -1) {
- int32 fontIndex = 0;
- while (fontIndex < fonts.Count() && !fonts[fontIndex]->ContainsChar(c))
- {
- fontIndex++;
- }
-
- if (fontIndex == fonts.Count()) {
- return missing;
- }
-
- return fontIndex;
- }
+ API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c) const;
///
/// Flushes the size of the face with the Free Type library backend.
diff --git a/Source/Engine/Render2D/MultiFont.cpp b/Source/Engine/Render2D/MultiFont.cpp
index 9844c12e0..4a510a9f8 100644
--- a/Source/Engine/Render2D/MultiFont.cpp
+++ b/Source/Engine/Render2D/MultiFont.cpp
@@ -1 +1,431 @@
#include "MultiFont.h"
+#include "FontManager.h"
+#include "Engine/Core/Math/Math.h"
+
+MultiFont::MultiFont(const Array& fonts)
+ : ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer)),
+ _fonts(fonts)
+{
+
+}
+
+void MultiFont::ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
+{
+ float cursorX = 0;
+ int32 kerning;
+ MultiFontLineCache tmpLine;
+ MultiFontBlockCache tmpBlock;
+ FontCharacterEntry entry;
+ FontCharacterEntry previous;
+ int32 textLength = text.Length();
+ float scale = layout.Scale / FontManager::FontScale;
+ float boundsWidth = layout.Bounds.GetWidth();
+ float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
+
+ tmpBlock.Location = Float2::Zero;
+ tmpBlock.Size = Float2::Zero;
+ tmpBlock.FirstCharIndex = 0;
+ tmpBlock.LastCharIndex = -1;
+
+ tmpLine.Location = Float2::Zero;
+ tmpLine.Size = Float2::Zero;
+ tmpLine.Blocks = Array();
+
+ if (textLength == 0) {
+ return;
+ }
+
+ int32 lastWrapCharIndex = INVALID_INDEX;
+ float lastWrapCharX = 0;
+ bool lastMoveLine = false;
+ // The index of the font used by the current block
+ int32 currentFontIndex = GetCharFontIndex(text[0], 0);
+ // The maximum font height of the current line
+ float maxHeight = 0;
+ float maxAscender = 0;
+ float lastCursorX = 0;
+
+ // Process each character to split text into single lines
+ for (int32 currentIndex = 0; currentIndex < textLength;)
+ {
+ bool moveLine = false;
+ bool moveBlock = false;
+ float xAdvance = 0;
+ int32 nextCharIndex = currentIndex + 1;
+
+ // Submit line and block if text ends
+ if (nextCharIndex == textLength) {
+ moveLine = moveBlock = true;
+ }
+
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Check if character can wrap words
+ const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar) || (currentChar >= 0x3040 && currentChar <= 0x9FFF);
+ if (isWrapChar && currentIndex != 0)
+ {
+ lastWrapCharIndex = currentIndex;
+ lastWrapCharX = cursorX;
+ }
+
+ int32 nextFontIndex = currentFontIndex;
+ // Check if it's a newline character
+ if (currentChar == '\n')
+ {
+ // Break line
+ moveLine = moveBlock = true;
+ tmpBlock.LastCharIndex++;
+ }
+ else
+ {
+ // Get character entry
+ if (nextCharIndex < textLength) {
+ nextFontIndex = GetCharFontIndex(text[nextCharIndex], currentFontIndex);
+ }
+
+ // Get character entry
+ _fonts[currentFontIndex]->GetCharacter(currentChar, entry);
+ maxHeight = Math::Max(maxHeight, static_cast(_fonts[currentFontIndex]->GetHeight()));
+ maxAscender = Math::Max(maxAscender, static_cast(_fonts[currentFontIndex]->GetAscender()));
+
+ // Move block if the font changes or text ends
+ if (nextFontIndex != currentFontIndex || nextCharIndex == textLength) {
+ moveBlock = true;
+ }
+
+ // Get kerning, only when the font hasn't changed
+ if (!isWhitespace && previous.IsValid && !moveBlock)
+ {
+ kerning = _fonts[currentFontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ else
+ {
+ kerning = 0;
+ }
+ previous = entry;
+ xAdvance = (kerning + entry.AdvanceX) * scale;
+
+ // Check if character fits the line or skip wrapping
+ if (cursorX + xAdvance <= boundsWidth || layout.TextWrapping == TextWrapping::NoWrap)
+ {
+ // Move character
+ cursorX += xAdvance;
+ tmpBlock.LastCharIndex++;
+ }
+ else if (layout.TextWrapping == TextWrapping::WrapWords)
+ {
+ if (lastWrapCharIndex != INVALID_INDEX)
+ {
+ // Skip moving twice for the same character
+ int32 lastLineLastCharIndex = outputLines.HasItems() && outputLines.Last().Blocks.HasItems() ? outputLines.Last().Blocks.Last().LastCharIndex : -10000;
+ if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
+ {
+ currentIndex = nextCharIndex;
+ lastMoveLine = moveLine;
+ continue;
+ }
+
+ // Move line
+ const Char wrapChar = text[lastWrapCharIndex];
+ moveLine = true;
+ moveBlock = tmpBlock.FirstCharIndex < lastWrapCharIndex;
+
+ cursorX = lastWrapCharX;
+ if (StringUtils::IsWhitespace(wrapChar))
+ {
+ // Skip whitespaces
+ tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
+ nextCharIndex = currentIndex = lastWrapCharIndex + 1;
+ }
+ else
+ {
+ tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
+ nextCharIndex = currentIndex = lastWrapCharIndex;
+ }
+ }
+ }
+ else if (layout.TextWrapping == TextWrapping::WrapChars)
+ {
+ // Move line
+ moveLine = true;
+ moveBlock = tmpBlock.FirstCharIndex < currentChar;
+ nextCharIndex = currentIndex;
+
+ // Skip moving twice for the same character
+ if (lastMoveLine)
+ break;
+ }
+ }
+
+ if (moveBlock) {
+ // Add block
+ tmpBlock.Size.X = lastCursorX - cursorX;
+ tmpBlock.Size.Y = baseLinesDistanceScale * _fonts[currentFontIndex]->GetHeight();
+ tmpBlock.LastCharIndex = Math::Max(tmpBlock.LastCharIndex, tmpBlock.FirstCharIndex);
+ tmpBlock.FontIndex = currentFontIndex;
+ tmpLine.Blocks.Add(tmpBlock);
+
+ // Reset block
+ tmpBlock.Location.X = cursorX;
+ tmpBlock.FirstCharIndex = nextCharIndex;
+ tmpBlock.LastCharIndex = nextCharIndex - 1;
+
+ currentFontIndex = nextFontIndex;
+ lastCursorX = cursorX;
+ }
+
+ // Check if move to another line
+ if (moveLine)
+ {
+ // Add line
+ tmpLine.Size.X = cursorX;
+ tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
+ tmpLine.MaxAscender = maxAscender;
+ outputLines.Add(tmpLine);
+
+ // Reset line
+ tmpLine.Blocks.Clear();
+ tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
+ cursorX = 0;
+ tmpBlock.Location.X = cursorX;
+ lastWrapCharIndex = INVALID_INDEX;
+ lastWrapCharX = 0;
+ previous.IsValid = false;
+
+ // Reset max font height
+ maxHeight = 0;
+ maxAscender = 0;
+ lastCursorX = 0;
+ }
+
+ currentIndex = nextCharIndex;
+ lastMoveLine = moveLine;
+ }
+
+ // Check if an additional line should be created
+ if (text[textLength - 1] == '\n')
+ {
+ // Add line
+ tmpLine.Size.X = cursorX;
+ tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
+ outputLines.Add(tmpLine);
+
+ tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
+ }
+
+ // Check amount of lines
+ if (outputLines.IsEmpty())
+ return;
+
+ float totalHeight = tmpLine.Location.Y;
+
+ Float2 offset = Float2::Zero;
+ if (layout.VerticalAlignment == TextAlignment::Center)
+ {
+ offset.Y += (layout.Bounds.GetHeight() - totalHeight) * 0.5f;
+ }
+ else if (layout.VerticalAlignment == TextAlignment::Far)
+ {
+ offset.Y += layout.Bounds.GetHeight() - totalHeight;
+ }
+ for (int32 i = 0; i < outputLines.Count(); i++)
+ {
+ MultiFontLineCache& line = outputLines[i];
+ Float2 rootPos = line.Location + offset;
+
+ // Fix upper left line corner to match desire text alignment
+ if (layout.HorizontalAlignment == TextAlignment::Center)
+ {
+ rootPos.X += (layout.Bounds.GetWidth() - line.Size.X) * 0.5f;
+ }
+ else if (layout.HorizontalAlignment == TextAlignment::Far)
+ {
+ rootPos.X += layout.Bounds.GetWidth() - line.Size.X;
+ }
+
+ line.Location = rootPos;
+
+ // Align all blocks to center in case they have different heights
+ for (int32 j = 0; j < line.Blocks.Count(); j++)
+ {
+ MultiFontBlockCache& block = line.Blocks[j];
+ block.Location.Y += (line.MaxAscender - _fonts[block.FontIndex]->GetAscender()) / 2;
+ }
+ }
+}
+
+Float2 MultiFont::GetCharPosition(const StringView& text, int32 index, const TextLayoutOptions& layout)
+{
+ // Check if there is no need to do anything
+ if (text.IsEmpty())
+ return layout.Bounds.Location;
+
+ // Process text
+ Array lines;
+ ProcessText(text, lines, layout);
+ ASSERT(lines.HasItems());
+ float scale = layout.Scale / FontManager::FontScale;
+ float baseLinesDistance = layout.BaseLinesGapScale * scale;
+ Float2 rootOffset = layout.Bounds.Location;
+
+ // Find line with that position
+ FontCharacterEntry previous;
+ FontCharacterEntry entry;
+ for (int32 lineIndex = 0; lineIndex < lines.Count(); lineIndex++)
+ {
+ const MultiFontLineCache& line = lines[lineIndex];
+ for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
+ {
+ const MultiFontBlockCache& block = line.Blocks[blockIndex];
+ // Check if desire position is somewhere inside characters in line range
+ if (Math::IsInRange(index, block.FirstCharIndex, block.LastCharIndex))
+ {
+ float x = line.Location.X + block.Location.X;
+ float y = line.Location.Y + block.Location.Y;
+
+ // Check all characters in the line
+ for (int32 currentIndex = block.FirstCharIndex; currentIndex < index; currentIndex++)
+ {
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+ _fonts[block.FontIndex]->GetCharacter(currentChar, entry);
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Apply kerning
+ if (!isWhitespace && previous.IsValid)
+ {
+ x += _fonts[block.FontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ previous = entry;
+
+ // Move
+ x += entry.AdvanceX * scale;
+ }
+
+ // Upper left corner of the character
+ return rootOffset + Float2(x, y);
+ }
+ }
+ }
+
+ // Position after last character in the last line
+ return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, lines.Last().Location.Y);
+}
+
+int32 MultiFont::HitTestText(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
+{
+ // Check if there is no need to do anything
+ if (text.Length() <= 0)
+ return 0;
+
+ // Process text
+ Array lines;
+ ProcessText(text, lines, layout);
+ ASSERT(lines.HasItems());
+ float scale = layout.Scale / FontManager::FontScale;
+
+ // Offset position to match lines origin space
+ Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
+ Float2 testPoint = location - rootOffset;
+
+ // Get block which may intersect with the position (it's possible because lines have fixed height)
+ int32 lineIndex = 0;
+ while (lineIndex < lines.Count())
+ {
+ if (lines[lineIndex].Location.Y + lines[lineIndex].Size.Y >= location.Y) {
+ break;
+ }
+
+ lineIndex++;
+ }
+ lineIndex = Math::Clamp(lineIndex, 0, lines.Count() - 1);
+ const MultiFontLineCache& line = lines[lineIndex];
+
+ int32 blockIndex = 0;
+ while (blockIndex < line.Blocks.Count() - 1)
+ {
+ if (line.Location.X + line.Blocks[blockIndex + 1].Location.X >= location.X) {
+ break;
+ }
+
+ blockIndex++;
+ }
+ const MultiFontBlockCache& block = line.Blocks[blockIndex];
+ float x = line.Location.X;
+
+ // Check all characters in the line to find hit point
+ FontCharacterEntry previous;
+ FontCharacterEntry entry;
+ int32 smallestIndex = INVALID_INDEX;
+ float dst, smallestDst = MAX_float;
+ for (int32 currentIndex = block.FirstCharIndex; currentIndex <= block.LastCharIndex; currentIndex++)
+ {
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+
+ _fonts[block.FontIndex]->GetCharacter(currentChar, entry);
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Apply kerning
+ if (!isWhitespace && previous.IsValid)
+ {
+ x += _fonts[block.FontIndex]->GetKerning(previous.Character, entry.Character);
+ }
+ previous = entry;
+
+ // Test
+ dst = Math::Abs(testPoint.X - x);
+ if (dst < smallestDst)
+ {
+ // Found closer character
+ smallestIndex = currentIndex;
+ smallestDst = dst;
+ }
+ else if (dst > smallestDst)
+ {
+ // Current char is worse so return the best result
+ return smallestIndex;
+ }
+
+ // Move
+ x += entry.AdvanceX * scale;
+ }
+
+ // Test line end edge
+ dst = Math::Abs(testPoint.X - x);
+ if (dst < smallestDst)
+ {
+ // Pointer is behind the last character in the line
+ smallestIndex = block.LastCharIndex;
+
+ // Fix for last line
+ if (lineIndex == lines.Count() - 1)
+ smallestIndex++;
+ }
+
+ return smallestIndex;
+}
+
+Float2 MultiFont::MeasureText(const StringView& text, const TextLayoutOptions& layout)
+{
+ // Check if there is no need to do anything
+ if (text.IsEmpty())
+ return Float2::Zero;
+
+ // Process text
+ Array lines;
+ ProcessText(text, lines, layout);
+
+ // Calculate bounds
+ Float2 max = Float2::Zero;
+ for (int32 i = 0; i < lines.Count(); i++)
+ {
+ const MultiFontLineCache& line = lines[i];
+ max = Float2::Max(max, line.Location + line.Size);
+ }
+
+ return max;
+}
+
diff --git a/Source/Engine/Render2D/MultiFont.h b/Source/Engine/Render2D/MultiFont.h
index b1da832d5..870b8e668 100644
--- a/Source/Engine/Render2D/MultiFont.h
+++ b/Source/Engine/Render2D/MultiFont.h
@@ -3,23 +3,28 @@
#include "Engine/Core/Collections/Array.h"
#include "Engine/Core/Collections/Dictionary.h"
#include "Font.h"
+#include "FontAsset.h"
+
+struct TextRange;
+class Font;
+class FontAsset;
///
-/// The font segment info generated during text processing.
+/// The font block info generated during text processing.
///
-API_STRUCT(NoDefault) struct MultiFontSegmentCache
+API_STRUCT(NoDefault) struct MultiFontBlockCache
{
- DECLARE_SCRIPTING_TYPE_MINIMAL(MultiFontSegmentCache);
+ DECLARE_SCRIPTING_TYPE_MINIMAL(MultiFontBlockCache);
///
- /// The root position of the segment (upper left corner), relative to line.
+ /// The root position of the block (upper left corner), relative to line.
///
API_FIELD() Float2 Location;
///
- /// The height of the current segment
+ /// The height of the current block
///
- API_FIELD() float Height;
+ API_FIELD() Float2 Size;
///
/// The first character index (from the input text).
@@ -38,13 +43,13 @@ API_STRUCT(NoDefault) struct MultiFontSegmentCache
};
template<>
-struct TIsPODType
+struct TIsPODType
{
enum { Value = true };
};
///
-/// Line of font segments info generated during text processing.
+/// Line of font blocks info generated during text processing.
///
API_STRUCT(NoDefault) struct MultiFontLineCache
{
@@ -61,17 +66,288 @@ API_STRUCT(NoDefault) struct MultiFontLineCache
API_FIELD() Float2 Size;
///
- /// The maximum ascendent of the line.
+ /// The maximum ascender of the line.
///
API_FIELD() float MaxAscender;
///
/// The index of the font to render with
///
- API_FIELD() Array Segments;
+ API_FIELD() Array Blocks;
};
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API MultiFont : public ManagedScriptingObject
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(MultiFont);
+private:
+ Array _fonts;
+
+public:
+ MultiFont(const Array& fonts);
+
+ API_FUNCTION() FORCE_INLINE static MultiFont* Create(const Array& fonts) {
+ return New(fonts);
+ }
+
+ API_FUNCTION() FORCE_INLINE static MultiFont* Create(const Array& fontAssets, float size) {
+ Array fonts;
+ fonts.Resize(fontAssets.Count());
+ for (int32 i = 0; i < fontAssets.Count(); i++)
+ {
+ fonts[i] = fontAssets[i]->CreateFont(size);
+ }
+
+ return New(fonts);
+ }
+
+ API_PROPERTY() FORCE_INLINE Array& GetFonts() {
+ return _fonts;
+ }
+
+ API_PROPERTY() FORCE_INLINE void SetFonts(const Array& val) {
+ _fonts = val;
+ }
+
+ API_PROPERTY() FORCE_INLINE int32 GetMaxHeight() {
+ int32 maxHeight = 0;
+ for (int32 i = 0; i < _fonts.Count(); i++)
+ {
+ if (_fonts[i]) {
+ maxHeight = Math::Max(maxHeight, _fonts[i]->GetHeight());
+ }
+ }
+
+ return maxHeight;
+ }
+
+ API_PROPERTY() FORCE_INLINE int32 GetMaxAscender() {
+ int32 maxAsc = 0;
+ for (int32 i = 0; i < _fonts.Count(); i++)
+ {
+ if (_fonts[i]) {
+ maxAsc = Math::Max(maxAsc, _fonts[i]->GetAscender());
+ }
+ }
+
+ return maxAsc;
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The layout properties.
+ /// The output lines list.
+ void ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The layout properties.
+ /// The output lines list.
+ API_FUNCTION() Array ProcessText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ Array lines;
+ ProcessText(text, lines, layout);
+ return lines;
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The input text range (substring range of the input text parameter).
+ /// The layout properties.
+ /// The output lines list.
+ API_FUNCTION() Array ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ Array lines;
+ ProcessText(textRange.Substring(text), lines, layout);
+ return lines;
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The output lines list.
+ API_FUNCTION() FORCE_INLINE Array ProcessText(const StringView& text)
+ {
+ return ProcessText(text, TextLayoutOptions());
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The input text range (substring range of the input text parameter).
+ /// The output lines list.
+ API_FUNCTION() FORCE_INLINE Array ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ {
+ return ProcessText(textRange.Substring(text), TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text.
+ ///
+ /// The input text to test.
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return MeasureText(textRange.Substring(text), layout);
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text
+ /// .
+ /// The input text to test.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text)
+ {
+ return MeasureText(text, TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text
+ /// .
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ {
+ return MeasureText(textRange.Substring(text), TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return HitTestText(textRange.Substring(text), location, layout);
+ }
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location)
+ {
+ return HitTestText(text, location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
+ {
+ return HitTestText(textRange.Substring(text), location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index.
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Calculates character position for given text and character index.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return GetCharPosition(textRange.Substring(text), index, layout);
+ }
+
+ ///
+ /// Calculates character position for given text and character index
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index)
+ {
+ return GetCharPosition(text, index, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
+ {
+ return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
+ }
+
+ ///
+ /// Gets the index of the font that should be used to render the char
+ ///
+ /// The font list.
+ /// The char.
+ /// Number to return if char cannot be found.
+ ///
+ API_FUNCTION() FORCE_INLINE int32 GetCharFontIndex(Char c, int32 missing = -1) {
+ int32 fontIndex = 0;
+ while (fontIndex < _fonts.Count() && _fonts[fontIndex] && !_fonts[fontIndex]->ContainsChar(c))
+ {
+ fontIndex++;
+ }
+
+ if (fontIndex == _fonts.Count()) {
+ return missing;
+ }
+
+ return fontIndex;
+ }
+
+ API_FUNCTION() FORCE_INLINE bool Verify() {
+ for (int32 i = 0; i < _fonts.Count(); i++)
+ {
+ if (!_fonts[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
};
diff --git a/Source/Engine/Render2D/MultiFontReference.cs b/Source/Engine/Render2D/MultiFontReference.cs
new file mode 100644
index 000000000..dd3f4d179
--- /dev/null
+++ b/Source/Engine/Render2D/MultiFontReference.cs
@@ -0,0 +1,74 @@
+
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace FlaxEngine
+{
+ ///
+ /// Reference to multiple font references
+ ///
+ public class MultiFontReference : List
+ {
+ public MultiFontReference()
+ {
+ _cachedFont = null;
+ }
+
+ public MultiFontReference(IEnumerable other)
+ {
+ AddRange(other);
+ _cachedFont = null;
+ }
+
+ public MultiFontReference(MultiFontReference other)
+ {
+ AddRange(other);
+ _cachedFont = other._cachedFont;
+ }
+
+ public MultiFontReference(MultiFontReference other, float size)
+ {
+ AddRange(other.Select(x => new FontReference(x) { Size = size }));
+ _cachedFont = null;
+ }
+
+ public MultiFontReference(MultiFont other)
+ {
+ AddRange(other.Fonts.Select(x => new FontReference(x)));
+ _cachedFont = other;
+ }
+
+ public MultiFontReference(FontAsset[] assets, float size)
+ {
+ AddRange(assets.Select(x => new FontReference(x, size)));
+ _cachedFont = null;
+ }
+
+ [EditorOrder(0), Tooltip("The font asset to use as characters source.")]
+ public MultiFont GetMultiFont()
+ {
+ if (_cachedFont)
+ return _cachedFont;
+ var fontList = this.Where(x => x.Font).Select(x => x.GetFont()).ToArray();
+ _cachedFont = MultiFont.Create(fontList);
+ return _cachedFont;
+ }
+
+ public bool Verify()
+ {
+ foreach (var i in this)
+ {
+ if (!i.Font)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [NoSerialize]
+ private MultiFont _cachedFont;
+ }
+}
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index 8a39d29be..c68c2445d 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -1370,10 +1370,11 @@ void Render2D::DrawText(Font* font, const StringView& text, const TextRange& tex
DrawText(font, textRange.Substring(text), color, layout, customMaterial);
}
-void Render2D::DrawText(const Array& fonts, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
+ const Array& fonts = multiFont->GetFonts();
// Check if there is no need to do anything
if (fonts.IsEmpty() || text.Length() < 0)
return;
@@ -1408,7 +1409,7 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
{
if (text[currentIndex] != '\n') {
- int32 fontIndex = Font::GetCharFontIndex(fonts, text[currentIndex], 0);
+ int32 fontIndex = multiFont->GetCharFontIndex(text[currentIndex], 0);
maxAscenders[lineIndex] = Math::Max(maxAscenders[lineIndex], static_cast(fonts[fontIndex]->GetAscender()));
}
else {
@@ -1418,12 +1419,12 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
}
lineIndex = 0;
- // The following code cut the text into segments, according to the font used to render
+ // The following code cut the text into blocks, according to the font used to render
Float2 pointer = location;
- // The starting index of the current segment
+ // The starting index of the current block
int32 startIndex = 0;
- // The index of the font used by the current segment
- int32 currentFontIndex = Font::GetCharFontIndex(fonts, text[0], 0);
+ // The index of the font used by the current block
+ int32 currentFontIndex = multiFont->GetCharFontIndex(text[0], 0);
// The maximum font height of the current line
float maxHeight = 0;
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
@@ -1431,13 +1432,13 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
// Cache current character
const Char currentChar = text[currentIndex];
int32 nextCharIndex = currentIndex + 1;
- bool moveSegment = false;
+ bool moveBlock = false;
bool moveLine = false;
int32 nextFontIndex = currentFontIndex;
- // Submit segment if text ends
+ // Submit block if text ends
if (nextCharIndex == text.Length()) {
- moveSegment = true;
+ moveBlock = true;
}
// Check if it isn't a newline character
@@ -1445,21 +1446,21 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
{
// Get character entry
if (nextCharIndex < text.Length()) {
- nextFontIndex = Font::GetCharFontIndex(fonts, text[nextCharIndex], currentFontIndex);
+ nextFontIndex = multiFont->GetCharFontIndex(text[nextCharIndex], currentFontIndex);
}
if (nextFontIndex != currentFontIndex) {
- moveSegment = true;
+ moveBlock = true;
}
}
else
{
// Move
- moveLine = moveSegment = true;
+ moveLine = moveBlock = true;
}
- if (moveSegment) {
- // Render the pending segment before beginning the new segment
+ if (moveBlock) {
+ // Render the pending block before beginning the new block
auto fontHeight = fonts[currentFontIndex]->GetHeight();
maxHeight = Math::Max(maxHeight, static_cast(fontHeight));
auto fontDescender = fonts[currentFontIndex]->GetDescender();
@@ -1533,22 +1534,23 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
lineIndex++;
}
- // Start new segment
+ // Start new block
startIndex = nextCharIndex;
currentFontIndex = nextFontIndex;
}
}
}
-void Render2D::DrawText(const Array& fonts, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
- DrawText(fonts, textRange.Substring(text), color, location, customMaterial);
+ DrawText(multiFont, textRange.Substring(text), color, location, customMaterial);
}
-void Render2D::DrawText(const Array& fonts, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
+ const Array& fonts = multiFont->GetFonts();
// Check if there is no need to do anything
if (fonts.IsEmpty() || text.IsEmpty() || layout.Scale <= ZeroTolerance)
return;
@@ -1563,7 +1565,7 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
// Process text to get lines
MultiFontLines.Clear();
- Font::ProcessText(fonts, text, MultiFontLines, layout);
+ multiFont->ProcessText(text, MultiFontLines, layout);
// Render all lines
FontCharacterEntry entry;
@@ -1582,14 +1584,14 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
for (int32 lineIndex = 0; lineIndex < MultiFontLines.Count(); lineIndex++)
{
const MultiFontLineCache& line = MultiFontLines[lineIndex];
- for (int32 segmentIndex = 0; segmentIndex < line.Segments.Count(); segmentIndex++)
+ for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
{
- const MultiFontSegmentCache& segment = MultiFontLines[lineIndex].Segments[segmentIndex];
- auto fontHeight = fonts[segment.FontIndex]->GetHeight();
- auto fontDescender = fonts[segment.FontIndex]->GetDescender();
- Float2 pointer = line.Location + segment.Location;
+ const MultiFontBlockCache& block = MultiFontLines[lineIndex].Blocks[blockIndex];
+ auto fontHeight = fonts[block.FontIndex]->GetHeight();
+ auto fontDescender = fonts[block.FontIndex]->GetDescender();
+ Float2 pointer = line.Location + block.Location;
- for (int32 charIndex = segment.FirstCharIndex; charIndex <= segment.LastCharIndex; charIndex++)
+ for (int32 charIndex = block.FirstCharIndex; charIndex <= block.LastCharIndex; charIndex++)
{
Char c = text[charIndex];
if (c == '\n')
@@ -1598,7 +1600,7 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
}
// Get character entry
- fonts[segment.FontIndex]->GetCharacter(c, entry);
+ fonts[block.FontIndex]->GetCharacter(c, entry);
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
@@ -1623,7 +1625,7 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
const bool isWhitespace = StringUtils::IsWhitespace(c);
if (!isWhitespace && previous.IsValid)
{
- kerning = fonts[segment.FontIndex]->GetKerning(previous.Character, entry.Character);
+ kerning = fonts[block.FontIndex]->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -1659,9 +1661,9 @@ void Render2D::DrawText(const Array& fonts, const StringView& text, const
}
}
-void Render2D::DrawText(const Array& fonts, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
- DrawText(fonts, textRange.Substring(text), color, layout, customMaterial);
+ DrawText(multiFont, textRange.Substring(text), color, layout, customMaterial);
}
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
@@ -2165,22 +2167,22 @@ void Render2D::DrawBezier(const Float2& p1, const Float2& p2, const Float2& p3,
{
RENDER2D_CHECK_RENDERING_STATE;
- // Find amount of segments to use
+ // Find amount of blocks to use
const Float2 d1 = p2 - p1;
const Float2 d2 = p3 - p2;
const Float2 d3 = p4 - p3;
const float len = d1.Length() + d2.Length() + d3.Length();
- const int32 segmentCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
- const float segmentCountInv = 1.0f / segmentCount;
+ const int32 blockCount = Math::Clamp(Math::CeilToInt(len * 0.05f), 1, 100);
+ const float blockCountInv = 1.0f / blockCount;
- // Draw segmented curve
+ // Draw blocked curve
Float2 p;
AnimationUtils::Bezier(p1, p2, p3, p4, 0, p);
Lines2.Clear();
Lines2.Add(p);
- for (int32 i = 1; i <= segmentCount; i++)
+ for (int32 i = 1; i <= blockCount; i++)
{
- const float t = i * segmentCountInv;
+ const float t = i * blockCountInv;
AnimationUtils::Bezier(p1, p2, p3, p4, t, p);
Lines2.Add(p);
}
diff --git a/Source/Engine/Render2D/Render2D.cs b/Source/Engine/Render2D/Render2D.cs
index a73556f7b..cad8380ab 100644
--- a/Source/Engine/Render2D/Render2D.cs
+++ b/Source/Engine/Render2D/Render2D.cs
@@ -164,7 +164,7 @@ namespace FlaxEngine
/// Describes how wrap text inside a layout rectangle.
/// The scale for distance one baseline from another. Default is 1.
/// The text drawing scale. Default is 1.
- public static void DrawText(Font[] fonts, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ public static void DrawText(MultiFont fonts, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
{
var layout = new TextLayoutOptions
{
@@ -175,6 +175,8 @@ namespace FlaxEngine
Scale = scale,
BaseLinesGapScale = baseLinesGapScale,
};
+
+
DrawText(fonts, text, color, ref layout);
}
@@ -191,7 +193,7 @@ namespace FlaxEngine
/// Describes how wrap text inside a layout rectangle.
/// The scale for distance one baseline from another. Default is 1.
/// The text drawing scale. Default is 1.
- public static void DrawText(Font[] fonts, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ public static void DrawText(MultiFont fonts, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
{
var layout = new TextLayoutOptions
{
@@ -202,6 +204,7 @@ namespace FlaxEngine
Scale = scale,
BaseLinesGapScale = baseLinesGapScale,
};
+
DrawText(fonts, text, color, ref layout, customMaterial);
}
diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h
index 0ec88edc0..5050171b2 100644
--- a/Source/Engine/Render2D/Render2D.h
+++ b/Source/Engine/Render2D/Render2D.h
@@ -15,6 +15,7 @@ struct Matrix3x3;
struct Viewport;
struct TextRange;
class Font;
+class MultiFont;
class GPUPipelineState;
class GPUTexture;
class GPUTextureView;
@@ -224,7 +225,7 @@ public:
/// The text color.
/// The text location.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
/// Draws a text with formatting.
@@ -234,7 +235,7 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
/// Draws a text with formatting.
@@ -245,7 +246,7 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
/// Draws a text with formatting.
@@ -256,7 +257,7 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(const Array& fonts, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
/// Fills a rectangle area.
diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs
index 8e71c9f31..bc800f88a 100644
--- a/Source/Engine/Scripting/Scripting.cs
+++ b/Source/Engine/Scripting/Scripting.cs
@@ -294,15 +294,12 @@ namespace FlaxEngine
style.DragWindow = style.BackgroundSelected * 0.7f;
// Use optionally bundled default font (matches Editor)
- var defaultFont = Content.LoadAsyncInternal("Editor/Fonts/Roboto-Regular");
- var cjkFont = Content.LoadAsyncInternal("NotoSansSC-Medium");
- if (defaultFont)
- {
- style.FontTitle = defaultFont.CreateFont(18);
- style.FontLarge = defaultFont.CreateFont(14);
- style.FontMedium = new Font[] { defaultFont.CreateFont(9), cjkFont.CreateFont(9) };
- style.FontSmall = new Font[] { defaultFont.CreateFont(9), cjkFont.CreateFont(9) };
- }
+ FontAsset[] defaultFont = [Content.LoadAsyncInternal("Editor/Fonts/Roboto-Regular"), Content.LoadAsyncInternal("Editor/Fonts/NotoSansSC-Regular")];
+
+ style.FontTitle = new MultiFontReference(defaultFont, 18).GetMultiFont();
+ style.FontLarge = new MultiFontReference(defaultFont, 14).GetMultiFont();
+ style.FontMedium = new MultiFontReference(defaultFont, 9).GetMultiFont();
+ style.FontSmall = new MultiFontReference(defaultFont, 9).GetMultiFont();
Style.Current = style;
}
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index 1b965b8d1..f21a29191 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -23,7 +23,7 @@ namespace FlaxEngine.GUI
///
/// The font.
///
- protected FontReference _font;
+ protected MultiFontReference _font;
///
/// The text.
@@ -44,7 +44,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font used to draw button text.
///
[EditorDisplay("Text Style"), EditorOrder(2022), ExpandGroups]
- public FontReference Font
+ public MultiFontReference Font
{
get => _font;
set => _font = value;
@@ -156,7 +156,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
if (style != null)
{
- _font = new FontReference(style.FontMedium.First());
+ _font = new MultiFontReference(style.FontMedium);
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BorderColor = style.BorderNormal;
@@ -262,7 +262,7 @@ namespace FlaxEngine.GUI
Render2D.DrawRectangle(clientRect, borderColor, BorderThickness);
// Draw text
- Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(_font?.GetMultiFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index 21ca9cbea..2681aac1b 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -278,7 +278,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font used to draw text.
///
[EditorDisplay("Text Style"), EditorOrder(2021)]
- public FontReference Font { get; set; }
+ public MultiFontReference Font { get; set; }
///
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
@@ -359,7 +359,7 @@ namespace FlaxEngine.GUI
: base(0, 0, 120, 18.0f)
{
var style = Style.Current;
- Font = new FontReference(style.FontMedium.First());
+ Font = new MultiFontReference(style.FontMedium);
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BackgroundColorHighlighted = BackgroundColor;
@@ -674,7 +674,7 @@ namespace FlaxEngine.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(Font.GetMultiFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index 5fa8ad21d..ccc1cc190 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -26,7 +26,7 @@ namespace FlaxEngine.GUI
///
/// The font.
///
- protected FontReference _font;
+ protected MultiFontReference _font;
///
/// Gets or sets the text.
@@ -86,7 +86,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font.
///
[EditorDisplay("Text Style"), EditorOrder(2024)]
- public FontReference Font
+ public MultiFontReference Font
{
get => _font;
set
@@ -192,7 +192,7 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
- Font = new FontReference(style.FontMedium.First());
+ Font = new MultiFontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
@@ -203,7 +203,7 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
- Font = new FontReference(style.FontMedium.First());
+ Font = new MultiFontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
@@ -235,7 +235,7 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText([_font.GetFont(), Style.Current.FontCJK], Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ Render2D.DrawText(_font.GetMultiFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
Render2D.PopClip();
@@ -246,7 +246,7 @@ namespace FlaxEngine.GUI
{
if (_autoWidth || _autoHeight || _autoFitText)
{
- var font = _font.GetFont();
+ var font = _font.GetMultiFont();
if (font)
{
// Calculate text size
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs
index 2270136ae..9523ad30a 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using FlaxEngine.Utilities;
@@ -185,7 +186,7 @@ namespace FlaxEngine.GUI
};
// Process text into text blocks (handle newlines etc.)
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
return;
var lines = font.ProcessText(_text, ref textBlock.Range);
@@ -194,20 +195,27 @@ namespace FlaxEngine.GUI
for (int i = 0; i < lines.Length; i++)
{
ref var line = ref lines[i];
- textBlock.Range = new TextRange
- {
- StartIndex = start + line.FirstCharIndex,
- EndIndex = start + line.LastCharIndex,
- };
+
if (i != 0)
{
context.Caret.X = 0;
OnLineAdded(ref context, textBlock.Range.StartIndex - 1);
}
- textBlock.Bounds = new Rectangle(context.Caret, line.Size);
- textBlock.Bounds.X += line.Location.X;
+ for (int k = 0; k < line.Blocks.Length; k++)
+ {
+ ref var block = ref line.Blocks[k];
- context.AddTextBlock(ref textBlock);
+ textBlock.Range = new TextRange
+ {
+ StartIndex = start + block.FirstCharIndex,
+ EndIndex = start + block.LastCharIndex,
+ };
+
+ textBlock.Bounds = new Rectangle(context.Caret, block.Size);
+ textBlock.Bounds.X += block.Location.X;
+
+ context.AddTextBlock(ref textBlock);
+ }
}
// Update the caret location
@@ -236,9 +244,9 @@ namespace FlaxEngine.GUI
var ascender = textBlock.Ascender;
//if (ascender <= 0)
{
- var textBlockFont = textBlock.Style.Font.GetFont();
+ var textBlockFont = textBlock.Style.Font.GetMultiFont();
if (textBlockFont)
- ascender = textBlockFont.Ascender;
+ ascender = textBlockFont.MaxAscender;
}
lineAscender = Mathf.Max(lineAscender, ascender);
lineSize = Float2.Max(lineSize, textBlockSize);
@@ -259,9 +267,9 @@ namespace FlaxEngine.GUI
var ascender = textBlock.Ascender;
if (ascender <= 0)
{
- var textBlockFont = textBlock.Style.Font.GetFont();
+ var textBlockFont = textBlock.Style.Font.GetMultiFont();
if (textBlockFont)
- ascender = textBlockFont.Ascender;
+ ascender = textBlockFont.MaxAscender;
}
vOffset = lineAscender - ascender;
textBlock.Bounds.Location.Y += vOffset;
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
index 044c65044..08637918d 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using FlaxEngine.Utilities;
+using System.Linq;
namespace FlaxEngine.GUI
{
@@ -10,9 +11,9 @@ namespace FlaxEngine.GUI
{
context.Caret.X = 0;
var style = context.StyleStack.Peek();
- var font = style.Font.GetFont();
+ var font = style.Font.GetMultiFont();
if (font)
- context.Caret.Y += font.Height;
+ context.Caret.Y += font.MaxHeight;
}
private static void ProcessColor(ref ParsingContext context, ref HtmlTag tag)
@@ -86,15 +87,14 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- style.Font = new FontReference(style.Font);
- if (tag.Attributes.TryGetValue(string.Empty, out var fontName))
+ style.Font = new MultiFontReference(style.Font);
+ if (tag.Attributes.TryGetValue("size", out var sizeText) && int.TryParse(sizeText, out var size) && tag.Attributes.TryGetValue(string.Empty, out var fontName))
{
var font = (FontAsset)FindAsset(fontName, typeof(FontAsset));
if (font)
- style.Font.Font = font;
+ style.Font = new MultiFontReference([font], size);
}
- if (tag.Attributes.TryGetValue("size", out var sizeText) && int.TryParse(sizeText, out var size))
- style.Font.Size = size;
+
context.StyleStack.Push(style);
}
}
@@ -108,7 +108,7 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- style.Font = style.Font.GetBold();
+ // style.Font = style.Font.GetBold();
context.StyleStack.Push(style);
}
}
@@ -122,7 +122,7 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- style.Font = style.Font.GetItalic();
+ // style.Font = style.Font.GetItalic();
context.StyleStack.Push(style);
}
}
@@ -136,9 +136,9 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- style.Font = new FontReference(style.Font);
- TryParseNumberTag(ref tag, string.Empty, style.Font.Size, out var size);
- style.Font.Size = (int)size;
+ style.Font = new MultiFontReference(style.Font);
+ TryParseNumberTag(ref tag, string.Empty, style.Font.First().Size, out var size);
+ style.Font = new MultiFontReference(style.Font, (int)size);
context.StyleStack.Push(style);
}
}
@@ -173,9 +173,9 @@ namespace FlaxEngine.GUI
imageBlock.Style.BackgroundBrush = image;
// Setup size
- var font = imageBlock.Style.Font.GetFont();
+ var font = imageBlock.Style.Font.GetMultiFont();
if (font)
- imageBlock.Bounds.Size = new Float2(font.Height);
+ imageBlock.Bounds.Size = new Float2(font.MaxHeight);
imageBlock.Bounds.Size.X *= image.Size.X / image.Size.Y; // Keep original aspect ratio
bool hasWidth = TryParseNumberTag(ref tag, "width", imageBlock.Bounds.Width, out var width);
imageBlock.Bounds.Width = width;
@@ -213,18 +213,18 @@ namespace FlaxEngine.GUI
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
switch (valign)
{
- case "top":
- style.Alignment = TextBlockStyle.Alignments.Top;
- break;
- case "bottom":
- style.Alignment = TextBlockStyle.Alignments.Bottom;
- break;
- case "middle":
- style.Alignment = TextBlockStyle.Alignments.Middle;
- break;
- case "baseline":
- style.Alignment = TextBlockStyle.Alignments.Baseline;
- break;
+ case "top":
+ style.Alignment = TextBlockStyle.Alignments.Top;
+ break;
+ case "bottom":
+ style.Alignment = TextBlockStyle.Alignments.Bottom;
+ break;
+ case "middle":
+ style.Alignment = TextBlockStyle.Alignments.Middle;
+ break;
+ case "baseline":
+ style.Alignment = TextBlockStyle.Alignments.Baseline;
+ break;
}
}
context.StyleStack.Push(style);
@@ -245,15 +245,15 @@ namespace FlaxEngine.GUI
style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask;
switch (valign)
{
- case "left":
- style.Alignment = TextBlockStyle.Alignments.Left;
- break;
- case "right":
- style.Alignment = TextBlockStyle.Alignments.Right;
- break;
- case "center":
- style.Alignment = TextBlockStyle.Alignments.Center;
- break;
+ case "left":
+ style.Alignment = TextBlockStyle.Alignments.Left;
+ break;
+ case "right":
+ style.Alignment = TextBlockStyle.Alignments.Right;
+ break;
+ case "center":
+ style.Alignment = TextBlockStyle.Alignments.Center;
+ break;
}
}
context.StyleStack.Push(style);
@@ -280,7 +280,7 @@ namespace FlaxEngine.GUI
foreach (var id in ids)
{
var path = Content.GetEditorAssetPath(id);
- if (!string.IsNullOrEmpty(path) &&
+ if (!string.IsNullOrEmpty(path) &&
string.Equals(name, System.IO.Path.GetFileNameWithoutExtension(path), System.StringComparison.OrdinalIgnoreCase))
{
return Content.LoadAsync(id, type);
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.cs b/Source/Engine/UI/GUI/Common/RichTextBox.cs
index e6a82c986..78da9621c 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.cs
@@ -46,7 +46,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
_textStyle = new TextBlockStyle
{
- Font = new FontReference(style.FontMedium.First()),
+ Font = new MultiFontReference(style.FontMedium),
Color = style.Foreground,
BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected),
};
diff --git a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
index 438a7e3d8..6247cb885 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
@@ -123,10 +123,10 @@ namespace FlaxEngine.GUI
if (index <= 0)
{
ref TextBlock textBlock = ref textBlocks[0];
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (font)
{
- height = font.Height / DpiScale;
+ height = font.MaxHeight / DpiScale;
return textBlock.Bounds.UpperLeft;
}
}
@@ -135,10 +135,10 @@ namespace FlaxEngine.GUI
if (index >= _text.Length)
{
ref TextBlock textBlock = ref textBlocks[count - 1];
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (font)
{
- height = font.Height / DpiScale;
+ height = font.MaxHeight / DpiScale;
return textBlock.Bounds.UpperRight;
}
}
@@ -150,10 +150,10 @@ namespace FlaxEngine.GUI
if (textBlock.Range.Contains(index))
{
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
break;
- height = font.Height / DpiScale;
+ height = font.MaxHeight / DpiScale;
return textBlock.Bounds.Location + font.GetCharPosition(_text, ref textBlock.Range, index - textBlock.Range.StartIndex);
}
}
@@ -165,10 +165,10 @@ namespace FlaxEngine.GUI
if (index >= textBlock.Range.EndIndex)
{
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
break;
- height = font.Height / DpiScale;
+ height = font.MaxHeight / DpiScale;
return textBlock.Bounds.UpperRight;
}
}
@@ -193,7 +193,7 @@ namespace FlaxEngine.GUI
if (containsY && (containsX || (i + 1 < count && textBlocks[i + 1].Bounds.Location.Y > textBlock.Bounds.Location.Y + 1.0f)))
{
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font && textBlock.Range.Length > 0)
break;
return font.HitTestText(_text, ref textBlock.Range, location - textBlock.Bounds.Location) + textBlock.Range.StartIndex;
@@ -281,7 +281,7 @@ namespace FlaxEngine.GUI
}
// Pick font
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
continue;
@@ -290,7 +290,7 @@ namespace FlaxEngine.GUI
{
var leftEdge = selection.StartIndex <= textBlock.Range.StartIndex ? textBlock.Bounds.UpperLeft : font.GetCharPosition(_text, selection.StartIndex);
var rightEdge = selection.EndIndex >= textBlock.Range.EndIndex ? textBlock.Bounds.UpperRight : font.GetCharPosition(_text, selection.EndIndex);
- float height = font.Height / DpiScale;
+ float height = font.MaxHeight / DpiScale;
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
alpha *= alpha;
Color selectionColor = Color.White * alpha;
@@ -305,7 +305,7 @@ namespace FlaxEngine.GUI
ref TextBlock textBlock = ref textBlocks[i];
// Pick font
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
continue;
@@ -332,7 +332,7 @@ namespace FlaxEngine.GUI
ref TextBlock textBlock = ref textBlocks[i];
// Pick font
- var font = textBlock.Style.Font.GetFont();
+ var font = textBlock.Style.Font.GetMultiFont();
if (!font)
continue;
@@ -340,7 +340,7 @@ namespace FlaxEngine.GUI
if (textBlock.Style.UnderlineBrush != null)
{
var underLineHeight = 2.0f;
- var height = font.Height / DpiScale;
+ var height = font.MaxHeight / DpiScale;
var underlineRect = new Rectangle(textBlock.Bounds.Location.X, textBlock.Bounds.Location.Y + height - underLineHeight * 0.5f, textBlock.Bounds.Width, underLineHeight);
textBlock.Style.UnderlineBrush.Draw(underlineRect, textBlock.Style.Color);
}
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index 967617649..d9c7c1a80 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -40,7 +40,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font.
///
[EditorDisplay("Text Style"), EditorOrder(2024)]
- public FontReference Font { get; set; }
+ public MultiFontReference Font { get; set; }
///
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
@@ -90,7 +90,7 @@ namespace FlaxEngine.GUI
_layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
var style = Style.Current;
- Font = new FontReference(style.FontMedium.First());
+ Font = new MultiFontReference(style.FontMedium);
TextColor = style.Foreground;
WatermarkTextColor = style.ForegroundDisabled;
SelectionColor = style.BackgroundSelected;
@@ -99,7 +99,7 @@ namespace FlaxEngine.GUI
///
public override Float2 GetTextSize()
{
- var font = Font.GetFont();
+ var font = Font.GetMultiFont();
if (font == null)
{
return Float2.Zero;
@@ -111,21 +111,21 @@ namespace FlaxEngine.GUI
///
public override Float2 GetCharPosition(int index, out float height)
{
- var font = Font.GetFont();
+ var font = Font.GetMultiFont();
if (font == null)
{
height = Height;
return Float2.Zero;
}
- height = font.Height / DpiScale;
+ height = font.MaxHeight / DpiScale;
return font.GetCharPosition(_text, index, ref _layout);
}
///
public override int HitTestText(Float2 location)
{
- var font = Font.GetFont();
+ var font = Font.GetMultiFont();
if (font == null)
{
return 0;
@@ -148,7 +148,7 @@ namespace FlaxEngine.GUI
// Cache data
var rect = new Rectangle(Float2.Zero, Size);
bool enabled = EnabledInHierarchy;
- var font = Font.GetFont();
+ var font = Font.GetMultiFont();
if (!font)
return;
@@ -172,7 +172,7 @@ namespace FlaxEngine.GUI
{
var leftEdge = font.GetCharPosition(_text, SelectionLeft, ref _layout);
var rightEdge = font.GetCharPosition(_text, SelectionRight, ref _layout);
- float fontHeight = font.Height / DpiScale;
+ float fontHeight = font.MaxHeight / DpiScale;
// Draw selection background
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
diff --git a/Source/Engine/UI/GUI/Panels/DropPanel.cs b/Source/Engine/UI/GUI/Panels/DropPanel.cs
index 33c2e1605..06256c9f8 100644
--- a/Source/Engine/UI/GUI/Panels/DropPanel.cs
+++ b/Source/Engine/UI/GUI/Panels/DropPanel.cs
@@ -130,7 +130,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font used to render panel header text.
///
[EditorDisplay("Header Text Style"), EditorOrder(2020), ExpandGroups]
- public FontReference HeaderTextFont { get; set; }
+ public MultiFontReference HeaderTextFont { get; set; }
///
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
@@ -238,7 +238,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
HeaderColor = style.BackgroundNormal;
HeaderColorMouseOver = style.BackgroundHighlighted;
- HeaderTextFont = new FontReference(style.FontMedium.First());
+ HeaderTextFont = new MultiFontReference(style.FontMedium);
HeaderTextColor = style.Foreground;
ArrowImageOpened = new SpriteBrush(style.ArrowDown);
ArrowImageClosed = new SpriteBrush(style.ArrowRight);
@@ -375,7 +375,7 @@ namespace FlaxEngine.GUI
textColor *= 0.6f;
}
- Render2D.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(HeaderTextFont.GetMultiFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!_isClosed && EnableContainmentLines)
{
diff --git a/Source/Engine/UI/GUI/Style.cs b/Source/Engine/UI/GUI/Style.cs
index d3375a670..a8b87fb3a 100644
--- a/Source/Engine/UI/GUI/Style.cs
+++ b/Source/Engine/UI/GUI/Style.cs
@@ -14,68 +14,60 @@ namespace FlaxEngine.GUI
///
public static Style Current { get; set; }
- public Font FontCJK
- {
- get => _fontCJK?.GetFont();
- set => _fontCJK = new FontReference(value);
- }
-
- private FontReference _fontCJK;
-
[Serialize]
- private FontReference _fontTitle;
+ private MultiFontReference _fontTitle;
///
/// The font title.
///
[NoSerialize]
[EditorOrder(10)]
- public Font FontTitle
+ public MultiFont FontTitle
{
- get => _fontTitle?.GetFont();
- set => _fontTitle = new FontReference(value);
+ get => _fontTitle?.GetMultiFont();
+ set => _fontTitle = new MultiFontReference(value);
}
[Serialize]
- private FontReference _fontLarge;
+ private MultiFontReference _fontLarge;
///
/// The font large.
///
[NoSerialize]
[EditorOrder(20)]
- public Font FontLarge
+ public MultiFont FontLarge
{
- get => _fontLarge?.GetFont();
- set => _fontLarge = new FontReference(value);
+ get => _fontLarge?.GetMultiFont();
+ set => _fontLarge = new MultiFontReference(value);
}
[Serialize]
- private FontReference[] _fontMedium;
+ private MultiFontReference _fontMedium;
///
/// The font medium.
///
[NoSerialize]
[EditorOrder(30)]
- public Font[] FontMedium
+ public MultiFont FontMedium
{
- get => _fontMedium?.Select((x)=>x.GetFont()).ToArray();
- set => _fontMedium = value.Select((x)=>new FontReference(x)).ToArray();
+ get => _fontMedium?.GetMultiFont();
+ set => _fontMedium = new MultiFontReference(value);
}
[Serialize]
- private FontReference[] _fontSmall;
+ private MultiFontReference _fontSmall;
///
/// The font small.
///
[NoSerialize]
[EditorOrder(40)]
- public Font[] FontSmall
+ public MultiFont FontSmall
{
- get => _fontSmall?.Select((x) => x.GetFont()).ToArray();
- set => _fontSmall = value.Select((x) => new FontReference(x)).ToArray();
+ get => _fontSmall?.GetMultiFont();
+ set => _fontSmall = new MultiFontReference(value);
}
///
diff --git a/Source/Engine/UI/GUI/TextBlockStyle.cs b/Source/Engine/UI/GUI/TextBlockStyle.cs
index c4c87715f..08f74e7c8 100644
--- a/Source/Engine/UI/GUI/TextBlockStyle.cs
+++ b/Source/Engine/UI/GUI/TextBlockStyle.cs
@@ -64,7 +64,7 @@ namespace FlaxEngine.GUI
/// The text font.
///
[EditorOrder(0)]
- public FontReference Font;
+ public MultiFontReference Font;
///
/// The custom material for the text rendering (must be GUI domain).
diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs
index e17b754c4..7a1026e55 100644
--- a/Source/Engine/UI/GUI/Tooltip.cs
+++ b/Source/Engine/UI/GUI/Tooltip.cs
@@ -244,6 +244,7 @@ namespace FlaxEngine.GUI
TextAlignment.Center,
TextWrapping.WrapWords
);
+
}
///
@@ -256,14 +257,14 @@ namespace FlaxEngine.GUI
// Calculate size of the tooltip
var size = Float2.Zero;
- if (style != null && style.FontMedium.First() && !string.IsNullOrEmpty(_currentText))
+ if (style != null && style.FontMedium && !string.IsNullOrEmpty(_currentText))
{
var layout = TextLayoutOptions.Default;
layout.Bounds = new Rectangle(0, 0, MaxWidth, 10000000);
layout.HorizontalAlignment = TextAlignment.Center;
layout.VerticalAlignment = TextAlignment.Center;
layout.TextWrapping = TextWrapping.WrapWords;
- var items = style.FontMedium.First().ProcessText(_currentText, ref layout);
+ var items = style.FontMedium.ProcessText(_currentText, ref layout);
for (int i = 0; i < items.Length; i++)
{
ref var item = ref items[i];
From 3365fb5afc6f7600acaa5e730a257bb378f2776f Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Thu, 30 Nov 2023 14:59:43 +0800
Subject: [PATCH 04/16] Fix console rendering bug
---
Source/Editor/Options/InterfaceOptions.cs | 11 ++-
Source/Editor/Windows/OutputLogWindow.cs | 74 +++++++++----------
.../UI/GUI/Common/RichTextBox.Parsing.cs | 33 ++++-----
.../Engine/UI/GUI/Common/RichTextBox.Tags.cs | 27 +++----
Source/Engine/UI/GUI/Common/RichTextBox.cs | 2 +-
.../Engine/UI/GUI/Common/RichTextBoxBase.cs | 28 +++----
Source/Engine/UI/GUI/TextBlockStyle.cs | 2 +-
7 files changed, 82 insertions(+), 95 deletions(-)
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index e43751fd1..91eebe4eb 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -166,13 +166,13 @@ namespace FlaxEditor.Options
/// Gets or sets the output log text font.
///
[EditorDisplay("Output Log", "Text Font"), EditorOrder(320), Tooltip("The output log text font.")]
- public MultiFontReference OutputLogTextFont
+ public FontReference OutputLogTextFont
{
get => _outputLogFont;
set
{
- if (value == null || !value.Verify())
- _outputLogFont = new MultiFontReference(ConsoleFonts, 10);
+ if (value == null || !value.Font)
+ _outputLogFont = new FontReference(ConsoleFont, 10);
else
_outputLogFont = value;
}
@@ -238,14 +238,13 @@ namespace FlaxEditor.Options
[FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont),
FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CjkFont)];
- private static FontAsset[] ConsoleFonts => [FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont),
- FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CjkFont)];
+ private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont);
private MultiFontReference _titleFont = new MultiFontReference(DefaultFonts, 18);
private MultiFontReference _largeFont = new MultiFontReference(DefaultFonts, 14);
private MultiFontReference _mediumFont = new MultiFontReference(DefaultFonts, 9);
private MultiFontReference _smallFont = new MultiFontReference(DefaultFonts, 9);
- private MultiFontReference _outputLogFont = new MultiFontReference(ConsoleFonts, 10);
+ private FontReference _outputLogFont = new FontReference(ConsoleFont, 10);
///
diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs
index ac4fea5ba..f168d8d45 100644
--- a/Source/Editor/Windows/OutputLogWindow.cs
+++ b/Source/Editor/Windows/OutputLogWindow.cs
@@ -470,9 +470,9 @@ namespace FlaxEditor.Windows
var wasEmpty = _output.TextLength == 0;
// Cache fonts
- _output.DefaultStyle.Font.GetMultiFont();
- _output.WarningStyle.Font.GetMultiFont();
- _output.ErrorStyle.Font.GetMultiFont();
+ _output.DefaultStyle.Font.GetFont();
+ _output.WarningStyle.Font.GetFont();
+ _output.ErrorStyle.Font.GetFont();
// Generate the output log
Span entries = CollectionsMarshal.AsSpan(_entries);
@@ -536,7 +536,7 @@ namespace FlaxEditor.Windows
}
var prevBlockBottom = _textBlocks.Count == 0 ? 0.0f : _textBlocks[_textBlocks.Count - 1].Bounds.Bottom;
var entryText = _textBuffer.ToString(startIndex, endIndex - startIndex);
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
continue;
var style = textBlock.Style;
@@ -544,52 +544,46 @@ namespace FlaxEditor.Windows
for (int j = 0; j < lines.Length; j++)
{
ref var line = ref lines[j];
- for (int k = 0; k < line.Blocks.Length; k++)
+ textBlock.Range.StartIndex = startIndex + line.FirstCharIndex;
+ textBlock.Range.EndIndex = startIndex + line.LastCharIndex + 1;
+ textBlock.Bounds = new Rectangle(new Float2(0.0f, prevBlockBottom), line.Size);
+
+ if (textBlock.Range.Length > 0)
{
- ref var block = ref line.Blocks[k];
-
- textBlock.Range.StartIndex = startIndex + block.FirstCharIndex;
- textBlock.Range.EndIndex = startIndex + block.LastCharIndex + 1;
- textBlock.Bounds = new Rectangle(new Float2(block.Location.X, prevBlockBottom), block.Size);
-
- if (textBlock.Range.Length > 0)
+ // Parse compilation error/warning
+ var regexStart = line.FirstCharIndex;
+ if (j == 0)
+ regexStart += prefixLength;
+ var regexLength = line.LastCharIndex + 1 - regexStart;
+ if (regexLength > 0)
{
- // Parse compilation error/warning
- var regexStart = block.FirstCharIndex;
- if (j == 0)
- regexStart += prefixLength;
- var regexLength = block.LastCharIndex + 1 - regexStart;
- if (regexLength > 0)
+ var match = _compileRegex.Match(entryText, regexStart, regexLength);
+ if (match.Success)
{
- var match = _compileRegex.Match(entryText, regexStart, regexLength);
- if (match.Success)
+ switch (match.Groups["level"].Value)
{
- switch (match.Groups["level"].Value)
- {
- case "error":
- textBlock.Style = _output.ErrorStyle;
- break;
- case "warning":
- textBlock.Style = _output.WarningStyle;
- break;
- }
- textBlock.Tag = new TextBlockTag
- {
- Type = TextBlockTag.Types.CodeLocation,
- Url = match.Groups["path"].Value,
- Line = int.Parse(match.Groups["line"].Value),
- };
+ case "error":
+ textBlock.Style = _output.ErrorStyle;
+ break;
+ case "warning":
+ textBlock.Style = _output.WarningStyle;
+ break;
}
- // TODO: parsing hyperlinks with link
- // TODO: parsing file paths with link
+ textBlock.Tag = new TextBlockTag
+ {
+ Type = TextBlockTag.Types.CodeLocation,
+ Url = match.Groups["path"].Value,
+ Line = int.Parse(match.Groups["line"].Value),
+ };
}
+ // TODO: parsing hyperlinks with link
+ // TODO: parsing file paths with link
}
-
- _textBlocks.Add(textBlock);
- textBlock.Style = style;
}
prevBlockBottom += line.Size.Y;
+ _textBlocks.Add(textBlock);
+ textBlock.Style = style;
}
}
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs
index 9523ad30a..ab01df12b 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs
@@ -186,7 +186,7 @@ namespace FlaxEngine.GUI
};
// Process text into text blocks (handle newlines etc.)
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
return;
var lines = font.ProcessText(_text, ref textBlock.Range);
@@ -195,27 +195,20 @@ namespace FlaxEngine.GUI
for (int i = 0; i < lines.Length; i++)
{
ref var line = ref lines[i];
-
+ textBlock.Range = new TextRange
+ {
+ StartIndex = start + line.FirstCharIndex,
+ EndIndex = start + line.LastCharIndex,
+ };
if (i != 0)
{
context.Caret.X = 0;
OnLineAdded(ref context, textBlock.Range.StartIndex - 1);
}
- for (int k = 0; k < line.Blocks.Length; k++)
- {
- ref var block = ref line.Blocks[k];
+ textBlock.Bounds = new Rectangle(context.Caret, line.Size);
+ textBlock.Bounds.X += line.Location.X;
- textBlock.Range = new TextRange
- {
- StartIndex = start + block.FirstCharIndex,
- EndIndex = start + block.LastCharIndex,
- };
-
- textBlock.Bounds = new Rectangle(context.Caret, block.Size);
- textBlock.Bounds.X += block.Location.X;
-
- context.AddTextBlock(ref textBlock);
- }
+ context.AddTextBlock(ref textBlock);
}
// Update the caret location
@@ -244,9 +237,9 @@ namespace FlaxEngine.GUI
var ascender = textBlock.Ascender;
//if (ascender <= 0)
{
- var textBlockFont = textBlock.Style.Font.GetMultiFont();
+ var textBlockFont = textBlock.Style.Font.GetFont();
if (textBlockFont)
- ascender = textBlockFont.MaxAscender;
+ ascender = textBlockFont.Ascender;
}
lineAscender = Mathf.Max(lineAscender, ascender);
lineSize = Float2.Max(lineSize, textBlockSize);
@@ -267,9 +260,9 @@ namespace FlaxEngine.GUI
var ascender = textBlock.Ascender;
if (ascender <= 0)
{
- var textBlockFont = textBlock.Style.Font.GetMultiFont();
+ var textBlockFont = textBlock.Style.Font.GetFont();
if (textBlockFont)
- ascender = textBlockFont.MaxAscender;
+ ascender = textBlockFont.Ascender;
}
vOffset = lineAscender - ascender;
textBlock.Bounds.Location.Y += vOffset;
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
index 08637918d..d3c2feefe 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
@@ -11,9 +11,9 @@ namespace FlaxEngine.GUI
{
context.Caret.X = 0;
var style = context.StyleStack.Peek();
- var font = style.Font.GetMultiFont();
+ var font = style.Font.GetFont();
if (font)
- context.Caret.Y += font.MaxHeight;
+ context.Caret.Y += font.Height;
}
private static void ProcessColor(ref ParsingContext context, ref HtmlTag tag)
@@ -87,14 +87,15 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- style.Font = new MultiFontReference(style.Font);
- if (tag.Attributes.TryGetValue("size", out var sizeText) && int.TryParse(sizeText, out var size) && tag.Attributes.TryGetValue(string.Empty, out var fontName))
+ style.Font = new FontReference(style.Font);
+ if (tag.Attributes.TryGetValue(string.Empty, out var fontName))
{
var font = (FontAsset)FindAsset(fontName, typeof(FontAsset));
if (font)
- style.Font = new MultiFontReference([font], size);
+ style.Font.Font = font;
}
-
+ if (tag.Attributes.TryGetValue("size", out var sizeText) && int.TryParse(sizeText, out var size))
+ style.Font.Size = size;
context.StyleStack.Push(style);
}
}
@@ -108,7 +109,7 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- // style.Font = style.Font.GetBold();
+ style.Font = style.Font.GetBold();
context.StyleStack.Push(style);
}
}
@@ -122,7 +123,7 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- // style.Font = style.Font.GetItalic();
+ style.Font = style.Font.GetItalic();
context.StyleStack.Push(style);
}
}
@@ -136,9 +137,9 @@ namespace FlaxEngine.GUI
else
{
var style = context.StyleStack.Peek();
- style.Font = new MultiFontReference(style.Font);
- TryParseNumberTag(ref tag, string.Empty, style.Font.First().Size, out var size);
- style.Font = new MultiFontReference(style.Font, (int)size);
+ style.Font = new FontReference(style.Font);
+ TryParseNumberTag(ref tag, string.Empty, style.Font.Size, out var size);
+ style.Font.Size = (int)size;
context.StyleStack.Push(style);
}
}
@@ -173,9 +174,9 @@ namespace FlaxEngine.GUI
imageBlock.Style.BackgroundBrush = image;
// Setup size
- var font = imageBlock.Style.Font.GetMultiFont();
+ var font = imageBlock.Style.Font.GetFont();
if (font)
- imageBlock.Bounds.Size = new Float2(font.MaxHeight);
+ imageBlock.Bounds.Size = new Float2(font.Height);
imageBlock.Bounds.Size.X *= image.Size.X / image.Size.Y; // Keep original aspect ratio
bool hasWidth = TryParseNumberTag(ref tag, "width", imageBlock.Bounds.Width, out var width);
imageBlock.Bounds.Width = width;
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.cs b/Source/Engine/UI/GUI/Common/RichTextBox.cs
index 78da9621c..f8ac7d353 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.cs
@@ -46,7 +46,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
_textStyle = new TextBlockStyle
{
- Font = new MultiFontReference(style.FontMedium),
+ Font = new FontReference(style.FontMedium.Fonts.First()),
Color = style.Foreground,
BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected),
};
diff --git a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
index 6247cb885..438a7e3d8 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
@@ -123,10 +123,10 @@ namespace FlaxEngine.GUI
if (index <= 0)
{
ref TextBlock textBlock = ref textBlocks[0];
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (font)
{
- height = font.MaxHeight / DpiScale;
+ height = font.Height / DpiScale;
return textBlock.Bounds.UpperLeft;
}
}
@@ -135,10 +135,10 @@ namespace FlaxEngine.GUI
if (index >= _text.Length)
{
ref TextBlock textBlock = ref textBlocks[count - 1];
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (font)
{
- height = font.MaxHeight / DpiScale;
+ height = font.Height / DpiScale;
return textBlock.Bounds.UpperRight;
}
}
@@ -150,10 +150,10 @@ namespace FlaxEngine.GUI
if (textBlock.Range.Contains(index))
{
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
break;
- height = font.MaxHeight / DpiScale;
+ height = font.Height / DpiScale;
return textBlock.Bounds.Location + font.GetCharPosition(_text, ref textBlock.Range, index - textBlock.Range.StartIndex);
}
}
@@ -165,10 +165,10 @@ namespace FlaxEngine.GUI
if (index >= textBlock.Range.EndIndex)
{
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
break;
- height = font.MaxHeight / DpiScale;
+ height = font.Height / DpiScale;
return textBlock.Bounds.UpperRight;
}
}
@@ -193,7 +193,7 @@ namespace FlaxEngine.GUI
if (containsY && (containsX || (i + 1 < count && textBlocks[i + 1].Bounds.Location.Y > textBlock.Bounds.Location.Y + 1.0f)))
{
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font && textBlock.Range.Length > 0)
break;
return font.HitTestText(_text, ref textBlock.Range, location - textBlock.Bounds.Location) + textBlock.Range.StartIndex;
@@ -281,7 +281,7 @@ namespace FlaxEngine.GUI
}
// Pick font
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
continue;
@@ -290,7 +290,7 @@ namespace FlaxEngine.GUI
{
var leftEdge = selection.StartIndex <= textBlock.Range.StartIndex ? textBlock.Bounds.UpperLeft : font.GetCharPosition(_text, selection.StartIndex);
var rightEdge = selection.EndIndex >= textBlock.Range.EndIndex ? textBlock.Bounds.UpperRight : font.GetCharPosition(_text, selection.EndIndex);
- float height = font.MaxHeight / DpiScale;
+ float height = font.Height / DpiScale;
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
alpha *= alpha;
Color selectionColor = Color.White * alpha;
@@ -305,7 +305,7 @@ namespace FlaxEngine.GUI
ref TextBlock textBlock = ref textBlocks[i];
// Pick font
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
continue;
@@ -332,7 +332,7 @@ namespace FlaxEngine.GUI
ref TextBlock textBlock = ref textBlocks[i];
// Pick font
- var font = textBlock.Style.Font.GetMultiFont();
+ var font = textBlock.Style.Font.GetFont();
if (!font)
continue;
@@ -340,7 +340,7 @@ namespace FlaxEngine.GUI
if (textBlock.Style.UnderlineBrush != null)
{
var underLineHeight = 2.0f;
- var height = font.MaxHeight / DpiScale;
+ var height = font.Height / DpiScale;
var underlineRect = new Rectangle(textBlock.Bounds.Location.X, textBlock.Bounds.Location.Y + height - underLineHeight * 0.5f, textBlock.Bounds.Width, underLineHeight);
textBlock.Style.UnderlineBrush.Draw(underlineRect, textBlock.Style.Color);
}
diff --git a/Source/Engine/UI/GUI/TextBlockStyle.cs b/Source/Engine/UI/GUI/TextBlockStyle.cs
index 08f74e7c8..c4c87715f 100644
--- a/Source/Engine/UI/GUI/TextBlockStyle.cs
+++ b/Source/Engine/UI/GUI/TextBlockStyle.cs
@@ -64,7 +64,7 @@ namespace FlaxEngine.GUI
/// The text font.
///
[EditorOrder(0)]
- public MultiFontReference Font;
+ public FontReference Font;
///
/// The custom material for the text rendering (must be GUI domain).
From d3840bb1f36fafb2ca6d5154d9922b3c16b500fb Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Thu, 30 Nov 2023 16:25:32 +0800
Subject: [PATCH 05/16] Refractor C++ code structure
---
Source/Engine/Render2D/FallbackFonts.cpp | 11 +
Source/Engine/Render2D/FallbackFonts.h | 94 +++++
Source/Engine/Render2D/Font.cpp | 441 ++++++++++++++++++++++-
Source/Engine/Render2D/Font.h | 276 +++++++++++++-
Source/Engine/Render2D/FontAsset.cpp | 4 +
Source/Engine/Render2D/FontAsset.h | 7 +
Source/Engine/Render2D/MultiFont.cpp | 431 ----------------------
Source/Engine/Render2D/MultiFont.h | 353 ------------------
Source/Engine/Render2D/Render2D.cpp | 74 ++--
Source/Engine/Render2D/Render2D.h | 10 +-
10 files changed, 864 insertions(+), 837 deletions(-)
create mode 100644 Source/Engine/Render2D/FallbackFonts.cpp
create mode 100644 Source/Engine/Render2D/FallbackFonts.h
delete mode 100644 Source/Engine/Render2D/MultiFont.cpp
delete mode 100644 Source/Engine/Render2D/MultiFont.h
diff --git a/Source/Engine/Render2D/FallbackFonts.cpp b/Source/Engine/Render2D/FallbackFonts.cpp
new file mode 100644
index 000000000..b79a0db4e
--- /dev/null
+++ b/Source/Engine/Render2D/FallbackFonts.cpp
@@ -0,0 +1,11 @@
+#include "FallbackFonts.h"
+#include "FontManager.h"
+#include "Engine/Core/Math/Math.h"
+
+FallbackFonts::FallbackFonts(const Array& fonts)
+ : ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer)),
+ _fontAssets(fonts)
+{
+
+}
+
diff --git a/Source/Engine/Render2D/FallbackFonts.h b/Source/Engine/Render2D/FallbackFonts.h
new file mode 100644
index 000000000..4b97e1c11
--- /dev/null
+++ b/Source/Engine/Render2D/FallbackFonts.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "Engine/Core/Collections/Array.h"
+#include "Engine/Core/Collections/Dictionary.h"
+#include "Font.h"
+#include "FontAsset.h"
+
+struct TextRange;
+class Font;
+class FontAsset;
+
+API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FallbackFonts : public ManagedScriptingObject
+{
+ DECLARE_SCRIPTING_TYPE_NO_SPAWN(FallbackFonts);
+private:
+ ///
+ /// The list of fallback fonts, ordered by priority.
+ /// The first element is reserved for the primary font, fallback fonts starts from the second element.
+ ///
+ Array _fontAssets;
+
+ Dictionary*> _cache;
+
+public:
+ FallbackFonts(const Array& fonts);
+
+ API_FUNCTION() FORCE_INLINE static FallbackFonts* Create(const Array& fonts) {
+ return New(fonts);
+ }
+
+ API_PROPERTY() FORCE_INLINE Array& GetFonts() {
+ return _fontAssets;
+ }
+
+ API_PROPERTY() FORCE_INLINE void SetFonts(const Array& val) {
+ _fontAssets = val;
+ }
+
+ ///
+ /// Combine the primary fonts with the fallback fonts to get a font list
+ ///
+ API_PROPERTY() FORCE_INLINE Array& GetFontList(float size) {
+ Array* result;
+ if (_cache.TryGet(size, result)) {
+ return *result;
+ }
+
+ result = New>(_fontAssets.Count());
+ auto& arr = *result;
+ for (int32 i = 0; i < _fontAssets.Count(); i++)
+ {
+ arr.Add(_fontAssets[i]->CreateFont(size));
+ }
+
+ _cache[size] = result;
+ return *result;
+ }
+
+
+ ///
+ /// Gets the index of the fallback font that should be used to render the char
+ ///
+ /// The char.
+ /// -1 if char can be rendered with primary font, index if it matches a fallback font.
+ API_FUNCTION() FORCE_INLINE int32 GetCharFallbackIndex(Char c, Font* primaryFont = nullptr, int32 missing = -1) {
+ if (primaryFont && primaryFont->GetAsset()->ContainsChar(c)) {
+ return -1;
+ }
+
+ int32 fontIndex = 0;
+ while (fontIndex < _fontAssets.Count() && _fontAssets[fontIndex] && !_fontAssets[fontIndex]->ContainsChar(c))
+ {
+ fontIndex++;
+ }
+
+ if (fontIndex < _fontAssets.Count()) {
+ return fontIndex;
+
+ }
+
+ return missing;
+ }
+
+ API_FUNCTION() FORCE_INLINE bool Verify() {
+ for (int32 i = 0; i < _fontAssets.Count(); i++)
+ {
+ if (!_fontAssets[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index b33b10899..4cf1f73a2 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -6,7 +6,7 @@
#include "Engine/Core/Log.h"
#include "Engine/Threading/Threading.h"
#include "IncludeFreeType.h"
-#include "MultiFont.h"
+#include "FallbackFonts.h"
Font::Font(FontAsset* parentAsset, float size)
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer))
@@ -293,6 +293,261 @@ void Font::ProcessText(const StringView& text, Array& outputLines
}
}
+void Font::ProcessText(FallbackFonts* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
+{
+ const Array& fallbackFonts = fallbacks->GetFontList(GetSize());
+ float cursorX = 0;
+ int32 kerning;
+ BlockedTextLineCache tmpLine;
+ FontBlockCache tmpBlock;
+ FontCharacterEntry entry;
+ FontCharacterEntry previous;
+ int32 textLength = text.Length();
+ float scale = layout.Scale / FontManager::FontScale;
+ float boundsWidth = layout.Bounds.GetWidth();
+ float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
+
+ tmpBlock.Location = Float2::Zero;
+ tmpBlock.Size = Float2::Zero;
+ tmpBlock.FirstCharIndex = 0;
+ tmpBlock.LastCharIndex = -1;
+
+ tmpLine.Location = Float2::Zero;
+ tmpLine.Size = Float2::Zero;
+ tmpLine.Blocks = Array();
+
+ if (textLength == 0) {
+ return;
+ }
+
+ int32 lastWrapCharIndex = INVALID_INDEX;
+ float lastWrapCharX = 0;
+ bool lastMoveLine = false;
+ // The index of the font used by the current block
+ int32 currentFontIndex = fallbacks->GetCharFallbackIndex(text[0], this);
+ // The maximum font height of the current line
+ float maxHeight = 0;
+ float maxAscender = 0;
+ float lastCursorX = 0;
+
+ auto getFont = [&](int32 index)->Font* {
+ return index >= 0 ? fallbackFonts[index] : this;
+ };
+
+ // Process each character to split text into single blocks
+ for (int32 currentIndex = 0; currentIndex < textLength;)
+ {
+ bool moveLine = false;
+ bool moveBlock = false;
+ float xAdvance = 0;
+ int32 nextCharIndex = currentIndex + 1;
+
+ // Submit line and block if text ends
+ if (nextCharIndex == textLength) {
+ moveLine = moveBlock = true;
+ }
+
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Check if character can wrap words
+ const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar) || (currentChar >= 0x3040 && currentChar <= 0x9FFF);
+ if (isWrapChar && currentIndex != 0)
+ {
+ lastWrapCharIndex = currentIndex;
+ lastWrapCharX = cursorX;
+ }
+
+ int32 nextFontIndex = currentFontIndex;
+ // Check if it's a newline character
+ if (currentChar == '\n')
+ {
+ // Break line
+ moveLine = moveBlock = true;
+ tmpBlock.LastCharIndex++;
+ }
+ else
+ {
+ // Get character entry
+ if (nextCharIndex < textLength) {
+ nextFontIndex = fallbacks->GetCharFallbackIndex(text[nextCharIndex], this, currentFontIndex);
+ }
+
+ // Get character entry
+ getFont(currentFontIndex)->GetCharacter(currentChar, entry);
+
+ maxHeight = Math::Max(maxHeight,
+ static_cast(getFont(currentFontIndex)->GetHeight()));
+ maxAscender = Math::Max(maxAscender,
+ static_cast(getFont(currentFontIndex)->GetAscender()));
+
+ // Move block if the font changes or text ends
+ if (nextFontIndex != currentFontIndex || nextCharIndex == textLength) {
+ moveBlock = true;
+ }
+
+ // Get kerning, only when the font hasn't changed
+ if (!isWhitespace && previous.IsValid && !moveBlock)
+ {
+ kerning = getFont(currentFontIndex)->GetKerning(previous.Character, entry.Character);
+ }
+ else
+ {
+ kerning = 0;
+ }
+ previous = entry;
+ xAdvance = (kerning + entry.AdvanceX) * scale;
+
+ // Check if character fits the line or skip wrapping
+ if (cursorX + xAdvance <= boundsWidth || layout.TextWrapping == TextWrapping::NoWrap)
+ {
+ // Move character
+ cursorX += xAdvance;
+ tmpBlock.LastCharIndex++;
+ }
+ else if (layout.TextWrapping == TextWrapping::WrapWords)
+ {
+ if (lastWrapCharIndex != INVALID_INDEX)
+ {
+ // Skip moving twice for the same character
+ int32 lastLineLastCharIndex = outputLines.HasItems() && outputLines.Last().Blocks.HasItems() ? outputLines.Last().Blocks.Last().LastCharIndex : -10000;
+ if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
+ {
+ currentIndex = nextCharIndex;
+ lastMoveLine = moveLine;
+ continue;
+ }
+
+ // Move line
+ const Char wrapChar = text[lastWrapCharIndex];
+ moveLine = true;
+ moveBlock = tmpBlock.FirstCharIndex < lastWrapCharIndex;
+
+ cursorX = lastWrapCharX;
+ if (StringUtils::IsWhitespace(wrapChar))
+ {
+ // Skip whitespaces
+ tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
+ nextCharIndex = currentIndex = lastWrapCharIndex + 1;
+ }
+ else
+ {
+ tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
+ nextCharIndex = currentIndex = lastWrapCharIndex;
+ }
+ }
+ }
+ else if (layout.TextWrapping == TextWrapping::WrapChars)
+ {
+ // Move line
+ moveLine = true;
+ moveBlock = tmpBlock.FirstCharIndex < currentChar;
+ nextCharIndex = currentIndex;
+
+ // Skip moving twice for the same character
+ if (lastMoveLine)
+ break;
+ }
+ }
+
+ if (moveBlock) {
+ // Add block
+ tmpBlock.Size.X = lastCursorX - cursorX;
+ tmpBlock.Size.Y = baseLinesDistanceScale * getFont(currentFontIndex)->GetHeight();
+ tmpBlock.LastCharIndex = Math::Max(tmpBlock.LastCharIndex, tmpBlock.FirstCharIndex);
+ tmpBlock.FallbackFontIndex = currentFontIndex;
+ tmpLine.Blocks.Add(tmpBlock);
+
+ // Reset block
+ tmpBlock.Location.X = cursorX;
+ tmpBlock.FirstCharIndex = nextCharIndex;
+ tmpBlock.LastCharIndex = nextCharIndex - 1;
+
+ currentFontIndex = nextFontIndex;
+ lastCursorX = cursorX;
+ }
+
+ // Check if move to another line
+ if (moveLine)
+ {
+ // Add line
+ tmpLine.Size.X = cursorX;
+ tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
+ tmpLine.MaxAscender = maxAscender;
+ outputLines.Add(tmpLine);
+
+ // Reset line
+ tmpLine.Blocks.Clear();
+ tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
+ cursorX = 0;
+ tmpBlock.Location.X = cursorX;
+ lastWrapCharIndex = INVALID_INDEX;
+ lastWrapCharX = 0;
+ previous.IsValid = false;
+
+ // Reset max font height
+ maxHeight = 0;
+ maxAscender = 0;
+ lastCursorX = 0;
+ }
+
+ currentIndex = nextCharIndex;
+ lastMoveLine = moveLine;
+ }
+
+ // Check if an additional line should be created
+ if (text[textLength - 1] == '\n')
+ {
+ // Add line
+ tmpLine.Size.X = cursorX;
+ tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
+ outputLines.Add(tmpLine);
+
+ tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
+ }
+
+ // Check amount of lines
+ if (outputLines.IsEmpty())
+ return;
+
+ float totalHeight = tmpLine.Location.Y;
+
+ Float2 offset = Float2::Zero;
+ if (layout.VerticalAlignment == TextAlignment::Center)
+ {
+ offset.Y += (layout.Bounds.GetHeight() - totalHeight) * 0.5f;
+ }
+ else if (layout.VerticalAlignment == TextAlignment::Far)
+ {
+ offset.Y += layout.Bounds.GetHeight() - totalHeight;
+ }
+ for (int32 i = 0; i < outputLines.Count(); i++)
+ {
+ BlockedTextLineCache& line = outputLines[i];
+ Float2 rootPos = line.Location + offset;
+
+ // Fix upper left line corner to match desire text alignment
+ if (layout.HorizontalAlignment == TextAlignment::Center)
+ {
+ rootPos.X += (layout.Bounds.GetWidth() - line.Size.X) * 0.5f;
+ }
+ else if (layout.HorizontalAlignment == TextAlignment::Far)
+ {
+ rootPos.X += layout.Bounds.GetWidth() - line.Size.X;
+ }
+
+ line.Location = rootPos;
+
+ // Align all blocks to center in case they have different heights
+ for (int32 j = 0; j < line.Blocks.Count(); j++)
+ {
+ FontBlockCache& block = line.Blocks[j];
+ block.Location.Y += (line.MaxAscender - getFont(block.FallbackFontIndex)->GetAscender()) / 2;
+ }
+ }
+}
+
Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
@@ -314,6 +569,27 @@ Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout
return max;
}
+Float2 Font::MeasureText(FallbackFonts* fallbacks, const StringView& text, const TextLayoutOptions& layout)
+{
+ // Check if there is no need to do anything
+ if (text.IsEmpty())
+ return Float2::Zero;
+
+ // Process text
+ Array lines;
+ ProcessText(fallbacks, text, lines, layout);
+
+ // Calculate bounds
+ Float2 max = Float2::Zero;
+ for (int32 i = 0; i < lines.Count(); i++)
+ {
+ const BlockedTextLineCache& line = lines[i];
+ max = Float2::Max(max, line.Location + line.Size);
+ }
+
+ return max;
+}
+
int32 Font::HitTestText(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
@@ -388,6 +664,106 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te
return smallestIndex;
}
+int32 Font::HitTestText(FallbackFonts* fallbacks, const StringView& text, const Float2& location, const TextLayoutOptions& layout)
+{
+ // Check if there is no need to do anything
+ if (text.Length() <= 0)
+ return 0;
+
+ // Process text
+ const Array& fallbackFonts = fallbacks->GetFontList(GetSize());
+ Array lines;
+ ProcessText(fallbacks, text, lines, layout);
+ ASSERT(lines.HasItems());
+ float scale = layout.Scale / FontManager::FontScale;
+
+ // Offset position to match lines origin space
+ Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
+ Float2 testPoint = location - rootOffset;
+
+ // Get block which may intersect with the position (it's possible because lines have fixed height)
+ int32 lineIndex = 0;
+ while (lineIndex < lines.Count())
+ {
+ if (lines[lineIndex].Location.Y + lines[lineIndex].Size.Y >= location.Y) {
+ break;
+ }
+
+ lineIndex++;
+ }
+ lineIndex = Math::Clamp(lineIndex, 0, lines.Count() - 1);
+ const BlockedTextLineCache& line = lines[lineIndex];
+
+ int32 blockIndex = 0;
+ while (blockIndex < line.Blocks.Count() - 1)
+ {
+ if (line.Location.X + line.Blocks[blockIndex + 1].Location.X >= location.X) {
+ break;
+ }
+
+ blockIndex++;
+ }
+ const FontBlockCache& block = line.Blocks[blockIndex];
+ float x = line.Location.X;
+
+ // Check all characters in the line to find hit point
+ FontCharacterEntry previous;
+ FontCharacterEntry entry;
+ int32 smallestIndex = INVALID_INDEX;
+ float dst, smallestDst = MAX_float;
+
+ auto getFont = [&](int32 index)->Font* {
+ return index >= 0 ? fallbackFonts[index] : this;
+ };
+
+ for (int32 currentIndex = block.FirstCharIndex; currentIndex <= block.LastCharIndex; currentIndex++)
+ {
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+
+ getFont(block.FallbackFontIndex)->GetCharacter(currentChar, entry);
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Apply kerning
+ if (!isWhitespace && previous.IsValid)
+ {
+ x += getFont(block.FallbackFontIndex)->GetKerning(previous.Character, entry.Character);
+ }
+ previous = entry;
+
+ // Test
+ dst = Math::Abs(testPoint.X - x);
+ if (dst < smallestDst)
+ {
+ // Found closer character
+ smallestIndex = currentIndex;
+ smallestDst = dst;
+ }
+ else if (dst > smallestDst)
+ {
+ // Current char is worse so return the best result
+ return smallestIndex;
+ }
+
+ // Move
+ x += entry.AdvanceX * scale;
+ }
+
+ // Test line end edge
+ dst = Math::Abs(testPoint.X - x);
+ if (dst < smallestDst)
+ {
+ // Pointer is behind the last character in the line
+ smallestIndex = block.LastCharIndex;
+
+ // Fix for last line
+ if (lineIndex == lines.Count() - 1)
+ smallestIndex++;
+ }
+
+ return smallestIndex;
+}
+
Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
@@ -442,9 +818,68 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, static_cast((lines.Count() - 1) * baseLinesDistance));
}
-bool Font::ContainsChar(Char c) const
+Float2 Font::GetCharPosition(FallbackFonts* fallbacks, const StringView& text, int32 index, const TextLayoutOptions& layout)
{
- return FT_Get_Char_Index(GetAsset()->GetFTFace(), c) > 0;
+ // Check if there is no need to do anything
+ if (text.IsEmpty())
+ return layout.Bounds.Location;
+
+ // Process text
+ const Array& fallbackFonts = fallbacks->GetFontList(GetSize());
+ Array lines;
+ ProcessText(fallbacks, text, lines, layout);
+ ASSERT(lines.HasItems());
+ float scale = layout.Scale / FontManager::FontScale;
+ float baseLinesDistance = layout.BaseLinesGapScale * scale;
+ Float2 rootOffset = layout.Bounds.Location;
+
+ // Find line with that position
+ FontCharacterEntry previous;
+ FontCharacterEntry entry;
+
+ auto getFont = [&](int32 index)->Font* {
+ return index >= 0 ? fallbackFonts[index] : this;
+ };
+
+ for (int32 lineIndex = 0; lineIndex < lines.Count(); lineIndex++)
+ {
+ const BlockedTextLineCache& line = lines[lineIndex];
+ for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
+ {
+ const FontBlockCache& block = line.Blocks[blockIndex];
+ // Check if desire position is somewhere inside characters in line range
+ if (Math::IsInRange(index, block.FirstCharIndex, block.LastCharIndex))
+ {
+ float x = line.Location.X + block.Location.X;
+ float y = line.Location.Y + block.Location.Y;
+
+ // Check all characters in the line
+ for (int32 currentIndex = block.FirstCharIndex; currentIndex < index; currentIndex++)
+ {
+ // Cache current character
+ const Char currentChar = text[currentIndex];
+ getFont(block.FallbackFontIndex)->GetCharacter(currentChar, entry);
+ const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
+
+ // Apply kerning
+ if (!isWhitespace && previous.IsValid)
+ {
+ x += getFont(block.FallbackFontIndex)->GetKerning(previous.Character, entry.Character);
+ }
+ previous = entry;
+
+ // Move
+ x += entry.AdvanceX * scale;
+ }
+
+ // Upper left corner of the character
+ return rootOffset + Float2(x, y);
+ }
+ }
+ }
+
+ // Position after last character in the last line
+ return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, lines.Last().Location.Y);
}
void Font::FlushFaceSize() const
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index 453872582..d932888fb 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -10,8 +10,9 @@
#include "TextLayoutOptions.h"
class FontAsset;
+class FallbackFonts;
struct FontTextureAtlasSlot;
-struct MultiFontLineCache;
+struct BlockedTextLineCache;
// The default DPI that engine is using
#define DefaultDPI 96
@@ -120,6 +121,73 @@ struct TIsPODType
enum { Value = true };
};
+///
+/// The font block info generated during text processing.
+///
+API_STRUCT(NoDefault) struct FontBlockCache
+{
+ DECLARE_SCRIPTING_TYPE_MINIMAL(FontBlockCache);
+
+ ///
+ /// The root position of the block (upper left corner), relative to line.
+ ///
+ API_FIELD() Float2 Location;
+
+ ///
+ /// The height of the current block
+ ///
+ API_FIELD() Float2 Size;
+
+ ///
+ /// The first character index (from the input text).
+ ///
+ API_FIELD() int32 FirstCharIndex;
+
+ ///
+ /// The last character index (from the input text), inclusive.
+ ///
+ API_FIELD() int32 LastCharIndex;
+
+ ///
+ /// Indicates the fallback font to render this block with, -1 if doesn't require fallback.
+ ///
+ API_FIELD() int32 FallbackFontIndex;
+};
+
+template<>
+struct TIsPODType
+{
+ enum { Value = true };
+};
+
+///
+/// Line of font blocks info generated during text processing.
+///
+API_STRUCT(NoDefault) struct BlockedTextLineCache
+{
+ DECLARE_SCRIPTING_TYPE_MINIMAL(BlockedTextLineCache);
+
+ ///
+ /// The root position of the line (upper left corner).
+ ///
+ API_FIELD() Float2 Location;
+
+ ///
+ /// The line bounds (width and height).
+ ///
+ API_FIELD() Float2 Size;
+
+ ///
+ /// The maximum ascender of the line.
+ ///
+ API_FIELD() float MaxAscender;
+
+ ///
+ /// The index of the font to render with
+ ///
+ API_FIELD() Array Blocks;
+};
+
// Font glyph metrics:
//
// xmin xmax
@@ -388,6 +456,62 @@ public:
return ProcessText(textRange.Substring(text), TextLayoutOptions());
}
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The layout properties.
+ /// The output lines list.
+ void ProcessText(FallbackFonts* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The layout properties.
+ /// The output lines list.
+ API_FUNCTION() Array ProcessText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ Array lines;
+ ProcessText(fallbacks, text, lines, layout);
+ return lines;
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The input text range (substring range of the input text parameter).
+ /// The layout properties.
+ /// The output lines list.
+ API_FUNCTION() Array ProcessText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ Array lines;
+ ProcessText(fallbacks, textRange.Substring(text), lines, layout);
+ return lines;
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The output lines list.
+ API_FUNCTION() FORCE_INLINE Array ProcessText(FallbackFonts* fallbacks, const StringView& text)
+ {
+ return ProcessText(fallbacks, text, TextLayoutOptions());
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering.
+ ///
+ /// The input text.
+ /// The input text range (substring range of the input text parameter).
+ /// The output lines list.
+ API_FUNCTION() FORCE_INLINE Array ProcessText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ {
+ return ProcessText(fallbacks, textRange.Substring(text), TextLayoutOptions());
+ }
+
///
/// Measures minimum size of the rectangle that will be needed to draw given text.
///
@@ -429,6 +553,56 @@ public:
return MeasureText(textRange.Substring(text), TextLayoutOptions());
}
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text.
+ ///
+ /// The input text to test.
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return MeasureText(fallbacks, textRange.Substring(text), layout);
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text
+ /// .
+ /// The input text to test.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text)
+ {
+ return MeasureText(fallbacks, text, TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text
+ /// .
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ {
+ return MeasureText(fallbacks, textRange.Substring(text), TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
+
///
/// Calculates hit character index at given location.
///
@@ -442,15 +616,6 @@ public:
return HitTestText(textRange.Substring(text), location, layout);
}
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input location to test.
- /// The text layout properties.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
-
///
/// Calculates hit character index at given location.
///
@@ -474,6 +639,51 @@ public:
return HitTestText(textRange.Substring(text), location, TextLayoutOptions());
}
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return HitTestText(fallbacks, textRange.Substring(text), location, layout);
+ }
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, const Float2& location)
+ {
+ return HitTestText(fallbacks, text, location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
+ {
+ return HitTestText(fallbacks, textRange.Substring(text), location, TextLayoutOptions());
+ }
+
///
/// Calculates character position for given text and character index.
///
@@ -520,11 +730,49 @@ public:
}
///
- /// Check if the font contains the glyph of a char
+ /// Calculates character position for given text and character index.
///
- /// The char to test.
- /// True if the font contains the glyph of the char, otherwise false.
- API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c) const;
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Calculates character position for given text and character index.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return GetCharPosition(fallbacks, textRange.Substring(text), index, layout);
+ }
+
+ ///
+ /// Calculates character position for given text and character index
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, int32 index)
+ {
+ return GetCharPosition(fallbacks, text, index, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
+ {
+ return GetCharPosition(fallbacks, textRange.Substring(text), index, TextLayoutOptions());
+ }
///
/// Flushes the size of the face with the Free Type library backend.
diff --git a/Source/Engine/Render2D/FontAsset.cpp b/Source/Engine/Render2D/FontAsset.cpp
index a477e5f4d..1e94b19b1 100644
--- a/Source/Engine/Render2D/FontAsset.cpp
+++ b/Source/Engine/Render2D/FontAsset.cpp
@@ -199,6 +199,10 @@ bool FontAsset::Save(const StringView& path)
#endif
+bool FontAsset::ContainsChar(Char c) const {
+ return FT_Get_Char_Index(GetFTFace(), c) > 0;
+}
+
void FontAsset::Invalidate()
{
ScopeLock lock(Locker);
diff --git a/Source/Engine/Render2D/FontAsset.h b/Source/Engine/Render2D/FontAsset.h
index 4dea84a5b..a773a8ad6 100644
--- a/Source/Engine/Render2D/FontAsset.h
+++ b/Source/Engine/Render2D/FontAsset.h
@@ -174,6 +174,13 @@ public:
API_FUNCTION() bool Save(const StringView& path = StringView::Empty);
#endif
+ ///
+ /// Check if the font contains the glyph of a char
+ ///
+ /// The char to test.
+ /// True if the font contains the glyph of the char, otherwise false.
+ API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c) const;
+
///
/// Invalidates all cached dynamic font atlases using this font. Can be used to reload font characters after changing font asset options.
///
diff --git a/Source/Engine/Render2D/MultiFont.cpp b/Source/Engine/Render2D/MultiFont.cpp
deleted file mode 100644
index 4a510a9f8..000000000
--- a/Source/Engine/Render2D/MultiFont.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-#include "MultiFont.h"
-#include "FontManager.h"
-#include "Engine/Core/Math/Math.h"
-
-MultiFont::MultiFont(const Array& fonts)
- : ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer)),
- _fonts(fonts)
-{
-
-}
-
-void MultiFont::ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
-{
- float cursorX = 0;
- int32 kerning;
- MultiFontLineCache tmpLine;
- MultiFontBlockCache tmpBlock;
- FontCharacterEntry entry;
- FontCharacterEntry previous;
- int32 textLength = text.Length();
- float scale = layout.Scale / FontManager::FontScale;
- float boundsWidth = layout.Bounds.GetWidth();
- float baseLinesDistanceScale = layout.BaseLinesGapScale * scale;
-
- tmpBlock.Location = Float2::Zero;
- tmpBlock.Size = Float2::Zero;
- tmpBlock.FirstCharIndex = 0;
- tmpBlock.LastCharIndex = -1;
-
- tmpLine.Location = Float2::Zero;
- tmpLine.Size = Float2::Zero;
- tmpLine.Blocks = Array();
-
- if (textLength == 0) {
- return;
- }
-
- int32 lastWrapCharIndex = INVALID_INDEX;
- float lastWrapCharX = 0;
- bool lastMoveLine = false;
- // The index of the font used by the current block
- int32 currentFontIndex = GetCharFontIndex(text[0], 0);
- // The maximum font height of the current line
- float maxHeight = 0;
- float maxAscender = 0;
- float lastCursorX = 0;
-
- // Process each character to split text into single lines
- for (int32 currentIndex = 0; currentIndex < textLength;)
- {
- bool moveLine = false;
- bool moveBlock = false;
- float xAdvance = 0;
- int32 nextCharIndex = currentIndex + 1;
-
- // Submit line and block if text ends
- if (nextCharIndex == textLength) {
- moveLine = moveBlock = true;
- }
-
- // Cache current character
- const Char currentChar = text[currentIndex];
- const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
-
- // Check if character can wrap words
- const bool isWrapChar = !StringUtils::IsAlnum(currentChar) || isWhitespace || StringUtils::IsUpper(currentChar) || (currentChar >= 0x3040 && currentChar <= 0x9FFF);
- if (isWrapChar && currentIndex != 0)
- {
- lastWrapCharIndex = currentIndex;
- lastWrapCharX = cursorX;
- }
-
- int32 nextFontIndex = currentFontIndex;
- // Check if it's a newline character
- if (currentChar == '\n')
- {
- // Break line
- moveLine = moveBlock = true;
- tmpBlock.LastCharIndex++;
- }
- else
- {
- // Get character entry
- if (nextCharIndex < textLength) {
- nextFontIndex = GetCharFontIndex(text[nextCharIndex], currentFontIndex);
- }
-
- // Get character entry
- _fonts[currentFontIndex]->GetCharacter(currentChar, entry);
- maxHeight = Math::Max(maxHeight, static_cast(_fonts[currentFontIndex]->GetHeight()));
- maxAscender = Math::Max(maxAscender, static_cast(_fonts[currentFontIndex]->GetAscender()));
-
- // Move block if the font changes or text ends
- if (nextFontIndex != currentFontIndex || nextCharIndex == textLength) {
- moveBlock = true;
- }
-
- // Get kerning, only when the font hasn't changed
- if (!isWhitespace && previous.IsValid && !moveBlock)
- {
- kerning = _fonts[currentFontIndex]->GetKerning(previous.Character, entry.Character);
- }
- else
- {
- kerning = 0;
- }
- previous = entry;
- xAdvance = (kerning + entry.AdvanceX) * scale;
-
- // Check if character fits the line or skip wrapping
- if (cursorX + xAdvance <= boundsWidth || layout.TextWrapping == TextWrapping::NoWrap)
- {
- // Move character
- cursorX += xAdvance;
- tmpBlock.LastCharIndex++;
- }
- else if (layout.TextWrapping == TextWrapping::WrapWords)
- {
- if (lastWrapCharIndex != INVALID_INDEX)
- {
- // Skip moving twice for the same character
- int32 lastLineLastCharIndex = outputLines.HasItems() && outputLines.Last().Blocks.HasItems() ? outputLines.Last().Blocks.Last().LastCharIndex : -10000;
- if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
- {
- currentIndex = nextCharIndex;
- lastMoveLine = moveLine;
- continue;
- }
-
- // Move line
- const Char wrapChar = text[lastWrapCharIndex];
- moveLine = true;
- moveBlock = tmpBlock.FirstCharIndex < lastWrapCharIndex;
-
- cursorX = lastWrapCharX;
- if (StringUtils::IsWhitespace(wrapChar))
- {
- // Skip whitespaces
- tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
- nextCharIndex = currentIndex = lastWrapCharIndex + 1;
- }
- else
- {
- tmpBlock.LastCharIndex = lastWrapCharIndex - 1;
- nextCharIndex = currentIndex = lastWrapCharIndex;
- }
- }
- }
- else if (layout.TextWrapping == TextWrapping::WrapChars)
- {
- // Move line
- moveLine = true;
- moveBlock = tmpBlock.FirstCharIndex < currentChar;
- nextCharIndex = currentIndex;
-
- // Skip moving twice for the same character
- if (lastMoveLine)
- break;
- }
- }
-
- if (moveBlock) {
- // Add block
- tmpBlock.Size.X = lastCursorX - cursorX;
- tmpBlock.Size.Y = baseLinesDistanceScale * _fonts[currentFontIndex]->GetHeight();
- tmpBlock.LastCharIndex = Math::Max(tmpBlock.LastCharIndex, tmpBlock.FirstCharIndex);
- tmpBlock.FontIndex = currentFontIndex;
- tmpLine.Blocks.Add(tmpBlock);
-
- // Reset block
- tmpBlock.Location.X = cursorX;
- tmpBlock.FirstCharIndex = nextCharIndex;
- tmpBlock.LastCharIndex = nextCharIndex - 1;
-
- currentFontIndex = nextFontIndex;
- lastCursorX = cursorX;
- }
-
- // Check if move to another line
- if (moveLine)
- {
- // Add line
- tmpLine.Size.X = cursorX;
- tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
- tmpLine.MaxAscender = maxAscender;
- outputLines.Add(tmpLine);
-
- // Reset line
- tmpLine.Blocks.Clear();
- tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
- cursorX = 0;
- tmpBlock.Location.X = cursorX;
- lastWrapCharIndex = INVALID_INDEX;
- lastWrapCharX = 0;
- previous.IsValid = false;
-
- // Reset max font height
- maxHeight = 0;
- maxAscender = 0;
- lastCursorX = 0;
- }
-
- currentIndex = nextCharIndex;
- lastMoveLine = moveLine;
- }
-
- // Check if an additional line should be created
- if (text[textLength - 1] == '\n')
- {
- // Add line
- tmpLine.Size.X = cursorX;
- tmpLine.Size.Y = baseLinesDistanceScale * maxHeight;
- outputLines.Add(tmpLine);
-
- tmpLine.Location.Y += baseLinesDistanceScale * maxHeight;
- }
-
- // Check amount of lines
- if (outputLines.IsEmpty())
- return;
-
- float totalHeight = tmpLine.Location.Y;
-
- Float2 offset = Float2::Zero;
- if (layout.VerticalAlignment == TextAlignment::Center)
- {
- offset.Y += (layout.Bounds.GetHeight() - totalHeight) * 0.5f;
- }
- else if (layout.VerticalAlignment == TextAlignment::Far)
- {
- offset.Y += layout.Bounds.GetHeight() - totalHeight;
- }
- for (int32 i = 0; i < outputLines.Count(); i++)
- {
- MultiFontLineCache& line = outputLines[i];
- Float2 rootPos = line.Location + offset;
-
- // Fix upper left line corner to match desire text alignment
- if (layout.HorizontalAlignment == TextAlignment::Center)
- {
- rootPos.X += (layout.Bounds.GetWidth() - line.Size.X) * 0.5f;
- }
- else if (layout.HorizontalAlignment == TextAlignment::Far)
- {
- rootPos.X += layout.Bounds.GetWidth() - line.Size.X;
- }
-
- line.Location = rootPos;
-
- // Align all blocks to center in case they have different heights
- for (int32 j = 0; j < line.Blocks.Count(); j++)
- {
- MultiFontBlockCache& block = line.Blocks[j];
- block.Location.Y += (line.MaxAscender - _fonts[block.FontIndex]->GetAscender()) / 2;
- }
- }
-}
-
-Float2 MultiFont::GetCharPosition(const StringView& text, int32 index, const TextLayoutOptions& layout)
-{
- // Check if there is no need to do anything
- if (text.IsEmpty())
- return layout.Bounds.Location;
-
- // Process text
- Array lines;
- ProcessText(text, lines, layout);
- ASSERT(lines.HasItems());
- float scale = layout.Scale / FontManager::FontScale;
- float baseLinesDistance = layout.BaseLinesGapScale * scale;
- Float2 rootOffset = layout.Bounds.Location;
-
- // Find line with that position
- FontCharacterEntry previous;
- FontCharacterEntry entry;
- for (int32 lineIndex = 0; lineIndex < lines.Count(); lineIndex++)
- {
- const MultiFontLineCache& line = lines[lineIndex];
- for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
- {
- const MultiFontBlockCache& block = line.Blocks[blockIndex];
- // Check if desire position is somewhere inside characters in line range
- if (Math::IsInRange(index, block.FirstCharIndex, block.LastCharIndex))
- {
- float x = line.Location.X + block.Location.X;
- float y = line.Location.Y + block.Location.Y;
-
- // Check all characters in the line
- for (int32 currentIndex = block.FirstCharIndex; currentIndex < index; currentIndex++)
- {
- // Cache current character
- const Char currentChar = text[currentIndex];
- _fonts[block.FontIndex]->GetCharacter(currentChar, entry);
- const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
-
- // Apply kerning
- if (!isWhitespace && previous.IsValid)
- {
- x += _fonts[block.FontIndex]->GetKerning(previous.Character, entry.Character);
- }
- previous = entry;
-
- // Move
- x += entry.AdvanceX * scale;
- }
-
- // Upper left corner of the character
- return rootOffset + Float2(x, y);
- }
- }
- }
-
- // Position after last character in the last line
- return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, lines.Last().Location.Y);
-}
-
-int32 MultiFont::HitTestText(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
-{
- // Check if there is no need to do anything
- if (text.Length() <= 0)
- return 0;
-
- // Process text
- Array lines;
- ProcessText(text, lines, layout);
- ASSERT(lines.HasItems());
- float scale = layout.Scale / FontManager::FontScale;
-
- // Offset position to match lines origin space
- Float2 rootOffset = layout.Bounds.Location + lines.First().Location;
- Float2 testPoint = location - rootOffset;
-
- // Get block which may intersect with the position (it's possible because lines have fixed height)
- int32 lineIndex = 0;
- while (lineIndex < lines.Count())
- {
- if (lines[lineIndex].Location.Y + lines[lineIndex].Size.Y >= location.Y) {
- break;
- }
-
- lineIndex++;
- }
- lineIndex = Math::Clamp(lineIndex, 0, lines.Count() - 1);
- const MultiFontLineCache& line = lines[lineIndex];
-
- int32 blockIndex = 0;
- while (blockIndex < line.Blocks.Count() - 1)
- {
- if (line.Location.X + line.Blocks[blockIndex + 1].Location.X >= location.X) {
- break;
- }
-
- blockIndex++;
- }
- const MultiFontBlockCache& block = line.Blocks[blockIndex];
- float x = line.Location.X;
-
- // Check all characters in the line to find hit point
- FontCharacterEntry previous;
- FontCharacterEntry entry;
- int32 smallestIndex = INVALID_INDEX;
- float dst, smallestDst = MAX_float;
- for (int32 currentIndex = block.FirstCharIndex; currentIndex <= block.LastCharIndex; currentIndex++)
- {
- // Cache current character
- const Char currentChar = text[currentIndex];
-
- _fonts[block.FontIndex]->GetCharacter(currentChar, entry);
- const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
-
- // Apply kerning
- if (!isWhitespace && previous.IsValid)
- {
- x += _fonts[block.FontIndex]->GetKerning(previous.Character, entry.Character);
- }
- previous = entry;
-
- // Test
- dst = Math::Abs(testPoint.X - x);
- if (dst < smallestDst)
- {
- // Found closer character
- smallestIndex = currentIndex;
- smallestDst = dst;
- }
- else if (dst > smallestDst)
- {
- // Current char is worse so return the best result
- return smallestIndex;
- }
-
- // Move
- x += entry.AdvanceX * scale;
- }
-
- // Test line end edge
- dst = Math::Abs(testPoint.X - x);
- if (dst < smallestDst)
- {
- // Pointer is behind the last character in the line
- smallestIndex = block.LastCharIndex;
-
- // Fix for last line
- if (lineIndex == lines.Count() - 1)
- smallestIndex++;
- }
-
- return smallestIndex;
-}
-
-Float2 MultiFont::MeasureText(const StringView& text, const TextLayoutOptions& layout)
-{
- // Check if there is no need to do anything
- if (text.IsEmpty())
- return Float2::Zero;
-
- // Process text
- Array lines;
- ProcessText(text, lines, layout);
-
- // Calculate bounds
- Float2 max = Float2::Zero;
- for (int32 i = 0; i < lines.Count(); i++)
- {
- const MultiFontLineCache& line = lines[i];
- max = Float2::Max(max, line.Location + line.Size);
- }
-
- return max;
-}
-
diff --git a/Source/Engine/Render2D/MultiFont.h b/Source/Engine/Render2D/MultiFont.h
deleted file mode 100644
index 870b8e668..000000000
--- a/Source/Engine/Render2D/MultiFont.h
+++ /dev/null
@@ -1,353 +0,0 @@
-#pragma once
-
-#include "Engine/Core/Collections/Array.h"
-#include "Engine/Core/Collections/Dictionary.h"
-#include "Font.h"
-#include "FontAsset.h"
-
-struct TextRange;
-class Font;
-class FontAsset;
-
-///
-/// The font block info generated during text processing.
-///
-API_STRUCT(NoDefault) struct MultiFontBlockCache
-{
- DECLARE_SCRIPTING_TYPE_MINIMAL(MultiFontBlockCache);
-
- ///
- /// The root position of the block (upper left corner), relative to line.
- ///
- API_FIELD() Float2 Location;
-
- ///
- /// The height of the current block
- ///
- API_FIELD() Float2 Size;
-
- ///
- /// The first character index (from the input text).
- ///
- API_FIELD() int32 FirstCharIndex;
-
- ///
- /// The last character index (from the input text), inclusive.
- ///
- API_FIELD() int32 LastCharIndex;
-
- ///
- /// The index of the font to render with
- ///
- API_FIELD() int32 FontIndex;
-};
-
-template<>
-struct TIsPODType
-{
- enum { Value = true };
-};
-
-///
-/// Line of font blocks info generated during text processing.
-///
-API_STRUCT(NoDefault) struct MultiFontLineCache
-{
- DECLARE_SCRIPTING_TYPE_MINIMAL(MultiFontLineCache);
-
- ///
- /// The root position of the line (upper left corner).
- ///
- API_FIELD() Float2 Location;
-
- ///
- /// The line bounds (width and height).
- ///
- API_FIELD() Float2 Size;
-
- ///
- /// The maximum ascender of the line.
- ///
- API_FIELD() float MaxAscender;
-
- ///
- /// The index of the font to render with
- ///
- API_FIELD() Array Blocks;
-};
-
-API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API MultiFont : public ManagedScriptingObject
-{
- DECLARE_SCRIPTING_TYPE_NO_SPAWN(MultiFont);
-private:
- Array _fonts;
-
-public:
- MultiFont(const Array& fonts);
-
- API_FUNCTION() FORCE_INLINE static MultiFont* Create(const Array& fonts) {
- return New(fonts);
- }
-
- API_FUNCTION() FORCE_INLINE static MultiFont* Create(const Array& fontAssets, float size) {
- Array fonts;
- fonts.Resize(fontAssets.Count());
- for (int32 i = 0; i < fontAssets.Count(); i++)
- {
- fonts[i] = fontAssets[i]->CreateFont(size);
- }
-
- return New(fonts);
- }
-
- API_PROPERTY() FORCE_INLINE Array& GetFonts() {
- return _fonts;
- }
-
- API_PROPERTY() FORCE_INLINE void SetFonts(const Array& val) {
- _fonts = val;
- }
-
- API_PROPERTY() FORCE_INLINE int32 GetMaxHeight() {
- int32 maxHeight = 0;
- for (int32 i = 0; i < _fonts.Count(); i++)
- {
- if (_fonts[i]) {
- maxHeight = Math::Max(maxHeight, _fonts[i]->GetHeight());
- }
- }
-
- return maxHeight;
- }
-
- API_PROPERTY() FORCE_INLINE int32 GetMaxAscender() {
- int32 maxAsc = 0;
- for (int32 i = 0; i < _fonts.Count(); i++)
- {
- if (_fonts[i]) {
- maxAsc = Math::Max(maxAsc, _fonts[i]->GetAscender());
- }
- }
-
- return maxAsc;
- }
-
- ///
- /// Processes text to get cached lines for rendering.
- ///
- /// The input text.
- /// The layout properties.
- /// The output lines list.
- void ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Processes text to get cached lines for rendering.
- ///
- /// The input text.
- /// The layout properties.
- /// The output lines list.
- API_FUNCTION() Array ProcessText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- Array lines;
- ProcessText(text, lines, layout);
- return lines;
- }
-
- ///
- /// Processes text to get cached lines for rendering.
- ///
- /// The input text.
- /// The input text range (substring range of the input text parameter).
- /// The layout properties.
- /// The output lines list.
- API_FUNCTION() Array ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- Array lines;
- ProcessText(textRange.Substring(text), lines, layout);
- return lines;
- }
-
- ///
- /// Processes text to get cached lines for rendering.
- ///
- /// The input text.
- /// The output lines list.
- API_FUNCTION() FORCE_INLINE Array ProcessText(const StringView& text)
- {
- return ProcessText(text, TextLayoutOptions());
- }
-
- ///
- /// Processes text to get cached lines for rendering.
- ///
- /// The input text.
- /// The input text range (substring range of the input text parameter).
- /// The output lines list.
- API_FUNCTION() FORCE_INLINE Array ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
- {
- return ProcessText(textRange.Substring(text), TextLayoutOptions());
- }
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
- ///
- /// The input text to test.
- /// The layout properties.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The layout properties.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- return MeasureText(textRange.Substring(text), layout);
- }
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text
- /// .
- /// The input text to test.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text)
- {
- return MeasureText(text, TextLayoutOptions());
- }
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text
- /// .
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
- {
- return MeasureText(textRange.Substring(text), TextLayoutOptions());
- }
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The input location to test.
- /// The text layout properties.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- return HitTestText(textRange.Substring(text), location, layout);
- }
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input location to test.
- /// The text layout properties.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input location to test.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location)
- {
- return HitTestText(text, location, TextLayoutOptions());
- }
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The input location to test.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
- {
- return HitTestText(textRange.Substring(text), location, TextLayoutOptions());
- }
-
- ///
- /// Calculates character position for given text and character index.
- ///
- /// The input text to test.
- /// The text position to get coordinates of.
- /// The text layout properties.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Calculates character position for given text and character index.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The text position to get coordinates of.
- /// The text layout properties.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- return GetCharPosition(textRange.Substring(text), index, layout);
- }
-
- ///
- /// Calculates character position for given text and character index
- ///
- /// The input text to test.
- /// The text position to get coordinates of.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index)
- {
- return GetCharPosition(text, index, TextLayoutOptions());
- }
-
- ///
- /// Calculates character position for given text and character index
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The text position to get coordinates of.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
- {
- return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
- }
-
- ///
- /// Gets the index of the font that should be used to render the char
- ///
- /// The font list.
- /// The char.
- /// Number to return if char cannot be found.
- ///
- API_FUNCTION() FORCE_INLINE int32 GetCharFontIndex(Char c, int32 missing = -1) {
- int32 fontIndex = 0;
- while (fontIndex < _fonts.Count() && _fonts[fontIndex] && !_fonts[fontIndex]->ContainsChar(c))
- {
- fontIndex++;
- }
-
- if (fontIndex == _fonts.Count()) {
- return missing;
- }
-
- return fontIndex;
- }
-
- API_FUNCTION() FORCE_INLINE bool Verify() {
- for (int32 i = 0; i < _fonts.Count(); i++)
- {
- if (!_fonts[i]) {
- return false;
- }
- }
-
- return true;
- }
-};
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index c68c2445d..4e0cacb44 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -3,7 +3,7 @@
#include "Render2D.h"
#include "Font.h"
#include "FontManager.h"
-#include "MultiFont.h"
+#include "FallbackFonts.h"
#include "FontTextureAtlas.h"
#include "RotatedRectangle.h"
#include "SpriteAtlas.h"
@@ -195,7 +195,7 @@ namespace
// Drawing
Array DrawCalls;
Array Lines;
- Array MultiFontLines;
+ Array BlockedTextLines;
Array Lines2;
bool IsScissorsRectEmpty;
bool IsScissorsRectEnabled;
@@ -1370,16 +1370,16 @@ void Render2D::DrawText(Font* font, const StringView& text, const TextRange& tex
DrawText(font, textRange.Substring(text), color, layout, customMaterial);
}
-void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
- const Array& fonts = multiFont->GetFonts();
// Check if there is no need to do anything
- if (fonts.IsEmpty() || text.Length() < 0)
+ if (font == nullptr || text.Length() < 0)
return;
// Temporary data
+ const Array& fallbackFonts = fallbacks->GetFontList(font->GetSize());
uint32 fontAtlasIndex = 0;
FontTextureAtlas* fontAtlas = nullptr;
Float2 invAtlasSize = Float2::One;
@@ -1406,11 +1406,19 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
int32 lineIndex = 0;
maxAscenders.Add(0);
+
+ auto getFont = [&](int32 index)->Font* {
+ return index >= 0 ? fallbackFonts[index] : font;
+ };
+
+ // Preprocess the text to determine vertical offset of blocks
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
{
- if (text[currentIndex] != '\n') {
- int32 fontIndex = multiFont->GetCharFontIndex(text[currentIndex], 0);
- maxAscenders[lineIndex] = Math::Max(maxAscenders[lineIndex], static_cast(fonts[fontIndex]->GetAscender()));
+ const Char c = text[currentIndex];
+ if (c != '\n') {
+ int32 fontIndex = fallbacks->GetCharFallbackIndex(c, font);
+ maxAscenders[lineIndex] = Math::Max(maxAscenders[lineIndex],
+ static_cast(getFont(fontIndex)->GetAscender()));
}
else {
lineIndex++;
@@ -1424,7 +1432,7 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
// The starting index of the current block
int32 startIndex = 0;
// The index of the font used by the current block
- int32 currentFontIndex = multiFont->GetCharFontIndex(text[0], 0);
+ int32 currentFontIndex = fallbacks->GetCharFallbackIndex(text[0], font);
// The maximum font height of the current line
float maxHeight = 0;
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
@@ -1446,7 +1454,7 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
{
// Get character entry
if (nextCharIndex < text.Length()) {
- nextFontIndex = multiFont->GetCharFontIndex(text[nextCharIndex], currentFontIndex);
+ nextFontIndex = fallbacks->GetCharFallbackIndex(text[nextCharIndex], font);
}
if (nextFontIndex != currentFontIndex) {
@@ -1461,13 +1469,13 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
if (moveBlock) {
// Render the pending block before beginning the new block
- auto fontHeight = fonts[currentFontIndex]->GetHeight();
+ auto fontHeight = getFont(currentFontIndex)->GetHeight();
maxHeight = Math::Max(maxHeight, static_cast(fontHeight));
- auto fontDescender = fonts[currentFontIndex]->GetDescender();
+ auto fontDescender = getFont(currentFontIndex)->GetDescender();
for (int32 renderIndex = startIndex; renderIndex <= currentIndex; renderIndex++)
{
// Get character entry
- fonts[currentFontIndex]->GetCharacter(text[renderIndex], entry);
+ getFont(currentFontIndex)->GetCharacter(text[renderIndex], entry);
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
@@ -1494,7 +1502,7 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
// Get kerning
if (!isWhitespace && previous.IsValid)
{
- kerning = fonts[currentFontIndex]->GetKerning(previous.Character, entry.Character);
+ kerning = getFont(currentFontIndex)->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -1510,7 +1518,7 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
const float x = pointer.X + entry.OffsetX * scale;
const float y = pointer.Y + (fontHeight + fontDescender - entry.OffsetY) * scale;
- Rectangle charRect(x, y + (maxAscenders[lineIndex] - fonts[currentFontIndex]->GetAscender()) / 2, entry.UVSize.X * scale, entry.UVSize.Y * scale);
+ Rectangle charRect(x, y + (maxAscenders[lineIndex] - getFont(currentFontIndex)->GetAscender()) / 2, entry.UVSize.X * scale, entry.UVSize.Y * scale);
Float2 upperLeftUV = entry.UV * invAtlasSize;
Float2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;
@@ -1541,21 +1549,21 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
}
}
-void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
- DrawText(multiFont, textRange.Substring(text), color, location, customMaterial);
+ DrawText(font, fallbacks, textRange.Substring(text), color, location, customMaterial);
}
-void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
- const Array& fonts = multiFont->GetFonts();
// Check if there is no need to do anything
- if (fonts.IsEmpty() || text.IsEmpty() || layout.Scale <= ZeroTolerance)
+ if (font == nullptr || text.IsEmpty() || layout.Scale <= ZeroTolerance)
return;
// Temporary data
+ const Array& fallbackFonts = fallbacks->GetFontList(font->GetSize());
uint32 fontAtlasIndex = 0;
FontTextureAtlas* fontAtlas = nullptr;
Float2 invAtlasSize = Float2::One;
@@ -1564,8 +1572,8 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
float scale = layout.Scale / FontManager::FontScale;
// Process text to get lines
- MultiFontLines.Clear();
- multiFont->ProcessText(text, MultiFontLines, layout);
+ BlockedTextLines.Clear();
+ font->ProcessText(fallbacks, text, BlockedTextLines, layout);
// Render all lines
FontCharacterEntry entry;
@@ -1581,14 +1589,18 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
drawCall.AsChar.Mat = nullptr;
}
- for (int32 lineIndex = 0; lineIndex < MultiFontLines.Count(); lineIndex++)
+ auto getFont = [&](int32 index)->Font* {
+ return index >= 0 ? fallbackFonts[index] : font;
+ };
+
+ for (int32 lineIndex = 0; lineIndex < BlockedTextLines.Count(); lineIndex++)
{
- const MultiFontLineCache& line = MultiFontLines[lineIndex];
+ const BlockedTextLineCache& line = BlockedTextLines[lineIndex];
for (int32 blockIndex = 0; blockIndex < line.Blocks.Count(); blockIndex++)
{
- const MultiFontBlockCache& block = MultiFontLines[lineIndex].Blocks[blockIndex];
- auto fontHeight = fonts[block.FontIndex]->GetHeight();
- auto fontDescender = fonts[block.FontIndex]->GetDescender();
+ const FontBlockCache& block = BlockedTextLines[lineIndex].Blocks[blockIndex];
+ auto fontHeight = getFont(block.FallbackFontIndex)->GetHeight();
+ auto fontDescender = getFont(block.FallbackFontIndex)->GetDescender();
Float2 pointer = line.Location + block.Location;
for (int32 charIndex = block.FirstCharIndex; charIndex <= block.LastCharIndex; charIndex++)
@@ -1600,7 +1612,7 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
}
// Get character entry
- fonts[block.FontIndex]->GetCharacter(c, entry);
+ getFont(block.FallbackFontIndex)->GetCharacter(c, entry);
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
@@ -1625,7 +1637,7 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
const bool isWhitespace = StringUtils::IsWhitespace(c);
if (!isWhitespace && previous.IsValid)
{
- kerning = fonts[block.FontIndex]->GetKerning(previous.Character, entry.Character);
+ kerning = getFont(block.FallbackFontIndex)->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -1661,9 +1673,9 @@ void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const Colo
}
}
-void Render2D::DrawText(MultiFont* multiFont, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
- DrawText(multiFont, textRange.Substring(text), color, layout, customMaterial);
+ DrawText(font, fallbacks, textRange.Substring(text), color, layout, customMaterial);
}
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h
index 5050171b2..c99d38104 100644
--- a/Source/Engine/Render2D/Render2D.h
+++ b/Source/Engine/Render2D/Render2D.h
@@ -15,7 +15,7 @@ struct Matrix3x3;
struct Viewport;
struct TextRange;
class Font;
-class MultiFont;
+class FallbackFonts;
class GPUPipelineState;
class GPUTexture;
class GPUTextureView;
@@ -225,7 +225,7 @@ public:
/// The text color.
/// The text location.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
/// Draws a text with formatting.
@@ -235,7 +235,7 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
/// Draws a text with formatting.
@@ -246,7 +246,7 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
/// Draws a text with formatting.
@@ -257,7 +257,7 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(MultiFont* multiFont, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
/// Fills a rectangle area.
From cdbe59a3fbe4988660d9684b2fc9122ad2be4907 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Thu, 30 Nov 2023 23:12:56 +0800
Subject: [PATCH 06/16] Add fallback settings to CSharp
---
.../Content/Create/CreateFilesDialog.cs | 2 +-
.../Content/Import/ImportFilesDialog.cs | 2 +-
.../CustomEditors/Dedicated/RagdollEditor.cs | 2 +-
.../CustomEditors/Dedicated/ScriptsEditor.cs | 2 +-
.../Dedicated/UIControlEditor.cs | 6 +-
.../Editors/ActorTransformEditor.cs | 2 +-
.../Editor/CustomEditors/Editors/TagEditor.cs | 2 +-
.../CustomEditors/LayoutElementsContainer.cs | 4 +-
Source/Editor/GUI/ColumnDefinition.cs | 2 +-
Source/Editor/GUI/ComboBox.cs | 6 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 4 +-
Source/Editor/GUI/CurveEditor.cs | 2 +-
Source/Editor/GUI/Docking/DockWindow.cs | 2 +-
Source/Editor/GUI/MainMenu.cs | 8 +-
Source/Editor/GUI/MainMenuButton.cs | 2 +-
Source/Editor/GUI/NavigationButton.cs | 2 +-
Source/Editor/GUI/Row.cs | 4 +-
.../Editor/GUI/Timeline/Tracks/MemberTrack.cs | 2 +-
Source/Editor/GUI/ToolStripButton.cs | 2 +-
Source/Editor/GUI/Tree/TreeNode.cs | 10 +-
Source/Editor/Options/InterfaceOptions.cs | 54 ++++----
Source/Editor/Options/OptionsModule.cs | 20 +--
.../Archetypes/Animation.StateMachine.cs | 4 +-
.../Archetypes/Animation.TransitionEditor.cs | 2 +-
Source/Editor/Surface/Archetypes/Animation.cs | 2 +-
.../Editor/Surface/Archetypes/BehaviorTree.cs | 4 +-
Source/Editor/Surface/Archetypes/Function.cs | 2 +-
Source/Editor/Surface/AttributesEditor.cs | 2 +-
.../Editor/Surface/ContextMenu/VisjectCM.cs | 2 +-
.../Surface/ContextMenu/VisjectCMItem.cs | 2 +-
Source/Editor/Surface/Elements/InputBox.cs | 4 +-
Source/Editor/Surface/SurfaceNode.cs | 6 +-
Source/Editor/Tools/Foliage/FoliageTab.cs | 2 +-
Source/Editor/Tools/Terrain/CarveTab.cs | 2 +-
.../Tools/Terrain/CreateTerrainDialog.cs | 2 +-
Source/Editor/Utilities/TextRenderUtils.cs | 108 ++++++++++++++++
Source/Editor/Viewport/EditorViewport.cs | 6 +-
.../Viewport/Widgets/ViewportWidgetButton.cs | 2 +-
Source/Editor/Windows/AboutDialog.cs | 4 +-
Source/Editor/Windows/Assets/FontWindow.cs | 2 +-
Source/Editor/Windows/ContentWindow.Search.cs | 2 +-
Source/Editor/Windows/PluginsWindow.cs | 9 +-
Source/Editor/Windows/Profiler/Timeline.cs | 2 +-
Source/Engine/Render2D/FallbackFonts.h | 2 +-
Source/Engine/Render2D/MultiFontReference.cs | 74 -----------
Source/Engine/Render2D/Render2D.cs | 118 ++++++++++--------
Source/Engine/Scripting/Scripting.cs | 10 +-
Source/Engine/UI/GUI/Common/Button.cs | 8 +-
Source/Engine/UI/GUI/Common/Dropdown.cs | 8 +-
Source/Engine/UI/GUI/Common/Label.cs | 14 +--
Source/Engine/UI/GUI/Common/RichTextBox.cs | 2 +-
Source/Engine/UI/GUI/Common/TextBox.cs | 37 ++++--
Source/Engine/UI/GUI/Panels/DropPanel.cs | 6 +-
Source/Engine/UI/GUI/Style.cs | 38 +++---
54 files changed, 357 insertions(+), 273 deletions(-)
create mode 100644 Source/Editor/Utilities/TextRenderUtils.cs
delete mode 100644 Source/Engine/Render2D/MultiFontReference.cs
diff --git a/Source/Editor/Content/Create/CreateFilesDialog.cs b/Source/Editor/Content/Create/CreateFilesDialog.cs
index 48e4920bb..d48e878bc 100644
--- a/Source/Editor/Content/Create/CreateFilesDialog.cs
+++ b/Source/Editor/Content/Create/CreateFilesDialog.cs
@@ -39,7 +39,7 @@ namespace FlaxEditor.Content.Create
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, 0, 40),
Parent = this,
- Font = new MultiFontReference(Style.Current.FontTitle)
+ Font = new FontReference(Style.Current.FontTitle)
};
var infoLabel = new Label
{
diff --git a/Source/Editor/Content/Import/ImportFilesDialog.cs b/Source/Editor/Content/Import/ImportFilesDialog.cs
index 5a142d0f6..967583cf6 100644
--- a/Source/Editor/Content/Import/ImportFilesDialog.cs
+++ b/Source/Editor/Content/Import/ImportFilesDialog.cs
@@ -60,7 +60,7 @@ namespace FlaxEditor.Content.Import
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, 0, 40),
Parent = this,
- Font = new MultiFontReference(Style.Current.FontTitle)
+ Font = new FontReference(Style.Current.FontTitle)
};
var infoLabel = new Label
{
diff --git a/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs b/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs
index b6d14d81e..c4b334b3a 100644
--- a/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/RagdollEditor.cs
@@ -81,7 +81,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new MultiFontReference(FlaxEngine.GUI.Style.Current.FontLarge),
+ Font = new FontReference(FlaxEngine.GUI.Style.Current.FontLarge),
Text = "Ragdoll Options",
Parent = this
};
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index fd56422cb..90ae9ae54 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -43,7 +43,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Add script button
var buttonText = "Add script";
- var textSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
float addScriptButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
_addScriptsButton = new Button
diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index 9627edfd8..b8250918f 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -239,7 +239,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Title
var title = new Label(2, 2, DialogWidth - 4, TitleHeight)
{
- Font = new MultiFontReference(style.FontLarge),
+ Font = new FontReference(style.FontLarge),
Text = "Anchor Presets",
Parent = this
};
@@ -247,7 +247,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Info
var info = new Label(0, title.Bottom, DialogWidth, InfoHeight)
{
- Font = new MultiFontReference(style.FontSmall),
+ Font = new FontReference(style.FontSmall),
Text = "Shift: also set bounds\nControl: also set pivot",
Parent = this
};
@@ -423,7 +423,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Set control type button
var space = layout.Space(20);
var buttonText = "Set Type";
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Render2D.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
float setTypeButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var setTypeButton = new Button
{
diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
index 0cad200fd..e84bf5914 100644
--- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
@@ -101,7 +101,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.Clicked += ToggleLink;
ToggleEnabled();
SetLinkStyle();
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(LinkedLabel.Text.Value);
+ var textSize = Render2D.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, LinkedLabel.Text.Value);
_linkButton.LocalX += textSize.X + 10;
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
{
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index dbd5d124c..49ac9d937 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -631,7 +631,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Edit...",
Parent = _label,
};
- var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Render2D.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
if (textSize.Y > button.Width)
button.Width = textSize.Y + 2;
diff --git a/Source/Editor/CustomEditors/LayoutElementsContainer.cs b/Source/Editor/CustomEditors/LayoutElementsContainer.cs
index 1584e88de..936851b15 100644
--- a/Source/Editor/CustomEditors/LayoutElementsContainer.cs
+++ b/Source/Editor/CustomEditors/LayoutElementsContainer.cs
@@ -276,7 +276,7 @@ namespace FlaxEditor.CustomEditors
public LabelElement Header(string text)
{
var element = Label(text);
- element.Label.Font = new MultiFontReference(Style.Current.FontLarge);
+ element.Label.Font = new FontReference(Style.Current.FontLarge);
return element;
}
@@ -284,7 +284,7 @@ namespace FlaxEditor.CustomEditors
{
var element = Header(header.Text);
if (header.FontSize != -1)
- element.Label.Font = new MultiFontReference(element.Label.Font, header.FontSize);
+ element.Label.Font = new FontReference(element.Label.Font.Font, header.FontSize);
if (header.Color != 0)
element.Label.TextColor = Color.FromRGBA(header.Color);
return element;
diff --git a/Source/Editor/GUI/ColumnDefinition.cs b/Source/Editor/GUI/ColumnDefinition.cs
index c6e8f2889..aff1817c3 100644
--- a/Source/Editor/GUI/ColumnDefinition.cs
+++ b/Source/Editor/GUI/ColumnDefinition.cs
@@ -35,7 +35,7 @@ namespace FlaxEditor.GUI
///
/// The title font.
///
- public MultiFont TitleFont;
+ public Font TitleFont;
///
/// The column title text color.
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index 8e6cf39a0..0417cc7e3 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -191,7 +191,7 @@ namespace FlaxEditor.GUI
/// Gets or sets the font used to draw text.
///
[EditorDisplay("Style"), EditorOrder(2000)]
- public MultiFontReference Font { get; set; }
+ public FontReference Font { get; set; }
///
/// Gets or sets the color of the text.
@@ -273,7 +273,7 @@ namespace FlaxEditor.GUI
MaximumItemsInViewCount = 20;
var style = Style.Current;
- Font = new MultiFontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BackgroundColorHighlighted = BackgroundColor;
@@ -554,7 +554,7 @@ namespace FlaxEditor.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetMultiFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ Render2D.DrawText(Font.GetFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
}
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index ba3326412..3137de240 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -236,9 +236,9 @@ namespace FlaxEditor.GUI.ContextMenu
float width = 20;
if (style.FontMedium)
{
- width += style.FontMedium.MeasureText(Text).X;
+ width += Render2D.MeasureText(style.FontMedium, Text).X;
if (!string.IsNullOrEmpty(ShortKeys))
- width += 40 + style.FontMedium.MeasureText(ShortKeys).X;
+ width += 40 + Render2D.MeasureText(style.FontMedium, ShortKeys).X;
}
return Mathf.Max(width, base.MinimumWidth);
diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs
index ff14cdb24..22deec120 100644
--- a/Source/Editor/GUI/CurveEditor.cs
+++ b/Source/Editor/GUI/CurveEditor.cs
@@ -317,7 +317,7 @@ namespace FlaxEditor.GUI
private Color _contentsColor;
private Color _linesColor;
private Color _labelsColor;
- private MultiFont _labelsFont;
+ private Font _labelsFont;
///
/// The keyframe UI points.
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index 374885f01..36a4c112e 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -489,7 +489,7 @@ namespace FlaxEditor.GUI.Docking
{
var style = Style.Current;
if (style?.FontMedium != null)
- _titleSize = style.FontMedium.MeasureText(_title);
+ _titleSize = Render2D.MeasureText(style.FontMedium, _title);
}
base.PerformLayoutBeforeChildren();
diff --git a/Source/Editor/GUI/MainMenu.cs b/Source/Editor/GUI/MainMenu.cs
index aadfbf0a7..b313fed9f 100644
--- a/Source/Editor/GUI/MainMenu.cs
+++ b/Source/Editor/GUI/MainMenu.cs
@@ -76,7 +76,7 @@ namespace FlaxEditor.GUI
var windowIcon = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIcon);
FontAsset windowIconsFont = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WindowIconsFont);
- MultiFont iconFont = new MultiFontReference([windowIconsFont], 9).GetMultiFont();
+ Font iconFont = windowIconsFont?.CreateFont(9);
_window = mainWindow.RootWindow.Window;
_window.HitTest += OnHitTest;
@@ -108,7 +108,7 @@ namespace FlaxEditor.GUI
_closeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeClose).ToString(),
- Font = new MultiFontReference(iconFont),
+ Font = new FontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
@@ -124,7 +124,7 @@ namespace FlaxEditor.GUI
_minimizeButton = new Button
{
Text = ((char)EditorAssets.SegMDL2Icons.ChromeMinimize).ToString(),
- Font = new MultiFontReference(iconFont),
+ Font = new FontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
@@ -139,7 +139,7 @@ namespace FlaxEditor.GUI
_maximizeButton = new Button
{
Text = ((char)(_window.IsMaximized ? EditorAssets.SegMDL2Icons.ChromeRestore : EditorAssets.SegMDL2Icons.ChromeMaximize)).ToString(),
- Font = new MultiFontReference(iconFont),
+ Font = new FontReference(iconFont),
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 3bc57479c..3440996aa 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -103,7 +103,7 @@ namespace FlaxEditor.GUI
float width = 18;
if (style.FontMedium)
- width += style.FontMedium.MeasureText(Text).X;
+ width += Render2D.MeasureText(style.FontMedium, Text).X;
Width = width;
}
diff --git a/Source/Editor/GUI/NavigationButton.cs b/Source/Editor/GUI/NavigationButton.cs
index 6fd17332c..6face21ef 100644
--- a/Source/Editor/GUI/NavigationButton.cs
+++ b/Source/Editor/GUI/NavigationButton.cs
@@ -68,7 +68,7 @@ namespace FlaxEditor.GUI
if (style.FontMedium)
{
- Width = style.FontMedium.MeasureText(Text).X + 2 * DefaultMargin;
+ Width = Render2D.MeasureText(style.FontMedium, Text).X + 2 * DefaultMargin;
}
}
}
diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs
index 7533dfb17..ab74cbe96 100644
--- a/Source/Editor/GUI/Row.cs
+++ b/Source/Editor/GUI/Row.cs
@@ -39,8 +39,8 @@ namespace FlaxEditor.GUI
{
Depth = -1;
- if (Height < Style.Current.FontMedium.MaxHeight)
- Height = Style.Current.FontMedium.MaxHeight + 4;
+ if (Height < Style.Current.FontMedium.Height)
+ Height = Style.Current.FontMedium.Height + 4;
}
///
diff --git a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
index 63787df2c..b4433622e 100644
--- a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
@@ -345,7 +345,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (_previewValue != null)
{
// Based on Track.Draw for track text placement
- var left = _xOffset + 16 + Style.Current.FontSmall.MeasureText(Title ?? Name).X;
+ var left = _xOffset + 16 + Render2D.MeasureText(Style.Current.FontSmall, Title ?? Name).X;
if (Icon.IsValid)
left += 18;
if (IsExpanded)
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index d21fd5689..cf34fd36b 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -152,7 +152,7 @@ namespace FlaxEditor.GUI
if (hasSprite)
width += iconSize;
if (!string.IsNullOrEmpty(_text) && style.FontMedium)
- width += style.FontMedium.MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
+ width += Render2D.MeasureText(style.FontMedium, _text).X + (hasSprite ? DefaultMargin : 0);
Width = width;
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index acb67ea8f..7b47e5eb6 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -115,7 +115,7 @@ namespace FlaxEditor.GUI.Tree
/// Gets or sets the font used to render text.
///
[EditorDisplay("Style"), EditorOrder(2000)]
- public MultiFontReference TextFont { get; set; }
+ public FontReference TextFont { get; set; }
///
/// Gets or sets the color of the background when tree node is selected.
@@ -318,7 +318,7 @@ namespace FlaxEditor.GUI.Tree
BackgroundColorSelected = style.BackgroundSelected;
BackgroundColorHighlighted = style.BackgroundHighlighted;
BackgroundColorSelectedUnfocused = style.LightBackground;
- TextFont = new MultiFontReference(style.FontSmall);
+ TextFont = new FontReference(style.FontSmall);
}
///
@@ -573,10 +573,10 @@ namespace FlaxEditor.GUI.Tree
{
if (_textChanged)
{
- var font = TextFont.GetMultiFont();
+ var font = TextFont.GetFont();
if (font)
{
- _textWidth = font.MeasureText(_text).X;
+ _textWidth = Render2D.MeasureText(font, _text).X;
_textChanged = false;
}
}
@@ -657,7 +657,7 @@ namespace FlaxEditor.GUI.Tree
}
// Draw text
- Render2D.DrawText(TextFont.GetMultiFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
// Draw drag and drop effect
if (IsDragOver && _tree.DraggedOverNode == this)
diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs
index 91eebe4eb..af432baa7 100644
--- a/Source/Editor/Options/InterfaceOptions.cs
+++ b/Source/Editor/Options/InterfaceOptions.cs
@@ -171,8 +171,10 @@ namespace FlaxEditor.Options
get => _outputLogFont;
set
{
- if (value == null || !value.Font)
- _outputLogFont = new FontReference(ConsoleFont, 10);
+ if (value == null)
+ _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont), 10);
+ else if (!value.Font)
+ _outputLogFont.Font = FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont);
else
_outputLogFont = value;
}
@@ -234,30 +236,34 @@ namespace FlaxEditor.Options
[EditorDisplay("Cook & Run"), EditorOrder(500)]
public int NumberOfGameClientsToLaunch = 1;
- private static FontAsset[] DefaultFonts =>
- [FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont),
- FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CjkFont)];
+ private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont);
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont);
- private MultiFontReference _titleFont = new MultiFontReference(DefaultFonts, 18);
- private MultiFontReference _largeFont = new MultiFontReference(DefaultFonts, 14);
- private MultiFontReference _mediumFont = new MultiFontReference(DefaultFonts, 9);
- private MultiFontReference _smallFont = new MultiFontReference(DefaultFonts, 9);
+ private FontReference _titleFont = new FontReference(DefaultFont, 18);
+ private FontReference _largeFont = new FontReference(DefaultFont, 14);
+ private FontReference _mediumFont = new FontReference(DefaultFont, 9);
+ private FontReference _smallFont = new FontReference(DefaultFont, 9);
private FontReference _outputLogFont = new FontReference(ConsoleFont, 10);
+ ///
+ /// The fallback fonts.
+ ///
+ public FontAsset[] Fallbacks = [FlaxEngine.Content.LoadAsyncInternal(EditorAssets.CjkFont)];
///
/// Gets or sets the title font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(600), Tooltip("The title font for editor UI.")]
- public MultiFontReference TitleFont
+ public FontReference TitleFont
{
get => _titleFont;
set
{
- if (value == null || !value.Verify())
- _titleFont = new MultiFontReference(DefaultFonts, 18);
+ if (value == null)
+ _titleFont = new FontReference(DefaultFont, 18);
+ else if (!value.Font)
+ _titleFont.Font = DefaultFont;
else
_titleFont = value;
}
@@ -267,13 +273,15 @@ namespace FlaxEditor.Options
/// Gets or sets the large font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(610), Tooltip("The large font for editor UI.")]
- public MultiFontReference LargeFont
+ public FontReference LargeFont
{
get => _largeFont;
set
{
- if (value == null || !value.Verify())
- _largeFont = new MultiFontReference(DefaultFonts, 14);
+ if (value == null)
+ _largeFont = new FontReference(DefaultFont, 14);
+ else if (!value.Font)
+ _largeFont.Font = DefaultFont;
else
_largeFont = value;
}
@@ -283,13 +291,15 @@ namespace FlaxEditor.Options
/// Gets or sets the medium font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(620), Tooltip("The medium font for editor UI.")]
- public MultiFontReference MediumFont
+ public FontReference MediumFont
{
get => _mediumFont;
set
{
- if (value == null || !value.Verify())
- _mediumFont = new MultiFontReference(DefaultFonts, 9);
+ if (value == null)
+ _mediumFont = new FontReference(DefaultFont, 9);
+ else if (!value.Font)
+ _mediumFont.Font = DefaultFont;
else
_mediumFont = value;
}
@@ -299,13 +309,15 @@ namespace FlaxEditor.Options
/// Gets or sets the small font for editor UI.
///
[EditorDisplay("Fonts"), EditorOrder(630), Tooltip("The small font for editor UI.")]
- public MultiFontReference SmallFont
+ public FontReference SmallFont
{
get => _smallFont;
set
{
- if (value == null || !value.Verify())
- _smallFont = new MultiFontReference(DefaultFonts, 9);
+ if (value == null)
+ _smallFont = new FontReference(DefaultFont, 9);
+ else if (!value.Font)
+ _smallFont.Font = DefaultFont;
else
_smallFont = value;
}
diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs
index d138d7d0d..b13548016 100644
--- a/Source/Editor/Options/OptionsModule.cs
+++ b/Source/Editor/Options/OptionsModule.cs
@@ -217,12 +217,14 @@ namespace FlaxEditor.Options
if (styleName == ThemeOptions.LightDefault)
{
Style.Current = CreateLightStyle();
- }
+ }
else
{
Style.Current = CreateDefaultStyle();
}
}
+
+ Render2D.Fallbacks = FallbackFonts.Create(Options.Interface.Fallbacks);
}
///
@@ -259,10 +261,10 @@ namespace FlaxEditor.Options
},
// Fonts
- FontTitle = options.Interface.TitleFont.GetMultiFont(),
- FontLarge = options.Interface.LargeFont.GetMultiFont(),
- FontMedium = options.Interface.MediumFont.GetMultiFont(),
- FontSmall = options.Interface.SmallFont.GetMultiFont(),
+ FontTitle = options.Interface.TitleFont.GetFont(),
+ FontLarge = options.Interface.LargeFont.GetFont(),
+ FontMedium = options.Interface.MediumFont.GetFont(),
+ FontSmall = options.Interface.SmallFont.GetFont(),
// Icons
ArrowDown = Editor.Icons.ArrowDown12,
@@ -312,10 +314,10 @@ namespace FlaxEditor.Options
ProgressNormal = new Color(0.03f, 0.65f, 0.12f, 1f),
// Fonts
- FontTitle = options.Interface.TitleFont.GetMultiFont(),
- FontLarge = options.Interface.LargeFont.GetMultiFont(),
- FontMedium = options.Interface.MediumFont.GetMultiFont(),
- FontSmall = options.Interface.SmallFont.GetMultiFont(),
+ FontTitle = options.Interface.TitleFont.GetFont(),
+ FontLarge = options.Interface.LargeFont.GetFont(),
+ FontMedium = options.Interface.MediumFont.GetFont(),
+ FontSmall = options.Interface.SmallFont.GetFont(),
// Icons
ArrowDown = Editor.Icons.ArrowDown12,
diff --git a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
index 621c7c25e..19a995b1e 100644
--- a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
@@ -337,7 +337,7 @@ namespace FlaxEditor.Surface.Archetypes
_textRect = new Rectangle(Float2.Zero, Size);
var style = Style.Current;
- var titleSize = style.FontLarge.MeasureText(Title);
+ var titleSize = Render2D.MeasureText(style.FontLarge, Title);
var width = Mathf.Max(100, titleSize.X + 50);
Resize(width, 0);
titleSize.X += 8.0f;
@@ -1402,7 +1402,7 @@ namespace FlaxEditor.Surface.Archetypes
{
Title = StateTitle;
var style = Style.Current;
- var titleSize = style.FontLarge.MeasureText(Title);
+ var titleSize = Render2D.MeasureText(style.FontLarge, Title);
var width = Mathf.Max(100, titleSize.X + 50);
Resize(width, 0);
titleSize.X += 8.0f;
diff --git a/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs b/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs
index e1fdb0a42..84c2144b2 100644
--- a/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.TransitionEditor.cs
@@ -39,7 +39,7 @@ namespace FlaxEditor.Surface.Archetypes
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new MultiFontReference(Style.Current.FontLarge),
+ Font = new FontReference(Style.Current.FontLarge),
Text = transition.SurfaceName,
Parent = this
};
diff --git a/Source/Editor/Surface/Archetypes/Animation.cs b/Source/Editor/Surface/Archetypes/Animation.cs
index 40a3d2a63..dcf4a9689 100644
--- a/Source/Editor/Surface/Archetypes/Animation.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.cs
@@ -77,7 +77,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = asset?.ShortName ?? "Animation";
var style = Style.Current;
- Resize(Mathf.Max(230, style.FontLarge.MeasureText(Title).X + 30), 160);
+ Resize(Mathf.Max(230, Render2D.MeasureText(style.FontLarge, Title).X + 30), 160);
}
///
diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
index cca6856ae..364dfa1ef 100644
--- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs
+++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
@@ -101,7 +101,7 @@ namespace FlaxEditor.Surface.Archetypes
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
if (!string.IsNullOrEmpty(_debugInfo))
- _debugInfoSize = Style.Current.FontSmall.MeasureText(_debugInfo);
+ _debugInfoSize = Render2D.MeasureText(Style.Current.FontSmall, _debugInfo);
}
}
@@ -488,7 +488,7 @@ namespace FlaxEditor.Surface.Archetypes
var height = 0.0f;
var titleLabelFont = Style.Current.FontLarge;
width = Mathf.Max(width, 100.0f);
- width = Mathf.Max(width, titleLabelFont.MeasureText(Title).X + 30);
+ width = Mathf.Max(width, Render2D.MeasureText(titleLabelFont, Title).X + 30);
if (_debugInfoSize.X > 0)
{
width = Mathf.Max(width, _debugInfoSize.X + 8.0f);
diff --git a/Source/Editor/Surface/Archetypes/Function.cs b/Source/Editor/Surface/Archetypes/Function.cs
index bc982a510..53950dad2 100644
--- a/Source/Editor/Surface/Archetypes/Function.cs
+++ b/Source/Editor/Surface/Archetypes/Function.cs
@@ -1407,7 +1407,7 @@ namespace FlaxEditor.Surface.Archetypes
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new MultiFontReference(Style.Current.FontLarge),
+ Font = new FontReference(Style.Current.FontLarge),
Text = "Edit function signature",
Parent = this
};
diff --git a/Source/Editor/Surface/AttributesEditor.cs b/Source/Editor/Surface/AttributesEditor.cs
index c9e32e23a..81b11bb68 100644
--- a/Source/Editor/Surface/AttributesEditor.cs
+++ b/Source/Editor/Surface/AttributesEditor.cs
@@ -83,7 +83,7 @@ namespace FlaxEditor.Surface
// Title
var title = new Label(2, 2, width - 4, 23.0f)
{
- Font = new MultiFontReference(Style.Current.FontLarge),
+ Font = new FontReference(Style.Current.FontLarge),
Text = "Edit attributes",
Parent = this
};
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
index 0624d44b3..5256b3cb7 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
@@ -141,7 +141,7 @@ namespace FlaxEditor.Surface.ContextMenu
};
// Title bar
- var titleFontReference = new MultiFontReference(Style.Current.FontLarge);
+ var titleFontReference = new FontReference(Style.Current.FontLarge);
var titleLabel = new Label
{
Width = Width * 0.5f - 8f,
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index 207875a92..fd9f0c63b 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -286,7 +286,7 @@ namespace FlaxEditor.Surface.ContextMenu
Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
if (_archetype.SubTitle != null)
{
- var titleLength = style.FontSmall.MeasureText(_archetype.Title).X;
+ var titleLength = Render2D.MeasureText(style.FontSmall, _archetype.Title).X;
var subTitleRect = new Rectangle(textRect.X + titleLength, textRect.Y, textRect.Width - titleLength, textRect.Height);
Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs
index 2047bcd1a..2ab286bd9 100644
--- a/Source/Editor/Surface/Elements/InputBox.cs
+++ b/Source/Editor/Surface/Elements/InputBox.cs
@@ -1428,7 +1428,7 @@ namespace FlaxEditor.Surface.Elements
if (_defaultValueEditor != null)
{
- _defaultValueEditor.Location = new Float2(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y);
+ _defaultValueEditor.Location = new Float2(X + Width + 8 + Render2D.MeasureText(Style.Current.FontSmall, Text).X, Y);
}
}
@@ -1635,7 +1635,7 @@ namespace FlaxEditor.Surface.Elements
{
if (DefaultValueEditors[i].CanUse(this, ref _currentType))
{
- var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y, 90, Height);
+ var bounds = new Rectangle(X + Width + 8 + Render2D.MeasureText(Style.Current.FontSmall, Text).X, Y, 90, Height);
_editor = DefaultValueEditors[i];
try
{
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index b6436e542..60d776102 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -200,7 +200,7 @@ namespace FlaxEditor.Surface
continue;
if (child is InputBox inputBox)
{
- var boxWidth = boxLabelFont.MeasureText(inputBox.Text).X + 20;
+ var boxWidth = Render2D.MeasureText(boxLabelFont, inputBox.Text).X + 20;
if (inputBox.DefaultValueEditor != null)
boxWidth += inputBox.DefaultValueEditor.Width + 4;
leftWidth = Mathf.Max(leftWidth, boxWidth);
@@ -208,7 +208,7 @@ namespace FlaxEditor.Surface
}
else if (child is OutputBox outputBox)
{
- rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 20);
+ rightWidth = Mathf.Max(rightWidth, Render2D.MeasureText(boxLabelFont, outputBox.Text).X + 20);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
}
else if (child is Control control)
@@ -226,7 +226,7 @@ namespace FlaxEditor.Surface
}
}
width = Mathf.Max(width, leftWidth + rightWidth + 10);
- width = Mathf.Max(width, titleLabelFont.MeasureText(Title).X + 30);
+ width = Mathf.Max(width, Render2D.MeasureText(titleLabelFont, Title).X + 30);
height = Mathf.Max(height, Mathf.Max(leftHeight, rightHeight));
Resize(width, height);
}
diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs
index 1badb8c0c..58cf6f204 100644
--- a/Source/Editor/Tools/Foliage/FoliageTab.cs
+++ b/Source/Editor/Tools/Foliage/FoliageTab.cs
@@ -148,7 +148,7 @@ namespace FlaxEditor.Tools.Foliage
Parent = _noFoliagePanel,
Enabled = false
};
- var textSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
if (_createNewFoliage.Width < textSize.X)
{
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CarveTab.cs b/Source/Editor/Tools/Terrain/CarveTab.cs
index 4ff85ca23..12c9fd148 100644
--- a/Source/Editor/Tools/Terrain/CarveTab.cs
+++ b/Source/Editor/Tools/Terrain/CarveTab.cs
@@ -106,7 +106,7 @@ namespace FlaxEditor.Tools.Terrain
Parent = _noTerrainPanel,
Enabled = false
};
- var textSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var textSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
if (_createTerrainButton.Width < textSize.X)
{
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs
index cba52283d..252891d44 100644
--- a/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs
+++ b/Source/Editor/Tools/Terrain/CreateTerrainDialog.cs
@@ -96,7 +96,7 @@ namespace FlaxEditor.Tools.Terrain
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Offsets = new Margin(0, 0, 0, 40),
Parent = this,
- Font = new MultiFontReference(Style.Current.FontTitle)
+ Font = new FontReference(Style.Current.FontTitle)
};
var infoLabel = new Label
{
diff --git a/Source/Editor/Utilities/TextRenderUtils.cs b/Source/Editor/Utilities/TextRenderUtils.cs
new file mode 100644
index 000000000..d7b79ae81
--- /dev/null
+++ b/Source/Editor/Utilities/TextRenderUtils.cs
@@ -0,0 +1,108 @@
+using FlaxEngine.GUI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FlaxEngine
+{
+ public static class TextRenderUtils
+ {
+ ///
+ /// Draws a text using the global fallback defined in styles.
+ ///
+ /// The font to use.
+ /// The text to render.
+ /// The size and position of the area in which the text is drawn.
+ /// The text color.
+ /// The horizontal alignment of the text in a layout rectangle.
+ /// The vertical alignment of the text in a layout rectangle.
+ /// Describes how wrap text inside a layout rectangle.
+ /// The scale for distance one baseline from another. Default is 1.
+ /// The text drawing scale. Default is 1.
+ public static void DrawTextWithFallback(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+
+
+ Render2D.DrawText(font, Style.Current.Fallbacks, text, color, ref layout);
+ }
+
+ ///
+ /// Draws a text using the global fallback defined in styles. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling).
+ ///
+ /// The font to use.
+ /// Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ /// The text to render.
+ /// The size and position of the area in which the text is drawn.
+ /// The text color.
+ /// The horizontal alignment of the text in a layout rectangle.
+ /// The vertical alignment of the text in a layout rectangle.
+ /// Describes how wrap text inside a layout rectangle.
+ /// The scale for distance one baseline from another. Default is 1.
+ /// The text drawing scale. Default is 1.
+ public static void DrawTextWithFallback(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+
+ Render2D.DrawText(font, Style.Current.Fallbacks, text, color, ref layout, customMaterial);
+ }
+
+ public static Float2 MeasureTextWithFallback(Font font, string text)
+ {
+ return font.MeasureText(Style.Current.Fallbacks, text);
+ }
+
+ public static Float2 MeasureTextWithFallback(Font font, string text, ref TextRange textRange)
+ {
+ return font.MeasureText(Style.Current.Fallbacks, text, ref textRange);
+ }
+
+ public static Float2 MeasureTextWithFallback(Font font, string text, ref TextLayoutOptions layout)
+ {
+ return font.MeasureText(Style.Current.Fallbacks, text, ref layout);
+ }
+
+ public static Float2 MeasureTextWithFallback(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout)
+ {
+ return font.MeasureText(Style.Current.Fallbacks, text, ref textRange, ref layout);
+ }
+
+ public static Float2 GetCharPositionWithFallback(Font font, string text, int index)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, index);
+ }
+
+ public static Float2 GetCharPositionWithFallback(Font font, string text, ref TextRange textRange, int index)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index);
+ }
+
+ public static Float2 GetCharPositionWithFallback(Font font, string text, int index, ref TextLayoutOptions layout)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, index, ref layout);
+ }
+
+ public static Float2 GetCharPositionWithFallback(Font font, string text, ref TextRange textRange, int index, ref TextLayoutOptions layout)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index, ref layout);
+ }
+ }
+}
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index c49392d01..77a677c0c 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -548,9 +548,9 @@ namespace FlaxEditor.Viewport
#region Camera settings widget
var largestText = "Relative Panning";
- var textSize = Style.Current.FontMedium.MeasureText(largestText);
+ var textSize = Render2D.MeasureText(Style.Current.FontMedium, largestText);
var xLocationForExtras = textSize.X + 5;
- var cameraSpeedTextWidth = Style.Current.FontMedium.MeasureText("0.00").X;
+ var cameraSpeedTextWidth = Render2D.MeasureText(Style.Current.FontMedium, "0.00").X;
// Camera Settings Widget
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
@@ -801,7 +801,7 @@ namespace FlaxEditor.Viewport
#region View mode widget
largestText = "Brightness";
- textSize = Style.Current.FontMedium.MeasureText(largestText);
+ textSize = Render2D.MeasureText(Style.Current.FontMedium, largestText);
xLocationForExtras = textSize.X + 5;
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
index fe73048fd..250790621 100644
--- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
+++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
@@ -164,7 +164,7 @@ namespace FlaxEditor.Viewport.Widgets
var style = Style.Current;
if (style != null && style.FontMedium)
- Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.MeasureText(_text).X, Icon.IsValid);
+ Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : Render2D.MeasureText(style.FontMedium, _text).X, Icon.IsValid);
}
}
}
diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs
index 1a81a9421..ac887dadf 100644
--- a/Source/Editor/Windows/AboutDialog.cs
+++ b/Source/Editor/Windows/AboutDialog.cs
@@ -41,7 +41,7 @@ namespace FlaxEditor.Windows
var nameLabel = new Label(icon.Right + 10, icon.Top, 200, 34)
{
Text = "Flax Engine",
- Font = new MultiFontReference(Style.Current.FontTitle),
+ Font = new FontReference(Style.Current.FontTitle),
HorizontalAlignment = TextAlignment.Near,
VerticalAlignment = TextAlignment.Center,
Parent = this
@@ -54,7 +54,7 @@ namespace FlaxEditor.Windows
Parent = this
};
var buttonText = "Copy version info";
- var fontSize = Style.Current.FontMedium.MeasureText(buttonText);
+ var fontSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
var copyVersionButton = new Button(Width - fontSize.X - 8, 6, fontSize.X + 4, 20)
{
Text = buttonText,
diff --git a/Source/Editor/Windows/Assets/FontWindow.cs b/Source/Editor/Windows/Assets/FontWindow.cs
index 2e2e14d99..bc91ca5e2 100644
--- a/Source/Editor/Windows/Assets/FontWindow.cs
+++ b/Source/Editor/Windows/Assets/FontWindow.cs
@@ -144,7 +144,7 @@ namespace FlaxEditor.Windows.Assets
protected override void OnAssetLinked()
{
Asset.WaitForLoaded();
- _textPreview.Font = new MultiFontReference([Asset], 30);
+ _textPreview.Font = new FontReference(Asset, 30);
_inputText.Text = string.Format("This is a sample text using font {0}.", Asset.FamilyName);
var options = Asset.Options;
_proxy.Set(ref options);
diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs
index f29dc0bd6..a1072d158 100644
--- a/Source/Editor/Windows/ContentWindow.Search.cs
+++ b/Source/Editor/Windows/ContentWindow.Search.cs
@@ -57,7 +57,7 @@ namespace FlaxEditor.Windows
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetMultiFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ Render2D.DrawText(Font.GetFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
// Arrow
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index d6c14f4e4..4dfa0ed08 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -79,7 +79,7 @@ namespace FlaxEditor.Windows
HorizontalAlignment = TextAlignment.Near,
AnchorPreset = AnchorPresets.HorizontalStretchTop,
Text = desc.Name,
- Font = new MultiFontReference(Style.Current.FontLarge),
+ Font = new FontReference(Style.Current.FontLarge),
Parent = this,
Bounds = new Rectangle(tmp1, margin, Width - tmp1 - margin, 28),
};
@@ -120,9 +120,9 @@ namespace FlaxEditor.Windows
url = desc.HomepageUrl;
else if (!string.IsNullOrEmpty(desc.RepositoryUrl))
url = desc.RepositoryUrl;
- versionLabel.Font.ForEach(x => x.Font.WaitForLoaded());
- var font = versionLabel.Font.GetMultiFont();
- var authorWidth = font.MeasureText(desc.Author).X + 8;
+ versionLabel.Font.Font.WaitForLoaded();
+ var font = versionLabel.Font.GetFont();
+ var authorWidth = Render2D.MeasureText(font, desc.Author).X + 8;
var authorLabel = new ClickableLabel
{
HorizontalAlignment = TextAlignment.Far,
@@ -392,7 +392,6 @@ namespace FlaxEditor.Windows
}
Editor.Log("Plugin project has been cloned.");
-
try
{
// Start git submodule clone
diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs
index 917647f23..00365f74a 100644
--- a/Source/Editor/Windows/Profiler/Timeline.cs
+++ b/Source/Editor/Windows/Profiler/Timeline.cs
@@ -86,7 +86,7 @@ namespace FlaxEditor.Windows.Profiler
Render2D.DrawRectangle(bounds, color * 0.5f);
if (_nameLength < 0 && style.FontMedium)
- _nameLength = style.FontMedium.MeasureText(_name).X;
+ _nameLength = Render2D.MeasureText(style.FontMedium, _name).X;
if (_nameLength < bounds.Width + 4)
{
diff --git a/Source/Engine/Render2D/FallbackFonts.h b/Source/Engine/Render2D/FallbackFonts.h
index 4b97e1c11..5861354fc 100644
--- a/Source/Engine/Render2D/FallbackFonts.h
+++ b/Source/Engine/Render2D/FallbackFonts.h
@@ -39,7 +39,7 @@ public:
///
/// Combine the primary fonts with the fallback fonts to get a font list
///
- API_PROPERTY() FORCE_INLINE Array& GetFontList(float size) {
+ API_FUNCTION() FORCE_INLINE Array& GetFontList(float size) {
Array* result;
if (_cache.TryGet(size, result)) {
return *result;
diff --git a/Source/Engine/Render2D/MultiFontReference.cs b/Source/Engine/Render2D/MultiFontReference.cs
deleted file mode 100644
index dd3f4d179..000000000
--- a/Source/Engine/Render2D/MultiFontReference.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-using System.Collections.Generic;
-using System.Linq;
-
-namespace FlaxEngine
-{
- ///
- /// Reference to multiple font references
- ///
- public class MultiFontReference : List
- {
- public MultiFontReference()
- {
- _cachedFont = null;
- }
-
- public MultiFontReference(IEnumerable other)
- {
- AddRange(other);
- _cachedFont = null;
- }
-
- public MultiFontReference(MultiFontReference other)
- {
- AddRange(other);
- _cachedFont = other._cachedFont;
- }
-
- public MultiFontReference(MultiFontReference other, float size)
- {
- AddRange(other.Select(x => new FontReference(x) { Size = size }));
- _cachedFont = null;
- }
-
- public MultiFontReference(MultiFont other)
- {
- AddRange(other.Fonts.Select(x => new FontReference(x)));
- _cachedFont = other;
- }
-
- public MultiFontReference(FontAsset[] assets, float size)
- {
- AddRange(assets.Select(x => new FontReference(x, size)));
- _cachedFont = null;
- }
-
- [EditorOrder(0), Tooltip("The font asset to use as characters source.")]
- public MultiFont GetMultiFont()
- {
- if (_cachedFont)
- return _cachedFont;
- var fontList = this.Where(x => x.Font).Select(x => x.GetFont()).ToArray();
- _cachedFont = MultiFont.Create(fontList);
- return _cachedFont;
- }
-
- public bool Verify()
- {
- foreach (var i in this)
- {
- if (!i.Font)
- {
- return false;
- }
- }
-
- return true;
- }
-
- [NoSerialize]
- private MultiFont _cachedFont;
- }
-}
diff --git a/Source/Engine/Render2D/Render2D.cs b/Source/Engine/Render2D/Render2D.cs
index cad8380ab..b7158ccc7 100644
--- a/Source/Engine/Render2D/Render2D.cs
+++ b/Source/Engine/Render2D/Render2D.cs
@@ -1,11 +1,17 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using FlaxEngine.GUI;
using System;
namespace FlaxEngine
{
partial class Render2D
{
+ public static FallbackFonts Fallbacks
+ {
+ get; set;
+ } = null;
+
///
/// Pushes transformation layer.
///
@@ -111,7 +117,8 @@ namespace FlaxEngine
/// Describes how wrap text inside a layout rectangle.
/// The scale for distance one baseline from another. Default is 1.
/// The text drawing scale. Default is 1.
- public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ /// Whether to use fallback fonts for chars not renderable by the font.
+ public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
{
var layout = new TextLayoutOptions
{
@@ -122,7 +129,15 @@ namespace FlaxEngine
Scale = scale,
BaseLinesGapScale = baseLinesGapScale,
};
- DrawText(font, text, color, ref layout);
+
+ if (useFallback && Fallbacks != null)
+ {
+ DrawText(font, Fallbacks, text, color, ref layout);
+ }
+ else
+ {
+ DrawText(font, text, color, ref layout);
+ }
}
///
@@ -138,7 +153,8 @@ namespace FlaxEngine
/// Describes how wrap text inside a layout rectangle.
/// The scale for distance one baseline from another. Default is 1.
/// The text drawing scale. Default is 1.
- public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ /// Whether to use fallback fonts for chars not renderable by the font.
+ public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
{
var layout = new TextLayoutOptions
{
@@ -149,63 +165,63 @@ namespace FlaxEngine
Scale = scale,
BaseLinesGapScale = baseLinesGapScale,
};
- DrawText(font, text, color, ref layout, customMaterial);
+
+ if (useFallback && Fallbacks != null)
+ {
+ DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
+ }
+ else
+ {
+ DrawText(font, text, color, ref layout, customMaterial);
+ }
}
- ///
- /// Draws a text.
- ///
- /// The fonts to use, ordered by priority.
- /// The text to render.
- /// The size and position of the area in which the text is drawn.
- /// The text color.
- /// The horizontal alignment of the text in a layout rectangle.
- /// The vertical alignment of the text in a layout rectangle.
- /// Describes how wrap text inside a layout rectangle.
- /// The scale for distance one baseline from another. Default is 1.
- /// The text drawing scale. Default is 1.
- public static void DrawText(MultiFont fonts, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ public static Float2 MeasureText(Font font, string text, bool useFallback = true)
{
- var layout = new TextLayoutOptions
+ if (useFallback && Fallbacks != null)
{
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
-
- DrawText(fonts, text, color, ref layout);
+ return font.MeasureText(Style.Current.Fallbacks, text);
+ }
+ else
+ {
+ return font.MeasureText(text);
+ }
}
- ///
- /// Draws a text using a custom material shader. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling).
- ///
- /// The fonts to use, ordered by priority.
- /// Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- /// The text to render.
- /// The size and position of the area in which the text is drawn.
- /// The text color.
- /// The horizontal alignment of the text in a layout rectangle.
- /// The vertical alignment of the text in a layout rectangle.
- /// Describes how wrap text inside a layout rectangle.
- /// The scale for distance one baseline from another. Default is 1.
- /// The text drawing scale. Default is 1.
- public static void DrawText(MultiFont fonts, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ public static Float2 MeasureText(Font font, string text, ref TextRange textRange, bool useFallback = true)
{
- var layout = new TextLayoutOptions
+ if (useFallback && Fallbacks != null)
{
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
+ return font.MeasureText(Style.Current.Fallbacks, text, ref textRange);
+ }
+ else
+ {
+ return font.MeasureText(text, ref textRange);
+ }
+ }
- DrawText(fonts, text, color, ref layout, customMaterial);
+ public static Float2 MeasureText(Font font, string text, ref TextLayoutOptions layout, bool useFallback = true)
+ {
+ if (useFallback && Fallbacks != null)
+ {
+ return font.MeasureText(Style.Current.Fallbacks, text, ref layout);
+ }
+ else
+ {
+ return font.MeasureText(text, ref layout);
+ }
+ }
+
+ public static Float2 MeasureText(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout, bool useFallback = true)
+ {
+ if (useFallback && Fallbacks != null)
+ {
+ return font.MeasureText(Style.Current.Fallbacks, text, ref textRange, ref layout);
+ }
+ else
+ {
+ return font.MeasureText(text, ref textRange, ref layout);
+ }
}
///
diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs
index bc800f88a..a4cfd76b1 100644
--- a/Source/Engine/Scripting/Scripting.cs
+++ b/Source/Engine/Scripting/Scripting.cs
@@ -294,12 +294,12 @@ namespace FlaxEngine
style.DragWindow = style.BackgroundSelected * 0.7f;
// Use optionally bundled default font (matches Editor)
- FontAsset[] defaultFont = [Content.LoadAsyncInternal("Editor/Fonts/Roboto-Regular"), Content.LoadAsyncInternal("Editor/Fonts/NotoSansSC-Regular")];
+ FontAsset defaultFont = Content.LoadAsyncInternal("Editor/Fonts/Roboto-Regular");
- style.FontTitle = new MultiFontReference(defaultFont, 18).GetMultiFont();
- style.FontLarge = new MultiFontReference(defaultFont, 14).GetMultiFont();
- style.FontMedium = new MultiFontReference(defaultFont, 9).GetMultiFont();
- style.FontSmall = new MultiFontReference(defaultFont, 9).GetMultiFont();
+ style.FontTitle = new FontReference(defaultFont, 18).GetFont();
+ style.FontLarge = new FontReference(defaultFont, 14).GetFont();
+ style.FontMedium = new FontReference(defaultFont, 9).GetFont();
+ style.FontSmall = new FontReference(defaultFont, 9).GetFont();
Style.Current = style;
}
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index f21a29191..756501c5e 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -23,7 +23,7 @@ namespace FlaxEngine.GUI
///
/// The font.
///
- protected MultiFontReference _font;
+ protected FontReference _font;
///
/// The text.
@@ -44,7 +44,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font used to draw button text.
///
[EditorDisplay("Text Style"), EditorOrder(2022), ExpandGroups]
- public MultiFontReference Font
+ public FontReference Font
{
get => _font;
set => _font = value;
@@ -156,7 +156,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
if (style != null)
{
- _font = new MultiFontReference(style.FontMedium);
+ _font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BorderColor = style.BorderNormal;
@@ -262,7 +262,7 @@ namespace FlaxEngine.GUI
Render2D.DrawRectangle(clientRect, borderColor, BorderThickness);
// Draw text
- Render2D.DrawText(_font?.GetMultiFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index 2681aac1b..c9fef131c 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -278,7 +278,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font used to draw text.
///
[EditorDisplay("Text Style"), EditorOrder(2021)]
- public MultiFontReference Font { get; set; }
+ public FontReference Font { get; set; }
///
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
@@ -359,7 +359,7 @@ namespace FlaxEngine.GUI
: base(0, 0, 120, 18.0f)
{
var style = Style.Current;
- Font = new MultiFontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
BackgroundColor = style.BackgroundNormal;
BackgroundColorHighlighted = BackgroundColor;
@@ -476,7 +476,7 @@ namespace FlaxEngine.GUI
var font = Font.GetFont();
for (int i = 0; i < _items.Count; i++)
{
- itemsWidth = Mathf.Max(itemsWidth, itemsMargin + 4 + font.MeasureText(_items[i]).X);
+ itemsWidth = Mathf.Max(itemsWidth, itemsMargin + 4 + Render2D.MeasureText(font, _items[i]).X);
}
*/
var itemsWidth = Width;
@@ -674,7 +674,7 @@ namespace FlaxEngine.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetMultiFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(Font.GetFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index ccc1cc190..d7147d3ab 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -26,7 +26,7 @@ namespace FlaxEngine.GUI
///
/// The font.
///
- protected MultiFontReference _font;
+ protected FontReference _font;
///
/// Gets or sets the text.
@@ -86,7 +86,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font.
///
[EditorDisplay("Text Style"), EditorOrder(2024)]
- public MultiFontReference Font
+ public FontReference Font
{
get => _font;
set
@@ -192,7 +192,7 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
- Font = new MultiFontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
@@ -203,7 +203,7 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
- Font = new MultiFontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
@@ -235,7 +235,7 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText(_font.GetMultiFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
Render2D.PopClip();
@@ -246,7 +246,7 @@ namespace FlaxEngine.GUI
{
if (_autoWidth || _autoHeight || _autoFitText)
{
- var font = _font.GetMultiFont();
+ var font = _font.GetFont();
if (font)
{
// Calculate text size
@@ -256,7 +256,7 @@ namespace FlaxEngine.GUI
layout.Bounds.Size.X = Width - Margin.Width;
else if (_autoWidth && !_autoHeight)
layout.Bounds.Size.Y = Height - Margin.Height;
- _textSize = font.MeasureText(_text, ref layout);
+ _textSize = Render2D.MeasureText(font, _text, ref layout);
_textSize.Y *= BaseLinesGapScale;
// Check if size is controlled via text
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.cs b/Source/Engine/UI/GUI/Common/RichTextBox.cs
index f8ac7d353..514878b37 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.cs
@@ -46,7 +46,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
_textStyle = new TextBlockStyle
{
- Font = new FontReference(style.FontMedium.Fonts.First()),
+ Font = new FontReference(style.FontMedium),
Color = style.Foreground,
BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected),
};
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index d9c7c1a80..a32f3a76c 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using System.Drawing;
using System.Linq;
namespace FlaxEngine.GUI
@@ -40,7 +41,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font.
///
[EditorDisplay("Text Style"), EditorOrder(2024)]
- public MultiFontReference Font { get; set; }
+ public FontReference Font { get; set; }
///
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
@@ -90,7 +91,7 @@ namespace FlaxEngine.GUI
_layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
var style = Style.Current;
- Font = new MultiFontReference(style.FontMedium);
+ Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
WatermarkTextColor = style.ForegroundDisabled;
SelectionColor = style.BackgroundSelected;
@@ -99,33 +100,33 @@ namespace FlaxEngine.GUI
///
public override Float2 GetTextSize()
{
- var font = Font.GetMultiFont();
+ var font = Font.GetFont();
if (font == null)
{
return Float2.Zero;
}
- return font.MeasureText(_text, ref _layout);
+ return Render2D.MeasureText(font, _text, ref _layout);
}
///
public override Float2 GetCharPosition(int index, out float height)
{
- var font = Font.GetMultiFont();
+ var font = Font.GetFont();
if (font == null)
{
height = Height;
return Float2.Zero;
}
- height = font.MaxHeight / DpiScale;
+ height = font.Height / DpiScale;
return font.GetCharPosition(_text, index, ref _layout);
}
///
public override int HitTestText(Float2 location)
{
- var font = Font.GetMultiFont();
+ var font = Font.GetFont();
if (font == null)
{
return 0;
@@ -148,7 +149,7 @@ namespace FlaxEngine.GUI
// Cache data
var rect = new Rectangle(Float2.Zero, Size);
bool enabled = EnabledInHierarchy;
- var font = Font.GetMultiFont();
+ var font = Font.GetFont();
if (!font)
return;
@@ -172,7 +173,7 @@ namespace FlaxEngine.GUI
{
var leftEdge = font.GetCharPosition(_text, SelectionLeft, ref _layout);
var rightEdge = font.GetCharPosition(_text, SelectionRight, ref _layout);
- float fontHeight = font.MaxHeight / DpiScale;
+ float fontHeight = font.Height / DpiScale;
// Draw selection background
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
@@ -212,11 +213,25 @@ namespace FlaxEngine.GUI
var color = TextColor;
if (!enabled)
color *= 0.6f;
- Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
+ if (Render2D.Fallbacks != null)
+ {
+ Render2D.DrawText(font, Render2D.Fallbacks, _text, color, ref _layout, TextMaterial);
+ }
+ else
+ {
+ Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
+ }
}
else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
{
- Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ if (Render2D.Fallbacks != null)
+ {
+ Render2D.DrawText(font, Render2D.Fallbacks, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ }
+ else
+ {
+ Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ }
}
// Caret
diff --git a/Source/Engine/UI/GUI/Panels/DropPanel.cs b/Source/Engine/UI/GUI/Panels/DropPanel.cs
index 06256c9f8..ed620ab98 100644
--- a/Source/Engine/UI/GUI/Panels/DropPanel.cs
+++ b/Source/Engine/UI/GUI/Panels/DropPanel.cs
@@ -130,7 +130,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the font used to render panel header text.
///
[EditorDisplay("Header Text Style"), EditorOrder(2020), ExpandGroups]
- public MultiFontReference HeaderTextFont { get; set; }
+ public FontReference HeaderTextFont { get; set; }
///
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
@@ -238,7 +238,7 @@ namespace FlaxEngine.GUI
var style = Style.Current;
HeaderColor = style.BackgroundNormal;
HeaderColorMouseOver = style.BackgroundHighlighted;
- HeaderTextFont = new MultiFontReference(style.FontMedium);
+ HeaderTextFont = new FontReference(style.FontMedium);
HeaderTextColor = style.Foreground;
ArrowImageOpened = new SpriteBrush(style.ArrowDown);
ArrowImageClosed = new SpriteBrush(style.ArrowRight);
@@ -375,7 +375,7 @@ namespace FlaxEngine.GUI
textColor *= 0.6f;
}
- Render2D.DrawText(HeaderTextFont.GetMultiFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!_isClosed && EnableContainmentLines)
{
diff --git a/Source/Engine/UI/GUI/Style.cs b/Source/Engine/UI/GUI/Style.cs
index a8b87fb3a..c4b51b085 100644
--- a/Source/Engine/UI/GUI/Style.cs
+++ b/Source/Engine/UI/GUI/Style.cs
@@ -15,61 +15,67 @@ namespace FlaxEngine.GUI
public static Style Current { get; set; }
[Serialize]
- private MultiFontReference _fontTitle;
+ private FontReference _fontTitle;
///
/// The font title.
///
[NoSerialize]
[EditorOrder(10)]
- public MultiFont FontTitle
+ public Font FontTitle
{
- get => _fontTitle?.GetMultiFont();
- set => _fontTitle = new MultiFontReference(value);
+ get => _fontTitle?.GetFont();
+ set => _fontTitle = new FontReference(value);
}
[Serialize]
- private MultiFontReference _fontLarge;
+ private FontReference _fontLarge;
///
/// The font large.
///
[NoSerialize]
[EditorOrder(20)]
- public MultiFont FontLarge
+ public Font FontLarge
{
- get => _fontLarge?.GetMultiFont();
- set => _fontLarge = new MultiFontReference(value);
+ get => _fontLarge?.GetFont();
+ set => _fontLarge = new FontReference(value);
}
[Serialize]
- private MultiFontReference _fontMedium;
+ private FontReference _fontMedium;
///
/// The font medium.
///
[NoSerialize]
[EditorOrder(30)]
- public MultiFont FontMedium
+ public Font FontMedium
{
- get => _fontMedium?.GetMultiFont();
- set => _fontMedium = new MultiFontReference(value);
+ get => _fontMedium?.GetFont();
+ set => _fontMedium = new FontReference(value);
}
[Serialize]
- private MultiFontReference _fontSmall;
+ private FontReference _fontSmall;
///
/// The font small.
///
[NoSerialize]
[EditorOrder(40)]
- public MultiFont FontSmall
+ public Font FontSmall
{
- get => _fontSmall?.GetMultiFont();
- set => _fontSmall = new MultiFontReference(value);
+ get => _fontSmall?.GetFont();
+ set => _fontSmall = new FontReference(value);
}
+ ///
+ /// The fallback fonts to use if the primary font can't render the char.
+ ///
+ [EditorOrder(50)]
+ public FallbackFonts Fallbacks;
+
///
/// The background color.
///
From 623f478b4466bb248db1f6f7448124a1b338668b Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Thu, 30 Nov 2023 23:22:11 +0800
Subject: [PATCH 07/16] Move fallback rendering to new class
---
.../CustomEditors/Dedicated/ScriptsEditor.cs | 2 +-
.../Dedicated/UIControlEditor.cs | 2 +-
.../Editors/ActorTransformEditor.cs | 2 +-
.../Editor/CustomEditors/Editors/TagEditor.cs | 2 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 4 +-
Source/Editor/GUI/Docking/DockWindow.cs | 2 +-
Source/Editor/GUI/MainMenuButton.cs | 2 +-
Source/Editor/GUI/NavigationButton.cs | 2 +-
.../Editor/GUI/Timeline/Tracks/MemberTrack.cs | 2 +-
Source/Editor/GUI/ToolStripButton.cs | 2 +-
Source/Editor/GUI/Tree/TreeNode.cs | 2 +-
.../Archetypes/Animation.StateMachine.cs | 4 +-
Source/Editor/Surface/Archetypes/Animation.cs | 2 +-
.../Editor/Surface/Archetypes/BehaviorTree.cs | 4 +-
.../Surface/ContextMenu/VisjectCMItem.cs | 2 +-
Source/Editor/Surface/Elements/InputBox.cs | 4 +-
Source/Editor/Surface/SurfaceNode.cs | 6 +-
Source/Editor/Tools/Foliage/FoliageTab.cs | 2 +-
Source/Editor/Tools/Terrain/CarveTab.cs | 2 +-
Source/Editor/Utilities/TextRenderUtils.cs | 108 ---------------
Source/Editor/Viewport/EditorViewport.cs | 6 +-
.../Viewport/Widgets/ViewportWidgetButton.cs | 2 +-
Source/Editor/Windows/AboutDialog.cs | 2 +-
Source/Editor/Windows/PluginsWindow.cs | 2 +-
Source/Editor/Windows/Profiler/Timeline.cs | 2 +-
Source/Engine/Render2D/FallbackTextUtils.cs | 126 ++++++++++++++++++
Source/Engine/Render2D/Render2D.cs | 78 +----------
Source/Engine/UI/GUI/Common/Dropdown.cs | 2 +-
Source/Engine/UI/GUI/Common/Label.cs | 2 +-
Source/Engine/UI/GUI/Common/TextBox.cs | 2 +-
30 files changed, 165 insertions(+), 217 deletions(-)
delete mode 100644 Source/Editor/Utilities/TextRenderUtils.cs
create mode 100644 Source/Engine/Render2D/FallbackTextUtils.cs
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index 90ae9ae54..ab949508e 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -43,7 +43,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Add script button
var buttonText = "Add script";
- var textSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
+ var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
float addScriptButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
_addScriptsButton = new Button
diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index b8250918f..4efbee259 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -423,7 +423,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Set control type button
var space = layout.Space(20);
var buttonText = "Set Type";
- var textSize = Render2D.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
+ var textSize = FallbackTextUtils.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
float setTypeButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var setTypeButton = new Button
{
diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
index e84bf5914..8889a765a 100644
--- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
@@ -101,7 +101,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.Clicked += ToggleLink;
ToggleEnabled();
SetLinkStyle();
- var textSize = Render2D.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, LinkedLabel.Text.Value);
+ var textSize = FallbackTextUtils.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, LinkedLabel.Text.Value);
_linkButton.LocalX += textSize.X + 10;
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
{
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index 49ac9d937..bbece7e04 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -631,7 +631,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Edit...",
Parent = _label,
};
- var textSize = Render2D.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
+ var textSize = FallbackTextUtils.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
if (textSize.Y > button.Width)
button.Width = textSize.Y + 2;
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index 3137de240..d8c492e46 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -236,9 +236,9 @@ namespace FlaxEditor.GUI.ContextMenu
float width = 20;
if (style.FontMedium)
{
- width += Render2D.MeasureText(style.FontMedium, Text).X;
+ width += FallbackTextUtils.MeasureText(style.FontMedium, Text).X;
if (!string.IsNullOrEmpty(ShortKeys))
- width += 40 + Render2D.MeasureText(style.FontMedium, ShortKeys).X;
+ width += 40 + FallbackTextUtils.MeasureText(style.FontMedium, ShortKeys).X;
}
return Mathf.Max(width, base.MinimumWidth);
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index 36a4c112e..b7c12287f 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -489,7 +489,7 @@ namespace FlaxEditor.GUI.Docking
{
var style = Style.Current;
if (style?.FontMedium != null)
- _titleSize = Render2D.MeasureText(style.FontMedium, _title);
+ _titleSize = FallbackTextUtils.MeasureText(style.FontMedium, _title);
}
base.PerformLayoutBeforeChildren();
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 3440996aa..6fe8b98d3 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -103,7 +103,7 @@ namespace FlaxEditor.GUI
float width = 18;
if (style.FontMedium)
- width += Render2D.MeasureText(style.FontMedium, Text).X;
+ width += FallbackTextUtils.MeasureText(style.FontMedium, Text).X;
Width = width;
}
diff --git a/Source/Editor/GUI/NavigationButton.cs b/Source/Editor/GUI/NavigationButton.cs
index 6face21ef..5d399da02 100644
--- a/Source/Editor/GUI/NavigationButton.cs
+++ b/Source/Editor/GUI/NavigationButton.cs
@@ -68,7 +68,7 @@ namespace FlaxEditor.GUI
if (style.FontMedium)
{
- Width = Render2D.MeasureText(style.FontMedium, Text).X + 2 * DefaultMargin;
+ Width = FallbackTextUtils.MeasureText(style.FontMedium, Text).X + 2 * DefaultMargin;
}
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
index b4433622e..dd79922ac 100644
--- a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
@@ -345,7 +345,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (_previewValue != null)
{
// Based on Track.Draw for track text placement
- var left = _xOffset + 16 + Render2D.MeasureText(Style.Current.FontSmall, Title ?? Name).X;
+ var left = _xOffset + 16 + FallbackTextUtils.MeasureText(Style.Current.FontSmall, Title ?? Name).X;
if (Icon.IsValid)
left += 18;
if (IsExpanded)
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index cf34fd36b..50dce78b4 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -152,7 +152,7 @@ namespace FlaxEditor.GUI
if (hasSprite)
width += iconSize;
if (!string.IsNullOrEmpty(_text) && style.FontMedium)
- width += Render2D.MeasureText(style.FontMedium, _text).X + (hasSprite ? DefaultMargin : 0);
+ width += FallbackTextUtils.MeasureText(style.FontMedium, _text).X + (hasSprite ? DefaultMargin : 0);
Width = width;
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index 7b47e5eb6..700ba6da1 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -576,7 +576,7 @@ namespace FlaxEditor.GUI.Tree
var font = TextFont.GetFont();
if (font)
{
- _textWidth = Render2D.MeasureText(font, _text).X;
+ _textWidth = FallbackTextUtils.MeasureText(font, _text).X;
_textChanged = false;
}
}
diff --git a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
index 19a995b1e..078b89c56 100644
--- a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
@@ -337,7 +337,7 @@ namespace FlaxEditor.Surface.Archetypes
_textRect = new Rectangle(Float2.Zero, Size);
var style = Style.Current;
- var titleSize = Render2D.MeasureText(style.FontLarge, Title);
+ var titleSize = FallbackTextUtils.MeasureText(style.FontLarge, Title);
var width = Mathf.Max(100, titleSize.X + 50);
Resize(width, 0);
titleSize.X += 8.0f;
@@ -1402,7 +1402,7 @@ namespace FlaxEditor.Surface.Archetypes
{
Title = StateTitle;
var style = Style.Current;
- var titleSize = Render2D.MeasureText(style.FontLarge, Title);
+ var titleSize = FallbackTextUtils.MeasureText(style.FontLarge, Title);
var width = Mathf.Max(100, titleSize.X + 50);
Resize(width, 0);
titleSize.X += 8.0f;
diff --git a/Source/Editor/Surface/Archetypes/Animation.cs b/Source/Editor/Surface/Archetypes/Animation.cs
index dcf4a9689..dae16b425 100644
--- a/Source/Editor/Surface/Archetypes/Animation.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.cs
@@ -77,7 +77,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = asset?.ShortName ?? "Animation";
var style = Style.Current;
- Resize(Mathf.Max(230, Render2D.MeasureText(style.FontLarge, Title).X + 30), 160);
+ Resize(Mathf.Max(230, FallbackTextUtils.MeasureText(style.FontLarge, Title).X + 30), 160);
}
///
diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
index 364dfa1ef..5f3c0b0a2 100644
--- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs
+++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
@@ -101,7 +101,7 @@ namespace FlaxEditor.Surface.Archetypes
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
if (!string.IsNullOrEmpty(_debugInfo))
- _debugInfoSize = Render2D.MeasureText(Style.Current.FontSmall, _debugInfo);
+ _debugInfoSize = FallbackTextUtils.MeasureText(Style.Current.FontSmall, _debugInfo);
}
}
@@ -488,7 +488,7 @@ namespace FlaxEditor.Surface.Archetypes
var height = 0.0f;
var titleLabelFont = Style.Current.FontLarge;
width = Mathf.Max(width, 100.0f);
- width = Mathf.Max(width, Render2D.MeasureText(titleLabelFont, Title).X + 30);
+ width = Mathf.Max(width, FallbackTextUtils.MeasureText(titleLabelFont, Title).X + 30);
if (_debugInfoSize.X > 0)
{
width = Mathf.Max(width, _debugInfoSize.X + 8.0f);
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index fd9f0c63b..019be78b6 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -286,7 +286,7 @@ namespace FlaxEditor.Surface.ContextMenu
Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
if (_archetype.SubTitle != null)
{
- var titleLength = Render2D.MeasureText(style.FontSmall, _archetype.Title).X;
+ var titleLength = FallbackTextUtils.MeasureText(style.FontSmall, _archetype.Title).X;
var subTitleRect = new Rectangle(textRect.X + titleLength, textRect.Y, textRect.Width - titleLength, textRect.Height);
Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs
index 2ab286bd9..526d85d15 100644
--- a/Source/Editor/Surface/Elements/InputBox.cs
+++ b/Source/Editor/Surface/Elements/InputBox.cs
@@ -1428,7 +1428,7 @@ namespace FlaxEditor.Surface.Elements
if (_defaultValueEditor != null)
{
- _defaultValueEditor.Location = new Float2(X + Width + 8 + Render2D.MeasureText(Style.Current.FontSmall, Text).X, Y);
+ _defaultValueEditor.Location = new Float2(X + Width + 8 + FallbackTextUtils.MeasureText(Style.Current.FontSmall, Text).X, Y);
}
}
@@ -1635,7 +1635,7 @@ namespace FlaxEditor.Surface.Elements
{
if (DefaultValueEditors[i].CanUse(this, ref _currentType))
{
- var bounds = new Rectangle(X + Width + 8 + Render2D.MeasureText(Style.Current.FontSmall, Text).X, Y, 90, Height);
+ var bounds = new Rectangle(X + Width + 8 + FallbackTextUtils.MeasureText(Style.Current.FontSmall, Text).X, Y, 90, Height);
_editor = DefaultValueEditors[i];
try
{
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index 60d776102..3c2381192 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -200,7 +200,7 @@ namespace FlaxEditor.Surface
continue;
if (child is InputBox inputBox)
{
- var boxWidth = Render2D.MeasureText(boxLabelFont, inputBox.Text).X + 20;
+ var boxWidth = FallbackTextUtils.MeasureText(boxLabelFont, inputBox.Text).X + 20;
if (inputBox.DefaultValueEditor != null)
boxWidth += inputBox.DefaultValueEditor.Width + 4;
leftWidth = Mathf.Max(leftWidth, boxWidth);
@@ -208,7 +208,7 @@ namespace FlaxEditor.Surface
}
else if (child is OutputBox outputBox)
{
- rightWidth = Mathf.Max(rightWidth, Render2D.MeasureText(boxLabelFont, outputBox.Text).X + 20);
+ rightWidth = Mathf.Max(rightWidth, FallbackTextUtils.MeasureText(boxLabelFont, outputBox.Text).X + 20);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
}
else if (child is Control control)
@@ -226,7 +226,7 @@ namespace FlaxEditor.Surface
}
}
width = Mathf.Max(width, leftWidth + rightWidth + 10);
- width = Mathf.Max(width, Render2D.MeasureText(titleLabelFont, Title).X + 30);
+ width = Mathf.Max(width, FallbackTextUtils.MeasureText(titleLabelFont, Title).X + 30);
height = Mathf.Max(height, Mathf.Max(leftHeight, rightHeight));
Resize(width, height);
}
diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs
index 58cf6f204..c2b1fbe68 100644
--- a/Source/Editor/Tools/Foliage/FoliageTab.cs
+++ b/Source/Editor/Tools/Foliage/FoliageTab.cs
@@ -148,7 +148,7 @@ namespace FlaxEditor.Tools.Foliage
Parent = _noFoliagePanel,
Enabled = false
};
- var textSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
+ var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
if (_createNewFoliage.Width < textSize.X)
{
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CarveTab.cs b/Source/Editor/Tools/Terrain/CarveTab.cs
index 12c9fd148..0a86aab6f 100644
--- a/Source/Editor/Tools/Terrain/CarveTab.cs
+++ b/Source/Editor/Tools/Terrain/CarveTab.cs
@@ -106,7 +106,7 @@ namespace FlaxEditor.Tools.Terrain
Parent = _noTerrainPanel,
Enabled = false
};
- var textSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
+ var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
if (_createTerrainButton.Width < textSize.X)
{
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
diff --git a/Source/Editor/Utilities/TextRenderUtils.cs b/Source/Editor/Utilities/TextRenderUtils.cs
deleted file mode 100644
index d7b79ae81..000000000
--- a/Source/Editor/Utilities/TextRenderUtils.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using FlaxEngine.GUI;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace FlaxEngine
-{
- public static class TextRenderUtils
- {
- ///
- /// Draws a text using the global fallback defined in styles.
- ///
- /// The font to use.
- /// The text to render.
- /// The size and position of the area in which the text is drawn.
- /// The text color.
- /// The horizontal alignment of the text in a layout rectangle.
- /// The vertical alignment of the text in a layout rectangle.
- /// Describes how wrap text inside a layout rectangle.
- /// The scale for distance one baseline from another. Default is 1.
- /// The text drawing scale. Default is 1.
- public static void DrawTextWithFallback(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
- {
- var layout = new TextLayoutOptions
- {
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
-
- Render2D.DrawText(font, Style.Current.Fallbacks, text, color, ref layout);
- }
-
- ///
- /// Draws a text using the global fallback defined in styles. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling).
- ///
- /// The font to use.
- /// Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- /// The text to render.
- /// The size and position of the area in which the text is drawn.
- /// The text color.
- /// The horizontal alignment of the text in a layout rectangle.
- /// The vertical alignment of the text in a layout rectangle.
- /// Describes how wrap text inside a layout rectangle.
- /// The scale for distance one baseline from another. Default is 1.
- /// The text drawing scale. Default is 1.
- public static void DrawTextWithFallback(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
- {
- var layout = new TextLayoutOptions
- {
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
- Render2D.DrawText(font, Style.Current.Fallbacks, text, color, ref layout, customMaterial);
- }
-
- public static Float2 MeasureTextWithFallback(Font font, string text)
- {
- return font.MeasureText(Style.Current.Fallbacks, text);
- }
-
- public static Float2 MeasureTextWithFallback(Font font, string text, ref TextRange textRange)
- {
- return font.MeasureText(Style.Current.Fallbacks, text, ref textRange);
- }
-
- public static Float2 MeasureTextWithFallback(Font font, string text, ref TextLayoutOptions layout)
- {
- return font.MeasureText(Style.Current.Fallbacks, text, ref layout);
- }
-
- public static Float2 MeasureTextWithFallback(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout)
- {
- return font.MeasureText(Style.Current.Fallbacks, text, ref textRange, ref layout);
- }
-
- public static Float2 GetCharPositionWithFallback(Font font, string text, int index)
- {
- return font.GetCharPosition(Style.Current.Fallbacks, text, index);
- }
-
- public static Float2 GetCharPositionWithFallback(Font font, string text, ref TextRange textRange, int index)
- {
- return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index);
- }
-
- public static Float2 GetCharPositionWithFallback(Font font, string text, int index, ref TextLayoutOptions layout)
- {
- return font.GetCharPosition(Style.Current.Fallbacks, text, index, ref layout);
- }
-
- public static Float2 GetCharPositionWithFallback(Font font, string text, ref TextRange textRange, int index, ref TextLayoutOptions layout)
- {
- return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index, ref layout);
- }
- }
-}
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index 77a677c0c..0633d0ba9 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -548,9 +548,9 @@ namespace FlaxEditor.Viewport
#region Camera settings widget
var largestText = "Relative Panning";
- var textSize = Render2D.MeasureText(Style.Current.FontMedium, largestText);
+ var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, largestText);
var xLocationForExtras = textSize.X + 5;
- var cameraSpeedTextWidth = Render2D.MeasureText(Style.Current.FontMedium, "0.00").X;
+ var cameraSpeedTextWidth = FallbackTextUtils.MeasureText(Style.Current.FontMedium, "0.00").X;
// Camera Settings Widget
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
@@ -801,7 +801,7 @@ namespace FlaxEditor.Viewport
#region View mode widget
largestText = "Brightness";
- textSize = Render2D.MeasureText(Style.Current.FontMedium, largestText);
+ textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, largestText);
xLocationForExtras = textSize.X + 5;
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
index 250790621..598f4ee32 100644
--- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
+++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
@@ -164,7 +164,7 @@ namespace FlaxEditor.Viewport.Widgets
var style = Style.Current;
if (style != null && style.FontMedium)
- Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : Render2D.MeasureText(style.FontMedium, _text).X, Icon.IsValid);
+ Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : FallbackTextUtils.MeasureText(style.FontMedium, _text).X, Icon.IsValid);
}
}
}
diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs
index ac887dadf..02aad16ec 100644
--- a/Source/Editor/Windows/AboutDialog.cs
+++ b/Source/Editor/Windows/AboutDialog.cs
@@ -54,7 +54,7 @@ namespace FlaxEditor.Windows
Parent = this
};
var buttonText = "Copy version info";
- var fontSize = Render2D.MeasureText(Style.Current.FontMedium, buttonText);
+ var fontSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
var copyVersionButton = new Button(Width - fontSize.X - 8, 6, fontSize.X + 4, 20)
{
Text = buttonText,
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index 4dfa0ed08..03beab2fa 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -122,7 +122,7 @@ namespace FlaxEditor.Windows
url = desc.RepositoryUrl;
versionLabel.Font.Font.WaitForLoaded();
var font = versionLabel.Font.GetFont();
- var authorWidth = Render2D.MeasureText(font, desc.Author).X + 8;
+ var authorWidth = FallbackTextUtils.MeasureText(font, desc.Author).X + 8;
var authorLabel = new ClickableLabel
{
HorizontalAlignment = TextAlignment.Far,
diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs
index 00365f74a..780b31a3b 100644
--- a/Source/Editor/Windows/Profiler/Timeline.cs
+++ b/Source/Editor/Windows/Profiler/Timeline.cs
@@ -86,7 +86,7 @@ namespace FlaxEditor.Windows.Profiler
Render2D.DrawRectangle(bounds, color * 0.5f);
if (_nameLength < 0 && style.FontMedium)
- _nameLength = Render2D.MeasureText(style.FontMedium, _name).X;
+ _nameLength = FallbackTextUtils.MeasureText(style.FontMedium, _name).X;
if (_nameLength < bounds.Width + 4)
{
diff --git a/Source/Engine/Render2D/FallbackTextUtils.cs b/Source/Engine/Render2D/FallbackTextUtils.cs
new file mode 100644
index 000000000..eb676f0a9
--- /dev/null
+++ b/Source/Engine/Render2D/FallbackTextUtils.cs
@@ -0,0 +1,126 @@
+
+namespace FlaxEngine
+{
+ ///
+ /// A collection of functions to handle text rendering with fallback font
+ ///
+ public static class FallbackTextUtils
+ {
+ public static FallbackFonts Fallbacks
+ {
+ get; set;
+ } = null;
+
+ public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+
+ if (Fallbacks != null)
+ {
+ Render2D.DrawText(font, Fallbacks, text, color, ref layout);
+ }
+ else
+ {
+ Render2D.DrawText(font, text, color, ref layout);
+ }
+ }
+
+ public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+
+ if (Fallbacks != null)
+ {
+ Render2D.DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
+ }
+ else
+ {
+ Render2D.DrawText(font, text, color, ref layout, customMaterial);
+ }
+ }
+
+ public static Float2 MeasureText(Font font, string text)
+ {
+ if (Fallbacks != null)
+ {
+ return font.MeasureText(Fallbacks, text);
+ }
+ else
+ {
+ return font.MeasureText(text);
+ }
+ }
+
+ public static Float2 MeasureText(Font font, string text, ref TextRange textRange)
+ {
+ if (Fallbacks != null)
+ {
+ return font.MeasureText(Fallbacks, text, ref textRange);
+ }
+ else
+ {
+ return font.MeasureText(text, ref textRange);
+ }
+ }
+
+ public static Float2 MeasureText(Font font, string text, ref TextLayoutOptions layout)
+ {
+ if (Fallbacks != null)
+ {
+ return font.MeasureText(Fallbacks, text, ref layout);
+ }
+ else
+ {
+ return font.MeasureText(text, ref layout);
+ }
+ }
+
+ public static Float2 MeasureText(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout)
+ {
+ if (Fallbacks != null)
+ {
+ return font.MeasureText(Fallbacks, text, ref textRange, ref layout);
+ }
+ else
+ {
+ return font.MeasureText(text, ref textRange, ref layout);
+ }
+ }
+
+ public static Float2 GetCharPosition(Font font, string text, int index)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, index);
+ }
+
+ public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index);
+ }
+
+ public static Float2 GetCharPosition(Font font, string text, int index, ref TextLayoutOptions layout)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, index, ref layout);
+ }
+
+ public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index, ref TextLayoutOptions layout)
+ {
+ return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index, ref layout);
+ }
+ }
+}
diff --git a/Source/Engine/Render2D/Render2D.cs b/Source/Engine/Render2D/Render2D.cs
index b7158ccc7..6e4f1dc1d 100644
--- a/Source/Engine/Render2D/Render2D.cs
+++ b/Source/Engine/Render2D/Render2D.cs
@@ -7,10 +7,6 @@ namespace FlaxEngine
{
partial class Render2D
{
- public static FallbackFonts Fallbacks
- {
- get; set;
- } = null;
///
/// Pushes transformation layer.
@@ -117,8 +113,7 @@ namespace FlaxEngine
/// Describes how wrap text inside a layout rectangle.
/// The scale for distance one baseline from another. Default is 1.
/// The text drawing scale. Default is 1.
- /// Whether to use fallback fonts for chars not renderable by the font.
- public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
+ public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
{
var layout = new TextLayoutOptions
{
@@ -129,15 +124,7 @@ namespace FlaxEngine
Scale = scale,
BaseLinesGapScale = baseLinesGapScale,
};
-
- if (useFallback && Fallbacks != null)
- {
- DrawText(font, Fallbacks, text, color, ref layout);
- }
- else
- {
- DrawText(font, text, color, ref layout);
- }
+ DrawText(font, text, color, ref layout);
}
///
@@ -153,8 +140,7 @@ namespace FlaxEngine
/// Describes how wrap text inside a layout rectangle.
/// The scale for distance one baseline from another. Default is 1.
/// The text drawing scale. Default is 1.
- /// Whether to use fallback fonts for chars not renderable by the font.
- public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
+ public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
{
var layout = new TextLayoutOptions
{
@@ -165,63 +151,7 @@ namespace FlaxEngine
Scale = scale,
BaseLinesGapScale = baseLinesGapScale,
};
-
- if (useFallback && Fallbacks != null)
- {
- DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
- }
- else
- {
- DrawText(font, text, color, ref layout, customMaterial);
- }
- }
-
- public static Float2 MeasureText(Font font, string text, bool useFallback = true)
- {
- if (useFallback && Fallbacks != null)
- {
- return font.MeasureText(Style.Current.Fallbacks, text);
- }
- else
- {
- return font.MeasureText(text);
- }
- }
-
- public static Float2 MeasureText(Font font, string text, ref TextRange textRange, bool useFallback = true)
- {
- if (useFallback && Fallbacks != null)
- {
- return font.MeasureText(Style.Current.Fallbacks, text, ref textRange);
- }
- else
- {
- return font.MeasureText(text, ref textRange);
- }
- }
-
- public static Float2 MeasureText(Font font, string text, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (useFallback && Fallbacks != null)
- {
- return font.MeasureText(Style.Current.Fallbacks, text, ref layout);
- }
- else
- {
- return font.MeasureText(text, ref layout);
- }
- }
-
- public static Float2 MeasureText(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (useFallback && Fallbacks != null)
- {
- return font.MeasureText(Style.Current.Fallbacks, text, ref textRange, ref layout);
- }
- else
- {
- return font.MeasureText(text, ref textRange, ref layout);
- }
+ DrawText(font, text, color, ref layout, customMaterial);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index c9fef131c..46f05f516 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -476,7 +476,7 @@ namespace FlaxEngine.GUI
var font = Font.GetFont();
for (int i = 0; i < _items.Count; i++)
{
- itemsWidth = Mathf.Max(itemsWidth, itemsMargin + 4 + Render2D.MeasureText(font, _items[i]).X);
+ itemsWidth = Mathf.Max(itemsWidth, itemsMargin + 4 + FallbackTextUtils.MeasureText(font, _items[i]).X);
}
*/
var itemsWidth = Width;
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index d7147d3ab..4e26c1934 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -256,7 +256,7 @@ namespace FlaxEngine.GUI
layout.Bounds.Size.X = Width - Margin.Width;
else if (_autoWidth && !_autoHeight)
layout.Bounds.Size.Y = Height - Margin.Height;
- _textSize = Render2D.MeasureText(font, _text, ref layout);
+ _textSize = FallbackTextUtils.MeasureText(font, _text, ref layout);
_textSize.Y *= BaseLinesGapScale;
// Check if size is controlled via text
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index a32f3a76c..ea7523f48 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -106,7 +106,7 @@ namespace FlaxEngine.GUI
return Float2.Zero;
}
- return Render2D.MeasureText(font, _text, ref _layout);
+ return FallbackTextUtils.MeasureText(font, _text, ref _layout);
}
///
From 3d139a241ab4720e64ea03aae082de284bd5d26b Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Fri, 1 Dec 2023 09:28:29 +0800
Subject: [PATCH 08/16] Fix C# editor
---
Source/Editor/Content/GUI/ContentView.cs | 2 +-
Source/Editor/Content/Items/ContentItem.cs | 2 +-
Source/Editor/Content/Tree/ContentTreeNode.cs | 5 +-
.../Dedicated/MeshReferenceEditor.cs | 4 +-
.../CustomEditors/Dedicated/ScriptsEditor.cs | 3 +-
.../CustomEditors/Dedicated/SplineEditor.cs | 2 +-
.../Editors/ActorTransformEditor.cs | 1 -
.../Editors/FlaxObjectRefEditor.cs | 4 +-
.../CustomEditors/Editors/TypeEditor.cs | 4 +-
Source/Editor/GUI/AssetPicker.cs | 6 +-
Source/Editor/GUI/ComboBox.cs | 2 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 5 +-
Source/Editor/GUI/CurveEditor.cs | 2 +-
.../Editor/GUI/Dialogs/ColorPickerDialog.cs | 22 +-
Source/Editor/GUI/Docking/DockPanelProxy.cs | 4 +-
Source/Editor/GUI/Docking/DockWindow.cs | 1 -
Source/Editor/GUI/ItemsListContextMenu.cs | 7 +-
Source/Editor/GUI/MainMenuButton.cs | 3 +-
Source/Editor/GUI/NavigationButton.cs | 3 +-
Source/Editor/GUI/Row.cs | 3 +-
Source/Editor/GUI/StatusBar.cs | 2 +-
Source/Editor/GUI/StyleValueEditor.cs | 2 +-
Source/Editor/GUI/Table.cs | 3 +-
Source/Editor/GUI/Tabs/Tabs.cs | 2 +-
Source/Editor/GUI/Timeline/GUI/Background.cs | 2 +-
.../Editor/GUI/Timeline/GUI/PositionHandle.cs | 1 -
Source/Editor/GUI/Timeline/Track.cs | 2 +-
Source/Editor/GUI/ToolStripButton.cs | 3 +-
Source/Editor/GUI/Tree/TreeNode.cs | 3 +-
Source/Editor/Options/OptionsModule.cs | 2 +-
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 4 +-
.../Archetypes/Animation.StateMachine.cs | 4 +-
.../Editor/Surface/Archetypes/BehaviorTree.cs | 3 +-
.../Surface/Archetypes/ParticleModules.cs | 2 +-
Source/Editor/Surface/Archetypes/Particles.cs | 4 +-
.../Editor/Surface/ContextMenu/VisjectCM.cs | 2 +-
.../Surface/ContextMenu/VisjectCMItem.cs | 18 +-
Source/Editor/Surface/Elements/InputBox.cs | 2 +-
Source/Editor/Surface/Elements/OutputBox.cs | 2 +-
Source/Editor/Surface/Elements/TextView.cs | 2 +-
Source/Editor/Surface/SurfaceComment.cs | 2 +-
Source/Editor/Surface/SurfaceNode.cs | 3 +-
Source/Editor/Tools/Foliage/FoliageTab.cs | 1 -
Source/Editor/Tools/Terrain/CarveTab.cs | 1 -
Source/Editor/Viewport/EditorViewport.cs | 6 +-
.../Viewport/Previews/AnimationPreview.cs | 4 +-
.../Editor/Viewport/Previews/ModelPreview.cs | 4 +-
.../Previews/ParticleSystemPreview.cs | 2 +-
.../Viewport/Previews/SkinnedModelPreview.cs | 4 +-
.../Viewport/Previews/TexturePreview.cs | 2 +-
.../Viewport/Widgets/ViewportWidgetButton.cs | 3 +-
Source/Editor/Windows/AboutDialog.cs | 1 -
.../Windows/Assets/AnimationGraphWindow.cs | 2 +-
.../Editor/Windows/Assets/AnimationWindow.cs | 2 +-
Source/Editor/Windows/Assets/ModelWindow.cs | 4 +-
.../Windows/Assets/SkinnedModelWindow.cs | 4 +-
Source/Editor/Windows/ContentWindow.Search.cs | 2 +-
Source/Editor/Windows/DebugLogWindow.cs | 4 +-
Source/Editor/Windows/GameWindow.cs | 8 +-
Source/Editor/Windows/Profiler/SingleChart.cs | 4 +-
Source/Editor/Windows/Profiler/Timeline.cs | 5 +-
Source/Editor/Windows/SceneTreeWindow.cs | 2 +-
Source/Editor/Windows/ToolboxWindow.cs | 5 +-
Source/Engine/Render2D/FallbackTextUtils.cs | 205 +++++++++++++-----
Source/Engine/UI/GUI/Common/Button.cs | 3 +-
Source/Engine/UI/GUI/Common/Dropdown.cs | 3 +-
Source/Engine/UI/GUI/Common/Label.cs | 4 +-
.../Engine/UI/GUI/Common/RichTextBox.Tags.cs | 1 -
Source/Engine/UI/GUI/Common/RichTextBox.cs | 1 -
.../Engine/UI/GUI/Common/RichTextBoxBase.cs | 8 +-
Source/Engine/UI/GUI/Common/TextBox.cs | 28 +--
Source/Engine/UI/GUI/Panels/DropPanel.cs | 3 +-
Source/Engine/UI/GUI/Style.cs | 1 -
Source/Engine/UI/GUI/Tooltip.cs | 3 +-
74 files changed, 272 insertions(+), 213 deletions(-)
diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs
index 259be104b..1091c9cef 100644
--- a/Source/Editor/Content/GUI/ContentView.cs
+++ b/Source/Editor/Content/GUI/ContentView.cs
@@ -598,7 +598,7 @@ namespace FlaxEditor.Content.GUI
// Check if it's an empty thing
if (_items.Count == 0)
{
- Render2D.DrawText(style.FontSmall, IsSearching ? "No results" : "Empty", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, IsSearching ? "No results" : "Empty", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs
index 604caa704..0842dfff7 100644
--- a/Source/Editor/Content/Items/ContentItem.cs
+++ b/Source/Editor/Content/Items/ContentItem.cs
@@ -745,7 +745,7 @@ namespace FlaxEditor.Content
// Draw short name
Render2D.PushClip(ref textRect);
- Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
+ FallbackTextUtils.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
Render2D.PopClip();
}
diff --git a/Source/Editor/Content/Tree/ContentTreeNode.cs b/Source/Editor/Content/Tree/ContentTreeNode.cs
index ee9b463f7..2f378e7f5 100644
--- a/Source/Editor/Content/Tree/ContentTreeNode.cs
+++ b/Source/Editor/Content/Tree/ContentTreeNode.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.GUI.Tree;
@@ -151,8 +150,8 @@ namespace FlaxEditor.Content
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(text, ranges[i].StartIndex);
- var end = font.GetCharPosition(text, ranges[i].EndIndex);
+ var start = FallbackTextUtils.GetCharPosition(font, text, ranges[i].StartIndex);
+ var end = FallbackTextUtils.GetCharPosition(font, text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs b/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs
index 4099e5aee..66c1c791f 100644
--- a/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs
@@ -109,7 +109,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
// Draw name
Render2D.PushClip(nameRect);
- Render2D.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
// Draw deselect button
@@ -118,7 +118,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
else
{
// Draw info
- Render2D.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
}
// Draw picker button
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index ab949508e..017fd7655 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.Content;
using FlaxEditor.GUI;
@@ -87,7 +86,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var size = Size;
// Info
- Render2D.DrawText(style.FontSmall, "Drag scripts here", new Rectangle(2, _addScriptsButton.Height + 4, size.X - 4, size.Y - 4 - 20), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, "Drag scripts here", new Rectangle(2, _addScriptsButton.Height + 4, size.X - 4, size.Y - 4 - 20), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
// Check if drag is over
if (IsDragOver && _dragHandlers != null && _dragHandlers.HasValidDrag)
diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs
index 7b9b65c5c..fa4379db1 100644
--- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs
@@ -226,7 +226,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (!enabled)
color *= 0.6f;
Render2D.DrawSprite(tab._customIcon, iconRect, color);
- Render2D.DrawText(style.FontMedium, tab._customText, new Rectangle(0, iconSize, size.X, textHeight), color, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, tab._customText, new Rectangle(0, iconSize, size.X, textHeight), color, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
index 8889a765a..d8d16027b 100644
--- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
@@ -2,7 +2,6 @@
using FlaxEngine;
using FlaxEngine.GUI;
-using System.Linq;
namespace FlaxEditor.CustomEditors.Editors
{
diff --git a/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs b/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
index 731da3817..2f64ea159 100644
--- a/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
@@ -199,7 +199,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
// Draw name
Render2D.PushClip(nameRect);
- Render2D.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
// Draw deselect button
@@ -208,7 +208,7 @@ namespace FlaxEditor.CustomEditors.Editors
else
{
// Draw info
- Render2D.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
}
// Draw picker button
diff --git a/Source/Editor/CustomEditors/Editors/TypeEditor.cs b/Source/Editor/CustomEditors/Editors/TypeEditor.cs
index 38800a738..4d0b90383 100644
--- a/Source/Editor/CustomEditors/Editors/TypeEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TypeEditor.cs
@@ -160,13 +160,13 @@ namespace FlaxEditor.CustomEditors.Editors
// Draw name
Render2D.PushClip(nameRect);
- Render2D.DrawText(style.FontMedium, _valueName, nameRect, style.Foreground, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _valueName, nameRect, style.Foreground, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
else
{
// Draw info
- Render2D.DrawText(style.FontMedium, "-", nameRect, Color.OrangeRed, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "-", nameRect, Color.OrangeRed, TextAlignment.Near, TextAlignment.Center);
}
// Draw picker button
diff --git a/Source/Editor/GUI/AssetPicker.cs b/Source/Editor/GUI/AssetPicker.cs
index 84f58daf1..2abe5db38 100644
--- a/Source/Editor/GUI/AssetPicker.cs
+++ b/Source/Editor/GUI/AssetPicker.cs
@@ -139,7 +139,7 @@ namespace FlaxEditor.GUI
float sizeForTextLeft = Width - button1Rect.Right;
if (sizeForTextLeft > 30)
{
- Render2D.DrawText(
+ FallbackTextUtils.DrawText(
style.FontSmall,
Validator.SelectedItem.ShortName,
new Rectangle(button1Rect.Right + 2, 0, sizeForTextLeft, ButtonsSize),
@@ -161,7 +161,7 @@ namespace FlaxEditor.GUI
var name = Validator.SelectedAsset.GetType().Name;
if (Validator.SelectedAsset.IsVirtual)
name += " (virtual)";
- Render2D.DrawText(
+ FallbackTextUtils.DrawText(
style.FontSmall,
name,
new Rectangle(button1Rect.Right + 2, 0, sizeForTextLeft, ButtonsSize),
@@ -174,7 +174,7 @@ namespace FlaxEditor.GUI
{
// No element selected
Render2D.FillRectangle(iconRect, style.BackgroundNormal);
- Render2D.DrawText(style.FontMedium, "No asset\nselected", iconRect, Color.Orange, TextAlignment.Center, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, Height / DefaultIconSize);
+ FallbackTextUtils.DrawText(style.FontMedium, "No asset\nselected", iconRect, Color.Orange, TextAlignment.Center, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, Height / DefaultIconSize);
}
// Check if drag is over
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index 0417cc7e3..8f3a7cb4b 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -554,7 +554,7 @@ namespace FlaxEditor.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ FallbackTextUtils.DrawText(Font.GetFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
}
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index d8c492e46..035e997e9 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -129,12 +128,12 @@ namespace FlaxEditor.GUI.ContextMenu
base.Draw();
// Draw text
- Render2D.DrawText(style.FontMedium, Text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, Text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!string.IsNullOrEmpty(ShortKeys))
{
// Draw short keys
- Render2D.DrawText(style.FontMedium, ShortKeys, textRect, textColor, TextAlignment.Far, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, ShortKeys, textRect, textColor, TextAlignment.Far, TextAlignment.Center);
}
// Draw icon
diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs
index 22deec120..f4839acd5 100644
--- a/Source/Editor/GUI/CurveEditor.cs
+++ b/Source/Editor/GUI/CurveEditor.cs
@@ -832,7 +832,7 @@ namespace FlaxEditor.GUI
50,
LabelsSize
);
- Render2D.DrawText(_labelsFont, label, labelRect, _labelsColor.AlphaMultiplied(strength), TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.7f);
+ FallbackTextUtils.DrawText(_labelsFont, label, labelRect, _labelsColor.AlphaMultiplied(strength), TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.7f);
}
}
}
diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
index 27878a763..8b1881faf 100644
--- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
+++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
@@ -281,33 +281,33 @@ namespace FlaxEditor.GUI.Dialogs
// RGBA
var rgbaR = new Rectangle(_cRed.Left - ChannelTextWidth, _cRed.Y, 10000, _cRed.Height);
- Render2D.DrawText(style.FontMedium, "R", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "R", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cGreen.Y;
- Render2D.DrawText(style.FontMedium, "G", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "G", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cBlue.Y;
- Render2D.DrawText(style.FontMedium, "B", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "B", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cAlpha.Y;
- Render2D.DrawText(style.FontMedium, "A", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "A", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
// HSV left
var hsvHl = new Rectangle(_cHue.Left - ChannelTextWidth, _cHue.Y, 10000, _cHue.Height);
- Render2D.DrawText(style.FontMedium, "H", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "H", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHl.Location.Y = _cSaturation.Y;
- Render2D.DrawText(style.FontMedium, "S", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "S", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHl.Location.Y = _cValue.Y;
- Render2D.DrawText(style.FontMedium, "V", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "V", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
// HSV right
var hsvHr = new Rectangle(_cHue.Right + 2, _cHue.Y, 10000, _cHue.Height);
- Render2D.DrawText(style.FontMedium, "°", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "°", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHr.Location.Y = _cSaturation.Y;
- Render2D.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHr.Location.Y = _cValue.Y;
- Render2D.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
// Hex
var hex = new Rectangle(_cHex.Left - 26, _cHex.Y, 10000, _cHex.Height);
- Render2D.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
// Color difference
var newRect = new Rectangle(_cOK.X, _cHex.Bottom + PickerMargin, _cCancel.Right - _cOK.Left, 0);
diff --git a/Source/Editor/GUI/Docking/DockPanelProxy.cs b/Source/Editor/GUI/Docking/DockPanelProxy.cs
index e6e57de8e..0b36b85fa 100644
--- a/Source/Editor/GUI/Docking/DockPanelProxy.cs
+++ b/Source/Editor/GUI/Docking/DockPanelProxy.cs
@@ -208,7 +208,7 @@ namespace FlaxEditor.GUI.Docking
}
// Draw text
- Render2D.DrawText(
+ FallbackTextUtils.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(DockPanel.DefaultLeftTextMargin + iconWidth, 0, Width - DockPanel.DefaultLeftTextMargin - DockPanel.DefaultButtonsSize - 2 * DockPanel.DefaultButtonsMargin, DockPanel.DefaultHeaderHeight),
@@ -271,7 +271,7 @@ namespace FlaxEditor.GUI.Docking
}
// Draw text
- Render2D.DrawText(
+ FallbackTextUtils.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(x + DockPanel.DefaultLeftTextMargin + iconWidth, 0, 10000, DockPanel.DefaultHeaderHeight),
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index b7c12287f..561c898a0 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -6,7 +6,6 @@ using FlaxEngine;
using FlaxEngine.Assertions;
using FlaxEngine.GUI;
using FlaxEditor.Options;
-using System.Linq;
namespace FlaxEditor.GUI.Docking
{
diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs
index b823cc907..d3c433a47 100644
--- a/Source/Editor/GUI/ItemsListContextMenu.cs
+++ b/Source/Editor/GUI/ItemsListContextMenu.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Input;
using FlaxEditor.Utilities;
@@ -87,8 +86,8 @@ namespace FlaxEditor.GUI
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(Name, ranges[i].StartIndex);
- var end = font.GetCharPosition(Name, ranges[i].EndIndex);
+ var start = FallbackTextUtils.GetCharPosition(font, Name, ranges[i].StartIndex);
+ var end = FallbackTextUtils.GetCharPosition(font, Name, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
}
Visible = true;
@@ -137,7 +136,7 @@ namespace FlaxEditor.GUI
}
// Draw name
- Render2D.DrawText(style.FontSmall, Name, textRect, TintColor * (Enabled ? style.Foreground : style.ForegroundDisabled), TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, Name, textRect, TintColor * (Enabled ? style.Foreground : style.ForegroundDisabled), TextAlignment.Near, TextAlignment.Center);
}
///
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 6fe8b98d3..43849f4ab 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -2,7 +2,6 @@
using FlaxEngine;
using FlaxEngine.GUI;
-using System.Linq;
namespace FlaxEditor.GUI
{
@@ -73,7 +72,7 @@ namespace FlaxEditor.GUI
}
// Draw text
- Render2D.DrawText(style.FontMedium, Text, clientRect, enabled && hasChildItems ? style.Foreground : style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, Text, clientRect, enabled && hasChildItems ? style.Foreground : style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Editor/GUI/NavigationButton.cs b/Source/Editor/GUI/NavigationButton.cs
index 5d399da02..8dedf72fd 100644
--- a/Source/Editor/GUI/NavigationButton.cs
+++ b/Source/Editor/GUI/NavigationButton.cs
@@ -2,7 +2,6 @@
using FlaxEngine;
using FlaxEngine.GUI;
-using System.Linq;
namespace FlaxEditor.GUI
{
@@ -58,7 +57,7 @@ namespace FlaxEditor.GUI
}
// Draw text
- Render2D.DrawText(style.FontMedium, Text, textRect, EnabledInHierarchy ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, Text, textRect, EnabledInHierarchy ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
///
diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs
index ab74cbe96..c7be48626 100644
--- a/Source/Editor/GUI/Row.cs
+++ b/Source/Editor/GUI/Row.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -99,7 +98,7 @@ namespace FlaxEditor.GUI
rect.Width -= leftDepthMargin;
Render2D.PushClip(rect);
- Render2D.DrawText(style.FontMedium, text, rect, style.Foreground, column.CellAlignment, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, text, rect, style.Foreground, column.CellAlignment, TextAlignment.Center);
Render2D.PopClip();
x += width;
diff --git a/Source/Editor/GUI/StatusBar.cs b/Source/Editor/GUI/StatusBar.cs
index f8f7ae839..7770af9a1 100644
--- a/Source/Editor/GUI/StatusBar.cs
+++ b/Source/Editor/GUI/StatusBar.cs
@@ -56,7 +56,7 @@ namespace FlaxEditor.GUI
Render2D.DrawSprite(style.StatusBarSizeGrip, new Rectangle(Width - 12, 10, 12, 12), style.Foreground);
// Draw status text
- Render2D.DrawText(style.FontSmall, Text, new Rectangle(4, 0, Width - 20, Height), TextColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, Text, new Rectangle(4, 0, Width - 20, Height), TextColor, TextAlignment.Near, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/GUI/StyleValueEditor.cs b/Source/Editor/GUI/StyleValueEditor.cs
index a89902177..db6696152 100644
--- a/Source/Editor/GUI/StyleValueEditor.cs
+++ b/Source/Editor/GUI/StyleValueEditor.cs
@@ -157,7 +157,7 @@ namespace FlaxEditor.GUI
{
Rectangle textRectangle = r;
textRectangle.X = 4;
- Render2D.DrawText(style.FontMedium, "No Style", textRectangle, style.Foreground);
+ FallbackTextUtils.DrawText(style.FontMedium, "No Style", textRectangle, style.Foreground);
}
}
diff --git a/Source/Editor/GUI/Table.cs b/Source/Editor/GUI/Table.cs
index 54656a6c2..2358557c3 100644
--- a/Source/Editor/GUI/Table.cs
+++ b/Source/Editor/GUI/Table.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using System.Runtime.CompilerServices;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -131,7 +130,7 @@ namespace FlaxEditor.GUI
var style = Style.Current;
var font = column.TitleFont ?? style.FontMedium;
- Render2D.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
if (columnIndex < _columns.Length - 1)
{
diff --git a/Source/Editor/GUI/Tabs/Tabs.cs b/Source/Editor/GUI/Tabs/Tabs.cs
index 3c70363e7..5995c7ef5 100644
--- a/Source/Editor/GUI/Tabs/Tabs.cs
+++ b/Source/Editor/GUI/Tabs/Tabs.cs
@@ -98,7 +98,7 @@ namespace FlaxEditor.GUI.Tabs
// Draw text
if (!string.IsNullOrEmpty(Tab.Text))
{
- Render2D.DrawText(style.FontMedium, Tab.Text, new Rectangle(tabRect.X + textOffset, tabRect.Y, tabRect.Width - textOffset, tabRect.Height), style.Foreground, Tabs.TabsTextHorizontalAlignment, Tabs.TabsTextVerticalAlignment);
+ FallbackTextUtils.DrawText(style.FontMedium, Tab.Text, new Rectangle(tabRect.X + textOffset, tabRect.Y, tabRect.Width - textOffset, tabRect.Height), style.Foreground, Tabs.TabsTextHorizontalAlignment, Tabs.TabsTextVerticalAlignment);
}
}
}
diff --git a/Source/Editor/GUI/Timeline/GUI/Background.cs b/Source/Editor/GUI/Timeline/GUI/Background.cs
index b9eff562a..05c1121c0 100644
--- a/Source/Editor/GUI/Timeline/GUI/Background.cs
+++ b/Source/Editor/GUI/Timeline/GUI/Background.cs
@@ -301,7 +301,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
default: throw new ArgumentOutOfRangeException();
}
var labelRect = new Rectangle(x + 2, -verticalLinesHeaderExtend * 0.8f + timeAxisHeaderOffset, 50, verticalLinesHeaderExtend);
- Render2D.DrawText(style.FontSmall, labelText, labelRect, labelColor, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.8f);
+ FallbackTextUtils.DrawText(style.FontSmall, labelText, labelRect, labelColor, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.8f);
}
}
}
diff --git a/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs b/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs
index 791fb7133..3f835a35f 100644
--- a/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs
+++ b/Source/Editor/GUI/Timeline/GUI/PositionHandle.cs
@@ -2,7 +2,6 @@
using System;
using System.Globalization;
-using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
diff --git a/Source/Editor/GUI/Timeline/Track.cs b/Source/Editor/GUI/Timeline/Track.cs
index f38917aa6..20be8f0c2 100644
--- a/Source/Editor/GUI/Timeline/Track.cs
+++ b/Source/Editor/GUI/Timeline/Track.cs
@@ -965,7 +965,7 @@ namespace FlaxEditor.GUI.Timeline
}
// Draw text
- Render2D.DrawText(style.FontSmall, Title ?? Name, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, Title ?? Name, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
// Disabled overlay
DrawDisabled = Mute || (ParentTrack != null && ParentTrack.DrawDisabled);
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index 50dce78b4..c4f4603e2 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -137,7 +136,7 @@ namespace FlaxEditor.GUI
if (!string.IsNullOrEmpty(_text))
{
textRect.Size.X = Width - DefaultMargin - textRect.Left;
- Render2D.DrawText(style.FontMedium, _text, textRect, enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _text, textRect, enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index 700ba6da1..6680e3608 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -657,7 +656,7 @@ namespace FlaxEditor.GUI.Tree
}
// Draw text
- Render2D.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
// Draw drag and drop effect
if (IsDragOver && _tree.DraggedOverNode == this)
diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs
index b13548016..dc376a0a2 100644
--- a/Source/Editor/Options/OptionsModule.cs
+++ b/Source/Editor/Options/OptionsModule.cs
@@ -224,7 +224,7 @@ namespace FlaxEditor.Options
}
}
- Render2D.Fallbacks = FallbackFonts.Create(Options.Interface.Fallbacks);
+ FallbackTextUtils.Fallbacks = FallbackFonts.Create(Options.Interface.Fallbacks);
}
///
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index f64e46385..eefd7f4dd 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -142,8 +142,8 @@ namespace FlaxEditor.SceneGraph.GUI
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(text, ranges[i].StartIndex);
- var end = font.GetCharPosition(text, ranges[i].EndIndex);
+ var start = FallbackTextUtils.GetCharPosition(font, text, ranges[i].StartIndex);
+ var end = FallbackTextUtils.GetCharPosition(font, text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
index 078b89c56..be9a96a7d 100644
--- a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
@@ -379,7 +379,7 @@ namespace FlaxEditor.Surface.Archetypes
}
// Name
- Render2D.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
}
///
@@ -1128,7 +1128,7 @@ namespace FlaxEditor.Surface.Archetypes
}
// Name
- Render2D.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// Close button
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey);
diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
index 5f3c0b0a2..b240685cc 100644
--- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs
+++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.CustomEditors.Dedicated;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Drag;
@@ -185,7 +184,7 @@ namespace FlaxEditor.Surface.Archetypes
if (!string.IsNullOrEmpty(_debugInfo))
{
var style = Style.Current;
- Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 4, _debugInfoSize), style.Foreground);
+ FallbackTextUtils.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 4, _debugInfoSize), style.Foreground);
}
// Debug relevancy outline
diff --git a/Source/Editor/Surface/Archetypes/ParticleModules.cs b/Source/Editor/Surface/Archetypes/ParticleModules.cs
index e5be3d35d..6082e212e 100644
--- a/Source/Editor/Surface/Archetypes/ParticleModules.cs
+++ b/Source/Editor/Surface/Archetypes/ParticleModules.cs
@@ -113,7 +113,7 @@ namespace FlaxEditor.Surface.Archetypes
var idx = (int)ModuleType;
var headerRect = new Rectangle(0, 0, Width, 16.0f);
//Render2D.FillRectangle(headerRect, Color.Red);
- Render2D.DrawText(style.FontMedium, Title, headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, Title, headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
DrawChildren();
diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs
index 40b38f7ce..bf7828960 100644
--- a/Source/Editor/Surface/Archetypes/Particles.cs
+++ b/Source/Editor/Surface/Archetypes/Particles.cs
@@ -154,7 +154,7 @@ namespace FlaxEditor.Surface.Archetypes
if (headerRect.Contains(mousePosition))
headerColor *= 1.07f;
Render2D.FillRectangle(headerRect, headerColor);
- Render2D.DrawText(style.FontLarge, Names[idx], headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, Names[idx], headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
DrawChildren();
}
@@ -194,7 +194,7 @@ namespace FlaxEditor.Surface.Archetypes
if (_headerRect.Contains(ref _mousePosition))
headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, headerColor);
- Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
DrawChildren();
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
index 5256b3cb7..930741807 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
@@ -141,7 +141,7 @@ namespace FlaxEditor.Surface.ContextMenu
};
// Title bar
- var titleFontReference = new FontReference(Style.Current.FontLarge);
+ var titleFontReference = new FontReference(Style.Current.FontLarge.Asset, 10);
var titleLabel = new Label
{
Width = Width * 0.5f - 8f,
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index 019be78b6..f4976be67 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -200,8 +200,8 @@ namespace FlaxEditor.Surface.ContextMenu
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
- var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
+ var start = FallbackTextUtils.GetCharPosition(font, _archetype.Title, ranges[i].StartIndex);
+ var end = FallbackTextUtils.GetCharPosition(font, _archetype.Title, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
if (ranges[i].StartIndex <= 0)
@@ -222,8 +222,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = font.GetCharPosition(_archetype.Title, 0);
- var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
+ var start = FallbackTextUtils.GetCharPosition(font, _archetype.Title, 0);
+ var end = FallbackTextUtils.GetCharPosition(font, _archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
_isFullMatch = true;
Visible = true;
@@ -237,8 +237,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = font.GetCharPosition(_archetype.Title, 0);
- var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
+ var start = FallbackTextUtils.GetCharPosition(font, _archetype.Title, 0);
+ var end = FallbackTextUtils.GetCharPosition(font, _archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
Visible = true;
@@ -283,19 +283,19 @@ namespace FlaxEditor.Surface.ContextMenu
}
// Draw name
- Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
if (_archetype.SubTitle != null)
{
var titleLength = FallbackTextUtils.MeasureText(style.FontSmall, _archetype.Title).X;
var subTitleRect = new Rectangle(textRect.X + titleLength, textRect.Y, textRect.Width - titleLength, textRect.Height);
- Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
// Reset transform and draw score mark
if (showScoreHit)
{
Render2D.PopTransform();
- Render2D.DrawText(style.FontSmall, "> ", textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, "> ", textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs
index 526d85d15..a5a99b932 100644
--- a/Source/Editor/Surface/Elements/InputBox.cs
+++ b/Source/Editor/Surface/Elements/InputBox.cs
@@ -1443,7 +1443,7 @@ namespace FlaxEditor.Surface.Elements
// Draw text
var style = Style.Current;
var rect = new Rectangle(Width + 4, 0, 1410, Height);
- Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
///
diff --git a/Source/Editor/Surface/Elements/OutputBox.cs b/Source/Editor/Surface/Elements/OutputBox.cs
index 497e2001a..5fb123700 100644
--- a/Source/Editor/Surface/Elements/OutputBox.cs
+++ b/Source/Editor/Surface/Elements/OutputBox.cs
@@ -189,7 +189,7 @@ namespace FlaxEditor.Surface.Elements
// Draw text
var style = Style.Current;
var rect = new Rectangle(-100, 0, 100 - 2, Height);
- Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Surface/Elements/TextView.cs b/Source/Editor/Surface/Elements/TextView.cs
index 284497396..c52667fe3 100644
--- a/Source/Editor/Surface/Elements/TextView.cs
+++ b/Source/Editor/Surface/Elements/TextView.cs
@@ -25,7 +25,7 @@ namespace FlaxEditor.Surface.Elements
var style = Style.Current;
var color = Enabled ? style.Foreground : style.ForegroundDisabled;
- Render2D.DrawText(style.FontSmall, Archetype.Text, new Rectangle(Float2.Zero, Size), color, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontSmall, Archetype.Text, new Rectangle(Float2.Zero, Size), color, TextAlignment.Near, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Surface/SurfaceComment.cs b/Source/Editor/Surface/SurfaceComment.cs
index aad45190e..26cc912ab 100644
--- a/Source/Editor/Surface/SurfaceComment.cs
+++ b/Source/Editor/Surface/SurfaceComment.cs
@@ -169,7 +169,7 @@ namespace FlaxEditor.Surface
// Header
Render2D.FillRectangle(_headerRect, headerColor);
- Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// Close button
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index 3c2381192..df706faa6 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.Scripting;
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
@@ -1028,7 +1027,7 @@ namespace FlaxEditor.Surface
if (_headerRect.Contains(ref _mousePosition))
headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, headerColor);
- Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// Close button
if ((Archetype.Flags & NodeFlags.NoCloseButton) == 0 && Surface.CanEdit)
diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs
index c2b1fbe68..d36c3b6ed 100644
--- a/Source/Editor/Tools/Foliage/FoliageTab.cs
+++ b/Source/Editor/Tools/Foliage/FoliageTab.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
diff --git a/Source/Editor/Tools/Terrain/CarveTab.cs b/Source/Editor/Tools/Terrain/CarveTab.cs
index 0a86aab6f..e64a364f0 100644
--- a/Source/Editor/Tools/Terrain/CarveTab.cs
+++ b/Source/Editor/Tools/Terrain/CarveTab.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index 0633d0ba9..515514131 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -1233,8 +1233,8 @@ namespace FlaxEditor.Viewport
color = Color.Yellow;
var text = string.Format("FPS: {0}", fps);
var font = Style.Current.FontMedium;
- Render2D.DrawText(font, text, new Rectangle(Float2.One, Size), Color.Black);
- Render2D.DrawText(font, text, new Rectangle(Float2.Zero, Size), color);
+ FallbackTextUtils.DrawText(font, text, new Rectangle(Float2.One, Size), Color.Black);
+ FallbackTextUtils.DrawText(font, text, new Rectangle(Float2.Zero, Size), color);
}
}
@@ -1814,7 +1814,7 @@ namespace FlaxEditor.Viewport
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
- Render2D.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Viewport/Previews/AnimationPreview.cs b/Source/Editor/Viewport/Previews/AnimationPreview.cs
index 1679a36bc..c4ada83c4 100644
--- a/Source/Editor/Viewport/Previews/AnimationPreview.cs
+++ b/Source/Editor/Viewport/Previews/AnimationPreview.cs
@@ -96,11 +96,11 @@ namespace FlaxEditor.Viewport.Previews
var skinnedModel = SkinnedModel;
if (skinnedModel == null)
{
- Render2D.DrawText(style.FontLarge, "Missing Base Model", new Rectangle(Float2.Zero, Size), Color.Red, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapWords);
+ FallbackTextUtils.DrawText(style.FontLarge, "Missing Base Model", new Rectangle(Float2.Zero, Size), Color.Red, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapWords);
}
else if (!skinnedModel.IsLoaded)
{
- Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Viewport/Previews/ModelPreview.cs b/Source/Editor/Viewport/Previews/ModelPreview.cs
index a6496aafe..b31776bf6 100644
--- a/Source/Editor/Viewport/Previews/ModelPreview.cs
+++ b/Source/Editor/Viewport/Previews/ModelPreview.cs
@@ -409,8 +409,8 @@ namespace FlaxEditor.Viewport.Previews
}
var font = Style.Current.FontMedium;
var pos = new Float2(10, 50);
- Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
- Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White);
+ FallbackTextUtils.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
+ FallbackTextUtils.DrawText(font, text, new Rectangle(pos, Size), Color.White);
}
}
diff --git a/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs b/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs
index c6ce5a7b5..a6eb721ce 100644
--- a/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs
+++ b/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs
@@ -254,7 +254,7 @@ namespace FlaxEditor.Viewport.Previews
if (_showParticlesCounter)
{
var count = _previewEffect.ParticlesCount;
- Render2D.DrawText(
+ FallbackTextUtils.DrawText(
Style.Current.FontSmall,
"Particles: " + count,
new Rectangle(Float2.Zero, Size),
diff --git a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs
index 8bcc506d9..6c02c019a 100644
--- a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs
+++ b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs
@@ -161,8 +161,8 @@ namespace FlaxEditor.Viewport.Previews
}
var font = Style.Current.FontMedium;
var pos = new Float2(10, 50);
- Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
- Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White);
+ FallbackTextUtils.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
+ FallbackTextUtils.DrawText(font, text, new Rectangle(pos, Size), Color.White);
}
}
diff --git a/Source/Editor/Viewport/Previews/TexturePreview.cs b/Source/Editor/Viewport/Previews/TexturePreview.cs
index ec10bb019..5e7594e9c 100644
--- a/Source/Editor/Viewport/Previews/TexturePreview.cs
+++ b/Source/Editor/Viewport/Previews/TexturePreview.cs
@@ -103,7 +103,7 @@ namespace FlaxEditor.Viewport.Previews
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
- Render2D.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
}
Render2D.PopClip();
diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
index 598f4ee32..43f990afb 100644
--- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
+++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
using FlaxEditor.GUI.ContextMenu;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -124,7 +123,7 @@ namespace FlaxEditor.Viewport.Widgets
}
// Draw text
- Render2D.DrawText(style.FontMedium, _text, textRect, style.ForegroundViewport * (IsMouseOver ? 1.0f : 0.9f), TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _text, textRect, style.ForegroundViewport * (IsMouseOver ? 1.0f : 0.9f), TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs
index 02aad16ec..8c38ed2a9 100644
--- a/Source/Editor/Windows/AboutDialog.cs
+++ b/Source/Editor/Windows/AboutDialog.cs
@@ -2,7 +2,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.GUI.Dialogs;
using FlaxEngine;
using FlaxEngine.GUI;
diff --git a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs
index 12eac22b5..eb4198fd8 100644
--- a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs
+++ b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs
@@ -51,7 +51,7 @@ namespace FlaxEditor.Windows.Assets
var style = Style.Current;
if (_window.Asset == null || !_window.Asset.IsLoaded)
{
- Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Windows/Assets/AnimationWindow.cs b/Source/Editor/Windows/Assets/AnimationWindow.cs
index 8f88d93f6..042cf2b37 100644
--- a/Source/Editor/Windows/Assets/AnimationWindow.cs
+++ b/Source/Editor/Windows/Assets/AnimationWindow.cs
@@ -61,7 +61,7 @@ namespace FlaxEditor.Windows.Assets
var animation = _window.Asset;
if (animation == null || !animation.IsLoaded)
{
- Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Windows/Assets/ModelWindow.cs b/Source/Editor/Windows/Assets/ModelWindow.cs
index c2764a5a6..d48966043 100644
--- a/Source/Editor/Windows/Assets/ModelWindow.cs
+++ b/Source/Editor/Windows/Assets/ModelWindow.cs
@@ -48,7 +48,7 @@ namespace FlaxEditor.Windows.Assets
var asset = _window.Asset;
if (asset == null || !asset.IsLoaded)
{
- Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
}
@@ -645,7 +645,7 @@ namespace FlaxEditor.Windows.Assets
if (!Proxy.Window._meshData.RequestMeshData(Proxy.Window._asset))
{
Invalidate();
- Render2D.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
return;
}
diff --git a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
index 95827240c..1e7192d9f 100644
--- a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
+++ b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
@@ -50,7 +50,7 @@ namespace FlaxEditor.Windows.Assets
var asset = _window.Asset;
if (asset == null || !asset.IsLoaded)
{
- Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
}
@@ -715,7 +715,7 @@ namespace FlaxEditor.Windows.Assets
if (!Proxy.Window.RequestMeshData())
{
Invalidate();
- Render2D.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
return;
}
diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs
index a1072d158..67b7deddd 100644
--- a/Source/Editor/Windows/ContentWindow.Search.cs
+++ b/Source/Editor/Windows/ContentWindow.Search.cs
@@ -57,7 +57,7 @@ namespace FlaxEditor.Windows
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ FallbackTextUtils.DrawText(Font.GetFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
// Arrow
diff --git a/Source/Editor/Windows/DebugLogWindow.cs b/Source/Editor/Windows/DebugLogWindow.cs
index ab0c07ec5..91d4f9d8c 100644
--- a/Source/Editor/Windows/DebugLogWindow.cs
+++ b/Source/Editor/Windows/DebugLogWindow.cs
@@ -140,11 +140,11 @@ namespace FlaxEditor.Windows
Render2D.PushClip(ref clientRect);
if (LogCount == 1)
{
- Render2D.DrawText(style.FontMedium, Desc.Title, textRect, style.Foreground);
+ FallbackTextUtils.DrawText(style.FontMedium, Desc.Title, textRect, style.Foreground);
}
else if (LogCount > 1)
{
- Render2D.DrawText(style.FontMedium, $"{Desc.Title} ({LogCount})", textRect, style.Foreground);
+ FallbackTextUtils.DrawText(style.FontMedium, $"{Desc.Title} ({LogCount})", textRect, style.Foreground);
}
Render2D.PopClip();
}
diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs
index 4a8c11176..2c0364995 100644
--- a/Source/Editor/Windows/GameWindow.cs
+++ b/Source/Editor/Windows/GameWindow.cs
@@ -827,7 +827,7 @@ namespace FlaxEditor.Windows
if (Camera.MainCamera == null)
{
var style = Style.Current;
- Render2D.DrawText(style.FontLarge, "No camera", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontLarge, "No camera", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
// Selected UI controls outline
@@ -866,8 +866,8 @@ namespace FlaxEditor.Windows
var alpha = Mathf.Saturate(-animTime / fadeOutTime);
var rect = new Rectangle(new Float2(6), Size - 12);
var text = "Press Shift+F11 to unlock the mouse";
- Render2D.DrawText(style.FontSmall, text, rect + new Float2(1.0f), style.Background * alpha, TextAlignment.Near, TextAlignment.Far);
- Render2D.DrawText(style.FontSmall, text, rect, style.Foreground * alpha, TextAlignment.Near, TextAlignment.Far);
+ FallbackTextUtils.DrawText(style.FontSmall, text, rect + new Float2(1.0f), style.Background * alpha, TextAlignment.Near, TextAlignment.Far);
+ FallbackTextUtils.DrawText(style.FontSmall, text, rect, style.Foreground * alpha, TextAlignment.Near, TextAlignment.Far);
}
timeout = 1.0f;
@@ -884,7 +884,7 @@ namespace FlaxEditor.Windows
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
- Render2D.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Windows/Profiler/SingleChart.cs b/Source/Editor/Windows/Profiler/SingleChart.cs
index 4f36692e5..25241b4c6 100644
--- a/Source/Editor/Windows/Profiler/SingleChart.cs
+++ b/Source/Editor/Windows/Profiler/SingleChart.cs
@@ -138,8 +138,8 @@ namespace FlaxEditor.Windows.Profiler
var headerRect = new Rectangle(0, chartHeight, Width, TitleHeight);
var headerTextRect = new Rectangle(2, chartHeight, Width - 4, TitleHeight);
Render2D.FillRectangle(headerRect, style.BackgroundNormal);
- Render2D.DrawText(style.FontMedium, Title, headerTextRect, style.ForegroundGrey, TextAlignment.Near, TextAlignment.Center);
- Render2D.DrawText(style.FontMedium, _sample, headerTextRect, style.Foreground, TextAlignment.Far, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, Title, headerTextRect, style.ForegroundGrey, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _sample, headerTextRect, style.Foreground, TextAlignment.Far, TextAlignment.Center);
}
private void OnClick(ref Float2 location)
diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs
index 780b31a3b..f87efdace 100644
--- a/Source/Editor/Windows/Profiler/Timeline.cs
+++ b/Source/Editor/Windows/Profiler/Timeline.cs
@@ -2,7 +2,6 @@
using FlaxEngine;
using FlaxEngine.GUI;
-using System.Linq;
namespace FlaxEditor.Windows.Profiler
{
@@ -91,7 +90,7 @@ namespace FlaxEditor.Windows.Profiler
if (_nameLength < bounds.Width + 4)
{
Render2D.PushClip(bounds);
- Render2D.DrawText(style.FontMedium, _name, bounds, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(style.FontMedium, _name, bounds, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center);
Render2D.PopClip();
}
}
@@ -116,7 +115,7 @@ namespace FlaxEditor.Windows.Profiler
var style = Style.Current;
var rect = new Rectangle(Float2.Zero, Size);
Render2D.PushClip(rect);
- Render2D.DrawText(style.FontMedium, Name, rect, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapChars);
+ FallbackTextUtils.DrawText(style.FontMedium, Name, rect, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapChars);
Render2D.PopClip();
}
}
diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs
index 63ba7b960..2fd990861 100644
--- a/Source/Editor/Windows/SceneTreeWindow.cs
+++ b/Source/Editor/Windows/SceneTreeWindow.cs
@@ -297,7 +297,7 @@ namespace FlaxEditor.Windows
}
if (overlayText != null)
{
- Render2D.DrawText(style.FontLarge, overlayText, GetClientArea(), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center, textWrap);
+ FallbackTextUtils.DrawText(style.FontLarge, overlayText, GetClientArea(), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center, textWrap);
}
base.Draw();
diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs
index 16b9165e1..f86341df3 100644
--- a/Source/Editor/Windows/ToolboxWindow.cs
+++ b/Source/Editor/Windows/ToolboxWindow.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.GUI.Input;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.GUI.Tree;
@@ -273,8 +272,8 @@ namespace FlaxEditor.Windows
var textRect = item.TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = font.GetCharPosition(text, ranges[i].StartIndex);
- var end = font.GetCharPosition(text, ranges[i].EndIndex);
+ var start = FallbackTextUtils.GetCharPosition(font, text, ranges[i].StartIndex);
+ var end = FallbackTextUtils.GetCharPosition(font, text, ranges[i].EndIndex);
highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
item.SetHighlights(highlights);
diff --git a/Source/Engine/Render2D/FallbackTextUtils.cs b/Source/Engine/Render2D/FallbackTextUtils.cs
index eb676f0a9..b6d8770e2 100644
--- a/Source/Engine/Render2D/FallbackTextUtils.cs
+++ b/Source/Engine/Render2D/FallbackTextUtils.cs
@@ -1,4 +1,6 @@
+using System.Runtime.CompilerServices;
+
namespace FlaxEngine
{
///
@@ -11,41 +13,10 @@ namespace FlaxEngine
get; set;
} = null;
- public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void DrawText(Font font, string text, Color color, ref TextLayoutOptions layout, MaterialBase customMaterial = null, bool useFallback = true)
{
- var layout = new TextLayoutOptions
- {
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
- if (Fallbacks != null)
- {
- Render2D.DrawText(font, Fallbacks, text, color, ref layout);
- }
- else
- {
- Render2D.DrawText(font, text, color, ref layout);
- }
- }
-
- public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f)
- {
- var layout = new TextLayoutOptions
- {
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
- if (Fallbacks != null)
+ if (Fallbacks != null && useFallback)
{
Render2D.DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
}
@@ -55,9 +26,56 @@ namespace FlaxEngine
}
}
- public static Float2 MeasureText(Font font, string text)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
{
- if (Fallbacks != null)
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+
+ if (Fallbacks != null && useFallback)
+ {
+ Render2D.DrawText(font, Fallbacks, text, color, ref layout);
+ }
+ else
+ {
+ Render2D.DrawText(font, text, color, ref layout);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = layoutRect,
+ HorizontalAlignment = horizontalAlignment,
+ VerticalAlignment = verticalAlignment,
+ TextWrapping = textWrapping,
+ Scale = scale,
+ BaseLinesGapScale = baseLinesGapScale,
+ };
+
+ if (Fallbacks != null && useFallback)
+ {
+ Render2D.DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
+ }
+ else
+ {
+ Render2D.DrawText(font, text, color, ref layout, customMaterial);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 MeasureText(Font font, string text, bool useFallback = true)
+ {
+ if (Fallbacks != null && useFallback)
{
return font.MeasureText(Fallbacks, text);
}
@@ -67,9 +85,10 @@ namespace FlaxEngine
}
}
- public static Float2 MeasureText(Font font, string text, ref TextRange textRange)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 MeasureText(Font font, string text, ref TextRange textRange, bool useFallback = true)
{
- if (Fallbacks != null)
+ if (Fallbacks != null && useFallback)
{
return font.MeasureText(Fallbacks, text, ref textRange);
}
@@ -79,9 +98,10 @@ namespace FlaxEngine
}
}
- public static Float2 MeasureText(Font font, string text, ref TextLayoutOptions layout)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 MeasureText(Font font, string text, ref TextLayoutOptions layout, bool useFallback = true)
{
- if (Fallbacks != null)
+ if (Fallbacks != null && useFallback)
{
return font.MeasureText(Fallbacks, text, ref layout);
}
@@ -91,9 +111,10 @@ namespace FlaxEngine
}
}
- public static Float2 MeasureText(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 MeasureText(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout, bool useFallback = true)
{
- if (Fallbacks != null)
+ if (Fallbacks != null && useFallback)
{
return font.MeasureText(Fallbacks, text, ref textRange, ref layout);
}
@@ -103,24 +124,108 @@ namespace FlaxEngine
}
}
- public static Float2 GetCharPosition(Font font, string text, int index)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int HitTestText(Font font, string text, Float2 location, bool useFallback = true)
{
- return font.GetCharPosition(Style.Current.Fallbacks, text, index);
+ if (Fallbacks != null && useFallback)
+ {
+ return font.HitTestText(Fallbacks, text, location);
+ }
+ else
+ {
+ return font.HitTestText(text, location);
+ }
}
- public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int HitTestText(Font font, string text, ref TextRange textRange, Float2 location, bool useFallback = true)
{
- return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index);
+ if (Fallbacks != null && useFallback)
+ {
+ return font.HitTestText(Fallbacks, text, ref textRange, location);
+ }
+ else
+ {
+ return font.HitTestText(text, ref textRange, location);
+ }
}
- public static Float2 GetCharPosition(Font font, string text, int index, ref TextLayoutOptions layout)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int HitTestText(Font font, string text, Float2 location, ref TextLayoutOptions layout, bool useFallback = true)
{
- return font.GetCharPosition(Style.Current.Fallbacks, text, index, ref layout);
+ if (Fallbacks != null && useFallback)
+ {
+ return font.HitTestText(Fallbacks, text, location, ref layout);
+ }
+ else
+ {
+ return font.HitTestText(text, location, ref layout);
+ }
}
- public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index, ref TextLayoutOptions layout)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int HitTestText(Font font, string text, ref TextRange textRange, Float2 location, ref TextLayoutOptions layout, bool useFallback = true)
{
- return font.GetCharPosition(Style.Current.Fallbacks, text, ref textRange, index, ref layout);
+ if (Fallbacks != null && useFallback)
+ {
+ return font.HitTestText(Fallbacks, text, ref textRange, location, ref layout);
+ }
+ else
+ {
+ return font.HitTestText(text, ref textRange, location, ref layout);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 GetCharPosition(Font font, string text, int index, bool useFallback = true)
+ {
+ if (Fallbacks != null && useFallback)
+ {
+ return font.GetCharPosition(Fallbacks, text, index);
+ }
+ else
+ {
+ return font.GetCharPosition(text, index);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index, bool useFallback = true)
+ {
+ if (Fallbacks != null && useFallback)
+ {
+ return font.GetCharPosition(Fallbacks, text, ref textRange, index);
+ }
+ else
+ {
+ return font.GetCharPosition(text, ref textRange, index);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 GetCharPosition(Font font, string text, int index, ref TextLayoutOptions layout, bool useFallback = true)
+ {
+ if (Fallbacks != null && useFallback)
+ {
+ return font.GetCharPosition(Fallbacks, text, index, ref layout);
+ }
+ else
+ {
+ return font.GetCharPosition(text, index, ref layout);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index, ref TextLayoutOptions layout, bool useFallback = true)
+ {
+ if (Fallbacks != null && useFallback)
+ {
+ return font.GetCharPosition(Fallbacks, text, ref textRange, index, ref layout);
+ }
+ else
+ {
+ return font.GetCharPosition(text, ref textRange, index, ref layout);
+ }
}
}
}
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index 756501c5e..feb34418b 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
namespace FlaxEngine.GUI
{
@@ -262,7 +261,7 @@ namespace FlaxEngine.GUI
Render2D.DrawRectangle(clientRect, borderColor, BorderThickness);
// Draw text
- Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
+ FallbackTextUtils.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index 46f05f516..3b298b136 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
namespace FlaxEngine.GUI
{
@@ -674,7 +673,7 @@ namespace FlaxEngine.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- Render2D.DrawText(Font.GetFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(Font.GetFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index 4e26c1934..3d1caad28 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -1,8 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
-using FlaxEditor.Options;
using System.ComponentModel;
-using System.Linq;
namespace FlaxEngine.GUI
{
@@ -235,7 +233,7 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ FallbackTextUtils.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
Render2D.PopClip();
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
index d3c2feefe..df8e0be7c 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using FlaxEngine.Utilities;
-using System.Linq;
namespace FlaxEngine.GUI
{
diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.cs b/Source/Engine/UI/GUI/Common/RichTextBox.cs
index 514878b37..ab922d93d 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBox.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBox.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
-using System.Linq;
namespace FlaxEngine.GUI
{
diff --git a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
index 438a7e3d8..a30d8e603 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
@@ -154,7 +154,7 @@ namespace FlaxEngine.GUI
if (!font)
break;
height = font.Height / DpiScale;
- return textBlock.Bounds.Location + font.GetCharPosition(_text, ref textBlock.Range, index - textBlock.Range.StartIndex);
+ return textBlock.Bounds.Location + FallbackTextUtils.GetCharPosition(font, _text, ref textBlock.Range, index - textBlock.Range.StartIndex);
}
}
@@ -196,7 +196,7 @@ namespace FlaxEngine.GUI
var font = textBlock.Style.Font.GetFont();
if (!font && textBlock.Range.Length > 0)
break;
- return font.HitTestText(_text, ref textBlock.Range, location - textBlock.Bounds.Location) + textBlock.Range.StartIndex;
+ return FallbackTextUtils.HitTestText(font, _text, ref textBlock.Range, location - textBlock.Bounds.Location) + textBlock.Range.StartIndex;
}
}
@@ -288,8 +288,8 @@ namespace FlaxEngine.GUI
// Selection
if (hasSelection && textBlock.Style.BackgroundSelectedBrush != null && textBlock.Range.Intersect(ref selection))
{
- var leftEdge = selection.StartIndex <= textBlock.Range.StartIndex ? textBlock.Bounds.UpperLeft : font.GetCharPosition(_text, selection.StartIndex);
- var rightEdge = selection.EndIndex >= textBlock.Range.EndIndex ? textBlock.Bounds.UpperRight : font.GetCharPosition(_text, selection.EndIndex);
+ var leftEdge = selection.StartIndex <= textBlock.Range.StartIndex ? textBlock.Bounds.UpperLeft : FallbackTextUtils.GetCharPosition(font, _text, selection.StartIndex);
+ var rightEdge = selection.EndIndex >= textBlock.Range.EndIndex ? textBlock.Bounds.UpperRight : FallbackTextUtils.GetCharPosition(font, _text, selection.EndIndex);
float height = font.Height / DpiScale;
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
alpha *= alpha;
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index ea7523f48..70a153faf 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -1,7 +1,5 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
-using System.Drawing;
-using System.Linq;
namespace FlaxEngine.GUI
{
@@ -120,7 +118,7 @@ namespace FlaxEngine.GUI
}
height = font.Height / DpiScale;
- return font.GetCharPosition(_text, index, ref _layout);
+ return FallbackTextUtils.GetCharPosition(font, _text, index, ref _layout);
}
///
@@ -132,7 +130,7 @@ namespace FlaxEngine.GUI
return 0;
}
- return font.HitTestText(_text, location, ref _layout);
+ return FallbackTextUtils.HitTestText(font, _text, location, ref _layout);
}
///
@@ -171,8 +169,8 @@ namespace FlaxEngine.GUI
// Check if sth is selected to draw selection
if (HasSelection)
{
- var leftEdge = font.GetCharPosition(_text, SelectionLeft, ref _layout);
- var rightEdge = font.GetCharPosition(_text, SelectionRight, ref _layout);
+ var leftEdge = FallbackTextUtils.GetCharPosition(font, _text, SelectionLeft, ref _layout);
+ var rightEdge = FallbackTextUtils.GetCharPosition(font, _text, SelectionRight, ref _layout);
float fontHeight = font.Height / DpiScale;
// Draw selection background
@@ -213,25 +211,11 @@ namespace FlaxEngine.GUI
var color = TextColor;
if (!enabled)
color *= 0.6f;
- if (Render2D.Fallbacks != null)
- {
- Render2D.DrawText(font, Render2D.Fallbacks, _text, color, ref _layout, TextMaterial);
- }
- else
- {
- Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
- }
+ FallbackTextUtils.DrawText(font, _text, color, ref _layout, TextMaterial);
}
else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
{
- if (Render2D.Fallbacks != null)
- {
- Render2D.DrawText(font, Render2D.Fallbacks, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
- }
- else
- {
- Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
- }
+ FallbackTextUtils.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
}
// Caret
diff --git a/Source/Engine/UI/GUI/Panels/DropPanel.cs b/Source/Engine/UI/GUI/Panels/DropPanel.cs
index ed620ab98..123e0f034 100644
--- a/Source/Engine/UI/GUI/Panels/DropPanel.cs
+++ b/Source/Engine/UI/GUI/Panels/DropPanel.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
namespace FlaxEngine.GUI
{
@@ -375,7 +374,7 @@ namespace FlaxEngine.GUI
textColor *= 0.6f;
}
- Render2D.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ FallbackTextUtils.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!_isClosed && EnableContainmentLines)
{
diff --git a/Source/Engine/UI/GUI/Style.cs b/Source/Engine/UI/GUI/Style.cs
index c4b51b085..f4fca13eb 100644
--- a/Source/Engine/UI/GUI/Style.cs
+++ b/Source/Engine/UI/GUI/Style.cs
@@ -1,6 +1,5 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
-using System.Linq;
namespace FlaxEngine.GUI
{
diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs
index 7a1026e55..41d06b017 100644
--- a/Source/Engine/UI/GUI/Tooltip.cs
+++ b/Source/Engine/UI/GUI/Tooltip.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
-using System.Linq;
namespace FlaxEngine.GUI
{
@@ -235,7 +234,7 @@ namespace FlaxEngine.GUI
Render2D.FillRectangle(new Rectangle(1.1f, 1.1f, Width - 2, Height - 2), style.Background);
// Tooltip text
- Render2D.DrawText(
+ FallbackTextUtils.DrawText(
style.FontMedium,
_currentText,
GetClientArea(),
From 3c5035d3e93540fa718ca97accd5ce94e7afa7a4 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Fri, 1 Dec 2023 18:06:25 +0800
Subject: [PATCH 09/16] Fix merge problem
---
Source/Editor/Windows/PluginsWindow.cs | 55 +++++++++++++++++++++-----
1 file changed, 45 insertions(+), 10 deletions(-)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index 03beab2fa..f43fb0342 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -14,7 +14,6 @@ using FlaxEditor.GUI.Tabs;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
-using FlaxEngine.Utilities;
namespace FlaxEditor.Windows
{
@@ -122,7 +121,7 @@ namespace FlaxEditor.Windows
url = desc.RepositoryUrl;
versionLabel.Font.Font.WaitForLoaded();
var font = versionLabel.Font.GetFont();
- var authorWidth = FallbackTextUtils.MeasureText(font, desc.Author).X + 8;
+ var authorWidth = font.MeasureText(desc.Author).X + 8;
var authorLabel = new ClickableLabel
{
HorizontalAlignment = TextAlignment.Far,
@@ -392,6 +391,7 @@ namespace FlaxEditor.Windows
}
Editor.Log("Plugin project has been cloned.");
+
try
{
// Start git submodule clone
@@ -412,24 +412,28 @@ namespace FlaxEditor.Windows
}
// Find project config file. Could be different then what the user named the folder.
- var files = Directory.GetFiles(clonePath);
string pluginProjectName = "";
- foreach (var file in files)
+ foreach (var file in Directory.GetFiles(clonePath))
{
if (file.Contains(".flaxproj", StringComparison.OrdinalIgnoreCase))
{
pluginProjectName = Path.GetFileNameWithoutExtension(file);
- Debug.Log(pluginProjectName);
+ break;
}
}
-
if (string.IsNullOrEmpty(pluginProjectName))
- Editor.LogError("Failed to find plugin project file to add to Project config. Please add manually.");
- else
{
- await AddReferenceToProject(pluginName, pluginProjectName);
- MessageBox.Show($"{pluginName} has been successfully cloned. Restart editor for changes to take effect.", "Plugin Project Created", MessageBoxButtons.OK);
+ Editor.LogError("Failed to find plugin project file to add to Project config. Please add manually.");
+ return;
}
+
+ await AddModuleReferencesInGameModule(clonePath);
+ await AddReferenceToProject(pluginName, pluginProjectName);
+
+ if (Editor.Options.Options.SourceCode.AutoGenerateScriptsProjectFiles)
+ Editor.ProgressReporting.GenerateScriptsProjectFiles.RunAsync();
+
+ MessageBox.Show($"{pluginName} has been successfully cloned. Restart editor for changes to take effect.", "Plugin Project Created", MessageBoxButtons.OK);
}
private void OnAddButtonClicked()
@@ -749,6 +753,37 @@ namespace FlaxEditor.Windows
MessageBox.Show($"{pluginName} has been successfully created. Restart editor for changes to take effect.", "Plugin Project Created", MessageBoxButtons.OK);
}
+ private async Task AddModuleReferencesInGameModule(string pluginFolderPath)
+ {
+ // Common game build script location
+ var gameScript = Path.Combine(Globals.ProjectFolder, "Source/Game/Game.Build.cs");
+ if (File.Exists(gameScript))
+ {
+ var gameScriptContents = await File.ReadAllTextAsync(gameScript);
+ var insertLocation = gameScriptContents.IndexOf("base.Setup(options);", StringComparison.Ordinal);
+ if (insertLocation != -1)
+ {
+ insertLocation += 20;
+ var modifiedAny = false;
+
+ // Find all code modules in a plugin to auto-reference them in game build script
+ foreach (var subDir in Directory.GetDirectories(Path.Combine(pluginFolderPath, "Source")))
+ {
+ var pluginModuleName = Path.GetFileName(subDir);
+ var pluginModuleScriptPath = Path.Combine(subDir, pluginModuleName + ".Build.cs");
+ if (File.Exists(pluginModuleScriptPath))
+ {
+ gameScriptContents = gameScriptContents.Insert(insertLocation, $"\n options.PublicDependencies.Add(\"{pluginModuleName}\");");
+ modifiedAny = true;
+ }
+ }
+
+ if (modifiedAny)
+ await File.WriteAllTextAsync(gameScript, gameScriptContents, Encoding.UTF8);
+ }
+ }
+ }
+
private async Task AddReferenceToProject(string pluginFolderName, string pluginName)
{
// Project flax config file
From 95f5e31e4852ab6e2a25177f3f587ba0840b03a4 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Fri, 1 Dec 2023 19:38:15 +0800
Subject: [PATCH 10/16] Fix textbox height
Fix build error under non-windows platforms
---
Source/Editor/GUI/Row.cs | 5 ++-
Source/Engine/Render2D/FallbackFonts.h | 35 +++++++++++++++---
Source/Engine/Render2D/FallbackTextUtils.cs | 37 +++++++++++++++++++
Source/Engine/Render2D/Font.h | 7 ++--
Source/Engine/Render2D/FontAsset.cpp | 7 ++++
Source/Engine/Render2D/FontAsset.h | 2 +-
.../Engine/UI/GUI/Common/RichTextBoxBase.cs | 1 +
Source/Engine/UI/GUI/Common/TextBox.cs | 4 +-
8 files changed, 85 insertions(+), 13 deletions(-)
diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs
index c7be48626..9868ab456 100644
--- a/Source/Editor/GUI/Row.cs
+++ b/Source/Editor/GUI/Row.cs
@@ -38,8 +38,9 @@ namespace FlaxEditor.GUI
{
Depth = -1;
- if (Height < Style.Current.FontMedium.Height)
- Height = Style.Current.FontMedium.Height + 4;
+ var mediumHeight = FallbackTextUtils.GetMaxHeight(Style.Current.FontMedium);
+ if (Height < mediumHeight)
+ Height = mediumHeight + 4;
}
///
diff --git a/Source/Engine/Render2D/FallbackFonts.h b/Source/Engine/Render2D/FallbackFonts.h
index 5861354fc..040ca8087 100644
--- a/Source/Engine/Render2D/FallbackFonts.h
+++ b/Source/Engine/Render2D/FallbackFonts.h
@@ -9,36 +9,55 @@ struct TextRange;
class Font;
class FontAsset;
+///
+/// Defines a list of fonts that can be used as a fallback, ordered by priority.
+///
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FallbackFonts : public ManagedScriptingObject
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(FallbackFonts);
private:
- ///
- /// The list of fallback fonts, ordered by priority.
- /// The first element is reserved for the primary font, fallback fonts starts from the second element.
- ///
Array _fontAssets;
+ // Cache fallback fonts of various sizes
Dictionary*> _cache;
public:
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The fallback font assets.
FallbackFonts(const Array& fonts);
+ ///
+ /// Initializes a new instance of the class, exposed for C#.
+ ///
+ /// The fallback font assets.
+ /// The new instance.
API_FUNCTION() FORCE_INLINE static FallbackFonts* Create(const Array& fonts) {
return New(fonts);
}
+ ///
+ /// Get the parent assets of fallback fonts.
+ ///
+ /// The font assets.
API_PROPERTY() FORCE_INLINE Array& GetFonts() {
return _fontAssets;
}
+ ///
+ /// Set the fallback fonts.
+ ///
+ /// The parent assets of the new fonts.
API_PROPERTY() FORCE_INLINE void SetFonts(const Array& val) {
_fontAssets = val;
}
///
- /// Combine the primary fonts with the fallback fonts to get a font list
+ /// Gets the fallback fonts with the given size.
///
+ /// The size.
+ /// The generated fonts.
API_FUNCTION() FORCE_INLINE Array& GetFontList(float size) {
Array* result;
if (_cache.TryGet(size, result)) {
@@ -61,6 +80,8 @@ public:
/// Gets the index of the fallback font that should be used to render the char
///
/// The char.
+ /// The primary font.
+ /// The number to return if none of the fonts can render.
/// -1 if char can be rendered with primary font, index if it matches a fallback font.
API_FUNCTION() FORCE_INLINE int32 GetCharFallbackIndex(Char c, Font* primaryFont = nullptr, int32 missing = -1) {
if (primaryFont && primaryFont->GetAsset()->ContainsChar(c)) {
@@ -81,6 +102,10 @@ public:
return missing;
}
+ ///
+ /// Checks if every font is properly loaded.
+ ///
+ /// True if every font asset is non-null, otherwise false.
API_FUNCTION() FORCE_INLINE bool Verify() {
for (int32 i = 0; i < _fontAssets.Count(); i++)
{
diff --git a/Source/Engine/Render2D/FallbackTextUtils.cs b/Source/Engine/Render2D/FallbackTextUtils.cs
index b6d8770e2..486a354bf 100644
--- a/Source/Engine/Render2D/FallbackTextUtils.cs
+++ b/Source/Engine/Render2D/FallbackTextUtils.cs
@@ -227,5 +227,42 @@ namespace FlaxEngine
return font.GetCharPosition(text, ref textRange, index, ref layout);
}
}
+
+ ///
+ /// Gets the max font height among the font and all fallback fonts of the same size.
+ ///
+ /// The primary font to use.
+ /// The fallback fonts.
+ /// The max height.
+ public static float GetMaxHeight(Font font, FallbackFonts fallbacks)
+ {
+ float height = font.Height;
+
+ var fallbackFonts = fallbacks.GetFontList(font.Size);
+ foreach (var item in fallbackFonts)
+ {
+ height = Mathf.Max(height, item.Height);
+ }
+
+ return height;
+ }
+
+ ///
+ /// Gets the max font height among the font and all fallback fonts of the same size.
+ ///
+ /// The primary font to use.
+ /// Whether to enable fallback fonts, uses if true.
+ /// The max height.
+ public static float GetMaxHeight(Font font, bool useFallback = true)
+ {
+ if(Fallbacks != null && useFallback)
+ {
+ return GetMaxHeight(font, Fallbacks);
+ }
+ else
+ {
+ return font.Height;
+ }
+ }
}
}
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index d932888fb..110a8fe70 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -122,7 +122,8 @@ struct TIsPODType
};
///
-/// The font block info generated during text processing.
+/// The font block info generated during text processing.
+/// A block means a range of text that belongs to the same line and can be rendered with the same font.
///
API_STRUCT(NoDefault) struct FontBlockCache
{
@@ -134,7 +135,7 @@ API_STRUCT(NoDefault) struct FontBlockCache
API_FIELD() Float2 Location;
///
- /// The height of the current block
+ /// The size of the current block
///
API_FIELD() Float2 Size;
@@ -183,7 +184,7 @@ API_STRUCT(NoDefault) struct BlockedTextLineCache
API_FIELD() float MaxAscender;
///
- /// The index of the font to render with
+ /// The blocks that belongs to this line
///
API_FIELD() Array Blocks;
};
diff --git a/Source/Engine/Render2D/FontAsset.cpp b/Source/Engine/Render2D/FontAsset.cpp
index 1e94b19b1..ea629367f 100644
--- a/Source/Engine/Render2D/FontAsset.cpp
+++ b/Source/Engine/Render2D/FontAsset.cpp
@@ -199,6 +199,13 @@ bool FontAsset::Save(const StringView& path)
#endif
+
+///
+/// Check if the font contains the glyph of a char
+///
+/// The char to test.
+/// True if the font contains the glyph of the char, otherwise false.
+
bool FontAsset::ContainsChar(Char c) const {
return FT_Get_Char_Index(GetFTFace(), c) > 0;
}
diff --git a/Source/Engine/Render2D/FontAsset.h b/Source/Engine/Render2D/FontAsset.h
index a773a8ad6..f3c909911 100644
--- a/Source/Engine/Render2D/FontAsset.h
+++ b/Source/Engine/Render2D/FontAsset.h
@@ -179,7 +179,7 @@ public:
///
/// The char to test.
/// True if the font contains the glyph of the char, otherwise false.
- API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c) const;
+ API_FUNCTION() bool ContainsChar(Char c) const;
///
/// Invalidates all cached dynamic font atlases using this font. Can be used to reload font characters after changing font asset options.
diff --git a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
index a30d8e603..8d7858af0 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
@@ -316,6 +316,7 @@ namespace FlaxEngine.GUI
color = textBlock.Style.ShadowColor;
if (!enabled)
color *= 0.6f;
+ // We don't need font fallbacks for rich text since the font is user-selected
Render2D.DrawText(font, _text, ref textBlock.Range, color, textBlock.Bounds.Location + textBlock.Style.ShadowOffset, textBlock.Style.CustomMaterial);
}
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index 70a153faf..b1861df56 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -117,7 +117,7 @@ namespace FlaxEngine.GUI
return Float2.Zero;
}
- height = font.Height / DpiScale;
+ height = FallbackTextUtils.GetMaxHeight(font) / DpiScale;
return FallbackTextUtils.GetCharPosition(font, _text, index, ref _layout);
}
@@ -171,7 +171,7 @@ namespace FlaxEngine.GUI
{
var leftEdge = FallbackTextUtils.GetCharPosition(font, _text, SelectionLeft, ref _layout);
var rightEdge = FallbackTextUtils.GetCharPosition(font, _text, SelectionRight, ref _layout);
- float fontHeight = font.Height / DpiScale;
+ float fontHeight = FallbackTextUtils.GetMaxHeight(font) / DpiScale;
// Draw selection background
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
From 29eb3954c5bc0da8c7ce0b2e997cc797c2b1754c Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Sat, 2 Dec 2023 17:48:51 +0800
Subject: [PATCH 11/16] Create global settings for font fallback
---
Source/Editor/Windows/SplashScreen.cpp | 6 +-
Source/Engine/Core/Config/GameSettings.cs | 2 +-
Source/Engine/Core/Config/GameSettings.h | 11 +++
.../Platform/Win32/IncludeWindowsHeaders.h | 2 +-
Source/Engine/Render2D/FallbackFonts.cpp | 2 +-
Source/Engine/Render2D/FallbackFonts.h | 14 ++--
Source/Engine/Render2D/Font.cpp | 8 +-
Source/Engine/Render2D/Font.h | 36 ++++-----
Source/Engine/Render2D/Render2D.cpp | 24 +++---
Source/Engine/Render2D/Render2D.h | 81 +++++++++++++++----
10 files changed, 122 insertions(+), 64 deletions(-)
diff --git a/Source/Editor/Windows/SplashScreen.cpp b/Source/Editor/Windows/SplashScreen.cpp
index 92894b537..cbb51ae3c 100644
--- a/Source/Editor/Windows/SplashScreen.cpp
+++ b/Source/Editor/Windows/SplashScreen.cpp
@@ -264,7 +264,7 @@ void SplashScreen::OnDraw()
layout.HorizontalAlignment = TextAlignment::Near;
layout.VerticalAlignment = TextAlignment::Near;
layout.Scale = Math::Min((width - 20 * s) / titleLength.X, 1.0f);
- Render2D::DrawText(_titleFont, GetTitle(), Color::White, layout);
+ Render2D::DrawTextInternal(_titleFont, GetTitle(), Color::White, layout);
// Subtitle
String subtitle(_quote);
@@ -279,14 +279,14 @@ void SplashScreen::OnDraw()
layout.Scale = 1.0f;
layout.HorizontalAlignment = TextAlignment::Far;
layout.VerticalAlignment = TextAlignment::Far;
- Render2D::DrawText(_subtitleFont, subtitle, Color::FromRGB(0x8C8C8C), layout);
+ Render2D::DrawTextInternal(_subtitleFont, subtitle, Color::FromRGB(0x8C8C8C), layout);
// Additional info
const float infoMargin = 6 * s;
layout.Bounds = Rectangle(infoMargin, lightBarHeight + infoMargin, width - (2 * infoMargin), height - lightBarHeight - (2 * infoMargin));
layout.HorizontalAlignment = TextAlignment::Near;
layout.VerticalAlignment = TextAlignment::Center;
- Render2D::DrawText(_subtitleFont, _infoText, Color::FromRGB(0xFFFFFF) * 0.9f, layout);
+ Render2D::DrawTextInternal(_subtitleFont, _infoText, Color::FromRGB(0xFFFFFF) * 0.9f, layout);
}
bool SplashScreen::HasLoadedFonts() const
diff --git a/Source/Engine/Core/Config/GameSettings.cs b/Source/Engine/Core/Config/GameSettings.cs
index 40d9f5dbc..76c968968 100644
--- a/Source/Engine/Core/Config/GameSettings.cs
+++ b/Source/Engine/Core/Config/GameSettings.cs
@@ -119,7 +119,7 @@ namespace FlaxEditor.Content.Settings
///
/// The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).
///
- [EditorOrder(1100), EditorDisplay("Other Settings"), Tooltip("The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).")]
+ [EditorOrder(1500), EditorDisplay("Other Settings"), Tooltip("The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).")]
public Dictionary CustomSettings;
#if FLAX_EDITOR || PLATFORM_WINDOWS
diff --git a/Source/Engine/Core/Config/GameSettings.h b/Source/Engine/Core/Config/GameSettings.h
index 54ad29a7b..6813f3ee2 100644
--- a/Source/Engine/Core/Config/GameSettings.h
+++ b/Source/Engine/Core/Config/GameSettings.h
@@ -7,6 +7,8 @@
#include "Engine/Core/Types/String.h"
#include "Engine/Core/Collections/Dictionary.h"
+class FontFallbackList;
+
///
/// The main game engine configuration service. Loads and applies game configuration.
///
@@ -33,6 +35,15 @@ public:
API_FIELD(Attributes="EditorOrder(15), EditorDisplay(\"General\")")
String CopyrightNotice;
+ ///
+ /// The copyright note used for content signing (eg. source code header).
+ ///
+ API_FIELD(Attributes = "EditorOrder(1200), EditorDisplay(\"Other Settings\")")
+ bool EnableFontFallback;
+
+ API_FIELD(Attributes = "EditorOrder(1205), EditorDisplay(\"Other Settings\")")
+ FontFallbackList* FontFallbacks;
+
///
/// The default application icon.
///
diff --git a/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h b/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h
index 3f2b8d36e..66ed97a20 100644
--- a/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h
+++ b/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h
@@ -57,7 +57,7 @@
#undef CreateWindow
#undef CreateProcess
#undef SetWindowText
-#undef DrawText
+#undef DrawTextInternal
#undef CreateFont
#undef IsMinimized
#undef IsMaximized
diff --git a/Source/Engine/Render2D/FallbackFonts.cpp b/Source/Engine/Render2D/FallbackFonts.cpp
index b79a0db4e..7f81a42bb 100644
--- a/Source/Engine/Render2D/FallbackFonts.cpp
+++ b/Source/Engine/Render2D/FallbackFonts.cpp
@@ -2,7 +2,7 @@
#include "FontManager.h"
#include "Engine/Core/Math/Math.h"
-FallbackFonts::FallbackFonts(const Array& fonts)
+FontFallbackList::FontFallbackList(const Array& fonts)
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer)),
_fontAssets(fonts)
{
diff --git a/Source/Engine/Render2D/FallbackFonts.h b/Source/Engine/Render2D/FallbackFonts.h
index 040ca8087..fb247e4e2 100644
--- a/Source/Engine/Render2D/FallbackFonts.h
+++ b/Source/Engine/Render2D/FallbackFonts.h
@@ -12,9 +12,9 @@ class FontAsset;
///
/// Defines a list of fonts that can be used as a fallback, ordered by priority.
///
-API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FallbackFonts : public ManagedScriptingObject
+API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API FontFallbackList : public ManagedScriptingObject
{
- DECLARE_SCRIPTING_TYPE_NO_SPAWN(FallbackFonts);
+ DECLARE_SCRIPTING_TYPE_NO_SPAWN(FontFallbackList);
private:
Array _fontAssets;
@@ -23,18 +23,18 @@ private:
public:
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The fallback font assets.
- FallbackFonts(const Array& fonts);
+ FontFallbackList(const Array& fonts);
///
- /// Initializes a new instance of the class, exposed for C#.
+ /// Initializes a new instance of the class, exposed for C#.
///
/// The fallback font assets.
/// The new instance.
- API_FUNCTION() FORCE_INLINE static FallbackFonts* Create(const Array& fonts) {
- return New(fonts);
+ API_FUNCTION() FORCE_INLINE static FontFallbackList* Create(const Array& fonts) {
+ return New(fonts);
}
///
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index 4cf1f73a2..5d029ca5e 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -293,7 +293,7 @@ void Font::ProcessText(const StringView& text, Array& outputLines
}
}
-void Font::ProcessText(FallbackFonts* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
+void Font::ProcessText(FontFallbackList* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout)
{
const Array& fallbackFonts = fallbacks->GetFontList(GetSize());
float cursorX = 0;
@@ -569,7 +569,7 @@ Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout
return max;
}
-Float2 Font::MeasureText(FallbackFonts* fallbacks, const StringView& text, const TextLayoutOptions& layout)
+Float2 Font::MeasureText(FontFallbackList* fallbacks, const StringView& text, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.IsEmpty())
@@ -664,7 +664,7 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te
return smallestIndex;
}
-int32 Font::HitTestText(FallbackFonts* fallbacks, const StringView& text, const Float2& location, const TextLayoutOptions& layout)
+int32 Font::HitTestText(FontFallbackList* fallbacks, const StringView& text, const Float2& location, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.Length() <= 0)
@@ -818,7 +818,7 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, static_cast((lines.Count() - 1) * baseLinesDistance));
}
-Float2 Font::GetCharPosition(FallbackFonts* fallbacks, const StringView& text, int32 index, const TextLayoutOptions& layout)
+Float2 Font::GetCharPosition(FontFallbackList* fallbacks, const StringView& text, int32 index, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.IsEmpty())
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index 110a8fe70..6bb2849e2 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -10,7 +10,7 @@
#include "TextLayoutOptions.h"
class FontAsset;
-class FallbackFonts;
+class FontFallbackList;
struct FontTextureAtlasSlot;
struct BlockedTextLineCache;
@@ -463,7 +463,7 @@ public:
/// The input text.
/// The layout properties.
/// The output lines list.
- void ProcessText(FallbackFonts* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
+ void ProcessText(FontFallbackList* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
///
/// Processes text to get cached lines for rendering.
@@ -471,7 +471,7 @@ public:
/// The input text.
/// The layout properties.
/// The output lines list.
- API_FUNCTION() Array ProcessText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
{
Array lines;
ProcessText(fallbacks, text, lines, layout);
@@ -485,7 +485,7 @@ public:
/// The input text range (substring range of the input text parameter).
/// The layout properties.
/// The output lines list.
- API_FUNCTION() Array ProcessText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
{
Array lines;
ProcessText(fallbacks, textRange.Substring(text), lines, layout);
@@ -497,7 +497,7 @@ public:
///
/// The input text.
/// The output lines list.
- API_FUNCTION() FORCE_INLINE Array ProcessText(FallbackFonts* fallbacks, const StringView& text)
+ API_FUNCTION() FORCE_INLINE Array ProcessText(FontFallbackList* fallbacks, const StringView& text)
{
return ProcessText(fallbacks, text, TextLayoutOptions());
}
@@ -508,7 +508,7 @@ public:
/// The input text.
/// The input text range (substring range of the input text parameter).
/// The output lines list.
- API_FUNCTION() FORCE_INLINE Array ProcessText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ API_FUNCTION() FORCE_INLINE Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
{
return ProcessText(fallbacks, textRange.Substring(text), TextLayoutOptions());
}
@@ -560,7 +560,7 @@ public:
/// The input text to test.
/// The layout properties.
/// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+ API_FUNCTION() Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
///
/// Measures minimum size of the rectangle that will be needed to draw given text.
@@ -569,7 +569,7 @@ public:
/// The input text range (substring range of the input text parameter).
/// The layout properties.
/// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
{
return MeasureText(fallbacks, textRange.Substring(text), layout);
}
@@ -579,7 +579,7 @@ public:
/// .
/// The input text to test.
/// The minimum size for that text and fot to render properly.
- API_FUNCTION() FORCE_INLINE Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text)
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text)
{
return MeasureText(fallbacks, text, TextLayoutOptions());
}
@@ -590,7 +590,7 @@ public:
/// The input text to test.
/// The input text range (substring range of the input text parameter).
/// The minimum size for that text and fot to render properly.
- API_FUNCTION() FORCE_INLINE Float2 MeasureText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
{
return MeasureText(fallbacks, textRange.Substring(text), TextLayoutOptions());
}
@@ -647,7 +647,7 @@ public:
/// The input location to test.
/// The text layout properties.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
+ API_FUNCTION() int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
///
/// Calculates hit character index at given location.
@@ -657,7 +657,7 @@ public:
/// The input location to test.
/// The text layout properties.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
{
return HitTestText(fallbacks, textRange.Substring(text), location, layout);
}
@@ -668,7 +668,7 @@ public:
/// The input text to test.
/// The input location to test.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() FORCE_INLINE int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, const Float2& location)
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, const Float2& location)
{
return HitTestText(fallbacks, text, location, TextLayoutOptions());
}
@@ -680,7 +680,7 @@ public:
/// The input text range (substring range of the input text parameter).
/// The input location to test.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() FORCE_INLINE int32 HitTestText(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
{
return HitTestText(fallbacks, textRange.Substring(text), location, TextLayoutOptions());
}
@@ -737,7 +737,7 @@ public:
/// The text position to get coordinates of.
/// The text layout properties.
/// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+ API_FUNCTION() Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
///
/// Calculates character position for given text and character index.
@@ -747,7 +747,7 @@ public:
/// The text position to get coordinates of.
/// The text layout properties.
/// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
{
return GetCharPosition(fallbacks, textRange.Substring(text), index, layout);
}
@@ -758,7 +758,7 @@ public:
/// The input text to test.
/// The text position to get coordinates of.
/// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, int32 index)
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, int32 index)
{
return GetCharPosition(fallbacks, text, index, TextLayoutOptions());
}
@@ -770,7 +770,7 @@ public:
/// The input text range (substring range of the input text parameter).
/// The text position to get coordinates of.
/// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
{
return GetCharPosition(fallbacks, textRange.Substring(text), index, TextLayoutOptions());
}
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index 4e0cacb44..351bb3700 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -1144,7 +1144,7 @@ void DrawBatch(int32 startIndex, int32 count)
Context->DrawIndexed(countIb, 0, d.StartIB);
}
-void Render2D::DrawText(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
@@ -1252,12 +1252,12 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
}
}
-void Render2D::DrawText(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
- DrawText(font, textRange.Substring(text), color, location, customMaterial);
+ DrawTextInternal(font, textRange.Substring(text), color, location, customMaterial);
}
-void Render2D::DrawText(Font* font, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
@@ -1365,12 +1365,12 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
}
}
-void Render2D::DrawText(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
- DrawText(font, textRange.Substring(text), color, layout, customMaterial);
+ DrawTextInternal(font, textRange.Substring(text), color, layout, customMaterial);
}
-void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
@@ -1549,12 +1549,12 @@ void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView&
}
}
-void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial)
{
- DrawText(font, fallbacks, textRange.Substring(text), color, location, customMaterial);
+ DrawTextInternal(font, fallbacks, textRange.Substring(text), color, location, customMaterial);
}
-void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
RENDER2D_CHECK_RENDERING_STATE;
@@ -1673,9 +1673,9 @@ void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView&
}
}
-void Render2D::DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
+void Render2D::DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const TextRange& textRange, const Color& color, const TextLayoutOptions& layout, MaterialBase* customMaterial)
{
- DrawText(font, fallbacks, textRange.Substring(text), color, layout, customMaterial);
+ DrawTextInternal(font, fallbacks, textRange.Substring(text), color, layout, customMaterial);
}
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h
index c99d38104..fa59b1d79 100644
--- a/Source/Engine/Render2D/Render2D.h
+++ b/Source/Engine/Render2D/Render2D.h
@@ -15,7 +15,7 @@ struct Matrix3x3;
struct Viewport;
struct TextRange;
class Font;
-class FallbackFonts;
+class FontFallbackList;
class GPUPipelineState;
class GPUTexture;
class GPUTextureView;
@@ -54,6 +54,9 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
};
public:
+ API_FIELD() static bool EnableFontFallback;
+ API_FIELD() static FontFallbackList* FallbackFonts;
+
///
/// Checks if interface is during rendering phrase (Draw calls may be performed without failing).
///
@@ -175,17 +178,17 @@ public:
public:
///
- /// Draws a text.
+ /// Draws a text, with font fallbacking disabled.
///
/// The font to use.
/// The text to render.
/// The text color.
/// The text location.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text.
+ /// Draws a text, with font fallbacking disabled.
///
/// The font to use.
/// The text to render.
@@ -193,20 +196,20 @@ public:
/// The text color.
/// The text location.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text with formatting.
+ /// Draws a text with formatting, with font fallbacking disabled.
///
/// The font to use.
/// The text to render.
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text with formatting.
+ /// Draws a text with formatting, with font fallbacking disabled.
///
/// The font to use.
/// The text to render.
@@ -214,10 +217,10 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text.
+ /// Draws a text, using custom fallback options.
///
/// The fonts to use, ordered by priority.
/// The text to render.
@@ -225,20 +228,20 @@ public:
/// The text color.
/// The text location.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text with formatting.
+ /// Draws a text with formatting, using custom fallback options.
///
/// The fonts to use, ordered by priority.
/// The text to render.
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text with formatting.
+ /// Draws a text with formatting, using custom fallback options.
///
/// The fonts to use, ordered by priority.
/// The text to render.
@@ -246,10 +249,10 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
///
- /// Draws a text with formatting.
+ /// Draws a text with formatting, using custom fallback options.
///
/// The fonts to use, ordered by priority.
/// The text to render.
@@ -257,7 +260,51 @@ public:
/// The text color.
/// The text layout properties.
/// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
- API_FUNCTION() static void DrawText(Font* font, FallbackFonts* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+ API_FUNCTION() static void DrawTextInternal(Font* font, FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
+
+ ///
+ /// Draws a text, follows the fallback settings defined in .
+ ///
+ /// The font to use.
+ /// The text to render.
+ /// The text color.
+ /// The text location.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
+ API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr) {
+ if (EnableFontFallback && FallbackFonts) {
+ DrawTextInternal(font, FallbackFonts, text, color, location, customMaterial);
+ }
+ else {
+ DrawTextInternal(font, text, color, location, customMaterial);
+ }
+ }
+
+ API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr) {
+ if (EnableFontFallback && FallbackFonts) {
+ DrawTextInternal(font, FallbackFonts, text, textRange, color, location, customMaterial);
+ }
+ else {
+ DrawTextInternal(font, text, textRange, color, location, customMaterial);
+ }
+ }
+
+ API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr) {
+ if (EnableFontFallback && FallbackFonts) {
+ DrawTextInternal(font, FallbackFonts, text, color, layout, customMaterial);
+ }
+ else {
+ DrawTextInternal(font, text, color, layout, customMaterial);
+ }
+ }
+
+ API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr) {
+ if (EnableFontFallback && FallbackFonts) {
+ DrawTextInternal(font, FallbackFonts, text, textRange, color, layout, customMaterial);
+ }
+ else {
+ DrawTextInternal(font, text, textRange, color, layout, customMaterial);
+ }
+ }
///
/// Fills a rectangle area.
From 2f019d4264fc7dfd57777297a8b592ab4064bf86 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Sat, 2 Dec 2023 17:51:32 +0800
Subject: [PATCH 12/16] Fix unintended unname
---
Source/Engine/Platform/Win32/IncludeWindowsHeaders.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h b/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h
index 66ed97a20..3f2b8d36e 100644
--- a/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h
+++ b/Source/Engine/Platform/Win32/IncludeWindowsHeaders.h
@@ -57,7 +57,7 @@
#undef CreateWindow
#undef CreateProcess
#undef SetWindowText
-#undef DrawTextInternal
+#undef DrawText
#undef CreateFont
#undef IsMinimized
#undef IsMaximized
From 23b71e7d3e825a3cb7d44300aa4e65c4fb684405 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Sun, 3 Dec 2023 15:11:47 +0800
Subject: [PATCH 13/16] Make font fallbacking the default option
---
Source/Editor/Content/GUI/ContentView.cs | 2 +-
Source/Editor/Content/Items/ContentItem.cs | 2 +-
Source/Editor/Content/Tree/ContentTreeNode.cs | 4 +-
.../Dedicated/MeshReferenceEditor.cs | 4 +-
.../CustomEditors/Dedicated/ScriptsEditor.cs | 4 +-
.../CustomEditors/Dedicated/SplineEditor.cs | 2 +-
.../Dedicated/UIControlEditor.cs | 2 +-
.../Editors/ActorTransformEditor.cs | 2 +-
.../Editors/FlaxObjectRefEditor.cs | 4 +-
.../Editor/CustomEditors/Editors/TagEditor.cs | 2 +-
.../CustomEditors/Editors/TypeEditor.cs | 4 +-
Source/Editor/GUI/AssetPicker.cs | 6 +-
Source/Editor/GUI/ComboBox.cs | 2 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 8 +-
Source/Editor/GUI/CurveEditor.cs | 2 +-
.../Editor/GUI/Dialogs/ColorPickerDialog.cs | 22 +-
Source/Editor/GUI/Docking/DockPanelProxy.cs | 4 +-
Source/Editor/GUI/Docking/DockWindow.cs | 2 +-
Source/Editor/GUI/ItemsListContextMenu.cs | 6 +-
Source/Editor/GUI/MainMenuButton.cs | 4 +-
Source/Editor/GUI/NavigationButton.cs | 4 +-
Source/Editor/GUI/Row.cs | 4 +-
Source/Editor/GUI/StatusBar.cs | 2 +-
Source/Editor/GUI/StyleValueEditor.cs | 2 +-
Source/Editor/GUI/Table.cs | 2 +-
Source/Editor/GUI/Tabs/Tabs.cs | 2 +-
Source/Editor/GUI/Timeline/GUI/Background.cs | 2 +-
Source/Editor/GUI/Timeline/Track.cs | 2 +-
.../Editor/GUI/Timeline/Tracks/MemberTrack.cs | 2 +-
Source/Editor/GUI/ToolStripButton.cs | 4 +-
Source/Editor/GUI/Tree/TreeNode.cs | 4 +-
Source/Editor/Options/OptionsModule.cs | 7 +-
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 4 +-
.../Archetypes/Animation.StateMachine.cs | 8 +-
Source/Editor/Surface/Archetypes/Animation.cs | 2 +-
.../Editor/Surface/Archetypes/BehaviorTree.cs | 6 +-
.../Surface/Archetypes/ParticleModules.cs | 2 +-
Source/Editor/Surface/Archetypes/Particles.cs | 4 +-
.../Surface/ContextMenu/VisjectCMItem.cs | 20 +-
Source/Editor/Surface/Elements/InputBox.cs | 6 +-
Source/Editor/Surface/Elements/OutputBox.cs | 2 +-
Source/Editor/Surface/Elements/TextView.cs | 2 +-
Source/Editor/Surface/SurfaceComment.cs | 2 +-
Source/Editor/Surface/SurfaceNode.cs | 8 +-
Source/Editor/Tools/Foliage/FoliageTab.cs | 2 +-
Source/Editor/Tools/Terrain/CarveTab.cs | 2 +-
Source/Editor/Viewport/EditorViewport.cs | 12 +-
.../Viewport/Previews/AnimationPreview.cs | 4 +-
.../Editor/Viewport/Previews/ModelPreview.cs | 4 +-
.../Previews/ParticleSystemPreview.cs | 2 +-
.../Viewport/Previews/SkinnedModelPreview.cs | 4 +-
.../Viewport/Previews/TexturePreview.cs | 2 +-
.../Viewport/Widgets/ViewportWidgetButton.cs | 4 +-
Source/Editor/Windows/AboutDialog.cs | 2 +-
.../Windows/Assets/AnimationGraphWindow.cs | 2 +-
.../Editor/Windows/Assets/AnimationWindow.cs | 2 +-
Source/Editor/Windows/Assets/ModelWindow.cs | 4 +-
.../Windows/Assets/SkinnedModelWindow.cs | 4 +-
Source/Editor/Windows/ContentWindow.Search.cs | 2 +-
Source/Editor/Windows/DebugLogWindow.cs | 4 +-
Source/Editor/Windows/GameWindow.cs | 8 +-
Source/Editor/Windows/Profiler/SingleChart.cs | 4 +-
Source/Editor/Windows/Profiler/Timeline.cs | 6 +-
Source/Editor/Windows/SceneTreeWindow.cs | 2 +-
Source/Editor/Windows/SplashScreen.cpp | 2 +-
Source/Editor/Windows/ToolboxWindow.cs | 4 +-
Source/Engine/Core/Config/GameSettings.h | 9 -
Source/Engine/Core/Config/GraphicsSettings.h | 14 +
Source/Engine/Graphics/Graphics.cpp | 4 +
Source/Engine/Render2D/FallbackTextUtils.cs | 268 ---------
Source/Engine/Render2D/Font.cpp | 24 +-
Source/Engine/Render2D/Font.h | 567 ++++++++++++------
Source/Engine/Render2D/Render2D.cpp | 2 +
Source/Engine/Render2D/Render2D.cs | 4 +-
Source/Engine/Render2D/Render2D.h | 6 +-
Source/Engine/UI/GUI/Common/Button.cs | 2 +-
Source/Engine/UI/GUI/Common/Dropdown.cs | 4 +-
Source/Engine/UI/GUI/Common/Label.cs | 4 +-
.../Engine/UI/GUI/Common/RichTextBoxBase.cs | 8 +-
Source/Engine/UI/GUI/Common/TextBox.cs | 18 +-
Source/Engine/UI/GUI/Panels/DropPanel.cs | 2 +-
Source/Engine/UI/GUI/Style.cs | 6 -
Source/Engine/UI/GUI/Tooltip.cs | 2 +-
83 files changed, 598 insertions(+), 619 deletions(-)
delete mode 100644 Source/Engine/Render2D/FallbackTextUtils.cs
diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs
index 1091c9cef..259be104b 100644
--- a/Source/Editor/Content/GUI/ContentView.cs
+++ b/Source/Editor/Content/GUI/ContentView.cs
@@ -598,7 +598,7 @@ namespace FlaxEditor.Content.GUI
// Check if it's an empty thing
if (_items.Count == 0)
{
- FallbackTextUtils.DrawText(style.FontSmall, IsSearching ? "No results" : "Empty", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, IsSearching ? "No results" : "Empty", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs
index 0842dfff7..604caa704 100644
--- a/Source/Editor/Content/Items/ContentItem.cs
+++ b/Source/Editor/Content/Items/ContentItem.cs
@@ -745,7 +745,7 @@ namespace FlaxEditor.Content
// Draw short name
Render2D.PushClip(ref textRect);
- FallbackTextUtils.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
+ Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
Render2D.PopClip();
}
diff --git a/Source/Editor/Content/Tree/ContentTreeNode.cs b/Source/Editor/Content/Tree/ContentTreeNode.cs
index 2f378e7f5..e2cd1e771 100644
--- a/Source/Editor/Content/Tree/ContentTreeNode.cs
+++ b/Source/Editor/Content/Tree/ContentTreeNode.cs
@@ -150,8 +150,8 @@ namespace FlaxEditor.Content
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = FallbackTextUtils.GetCharPosition(font, text, ranges[i].StartIndex);
- var end = FallbackTextUtils.GetCharPosition(font, text, ranges[i].EndIndex);
+ var start = font.GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs b/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs
index 66c1c791f..4099e5aee 100644
--- a/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/MeshReferenceEditor.cs
@@ -109,7 +109,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
// Draw name
Render2D.PushClip(nameRect);
- FallbackTextUtils.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
// Draw deselect button
@@ -118,7 +118,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
else
{
// Draw info
- FallbackTextUtils.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
}
// Draw picker button
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index 017fd7655..d7bfbbad7 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -42,7 +42,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Add script button
var buttonText = "Add script";
- var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
+ var textSize = Style.Current.FontMedium.MeasureText(buttonText);
float addScriptButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
_addScriptsButton = new Button
@@ -86,7 +86,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
var size = Size;
// Info
- FallbackTextUtils.DrawText(style.FontSmall, "Drag scripts here", new Rectangle(2, _addScriptsButton.Height + 4, size.X - 4, size.Y - 4 - 20), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, "Drag scripts here", new Rectangle(2, _addScriptsButton.Height + 4, size.X - 4, size.Y - 4 - 20), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
// Check if drag is over
if (IsDragOver && _dragHandlers != null && _dragHandlers.HasValidDrag)
diff --git a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs
index fa4379db1..7b9b65c5c 100644
--- a/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/SplineEditor.cs
@@ -226,7 +226,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (!enabled)
color *= 0.6f;
Render2D.DrawSprite(tab._customIcon, iconRect, color);
- FallbackTextUtils.DrawText(style.FontMedium, tab._customText, new Rectangle(0, iconSize, size.X, textHeight), color, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, tab._customText, new Rectangle(0, iconSize, size.X, textHeight), color, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index 4efbee259..296560507 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -423,7 +423,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Set control type button
var space = layout.Space(20);
var buttonText = "Set Type";
- var textSize = FallbackTextUtils.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
float setTypeButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
var setTypeButton = new Button
{
diff --git a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
index d8d16027b..4c153e759 100644
--- a/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ActorTransformEditor.cs
@@ -100,7 +100,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.Clicked += ToggleLink;
ToggleEnabled();
SetLinkStyle();
- var textSize = FallbackTextUtils.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, LinkedLabel.Text.Value);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(LinkedLabel.Text.Value);
_linkButton.LocalX += textSize.X + 10;
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
{
diff --git a/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs b/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
index 2f64ea159..731da3817 100644
--- a/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
@@ -199,7 +199,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
// Draw name
Render2D.PushClip(nameRect);
- FallbackTextUtils.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _valueName, nameRect, isEnabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
// Draw deselect button
@@ -208,7 +208,7 @@ namespace FlaxEditor.CustomEditors.Editors
else
{
// Draw info
- FallbackTextUtils.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "-", nameRect, isEnabled ? Color.OrangeRed : Color.DarkOrange, TextAlignment.Near, TextAlignment.Center);
}
// Draw picker button
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index bbece7e04..dbd5d124c 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -631,7 +631,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Edit...",
Parent = _label,
};
- var textSize = FallbackTextUtils.MeasureText(FlaxEngine.GUI.Style.Current.FontMedium, buttonText);
+ var textSize = FlaxEngine.GUI.Style.Current.FontMedium.MeasureText(buttonText);
if (textSize.Y > button.Width)
button.Width = textSize.Y + 2;
diff --git a/Source/Editor/CustomEditors/Editors/TypeEditor.cs b/Source/Editor/CustomEditors/Editors/TypeEditor.cs
index 4d0b90383..38800a738 100644
--- a/Source/Editor/CustomEditors/Editors/TypeEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TypeEditor.cs
@@ -160,13 +160,13 @@ namespace FlaxEditor.CustomEditors.Editors
// Draw name
Render2D.PushClip(nameRect);
- FallbackTextUtils.DrawText(style.FontMedium, _valueName, nameRect, style.Foreground, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _valueName, nameRect, style.Foreground, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
else
{
// Draw info
- FallbackTextUtils.DrawText(style.FontMedium, "-", nameRect, Color.OrangeRed, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "-", nameRect, Color.OrangeRed, TextAlignment.Near, TextAlignment.Center);
}
// Draw picker button
diff --git a/Source/Editor/GUI/AssetPicker.cs b/Source/Editor/GUI/AssetPicker.cs
index 2abe5db38..84f58daf1 100644
--- a/Source/Editor/GUI/AssetPicker.cs
+++ b/Source/Editor/GUI/AssetPicker.cs
@@ -139,7 +139,7 @@ namespace FlaxEditor.GUI
float sizeForTextLeft = Width - button1Rect.Right;
if (sizeForTextLeft > 30)
{
- FallbackTextUtils.DrawText(
+ Render2D.DrawText(
style.FontSmall,
Validator.SelectedItem.ShortName,
new Rectangle(button1Rect.Right + 2, 0, sizeForTextLeft, ButtonsSize),
@@ -161,7 +161,7 @@ namespace FlaxEditor.GUI
var name = Validator.SelectedAsset.GetType().Name;
if (Validator.SelectedAsset.IsVirtual)
name += " (virtual)";
- FallbackTextUtils.DrawText(
+ Render2D.DrawText(
style.FontSmall,
name,
new Rectangle(button1Rect.Right + 2, 0, sizeForTextLeft, ButtonsSize),
@@ -174,7 +174,7 @@ namespace FlaxEditor.GUI
{
// No element selected
Render2D.FillRectangle(iconRect, style.BackgroundNormal);
- FallbackTextUtils.DrawText(style.FontMedium, "No asset\nselected", iconRect, Color.Orange, TextAlignment.Center, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, Height / DefaultIconSize);
+ Render2D.DrawText(style.FontMedium, "No asset\nselected", iconRect, Color.Orange, TextAlignment.Center, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, Height / DefaultIconSize);
}
// Check if drag is over
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index 8f3a7cb4b..0417cc7e3 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -554,7 +554,7 @@ namespace FlaxEditor.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- FallbackTextUtils.DrawText(Font.GetFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ Render2D.DrawText(Font.GetFont(), text, textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
}
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index 035e997e9..e371f7c4b 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -128,12 +128,12 @@ namespace FlaxEditor.GUI.ContextMenu
base.Draw();
// Draw text
- FallbackTextUtils.DrawText(style.FontMedium, Text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, Text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!string.IsNullOrEmpty(ShortKeys))
{
// Draw short keys
- FallbackTextUtils.DrawText(style.FontMedium, ShortKeys, textRect, textColor, TextAlignment.Far, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, ShortKeys, textRect, textColor, TextAlignment.Far, TextAlignment.Center);
}
// Draw icon
@@ -235,9 +235,9 @@ namespace FlaxEditor.GUI.ContextMenu
float width = 20;
if (style.FontMedium)
{
- width += FallbackTextUtils.MeasureText(style.FontMedium, Text).X;
+ width += style.FontMedium.MeasureText(Text).X;
if (!string.IsNullOrEmpty(ShortKeys))
- width += 40 + FallbackTextUtils.MeasureText(style.FontMedium, ShortKeys).X;
+ width += 40 + style.FontMedium.MeasureText(ShortKeys).X;
}
return Mathf.Max(width, base.MinimumWidth);
diff --git a/Source/Editor/GUI/CurveEditor.cs b/Source/Editor/GUI/CurveEditor.cs
index f4839acd5..22deec120 100644
--- a/Source/Editor/GUI/CurveEditor.cs
+++ b/Source/Editor/GUI/CurveEditor.cs
@@ -832,7 +832,7 @@ namespace FlaxEditor.GUI
50,
LabelsSize
);
- FallbackTextUtils.DrawText(_labelsFont, label, labelRect, _labelsColor.AlphaMultiplied(strength), TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.7f);
+ Render2D.DrawText(_labelsFont, label, labelRect, _labelsColor.AlphaMultiplied(strength), TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.7f);
}
}
}
diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
index 8b1881faf..27878a763 100644
--- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
+++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs
@@ -281,33 +281,33 @@ namespace FlaxEditor.GUI.Dialogs
// RGBA
var rgbaR = new Rectangle(_cRed.Left - ChannelTextWidth, _cRed.Y, 10000, _cRed.Height);
- FallbackTextUtils.DrawText(style.FontMedium, "R", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "R", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cGreen.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "G", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "G", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cBlue.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "B", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "B", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
rgbaR.Location.Y = _cAlpha.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "A", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "A", rgbaR, textColor, TextAlignment.Near, TextAlignment.Center);
// HSV left
var hsvHl = new Rectangle(_cHue.Left - ChannelTextWidth, _cHue.Y, 10000, _cHue.Height);
- FallbackTextUtils.DrawText(style.FontMedium, "H", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "H", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHl.Location.Y = _cSaturation.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "S", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "S", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHl.Location.Y = _cValue.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "V", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "V", hsvHl, textColor, TextAlignment.Near, TextAlignment.Center);
// HSV right
var hsvHr = new Rectangle(_cHue.Right + 2, _cHue.Y, 10000, _cHue.Height);
- FallbackTextUtils.DrawText(style.FontMedium, "°", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "°", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHr.Location.Y = _cSaturation.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
hsvHr.Location.Y = _cValue.Y;
- FallbackTextUtils.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "%", hsvHr, textColor, TextAlignment.Near, TextAlignment.Center);
// Hex
var hex = new Rectangle(_cHex.Left - 26, _cHex.Y, 10000, _cHex.Height);
- FallbackTextUtils.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, "Hex", hex, textColor, TextAlignment.Near, TextAlignment.Center);
// Color difference
var newRect = new Rectangle(_cOK.X, _cHex.Bottom + PickerMargin, _cCancel.Right - _cOK.Left, 0);
diff --git a/Source/Editor/GUI/Docking/DockPanelProxy.cs b/Source/Editor/GUI/Docking/DockPanelProxy.cs
index 0b36b85fa..e6e57de8e 100644
--- a/Source/Editor/GUI/Docking/DockPanelProxy.cs
+++ b/Source/Editor/GUI/Docking/DockPanelProxy.cs
@@ -208,7 +208,7 @@ namespace FlaxEditor.GUI.Docking
}
// Draw text
- FallbackTextUtils.DrawText(
+ Render2D.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(DockPanel.DefaultLeftTextMargin + iconWidth, 0, Width - DockPanel.DefaultLeftTextMargin - DockPanel.DefaultButtonsSize - 2 * DockPanel.DefaultButtonsMargin, DockPanel.DefaultHeaderHeight),
@@ -271,7 +271,7 @@ namespace FlaxEditor.GUI.Docking
}
// Draw text
- FallbackTextUtils.DrawText(
+ Render2D.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(x + DockPanel.DefaultLeftTextMargin + iconWidth, 0, 10000, DockPanel.DefaultHeaderHeight),
diff --git a/Source/Editor/GUI/Docking/DockWindow.cs b/Source/Editor/GUI/Docking/DockWindow.cs
index 561c898a0..dd4e39ce2 100644
--- a/Source/Editor/GUI/Docking/DockWindow.cs
+++ b/Source/Editor/GUI/Docking/DockWindow.cs
@@ -488,7 +488,7 @@ namespace FlaxEditor.GUI.Docking
{
var style = Style.Current;
if (style?.FontMedium != null)
- _titleSize = FallbackTextUtils.MeasureText(style.FontMedium, _title);
+ _titleSize = style.FontMedium.MeasureText(_title);
}
base.PerformLayoutBeforeChildren();
diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs
index d3c433a47..42d236991 100644
--- a/Source/Editor/GUI/ItemsListContextMenu.cs
+++ b/Source/Editor/GUI/ItemsListContextMenu.cs
@@ -86,8 +86,8 @@ namespace FlaxEditor.GUI
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = FallbackTextUtils.GetCharPosition(font, Name, ranges[i].StartIndex);
- var end = FallbackTextUtils.GetCharPosition(font, Name, ranges[i].EndIndex);
+ var start = font.GetCharPosition(Name, ranges[i].StartIndex);
+ var end = font.GetCharPosition(Name, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
}
Visible = true;
@@ -136,7 +136,7 @@ namespace FlaxEditor.GUI
}
// Draw name
- FallbackTextUtils.DrawText(style.FontSmall, Name, textRect, TintColor * (Enabled ? style.Foreground : style.ForegroundDisabled), TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Name, textRect, TintColor * (Enabled ? style.Foreground : style.ForegroundDisabled), TextAlignment.Near, TextAlignment.Center);
}
///
diff --git a/Source/Editor/GUI/MainMenuButton.cs b/Source/Editor/GUI/MainMenuButton.cs
index 43849f4ab..117922361 100644
--- a/Source/Editor/GUI/MainMenuButton.cs
+++ b/Source/Editor/GUI/MainMenuButton.cs
@@ -72,7 +72,7 @@ namespace FlaxEditor.GUI
}
// Draw text
- FallbackTextUtils.DrawText(style.FontMedium, Text, clientRect, enabled && hasChildItems ? style.Foreground : style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, Text, clientRect, enabled && hasChildItems ? style.Foreground : style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
///
@@ -102,7 +102,7 @@ namespace FlaxEditor.GUI
float width = 18;
if (style.FontMedium)
- width += FallbackTextUtils.MeasureText(style.FontMedium, Text).X;
+ width += style.FontMedium.MeasureText(Text).X;
Width = width;
}
diff --git a/Source/Editor/GUI/NavigationButton.cs b/Source/Editor/GUI/NavigationButton.cs
index 8dedf72fd..18e862304 100644
--- a/Source/Editor/GUI/NavigationButton.cs
+++ b/Source/Editor/GUI/NavigationButton.cs
@@ -57,7 +57,7 @@ namespace FlaxEditor.GUI
}
// Draw text
- FallbackTextUtils.DrawText(style.FontMedium, Text, textRect, EnabledInHierarchy ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, Text, textRect, EnabledInHierarchy ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
///
@@ -67,7 +67,7 @@ namespace FlaxEditor.GUI
if (style.FontMedium)
{
- Width = FallbackTextUtils.MeasureText(style.FontMedium, Text).X + 2 * DefaultMargin;
+ Width = style.FontMedium.MeasureText(Text).X + 2 * DefaultMargin;
}
}
}
diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs
index 9868ab456..43785c735 100644
--- a/Source/Editor/GUI/Row.cs
+++ b/Source/Editor/GUI/Row.cs
@@ -38,7 +38,7 @@ namespace FlaxEditor.GUI
{
Depth = -1;
- var mediumHeight = FallbackTextUtils.GetMaxHeight(Style.Current.FontMedium);
+ var mediumHeight = Style.Current.FontMedium.GetMaxHeight();
if (Height < mediumHeight)
Height = mediumHeight + 4;
}
@@ -99,7 +99,7 @@ namespace FlaxEditor.GUI
rect.Width -= leftDepthMargin;
Render2D.PushClip(rect);
- FallbackTextUtils.DrawText(style.FontMedium, text, rect, style.Foreground, column.CellAlignment, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, text, rect, style.Foreground, column.CellAlignment, TextAlignment.Center);
Render2D.PopClip();
x += width;
diff --git a/Source/Editor/GUI/StatusBar.cs b/Source/Editor/GUI/StatusBar.cs
index 7770af9a1..f8f7ae839 100644
--- a/Source/Editor/GUI/StatusBar.cs
+++ b/Source/Editor/GUI/StatusBar.cs
@@ -56,7 +56,7 @@ namespace FlaxEditor.GUI
Render2D.DrawSprite(style.StatusBarSizeGrip, new Rectangle(Width - 12, 10, 12, 12), style.Foreground);
// Draw status text
- FallbackTextUtils.DrawText(style.FontSmall, Text, new Rectangle(4, 0, Width - 20, Height), TextColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Text, new Rectangle(4, 0, Width - 20, Height), TextColor, TextAlignment.Near, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/GUI/StyleValueEditor.cs b/Source/Editor/GUI/StyleValueEditor.cs
index db6696152..a89902177 100644
--- a/Source/Editor/GUI/StyleValueEditor.cs
+++ b/Source/Editor/GUI/StyleValueEditor.cs
@@ -157,7 +157,7 @@ namespace FlaxEditor.GUI
{
Rectangle textRectangle = r;
textRectangle.X = 4;
- FallbackTextUtils.DrawText(style.FontMedium, "No Style", textRectangle, style.Foreground);
+ Render2D.DrawText(style.FontMedium, "No Style", textRectangle, style.Foreground);
}
}
diff --git a/Source/Editor/GUI/Table.cs b/Source/Editor/GUI/Table.cs
index 2358557c3..1d22ddb15 100644
--- a/Source/Editor/GUI/Table.cs
+++ b/Source/Editor/GUI/Table.cs
@@ -130,7 +130,7 @@ namespace FlaxEditor.GUI
var style = Style.Current;
var font = column.TitleFont ?? style.FontMedium;
- FallbackTextUtils.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
if (columnIndex < _columns.Length - 1)
{
diff --git a/Source/Editor/GUI/Tabs/Tabs.cs b/Source/Editor/GUI/Tabs/Tabs.cs
index 5995c7ef5..3c70363e7 100644
--- a/Source/Editor/GUI/Tabs/Tabs.cs
+++ b/Source/Editor/GUI/Tabs/Tabs.cs
@@ -98,7 +98,7 @@ namespace FlaxEditor.GUI.Tabs
// Draw text
if (!string.IsNullOrEmpty(Tab.Text))
{
- FallbackTextUtils.DrawText(style.FontMedium, Tab.Text, new Rectangle(tabRect.X + textOffset, tabRect.Y, tabRect.Width - textOffset, tabRect.Height), style.Foreground, Tabs.TabsTextHorizontalAlignment, Tabs.TabsTextVerticalAlignment);
+ Render2D.DrawText(style.FontMedium, Tab.Text, new Rectangle(tabRect.X + textOffset, tabRect.Y, tabRect.Width - textOffset, tabRect.Height), style.Foreground, Tabs.TabsTextHorizontalAlignment, Tabs.TabsTextVerticalAlignment);
}
}
}
diff --git a/Source/Editor/GUI/Timeline/GUI/Background.cs b/Source/Editor/GUI/Timeline/GUI/Background.cs
index 05c1121c0..b9eff562a 100644
--- a/Source/Editor/GUI/Timeline/GUI/Background.cs
+++ b/Source/Editor/GUI/Timeline/GUI/Background.cs
@@ -301,7 +301,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
default: throw new ArgumentOutOfRangeException();
}
var labelRect = new Rectangle(x + 2, -verticalLinesHeaderExtend * 0.8f + timeAxisHeaderOffset, 50, verticalLinesHeaderExtend);
- FallbackTextUtils.DrawText(style.FontSmall, labelText, labelRect, labelColor, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.8f);
+ Render2D.DrawText(style.FontSmall, labelText, labelRect, labelColor, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.8f);
}
}
}
diff --git a/Source/Editor/GUI/Timeline/Track.cs b/Source/Editor/GUI/Timeline/Track.cs
index 20be8f0c2..f38917aa6 100644
--- a/Source/Editor/GUI/Timeline/Track.cs
+++ b/Source/Editor/GUI/Timeline/Track.cs
@@ -965,7 +965,7 @@ namespace FlaxEditor.GUI.Timeline
}
// Draw text
- FallbackTextUtils.DrawText(style.FontSmall, Title ?? Name, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Title ?? Name, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
// Disabled overlay
DrawDisabled = Mute || (ParentTrack != null && ParentTrack.DrawDisabled);
diff --git a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
index dd79922ac..63787df2c 100644
--- a/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/MemberTrack.cs
@@ -345,7 +345,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
if (_previewValue != null)
{
// Based on Track.Draw for track text placement
- var left = _xOffset + 16 + FallbackTextUtils.MeasureText(Style.Current.FontSmall, Title ?? Name).X;
+ var left = _xOffset + 16 + Style.Current.FontSmall.MeasureText(Title ?? Name).X;
if (Icon.IsValid)
left += 18;
if (IsExpanded)
diff --git a/Source/Editor/GUI/ToolStripButton.cs b/Source/Editor/GUI/ToolStripButton.cs
index c4f4603e2..e839a7356 100644
--- a/Source/Editor/GUI/ToolStripButton.cs
+++ b/Source/Editor/GUI/ToolStripButton.cs
@@ -136,7 +136,7 @@ namespace FlaxEditor.GUI
if (!string.IsNullOrEmpty(_text))
{
textRect.Size.X = Width - DefaultMargin - textRect.Left;
- FallbackTextUtils.DrawText(style.FontMedium, _text, textRect, enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _text, textRect, enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
}
@@ -151,7 +151,7 @@ namespace FlaxEditor.GUI
if (hasSprite)
width += iconSize;
if (!string.IsNullOrEmpty(_text) && style.FontMedium)
- width += FallbackTextUtils.MeasureText(style.FontMedium, _text).X + (hasSprite ? DefaultMargin : 0);
+ width += style.FontMedium.MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
Width = width;
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index 6680e3608..703079469 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -575,7 +575,7 @@ namespace FlaxEditor.GUI.Tree
var font = TextFont.GetFont();
if (font)
{
- _textWidth = FallbackTextUtils.MeasureText(font, _text).X;
+ _textWidth = font.MeasureText(_text).X;
_textChanged = false;
}
}
@@ -656,7 +656,7 @@ namespace FlaxEditor.GUI.Tree
}
// Draw text
- FallbackTextUtils.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(TextFont.GetFont(), _text, textRect, _cachedTextColor, TextAlignment.Near, TextAlignment.Center);
// Draw drag and drop effect
if (IsDragOver && _tree.DraggedOverNode == this)
diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs
index dc376a0a2..bf35105a5 100644
--- a/Source/Editor/Options/OptionsModule.cs
+++ b/Source/Editor/Options/OptionsModule.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using FlaxEditor.Content.Settings;
using FlaxEditor.Modules;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -224,7 +225,11 @@ namespace FlaxEditor.Options
}
}
- FallbackTextUtils.Fallbacks = FallbackFonts.Create(Options.Interface.Fallbacks);
+ var graphicsSetttings = GameSettings.Load();
+ if (graphicsSetttings.EnableFontFallback && graphicsSetttings.FallbackFonts == null)
+ {
+ Render2D.FallbackFonts = graphicsSetttings.FallbackFonts = FontFallbackList.Create(Options.Interface.Fallbacks);
+ }
}
///
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index eefd7f4dd..f64e46385 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -142,8 +142,8 @@ namespace FlaxEditor.SceneGraph.GUI
var textRect = TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = FallbackTextUtils.GetCharPosition(font, text, ranges[i].StartIndex);
- var end = FallbackTextUtils.GetCharPosition(font, text, ranges[i].EndIndex);
+ var start = font.GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.GetCharPosition(text, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
isThisVisible = true;
diff --git a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
index be9a96a7d..621c7c25e 100644
--- a/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.StateMachine.cs
@@ -337,7 +337,7 @@ namespace FlaxEditor.Surface.Archetypes
_textRect = new Rectangle(Float2.Zero, Size);
var style = Style.Current;
- var titleSize = FallbackTextUtils.MeasureText(style.FontLarge, Title);
+ var titleSize = style.FontLarge.MeasureText(Title);
var width = Mathf.Max(100, titleSize.X + 50);
Resize(width, 0);
titleSize.X += 8.0f;
@@ -379,7 +379,7 @@ namespace FlaxEditor.Surface.Archetypes
}
// Name
- FallbackTextUtils.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
}
///
@@ -1128,7 +1128,7 @@ namespace FlaxEditor.Surface.Archetypes
}
// Name
- FallbackTextUtils.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, Title, _textRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// Close button
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey);
@@ -1402,7 +1402,7 @@ namespace FlaxEditor.Surface.Archetypes
{
Title = StateTitle;
var style = Style.Current;
- var titleSize = FallbackTextUtils.MeasureText(style.FontLarge, Title);
+ var titleSize = style.FontLarge.MeasureText(Title);
var width = Mathf.Max(100, titleSize.X + 50);
Resize(width, 0);
titleSize.X += 8.0f;
diff --git a/Source/Editor/Surface/Archetypes/Animation.cs b/Source/Editor/Surface/Archetypes/Animation.cs
index dae16b425..40a3d2a63 100644
--- a/Source/Editor/Surface/Archetypes/Animation.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.cs
@@ -77,7 +77,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = asset?.ShortName ?? "Animation";
var style = Style.Current;
- Resize(Mathf.Max(230, FallbackTextUtils.MeasureText(style.FontLarge, Title).X + 30), 160);
+ Resize(Mathf.Max(230, style.FontLarge.MeasureText(Title).X + 30), 160);
}
///
diff --git a/Source/Editor/Surface/Archetypes/BehaviorTree.cs b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
index b240685cc..f8cd7bb5a 100644
--- a/Source/Editor/Surface/Archetypes/BehaviorTree.cs
+++ b/Source/Editor/Surface/Archetypes/BehaviorTree.cs
@@ -100,7 +100,7 @@ namespace FlaxEditor.Surface.Archetypes
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
if (!string.IsNullOrEmpty(_debugInfo))
- _debugInfoSize = FallbackTextUtils.MeasureText(Style.Current.FontSmall, _debugInfo);
+ _debugInfoSize = Style.Current.FontSmall.MeasureText(_debugInfo);
}
}
@@ -184,7 +184,7 @@ namespace FlaxEditor.Surface.Archetypes
if (!string.IsNullOrEmpty(_debugInfo))
{
var style = Style.Current;
- FallbackTextUtils.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 4, _debugInfoSize), style.Foreground);
+ Render2D.DrawText(style.FontSmall, _debugInfo, new Rectangle(4, _headerRect.Bottom + 4, _debugInfoSize), style.Foreground);
}
// Debug relevancy outline
@@ -487,7 +487,7 @@ namespace FlaxEditor.Surface.Archetypes
var height = 0.0f;
var titleLabelFont = Style.Current.FontLarge;
width = Mathf.Max(width, 100.0f);
- width = Mathf.Max(width, FallbackTextUtils.MeasureText(titleLabelFont, Title).X + 30);
+ width = Mathf.Max(width, titleLabelFont.MeasureText(Title).X + 30);
if (_debugInfoSize.X > 0)
{
width = Mathf.Max(width, _debugInfoSize.X + 8.0f);
diff --git a/Source/Editor/Surface/Archetypes/ParticleModules.cs b/Source/Editor/Surface/Archetypes/ParticleModules.cs
index 6082e212e..e5be3d35d 100644
--- a/Source/Editor/Surface/Archetypes/ParticleModules.cs
+++ b/Source/Editor/Surface/Archetypes/ParticleModules.cs
@@ -113,7 +113,7 @@ namespace FlaxEditor.Surface.Archetypes
var idx = (int)ModuleType;
var headerRect = new Rectangle(0, 0, Width, 16.0f);
//Render2D.FillRectangle(headerRect, Color.Red);
- FallbackTextUtils.DrawText(style.FontMedium, Title, headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, Title, headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
DrawChildren();
diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs
index bf7828960..40b38f7ce 100644
--- a/Source/Editor/Surface/Archetypes/Particles.cs
+++ b/Source/Editor/Surface/Archetypes/Particles.cs
@@ -154,7 +154,7 @@ namespace FlaxEditor.Surface.Archetypes
if (headerRect.Contains(mousePosition))
headerColor *= 1.07f;
Render2D.FillRectangle(headerRect, headerColor);
- FallbackTextUtils.DrawText(style.FontLarge, Names[idx], headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, Names[idx], headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
DrawChildren();
}
@@ -194,7 +194,7 @@ namespace FlaxEditor.Surface.Archetypes
if (_headerRect.Contains(ref _mousePosition))
headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, headerColor);
- FallbackTextUtils.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
DrawChildren();
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index f4976be67..207875a92 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -200,8 +200,8 @@ namespace FlaxEditor.Surface.ContextMenu
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
- var start = FallbackTextUtils.GetCharPosition(font, _archetype.Title, ranges[i].StartIndex);
- var end = FallbackTextUtils.GetCharPosition(font, _archetype.Title, ranges[i].EndIndex);
+ var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
+ var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
if (ranges[i].StartIndex <= 0)
@@ -222,8 +222,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = FallbackTextUtils.GetCharPosition(font, _archetype.Title, 0);
- var end = FallbackTextUtils.GetCharPosition(font, _archetype.Title, _archetype.Title.Length - 1);
+ var start = font.GetCharPosition(_archetype.Title, 0);
+ var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
_isFullMatch = true;
Visible = true;
@@ -237,8 +237,8 @@ namespace FlaxEditor.Surface.ContextMenu
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
- var start = FallbackTextUtils.GetCharPosition(font, _archetype.Title, 0);
- var end = FallbackTextUtils.GetCharPosition(font, _archetype.Title, _archetype.Title.Length - 1);
+ var start = font.GetCharPosition(_archetype.Title, 0);
+ var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
Visible = true;
@@ -283,19 +283,19 @@ namespace FlaxEditor.Surface.ContextMenu
}
// Draw name
- FallbackTextUtils.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
if (_archetype.SubTitle != null)
{
- var titleLength = FallbackTextUtils.MeasureText(style.FontSmall, _archetype.Title).X;
+ var titleLength = style.FontSmall.MeasureText(_archetype.Title).X;
var subTitleRect = new Rectangle(textRect.X + titleLength, textRect.Y, textRect.Width - titleLength, textRect.Height);
- FallbackTextUtils.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
// Reset transform and draw score mark
if (showScoreHit)
{
Render2D.PopTransform();
- FallbackTextUtils.DrawText(style.FontSmall, "> ", textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, "> ", textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Surface/Elements/InputBox.cs b/Source/Editor/Surface/Elements/InputBox.cs
index a5a99b932..2047bcd1a 100644
--- a/Source/Editor/Surface/Elements/InputBox.cs
+++ b/Source/Editor/Surface/Elements/InputBox.cs
@@ -1428,7 +1428,7 @@ namespace FlaxEditor.Surface.Elements
if (_defaultValueEditor != null)
{
- _defaultValueEditor.Location = new Float2(X + Width + 8 + FallbackTextUtils.MeasureText(Style.Current.FontSmall, Text).X, Y);
+ _defaultValueEditor.Location = new Float2(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y);
}
}
@@ -1443,7 +1443,7 @@ namespace FlaxEditor.Surface.Elements
// Draw text
var style = Style.Current;
var rect = new Rectangle(Width + 4, 0, 1410, Height);
- FallbackTextUtils.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
}
///
@@ -1635,7 +1635,7 @@ namespace FlaxEditor.Surface.Elements
{
if (DefaultValueEditors[i].CanUse(this, ref _currentType))
{
- var bounds = new Rectangle(X + Width + 8 + FallbackTextUtils.MeasureText(Style.Current.FontSmall, Text).X, Y, 90, Height);
+ var bounds = new Rectangle(X + Width + 8 + Style.Current.FontSmall.MeasureText(Text).X, Y, 90, Height);
_editor = DefaultValueEditors[i];
try
{
diff --git a/Source/Editor/Surface/Elements/OutputBox.cs b/Source/Editor/Surface/Elements/OutputBox.cs
index 5fb123700..497e2001a 100644
--- a/Source/Editor/Surface/Elements/OutputBox.cs
+++ b/Source/Editor/Surface/Elements/OutputBox.cs
@@ -189,7 +189,7 @@ namespace FlaxEditor.Surface.Elements
// Draw text
var style = Style.Current;
var rect = new Rectangle(-100, 0, 100 - 2, Height);
- FallbackTextUtils.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Text, rect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Far, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Surface/Elements/TextView.cs b/Source/Editor/Surface/Elements/TextView.cs
index c52667fe3..284497396 100644
--- a/Source/Editor/Surface/Elements/TextView.cs
+++ b/Source/Editor/Surface/Elements/TextView.cs
@@ -25,7 +25,7 @@ namespace FlaxEditor.Surface.Elements
var style = Style.Current;
var color = Enabled ? style.Foreground : style.ForegroundDisabled;
- FallbackTextUtils.DrawText(style.FontSmall, Archetype.Text, new Rectangle(Float2.Zero, Size), color, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontSmall, Archetype.Text, new Rectangle(Float2.Zero, Size), color, TextAlignment.Near, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Surface/SurfaceComment.cs b/Source/Editor/Surface/SurfaceComment.cs
index 26cc912ab..aad45190e 100644
--- a/Source/Editor/Surface/SurfaceComment.cs
+++ b/Source/Editor/Surface/SurfaceComment.cs
@@ -169,7 +169,7 @@ namespace FlaxEditor.Surface
// Header
Render2D.FillRectangle(_headerRect, headerColor);
- FallbackTextUtils.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// Close button
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index df706faa6..780ef81f0 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -199,7 +199,7 @@ namespace FlaxEditor.Surface
continue;
if (child is InputBox inputBox)
{
- var boxWidth = FallbackTextUtils.MeasureText(boxLabelFont, inputBox.Text).X + 20;
+ var boxWidth = boxLabelFont.MeasureText(inputBox.Text).X + 20;
if (inputBox.DefaultValueEditor != null)
boxWidth += inputBox.DefaultValueEditor.Width + 4;
leftWidth = Mathf.Max(leftWidth, boxWidth);
@@ -207,7 +207,7 @@ namespace FlaxEditor.Surface
}
else if (child is OutputBox outputBox)
{
- rightWidth = Mathf.Max(rightWidth, FallbackTextUtils.MeasureText(boxLabelFont, outputBox.Text).X + 20);
+ rightWidth = Mathf.Max(rightWidth, boxLabelFont.MeasureText(outputBox.Text).X + 20);
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
}
else if (child is Control control)
@@ -225,7 +225,7 @@ namespace FlaxEditor.Surface
}
}
width = Mathf.Max(width, leftWidth + rightWidth + 10);
- width = Mathf.Max(width, FallbackTextUtils.MeasureText(titleLabelFont, Title).X + 30);
+ width = Mathf.Max(width, titleLabelFont.MeasureText(Title).X + 30);
height = Mathf.Max(height, Mathf.Max(leftHeight, rightHeight));
Resize(width, height);
}
@@ -1027,7 +1027,7 @@ namespace FlaxEditor.Surface
if (_headerRect.Contains(ref _mousePosition))
headerColor *= 1.07f;
Render2D.FillRectangle(_headerRect, headerColor);
- FallbackTextUtils.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
// Close button
if ((Archetype.Flags & NodeFlags.NoCloseButton) == 0 && Surface.CanEdit)
diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs
index d36c3b6ed..1b46a42be 100644
--- a/Source/Editor/Tools/Foliage/FoliageTab.cs
+++ b/Source/Editor/Tools/Foliage/FoliageTab.cs
@@ -147,7 +147,7 @@ namespace FlaxEditor.Tools.Foliage
Parent = _noFoliagePanel,
Enabled = false
};
- var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
+ var textSize = Style.Current.FontMedium.MeasureText(buttonText);
if (_createNewFoliage.Width < textSize.X)
{
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
diff --git a/Source/Editor/Tools/Terrain/CarveTab.cs b/Source/Editor/Tools/Terrain/CarveTab.cs
index e64a364f0..d51915acf 100644
--- a/Source/Editor/Tools/Terrain/CarveTab.cs
+++ b/Source/Editor/Tools/Terrain/CarveTab.cs
@@ -105,7 +105,7 @@ namespace FlaxEditor.Tools.Terrain
Parent = _noTerrainPanel,
Enabled = false
};
- var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
+ var textSize = Style.Current.FontMedium.MeasureText(buttonText);
if (_createTerrainButton.Width < textSize.X)
{
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index 515514131..c49392d01 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -548,9 +548,9 @@ namespace FlaxEditor.Viewport
#region Camera settings widget
var largestText = "Relative Panning";
- var textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, largestText);
+ var textSize = Style.Current.FontMedium.MeasureText(largestText);
var xLocationForExtras = textSize.X + 5;
- var cameraSpeedTextWidth = FallbackTextUtils.MeasureText(Style.Current.FontMedium, "0.00").X;
+ var cameraSpeedTextWidth = Style.Current.FontMedium.MeasureText("0.00").X;
// Camera Settings Widget
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
@@ -801,7 +801,7 @@ namespace FlaxEditor.Viewport
#region View mode widget
largestText = "Brightness";
- textSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, largestText);
+ textSize = Style.Current.FontMedium.MeasureText(largestText);
xLocationForExtras = textSize.X + 5;
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
@@ -1233,8 +1233,8 @@ namespace FlaxEditor.Viewport
color = Color.Yellow;
var text = string.Format("FPS: {0}", fps);
var font = Style.Current.FontMedium;
- FallbackTextUtils.DrawText(font, text, new Rectangle(Float2.One, Size), Color.Black);
- FallbackTextUtils.DrawText(font, text, new Rectangle(Float2.Zero, Size), color);
+ Render2D.DrawText(font, text, new Rectangle(Float2.One, Size), Color.Black);
+ Render2D.DrawText(font, text, new Rectangle(Float2.Zero, Size), color);
}
}
@@ -1814,7 +1814,7 @@ namespace FlaxEditor.Viewport
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
- FallbackTextUtils.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Viewport/Previews/AnimationPreview.cs b/Source/Editor/Viewport/Previews/AnimationPreview.cs
index c4ada83c4..1679a36bc 100644
--- a/Source/Editor/Viewport/Previews/AnimationPreview.cs
+++ b/Source/Editor/Viewport/Previews/AnimationPreview.cs
@@ -96,11 +96,11 @@ namespace FlaxEditor.Viewport.Previews
var skinnedModel = SkinnedModel;
if (skinnedModel == null)
{
- FallbackTextUtils.DrawText(style.FontLarge, "Missing Base Model", new Rectangle(Float2.Zero, Size), Color.Red, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapWords);
+ Render2D.DrawText(style.FontLarge, "Missing Base Model", new Rectangle(Float2.Zero, Size), Color.Red, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapWords);
}
else if (!skinnedModel.IsLoaded)
{
- FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Viewport/Previews/ModelPreview.cs b/Source/Editor/Viewport/Previews/ModelPreview.cs
index b31776bf6..a6496aafe 100644
--- a/Source/Editor/Viewport/Previews/ModelPreview.cs
+++ b/Source/Editor/Viewport/Previews/ModelPreview.cs
@@ -409,8 +409,8 @@ namespace FlaxEditor.Viewport.Previews
}
var font = Style.Current.FontMedium;
var pos = new Float2(10, 50);
- FallbackTextUtils.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
- FallbackTextUtils.DrawText(font, text, new Rectangle(pos, Size), Color.White);
+ Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
+ Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White);
}
}
diff --git a/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs b/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs
index a6eb721ce..c6ce5a7b5 100644
--- a/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs
+++ b/Source/Editor/Viewport/Previews/ParticleSystemPreview.cs
@@ -254,7 +254,7 @@ namespace FlaxEditor.Viewport.Previews
if (_showParticlesCounter)
{
var count = _previewEffect.ParticlesCount;
- FallbackTextUtils.DrawText(
+ Render2D.DrawText(
Style.Current.FontSmall,
"Particles: " + count,
new Rectangle(Float2.Zero, Size),
diff --git a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs
index 6c02c019a..8bcc506d9 100644
--- a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs
+++ b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs
@@ -161,8 +161,8 @@ namespace FlaxEditor.Viewport.Previews
}
var font = Style.Current.FontMedium;
var pos = new Float2(10, 50);
- FallbackTextUtils.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
- FallbackTextUtils.DrawText(font, text, new Rectangle(pos, Size), Color.White);
+ Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
+ Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White);
}
}
diff --git a/Source/Editor/Viewport/Previews/TexturePreview.cs b/Source/Editor/Viewport/Previews/TexturePreview.cs
index 5e7594e9c..ec10bb019 100644
--- a/Source/Editor/Viewport/Previews/TexturePreview.cs
+++ b/Source/Editor/Viewport/Previews/TexturePreview.cs
@@ -103,7 +103,7 @@ namespace FlaxEditor.Viewport.Previews
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
- FallbackTextUtils.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
}
Render2D.PopClip();
diff --git a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
index 43f990afb..77e94ae53 100644
--- a/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
+++ b/Source/Editor/Viewport/Widgets/ViewportWidgetButton.cs
@@ -123,7 +123,7 @@ namespace FlaxEditor.Viewport.Widgets
}
// Draw text
- FallbackTextUtils.DrawText(style.FontMedium, _text, textRect, style.ForegroundViewport * (IsMouseOver ? 1.0f : 0.9f), TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _text, textRect, style.ForegroundViewport * (IsMouseOver ? 1.0f : 0.9f), TextAlignment.Center, TextAlignment.Center);
}
///
@@ -163,7 +163,7 @@ namespace FlaxEditor.Viewport.Widgets
var style = Style.Current;
if (style != null && style.FontMedium)
- Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : FallbackTextUtils.MeasureText(style.FontMedium, _text).X, Icon.IsValid);
+ Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.MeasureText(_text).X, Icon.IsValid);
}
}
}
diff --git a/Source/Editor/Windows/AboutDialog.cs b/Source/Editor/Windows/AboutDialog.cs
index 8c38ed2a9..b059dadcb 100644
--- a/Source/Editor/Windows/AboutDialog.cs
+++ b/Source/Editor/Windows/AboutDialog.cs
@@ -53,7 +53,7 @@ namespace FlaxEditor.Windows
Parent = this
};
var buttonText = "Copy version info";
- var fontSize = FallbackTextUtils.MeasureText(Style.Current.FontMedium, buttonText);
+ var fontSize = Style.Current.FontMedium.MeasureText(buttonText);
var copyVersionButton = new Button(Width - fontSize.X - 8, 6, fontSize.X + 4, 20)
{
Text = buttonText,
diff --git a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs
index eb4198fd8..12eac22b5 100644
--- a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs
+++ b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs
@@ -51,7 +51,7 @@ namespace FlaxEditor.Windows.Assets
var style = Style.Current;
if (_window.Asset == null || !_window.Asset.IsLoaded)
{
- FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Windows/Assets/AnimationWindow.cs b/Source/Editor/Windows/Assets/AnimationWindow.cs
index 042cf2b37..8f88d93f6 100644
--- a/Source/Editor/Windows/Assets/AnimationWindow.cs
+++ b/Source/Editor/Windows/Assets/AnimationWindow.cs
@@ -61,7 +61,7 @@ namespace FlaxEditor.Windows.Assets
var animation = _window.Asset;
if (animation == null || !animation.IsLoaded)
{
- FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
diff --git a/Source/Editor/Windows/Assets/ModelWindow.cs b/Source/Editor/Windows/Assets/ModelWindow.cs
index d48966043..c2764a5a6 100644
--- a/Source/Editor/Windows/Assets/ModelWindow.cs
+++ b/Source/Editor/Windows/Assets/ModelWindow.cs
@@ -48,7 +48,7 @@ namespace FlaxEditor.Windows.Assets
var asset = _window.Asset;
if (asset == null || !asset.IsLoaded)
{
- FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
}
@@ -645,7 +645,7 @@ namespace FlaxEditor.Windows.Assets
if (!Proxy.Window._meshData.RequestMeshData(Proxy.Window._asset))
{
Invalidate();
- FallbackTextUtils.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
return;
}
diff --git a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
index 1e7192d9f..95827240c 100644
--- a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
+++ b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
@@ -50,7 +50,7 @@ namespace FlaxEditor.Windows.Assets
var asset = _window.Asset;
if (asset == null || !asset.IsLoaded)
{
- FallbackTextUtils.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, "Loading...", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
}
}
@@ -715,7 +715,7 @@ namespace FlaxEditor.Windows.Assets
if (!Proxy.Window.RequestMeshData())
{
Invalidate();
- FallbackTextUtils.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(Style.Current.FontMedium, "Loading...", new Rectangle(Float2.Zero, size), Color.White, TextAlignment.Center, TextAlignment.Center);
return;
}
diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs
index 67b7deddd..a1072d158 100644
--- a/Source/Editor/Windows/ContentWindow.Search.cs
+++ b/Source/Editor/Windows/ContentWindow.Search.cs
@@ -57,7 +57,7 @@ namespace FlaxEditor.Windows
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- FallbackTextUtils.DrawText(Font.GetFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
+ Render2D.DrawText(Font.GetFont(), "View", textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, textScale);
Render2D.PopClip();
// Arrow
diff --git a/Source/Editor/Windows/DebugLogWindow.cs b/Source/Editor/Windows/DebugLogWindow.cs
index 91d4f9d8c..ab0c07ec5 100644
--- a/Source/Editor/Windows/DebugLogWindow.cs
+++ b/Source/Editor/Windows/DebugLogWindow.cs
@@ -140,11 +140,11 @@ namespace FlaxEditor.Windows
Render2D.PushClip(ref clientRect);
if (LogCount == 1)
{
- FallbackTextUtils.DrawText(style.FontMedium, Desc.Title, textRect, style.Foreground);
+ Render2D.DrawText(style.FontMedium, Desc.Title, textRect, style.Foreground);
}
else if (LogCount > 1)
{
- FallbackTextUtils.DrawText(style.FontMedium, $"{Desc.Title} ({LogCount})", textRect, style.Foreground);
+ Render2D.DrawText(style.FontMedium, $"{Desc.Title} ({LogCount})", textRect, style.Foreground);
}
Render2D.PopClip();
}
diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs
index 2c0364995..4a8c11176 100644
--- a/Source/Editor/Windows/GameWindow.cs
+++ b/Source/Editor/Windows/GameWindow.cs
@@ -827,7 +827,7 @@ namespace FlaxEditor.Windows
if (Camera.MainCamera == null)
{
var style = Style.Current;
- FallbackTextUtils.DrawText(style.FontLarge, "No camera", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontLarge, "No camera", new Rectangle(Float2.Zero, Size), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center);
}
// Selected UI controls outline
@@ -866,8 +866,8 @@ namespace FlaxEditor.Windows
var alpha = Mathf.Saturate(-animTime / fadeOutTime);
var rect = new Rectangle(new Float2(6), Size - 12);
var text = "Press Shift+F11 to unlock the mouse";
- FallbackTextUtils.DrawText(style.FontSmall, text, rect + new Float2(1.0f), style.Background * alpha, TextAlignment.Near, TextAlignment.Far);
- FallbackTextUtils.DrawText(style.FontSmall, text, rect, style.Foreground * alpha, TextAlignment.Near, TextAlignment.Far);
+ Render2D.DrawText(style.FontSmall, text, rect + new Float2(1.0f), style.Background * alpha, TextAlignment.Near, TextAlignment.Far);
+ Render2D.DrawText(style.FontSmall, text, rect, style.Foreground * alpha, TextAlignment.Near, TextAlignment.Far);
}
timeout = 1.0f;
@@ -884,7 +884,7 @@ namespace FlaxEditor.Windows
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
- FallbackTextUtils.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(Style.Current.FontLarge, "Debugger breakpoint hit...", bounds, Color.White, TextAlignment.Center, TextAlignment.Center);
}
}
}
diff --git a/Source/Editor/Windows/Profiler/SingleChart.cs b/Source/Editor/Windows/Profiler/SingleChart.cs
index 25241b4c6..4f36692e5 100644
--- a/Source/Editor/Windows/Profiler/SingleChart.cs
+++ b/Source/Editor/Windows/Profiler/SingleChart.cs
@@ -138,8 +138,8 @@ namespace FlaxEditor.Windows.Profiler
var headerRect = new Rectangle(0, chartHeight, Width, TitleHeight);
var headerTextRect = new Rectangle(2, chartHeight, Width - 4, TitleHeight);
Render2D.FillRectangle(headerRect, style.BackgroundNormal);
- FallbackTextUtils.DrawText(style.FontMedium, Title, headerTextRect, style.ForegroundGrey, TextAlignment.Near, TextAlignment.Center);
- FallbackTextUtils.DrawText(style.FontMedium, _sample, headerTextRect, style.Foreground, TextAlignment.Far, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, Title, headerTextRect, style.ForegroundGrey, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _sample, headerTextRect, style.Foreground, TextAlignment.Far, TextAlignment.Center);
}
private void OnClick(ref Float2 location)
diff --git a/Source/Editor/Windows/Profiler/Timeline.cs b/Source/Editor/Windows/Profiler/Timeline.cs
index f87efdace..59a7a0e26 100644
--- a/Source/Editor/Windows/Profiler/Timeline.cs
+++ b/Source/Editor/Windows/Profiler/Timeline.cs
@@ -85,12 +85,12 @@ namespace FlaxEditor.Windows.Profiler
Render2D.DrawRectangle(bounds, color * 0.5f);
if (_nameLength < 0 && style.FontMedium)
- _nameLength = FallbackTextUtils.MeasureText(style.FontMedium, _name).X;
+ _nameLength = style.FontMedium.MeasureText(_name).X;
if (_nameLength < bounds.Width + 4)
{
Render2D.PushClip(bounds);
- FallbackTextUtils.DrawText(style.FontMedium, _name, bounds, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(style.FontMedium, _name, bounds, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center);
Render2D.PopClip();
}
}
@@ -115,7 +115,7 @@ namespace FlaxEditor.Windows.Profiler
var style = Style.Current;
var rect = new Rectangle(Float2.Zero, Size);
Render2D.PushClip(rect);
- FallbackTextUtils.DrawText(style.FontMedium, Name, rect, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapChars);
+ Render2D.DrawText(style.FontMedium, Name, rect, Style.Current.Foreground, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapChars);
Render2D.PopClip();
}
}
diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs
index 2fd990861..63ba7b960 100644
--- a/Source/Editor/Windows/SceneTreeWindow.cs
+++ b/Source/Editor/Windows/SceneTreeWindow.cs
@@ -297,7 +297,7 @@ namespace FlaxEditor.Windows
}
if (overlayText != null)
{
- FallbackTextUtils.DrawText(style.FontLarge, overlayText, GetClientArea(), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center, textWrap);
+ Render2D.DrawText(style.FontLarge, overlayText, GetClientArea(), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center, textWrap);
}
base.Draw();
diff --git a/Source/Editor/Windows/SplashScreen.cpp b/Source/Editor/Windows/SplashScreen.cpp
index cbb51ae3c..cba59191e 100644
--- a/Source/Editor/Windows/SplashScreen.cpp
+++ b/Source/Editor/Windows/SplashScreen.cpp
@@ -258,7 +258,7 @@ void SplashScreen::OnDraw()
return;
// Title
- const auto titleLength = _titleFont->MeasureText(GetTitle());
+ const auto titleLength = _titleFont->MeasureTextInternal(GetTitle());
TextLayoutOptions layout;
layout.Bounds = Rectangle(10 * s, 10 * s, width - 10 * s, 50 * s);
layout.HorizontalAlignment = TextAlignment::Near;
diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs
index f86341df3..e2b04669b 100644
--- a/Source/Editor/Windows/ToolboxWindow.cs
+++ b/Source/Editor/Windows/ToolboxWindow.cs
@@ -272,8 +272,8 @@ namespace FlaxEditor.Windows
var textRect = item.TextRect;
for (int i = 0; i < ranges.Length; i++)
{
- var start = FallbackTextUtils.GetCharPosition(font, text, ranges[i].StartIndex);
- var end = FallbackTextUtils.GetCharPosition(font, text, ranges[i].EndIndex);
+ var start = font.GetCharPosition(text, ranges[i].StartIndex);
+ var end = font.GetCharPosition(text, ranges[i].EndIndex);
highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
}
item.SetHighlights(highlights);
diff --git a/Source/Engine/Core/Config/GameSettings.h b/Source/Engine/Core/Config/GameSettings.h
index 6813f3ee2..675c26bd1 100644
--- a/Source/Engine/Core/Config/GameSettings.h
+++ b/Source/Engine/Core/Config/GameSettings.h
@@ -35,15 +35,6 @@ public:
API_FIELD(Attributes="EditorOrder(15), EditorDisplay(\"General\")")
String CopyrightNotice;
- ///
- /// The copyright note used for content signing (eg. source code header).
- ///
- API_FIELD(Attributes = "EditorOrder(1200), EditorDisplay(\"Other Settings\")")
- bool EnableFontFallback;
-
- API_FIELD(Attributes = "EditorOrder(1205), EditorDisplay(\"Other Settings\")")
- FontFallbackList* FontFallbacks;
-
///
/// The default application icon.
///
diff --git a/Source/Engine/Core/Config/GraphicsSettings.h b/Source/Engine/Core/Config/GraphicsSettings.h
index 81d80cb35..7abfbb048 100644
--- a/Source/Engine/Core/Config/GraphicsSettings.h
+++ b/Source/Engine/Core/Config/GraphicsSettings.h
@@ -6,6 +6,8 @@
#include "Engine/Graphics/Enums.h"
#include "Engine/Graphics/PostProcessSettings.h"
+class FontFallbackList;
+
///
/// Graphics rendering settings.
///
@@ -118,6 +120,18 @@ public:
API_FIELD(Attributes="EditorOrder(10000), EditorDisplay(\"Post Process Settings\", EditorDisplayAttribute.InlineStyle)")
PostProcessSettings PostProcessSettings;
+ ///
+ ///
+ ///
+ API_FIELD(Attributes = "EditorOrder(12000), EditorDisplay(\"Text Render Settings\", EditorDisplayAttribute.InlineStyle)")
+ bool EnableFontFallback = true;
+
+ ///
+ ///
+ ///
+ API_FIELD(Attributes = "EditorOrder(12005), EditorDisplay(\"Text Render Settings\", EditorDisplayAttribute.InlineStyle)")
+ FontFallbackList* FallbackFonts;
+
private:
///
/// Renamed UeeHDRProbes into UseHDRProbes
diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp
index f91c58cea..20f29288b 100644
--- a/Source/Engine/Graphics/Graphics.cpp
+++ b/Source/Engine/Graphics/Graphics.cpp
@@ -8,6 +8,7 @@
#include "Engine/Core/Config/GraphicsSettings.h"
#include "Engine/Engine/CommandLine.h"
#include "Engine/Engine/EngineService.h"
+#include "Engine/Render2D/Render2D.h"
bool Graphics::UseVSync = false;
Quality Graphics::AAQuality = Quality::Medium;
@@ -69,6 +70,9 @@ void GraphicsSettings::Apply()
Graphics::GIQuality = GIQuality;
Graphics::PostProcessSettings = ::PostProcessSettings();
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
+
+ Render2D::EnableFontFallback = EnableFontFallback;
+ Render2D::FallbackFonts = FallbackFonts;
}
void Graphics::DisposeDevice()
diff --git a/Source/Engine/Render2D/FallbackTextUtils.cs b/Source/Engine/Render2D/FallbackTextUtils.cs
deleted file mode 100644
index 486a354bf..000000000
--- a/Source/Engine/Render2D/FallbackTextUtils.cs
+++ /dev/null
@@ -1,268 +0,0 @@
-
-using System.Runtime.CompilerServices;
-
-namespace FlaxEngine
-{
- ///
- /// A collection of functions to handle text rendering with fallback font
- ///
- public static class FallbackTextUtils
- {
- public static FallbackFonts Fallbacks
- {
- get; set;
- } = null;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void DrawText(Font font, string text, Color color, ref TextLayoutOptions layout, MaterialBase customMaterial = null, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- Render2D.DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
- }
- else
- {
- Render2D.DrawText(font, text, color, ref layout, customMaterial);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void DrawText(Font font, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
- {
- var layout = new TextLayoutOptions
- {
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
- if (Fallbacks != null && useFallback)
- {
- Render2D.DrawText(font, Fallbacks, text, color, ref layout);
- }
- else
- {
- Render2D.DrawText(font, text, color, ref layout);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void DrawText(Font font, MaterialBase customMaterial, string text, Rectangle layoutRect, Color color, TextAlignment horizontalAlignment = TextAlignment.Near, TextAlignment verticalAlignment = TextAlignment.Near, TextWrapping textWrapping = TextWrapping.NoWrap, float baseLinesGapScale = 1.0f, float scale = 1.0f, bool useFallback = true)
- {
- var layout = new TextLayoutOptions
- {
- Bounds = layoutRect,
- HorizontalAlignment = horizontalAlignment,
- VerticalAlignment = verticalAlignment,
- TextWrapping = textWrapping,
- Scale = scale,
- BaseLinesGapScale = baseLinesGapScale,
- };
-
- if (Fallbacks != null && useFallback)
- {
- Render2D.DrawText(font, Fallbacks, text, color, ref layout, customMaterial);
- }
- else
- {
- Render2D.DrawText(font, text, color, ref layout, customMaterial);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 MeasureText(Font font, string text, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.MeasureText(Fallbacks, text);
- }
- else
- {
- return font.MeasureText(text);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 MeasureText(Font font, string text, ref TextRange textRange, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.MeasureText(Fallbacks, text, ref textRange);
- }
- else
- {
- return font.MeasureText(text, ref textRange);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 MeasureText(Font font, string text, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.MeasureText(Fallbacks, text, ref layout);
- }
- else
- {
- return font.MeasureText(text, ref layout);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 MeasureText(Font font, string text, ref TextRange textRange, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.MeasureText(Fallbacks, text, ref textRange, ref layout);
- }
- else
- {
- return font.MeasureText(text, ref textRange, ref layout);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int HitTestText(Font font, string text, Float2 location, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.HitTestText(Fallbacks, text, location);
- }
- else
- {
- return font.HitTestText(text, location);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int HitTestText(Font font, string text, ref TextRange textRange, Float2 location, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.HitTestText(Fallbacks, text, ref textRange, location);
- }
- else
- {
- return font.HitTestText(text, ref textRange, location);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int HitTestText(Font font, string text, Float2 location, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.HitTestText(Fallbacks, text, location, ref layout);
- }
- else
- {
- return font.HitTestText(text, location, ref layout);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int HitTestText(Font font, string text, ref TextRange textRange, Float2 location, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.HitTestText(Fallbacks, text, ref textRange, location, ref layout);
- }
- else
- {
- return font.HitTestText(text, ref textRange, location, ref layout);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 GetCharPosition(Font font, string text, int index, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.GetCharPosition(Fallbacks, text, index);
- }
- else
- {
- return font.GetCharPosition(text, index);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.GetCharPosition(Fallbacks, text, ref textRange, index);
- }
- else
- {
- return font.GetCharPosition(text, ref textRange, index);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 GetCharPosition(Font font, string text, int index, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.GetCharPosition(Fallbacks, text, index, ref layout);
- }
- else
- {
- return font.GetCharPosition(text, index, ref layout);
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Float2 GetCharPosition(Font font, string text, ref TextRange textRange, int index, ref TextLayoutOptions layout, bool useFallback = true)
- {
- if (Fallbacks != null && useFallback)
- {
- return font.GetCharPosition(Fallbacks, text, ref textRange, index, ref layout);
- }
- else
- {
- return font.GetCharPosition(text, ref textRange, index, ref layout);
- }
- }
-
- ///
- /// Gets the max font height among the font and all fallback fonts of the same size.
- ///
- /// The primary font to use.
- /// The fallback fonts.
- /// The max height.
- public static float GetMaxHeight(Font font, FallbackFonts fallbacks)
- {
- float height = font.Height;
-
- var fallbackFonts = fallbacks.GetFontList(font.Size);
- foreach (var item in fallbackFonts)
- {
- height = Mathf.Max(height, item.Height);
- }
-
- return height;
- }
-
- ///
- /// Gets the max font height among the font and all fallback fonts of the same size.
- ///
- /// The primary font to use.
- /// Whether to enable fallback fonts, uses if true.
- /// The max height.
- public static float GetMaxHeight(Font font, bool useFallback = true)
- {
- if(Fallbacks != null && useFallback)
- {
- return GetMaxHeight(font, Fallbacks);
- }
- else
- {
- return font.Height;
- }
- }
- }
-}
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index 5d029ca5e..9f28aac01 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -103,6 +103,18 @@ void Font::Invalidate()
_characters.Clear();
}
+inline API_FUNCTION() float Font::GetMaxHeight(FontFallbackList* fallbacks) const
+{
+ float height = GetHeight();
+ auto& fallbackFonts = fallbacks->GetFontList(GetSize());
+ for (int32 i = 0; i < fallbackFonts.Count(); i++)
+ {
+ height = Math::Max(height, static_cast(fallbackFonts[i]->GetHeight()));
+ }
+
+ return height;
+}
+
void Font::ProcessText(const StringView& text, Array& outputLines, const TextLayoutOptions& layout)
{
float cursorX = 0;
@@ -548,7 +560,7 @@ void Font::ProcessText(FontFallbackList* fallbacks, const StringView& text, Arra
}
}
-Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout)
+Float2 Font::MeasureTextInternal(const StringView& text, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.IsEmpty())
@@ -569,7 +581,7 @@ Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout
return max;
}
-Float2 Font::MeasureText(FontFallbackList* fallbacks, const StringView& text, const TextLayoutOptions& layout)
+Float2 Font::MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.IsEmpty())
@@ -590,7 +602,7 @@ Float2 Font::MeasureText(FontFallbackList* fallbacks, const StringView& text, co
return max;
}
-int32 Font::HitTestText(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
+int32 Font::HitTestTextInternal(const StringView& text, const Float2& location, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.Length() <= 0)
@@ -664,7 +676,7 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te
return smallestIndex;
}
-int32 Font::HitTestText(FontFallbackList* fallbacks, const StringView& text, const Float2& location, const TextLayoutOptions& layout)
+int32 Font::HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, const Float2& location, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.Length() <= 0)
@@ -764,7 +776,7 @@ int32 Font::HitTestText(FontFallbackList* fallbacks, const StringView& text, con
return smallestIndex;
}
-Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayoutOptions& layout)
+Float2 Font::GetCharPositionInternal(const StringView& text, int32 index, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.IsEmpty())
@@ -818,7 +830,7 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
return rootOffset + Float2(lines.Last().Location.X + lines.Last().Size.X, static_cast((lines.Count() - 1) * baseLinesDistance));
}
-Float2 Font::GetCharPosition(FontFallbackList* fallbacks, const StringView& text, int32 index, const TextLayoutOptions& layout)
+Float2 Font::GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, int32 index, const TextLayoutOptions& layout)
{
// Check if there is no need to do anything
if (text.IsEmpty())
diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h
index 6bb2849e2..1fb41d032 100644
--- a/Source/Engine/Render2D/Font.h
+++ b/Source/Engine/Render2D/Font.h
@@ -8,6 +8,7 @@
#include "Engine/Content/AssetReference.h"
#include "Engine/Scripting/ScriptingObject.h"
#include "TextLayoutOptions.h"
+#include "Render2D.h"
class FontAsset;
class FontFallbackList;
@@ -402,7 +403,31 @@ public:
public:
///
- /// Processes text to get cached lines for rendering.
+ /// Gets the maximum height among the font and the fallback fonts.
+ ///
+ /// The fallback fonts.
+ /// The maximum height.
+ API_FUNCTION() float GetMaxHeight(FontFallbackList* fallbacks) const;
+
+ ///
+ /// Gets the maximum height among the font and the fallback fonts, uses the default font defined in .
+ ///
+ /// The fallback fonts.
+ /// The maximum height.
+ API_FUNCTION() FORCE_INLINE float GetMaxHeight() const
+ {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts)
+ {
+ return GetMaxHeight(Render2D::FallbackFonts);
+ }
+ else
+ {
+ return GetHeight();
+ }
+ }
+
+ ///
+ /// Processes text to get cached lines for rendering, with font fallbacking disabled.
///
/// The input text.
/// The layout properties.
@@ -410,12 +435,12 @@ public:
void ProcessText(const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, with font fallbacking disabled.
///
/// The input text.
/// The layout properties.
/// The output lines list.
- API_FUNCTION() Array ProcessText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE Array ProcessText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
{
Array lines;
ProcessText(text, lines, layout);
@@ -423,13 +448,13 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, with font fallbacking disabled.
///
/// The input text.
/// The input text range (substring range of the input text parameter).
/// The layout properties.
/// The output lines list.
- API_FUNCTION() Array ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE Array ProcessText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
{
Array lines;
ProcessText(textRange.Substring(text), lines, layout);
@@ -437,7 +462,7 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, with font fallbacking disabled.
///
/// The input text.
/// The output lines list.
@@ -447,7 +472,7 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, with font fallbacking disabled.
///
/// The input text.
/// The input text range (substring range of the input text parameter).
@@ -458,7 +483,7 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, using custom fallback options.
///
/// The input text.
/// The layout properties.
@@ -466,12 +491,12 @@ public:
void ProcessText(FontFallbackList* fallbacks, const StringView& text, Array& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, using custom fallback options.
///
/// The input text.
/// The layout properties.
/// The output lines list.
- API_FUNCTION() Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout)
{
Array lines;
ProcessText(fallbacks, text, lines, layout);
@@ -479,13 +504,13 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, using custom fallback options.
///
/// The input text.
/// The input text range (substring range of the input text parameter).
/// The layout properties.
/// The output lines list.
- API_FUNCTION() Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE Array ProcessText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
{
Array lines;
ProcessText(fallbacks, textRange.Substring(text), lines, layout);
@@ -493,7 +518,7 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, using custom fallback options.
///
/// The input text.
/// The output lines list.
@@ -503,7 +528,7 @@ public:
}
///
- /// Processes text to get cached lines for rendering.
+ /// Processes text to get cached lines for rendering, using custom fallback options.
///
/// The input text.
/// The input text range (substring range of the input text parameter).
@@ -514,122 +539,293 @@ public:
}
///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
+ /// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
///
/// The input text to test.
/// The layout properties.
/// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+ API_FUNCTION() Float2 MeasureTextInternal(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
+ /// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
///
/// The input text to test.
/// The input text range (substring range of the input text parameter).
/// The layout properties.
/// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
{
- return MeasureText(textRange.Substring(text), layout);
+ return MeasureTextInternal(textRange.Substring(text), layout);
}
///
- /// Measures minimum size of the rectangle that will be needed to draw given text
+ /// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
+ /// .
+ /// The input text to test.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(const StringView& text)
+ {
+ return MeasureTextInternal(text, TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, with font fallbacking disabled.
+ /// .
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ {
+ return MeasureTextInternal(textRange.Substring(text), TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return MeasureTextInternal(fallbacks, textRange.Substring(text), layout);
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
+ /// .
+ /// The input text to test.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text)
+ {
+ return MeasureTextInternal(fallbacks, text, TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, using custom fallback options.
+ /// .
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
+ {
+ return MeasureTextInternal(fallbacks, textRange.Substring(text), TextLayoutOptions());
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in .
+ ///
+ /// The input text to test.
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout) {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return MeasureTextInternal(Render2D::FallbackFonts, text, layout);
+ }
+ else {
+ return MeasureTextInternal(text, layout);
+ }
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in .
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The layout properties.
+ /// The minimum size for that text and fot to render properly.
+ API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return MeasureTextInternal(Render2D::FallbackFonts, textRange.Substring(text), layout);
+ }
+ else {
+ return MeasureTextInternal(textRange.Substring(text), layout);
+ }
+ }
+
+ ///
+ /// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in .
/// .
/// The input text to test.
/// The minimum size for that text and fot to render properly.
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text)
{
- return MeasureText(text, TextLayoutOptions());
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return MeasureTextInternal(Render2D::FallbackFonts, text, TextLayoutOptions());
+ }
+ else {
+ return MeasureTextInternal(text, TextLayoutOptions());
+ }
}
///
- /// Measures minimum size of the rectangle that will be needed to draw given text
+ /// Measures minimum size of the rectangle that will be needed to draw given text, follows the fallback settings defined in .
/// .
/// The input text to test.
/// The input text range (substring range of the input text parameter).
/// The minimum size for that text and fot to render properly.
API_FUNCTION() FORCE_INLINE Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextRange& textRange)
{
- return MeasureText(textRange.Substring(text), TextLayoutOptions());
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return MeasureTextInternal(Render2D::FallbackFonts, textRange.Substring(text), TextLayoutOptions());
+ }
+ else {
+ return MeasureTextInternal(textRange.Substring(text), TextLayoutOptions());
+ }
}
///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
- ///
- /// The input text to test.
- /// The layout properties.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The layout properties.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- return MeasureText(fallbacks, textRange.Substring(text), layout);
- }
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text
- /// .
- /// The input text to test.
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() FORCE_INLINE Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text)
- {
- return MeasureText(fallbacks, text, TextLayoutOptions());
- }
-
- ///
- /// Measures minimum size of the rectangle that will be needed to draw given text
- /// .
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The minimum size for that text and fot to render properly.
- API_FUNCTION() FORCE_INLINE Float2 MeasureText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange)
- {
- return MeasureText(fallbacks, textRange.Substring(text), TextLayoutOptions());
- }
-
- ///
- /// Calculates hit character index at given location.
+ /// Calculates hit character index at given location, with font fallbacking disabled.
///
/// The input text to test.
/// The input location to test.
/// The text layout properties.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
+ API_FUNCTION() int32 HitTestTextInternal(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
///
- /// Calculates hit character index at given location.
+ /// Calculates hit character index at given location, with font fallbacking disabled.
///
/// The input text to test.
/// The input text range (substring range of the input text parameter).
/// The input location to test.
/// The text layout properties.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
{
- return HitTestText(textRange.Substring(text), location, layout);
+ return HitTestTextInternal(textRange.Substring(text), location, layout);
}
///
- /// Calculates hit character index at given location.
+ /// Calculates hit character index at given location, with font fallbacking disabled.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(const StringView& text, const Float2& location)
+ {
+ return HitTestTextInternal(text, location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location, with font fallbacking disabled.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
+ {
+ return HitTestTextInternal(textRange.Substring(text), location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Calculates hit character index at given location, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return HitTestTextInternal(fallbacks, textRange.Substring(text), location, layout);
+ }
+
+ ///
+ /// Calculates hit character index at given location, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, const Float2& location)
+ {
+ return HitTestTextInternal(fallbacks, text, location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestTextInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
+ {
+ return HitTestTextInternal(fallbacks, textRange.Substring(text), location, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates hit character index at given location, follows the fallback settings defined in .
+ ///
+ /// The input text to test.
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout) {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return HitTestTextInternal(Render2D::FallbackFonts, text, location, layout);
+ }
+ else {
+ return HitTestTextInternal(text, location, layout);
+ }
+ }
+
+ ///
+ /// Calculates hit character index at given location, follows the fallback settings defined in .
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The input location to test.
+ /// The text layout properties.
+ /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
+ API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return HitTestTextInternal(Render2D::FallbackFonts, textRange.Substring(text), location, layout);
+ }
+ else {
+ return HitTestTextInternal(textRange.Substring(text), location, layout);
+ }
+
+ }
+
+ ///
+ /// Calculates hit character index at given location, follows the fallback settings defined in .
///
/// The input text to test.
/// The input location to test.
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, const Float2& location)
{
- return HitTestText(text, location, TextLayoutOptions());
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return HitTestTextInternal(Render2D::FallbackFonts, text, location, TextLayoutOptions());
+ }
+ else {
+ return HitTestTextInternal(text, location, TextLayoutOptions());
+ }
}
///
- /// Calculates hit character index at given location.
+ /// Calculates hit character index at given location, follows the fallback settings defined in .
///
/// The input text to test.
/// The input text range (substring range of the input text parameter).
@@ -637,89 +833,156 @@ public:
/// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
API_FUNCTION() FORCE_INLINE int32 HitTestText(const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
{
- return HitTestText(textRange.Substring(text), location, TextLayoutOptions());
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return HitTestTextInternal(Render2D::FallbackFonts, textRange.Substring(text), location, TextLayoutOptions());
+ }
+ else {
+ return HitTestTextInternal(textRange.Substring(text), location, TextLayoutOptions());
+ }
}
///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input location to test.
- /// The text layout properties.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The input location to test.
- /// The text layout properties.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- return HitTestText(fallbacks, textRange.Substring(text), location, layout);
- }
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input location to test.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() FORCE_INLINE int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, const Float2& location)
- {
- return HitTestText(fallbacks, text, location, TextLayoutOptions());
- }
-
- ///
- /// Calculates hit character index at given location.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The input location to test.
- /// The selected character position index (can be equal to text length if location is outside of the layout rectangle).
- API_FUNCTION() FORCE_INLINE int32 HitTestText(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Float2& location)
- {
- return HitTestText(fallbacks, textRange.Substring(text), location, TextLayoutOptions());
- }
-
- ///
- /// Calculates character position for given text and character index.
+ /// Calculates character position for given text and character index, with font fallbacking disabled.
///
/// The input text to test.
/// The text position to get coordinates of.
/// The text layout properties.
/// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+ API_FUNCTION() Float2 GetCharPositionInternal(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
///
- /// Calculates character position for given text and character index.
+ /// Calculates character position for given text and character index, with font fallbacking disabled.
///
/// The input text to test.
/// The input text range (substring range of the input text parameter).
/// The text position to get coordinates of.
/// The text layout properties.
/// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
{
- return GetCharPosition(textRange.Substring(text), index, layout);
+ return GetCharPositionInternal(textRange.Substring(text), index, layout);
}
///
- /// Calculates character position for given text and character index
+ /// Calculates character position for given text and character index, with font fallbacking disabled.
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(const StringView& text, int32 index)
+ {
+ return GetCharPositionInternal(text, index, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index, with font fallbacking disabled.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
+ {
+ return GetCharPositionInternal(textRange.Substring(text), index, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
+
+ ///
+ /// Calculates character position for given text and character index, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ return GetCharPositionInternal(fallbacks, textRange.Substring(text), index, layout);
+ }
+
+ ///
+ /// Calculates character position for given text and character index, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, int32 index)
+ {
+ return GetCharPositionInternal(fallbacks, text, index, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index, using custom fallback options.
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPositionInternal(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
+ {
+ return GetCharPositionInternal(fallbacks, textRange.Substring(text), index, TextLayoutOptions());
+ }
+
+ ///
+ /// Calculates character position for given text and character index, follows the fallback settings defined in .
+ ///
+ /// The input text to test.
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout) {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return GetCharPositionInternal(Render2D::FallbackFonts, text, index, layout);
+ }
+ else {
+ return GetCharPositionInternal(text, index, layout);
+ }
+ }
+
+ ///
+ /// Calculates character position for given text and character index, follows the fallback settings defined in .
+ ///
+ /// The input text to test.
+ /// The input text range (substring range of the input text parameter).
+ /// The text position to get coordinates of.
+ /// The text layout properties.
+ /// The character position (upper left corner which can be used for a caret position).
+ API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
+ {
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return GetCharPositionInternal(Render2D::FallbackFonts, textRange.Substring(text), index, layout);
+ }
+ else {
+ return GetCharPositionInternal(textRange.Substring(text), index, layout);
+ }
+ }
+
+ ///
+ /// Calculates character position for given text and character index, follows the fallback settings defined in .
///
/// The input text to test.
/// The text position to get coordinates of.
/// The character position (upper left corner which can be used for a caret position).
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, int32 index)
{
- return GetCharPosition(text, index, TextLayoutOptions());
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return GetCharPositionInternal(Render2D::FallbackFonts, text, index, TextLayoutOptions());
+ }
+ else {
+ return GetCharPositionInternal(text, index, TextLayoutOptions());
+ }
}
///
- /// Calculates character position for given text and character index
+ /// Calculates character position for given text and character index, follows the fallback settings defined in .
///
/// The input text to test.
/// The input text range (substring range of the input text parameter).
@@ -727,52 +990,12 @@ public:
/// The character position (upper left corner which can be used for a caret position).
API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
{
- return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
- }
-
- ///
- /// Calculates character position for given text and character index.
- ///
- /// The input text to test.
- /// The text position to get coordinates of.
- /// The text layout properties.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
-
- ///
- /// Calculates character position for given text and character index.
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The text position to get coordinates of.
- /// The text layout properties.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout)
- {
- return GetCharPosition(fallbacks, textRange.Substring(text), index, layout);
- }
-
- ///
- /// Calculates character position for given text and character index
- ///
- /// The input text to test.
- /// The text position to get coordinates of.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, int32 index)
- {
- return GetCharPosition(fallbacks, text, index, TextLayoutOptions());
- }
-
- ///
- /// Calculates character position for given text and character index
- ///
- /// The input text to test.
- /// The input text range (substring range of the input text parameter).
- /// The text position to get coordinates of.
- /// The character position (upper left corner which can be used for a caret position).
- API_FUNCTION() FORCE_INLINE Float2 GetCharPosition(FontFallbackList* fallbacks, const StringView& text, API_PARAM(Ref) const TextRange& textRange, int32 index)
- {
- return GetCharPosition(fallbacks, textRange.Substring(text), index, TextLayoutOptions());
+ if (Render2D::EnableFontFallback && Render2D::FallbackFonts) {
+ return GetCharPositionInternal(Render2D::FallbackFonts, textRange.Substring(text), index, TextLayoutOptions());
+ }
+ else {
+ return GetCharPositionInternal(textRange.Substring(text), index, TextLayoutOptions());
+ }
}
///
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index 351bb3700..fa52baff0 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -182,6 +182,8 @@ struct ClipMask
};
Render2D::RenderingFeatures Render2D::Features = RenderingFeatures::VertexSnapping;
+bool Render2D::EnableFontFallback = true;
+FontFallbackList* Render2D::FallbackFonts = nullptr;
namespace
{
diff --git a/Source/Engine/Render2D/Render2D.cs b/Source/Engine/Render2D/Render2D.cs
index 6e4f1dc1d..b36f155df 100644
--- a/Source/Engine/Render2D/Render2D.cs
+++ b/Source/Engine/Render2D/Render2D.cs
@@ -102,7 +102,7 @@ namespace FlaxEngine
}
///
- /// Draws a text.
+ /// Draws a text, follows the font fallback settings defined in .
///
/// The font to use.
/// The text to render.
@@ -128,7 +128,7 @@ namespace FlaxEngine
}
///
- /// Draws a text using a custom material shader. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling).
+ /// Draws a text using a custom material shader. Given material must have GUI domain and a public parameter named Font (texture parameter used for a font atlas sampling). Follows the font fallback settings defined in .
///
/// The font to use.
/// Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h
index fa59b1d79..5813d6f87 100644
--- a/Source/Engine/Render2D/Render2D.h
+++ b/Source/Engine/Render2D/Render2D.h
@@ -54,8 +54,6 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
};
public:
- API_FIELD() static bool EnableFontFallback;
- API_FIELD() static FontFallbackList* FallbackFonts;
///
/// Checks if interface is during rendering phrase (Draw calls may be performed without failing).
@@ -72,6 +70,10 @@ public:
///
API_FIELD() static RenderingFeatures Features;
+ API_FIELD() static bool EnableFontFallback;
+
+ API_FIELD() static FontFallbackList* FallbackFonts;
+
///
/// Called when frame rendering begins by the graphics device.
///
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index feb34418b..02337411b 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -261,7 +261,7 @@ namespace FlaxEngine.GUI
Render2D.DrawRectangle(clientRect, borderColor, BorderThickness);
// Draw text
- FallbackTextUtils.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index 3b298b136..ecca2978f 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -475,7 +475,7 @@ namespace FlaxEngine.GUI
var font = Font.GetFont();
for (int i = 0; i < _items.Count; i++)
{
- itemsWidth = Mathf.Max(itemsWidth, itemsMargin + 4 + FallbackTextUtils.MeasureText(font, _items[i]).X);
+ itemsWidth = Mathf.Max(itemsWidth, itemsMargin + 4 + font.MeasureText(_items[i]).X);
}
*/
var itemsWidth = Width;
@@ -673,7 +673,7 @@ namespace FlaxEngine.GUI
var textRect = new Rectangle(margin, 0, clientRect.Width - boxSize - 2.0f * margin, clientRect.Height);
Render2D.PushClip(textRect);
var textColor = TextColor;
- FallbackTextUtils.DrawText(Font.GetFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(Font.GetFont(), FontMaterial, _items[_selectedIndex], textRect, enabled ? textColor : textColor * 0.5f, TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index 3d1caad28..3c7c04fb2 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -233,7 +233,7 @@ namespace FlaxEngine.GUI
}
}
- FallbackTextUtils.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
Render2D.PopClip();
@@ -254,7 +254,7 @@ namespace FlaxEngine.GUI
layout.Bounds.Size.X = Width - Margin.Width;
else if (_autoWidth && !_autoHeight)
layout.Bounds.Size.Y = Height - Margin.Height;
- _textSize = FallbackTextUtils.MeasureText(font, _text, ref layout);
+ _textSize = font.MeasureText(_text, ref layout);
_textSize.Y *= BaseLinesGapScale;
// Check if size is controlled via text
diff --git a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
index 8d7858af0..46f0fb1ad 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
@@ -154,7 +154,7 @@ namespace FlaxEngine.GUI
if (!font)
break;
height = font.Height / DpiScale;
- return textBlock.Bounds.Location + FallbackTextUtils.GetCharPosition(font, _text, ref textBlock.Range, index - textBlock.Range.StartIndex);
+ return textBlock.Bounds.Location + font.GetCharPosition(_text, ref textBlock.Range, index - textBlock.Range.StartIndex);
}
}
@@ -196,7 +196,7 @@ namespace FlaxEngine.GUI
var font = textBlock.Style.Font.GetFont();
if (!font && textBlock.Range.Length > 0)
break;
- return FallbackTextUtils.HitTestText(font, _text, ref textBlock.Range, location - textBlock.Bounds.Location) + textBlock.Range.StartIndex;
+ return font.HitTestText(_text, ref textBlock.Range, location - textBlock.Bounds.Location) + textBlock.Range.StartIndex;
}
}
@@ -288,8 +288,8 @@ namespace FlaxEngine.GUI
// Selection
if (hasSelection && textBlock.Style.BackgroundSelectedBrush != null && textBlock.Range.Intersect(ref selection))
{
- var leftEdge = selection.StartIndex <= textBlock.Range.StartIndex ? textBlock.Bounds.UpperLeft : FallbackTextUtils.GetCharPosition(font, _text, selection.StartIndex);
- var rightEdge = selection.EndIndex >= textBlock.Range.EndIndex ? textBlock.Bounds.UpperRight : FallbackTextUtils.GetCharPosition(font, _text, selection.EndIndex);
+ var leftEdge = selection.StartIndex <= textBlock.Range.StartIndex ? textBlock.Bounds.UpperLeft : font.GetCharPosition(_text, selection.StartIndex);
+ var rightEdge = selection.EndIndex >= textBlock.Range.EndIndex ? textBlock.Bounds.UpperRight : font.GetCharPosition(_text, selection.EndIndex);
float height = font.Height / DpiScale;
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
alpha *= alpha;
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index b1861df56..3c0d55008 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -104,7 +104,7 @@ namespace FlaxEngine.GUI
return Float2.Zero;
}
- return FallbackTextUtils.MeasureText(font, _text, ref _layout);
+ return font.MeasureText(_text, ref _layout);
}
///
@@ -117,8 +117,8 @@ namespace FlaxEngine.GUI
return Float2.Zero;
}
- height = FallbackTextUtils.GetMaxHeight(font) / DpiScale;
- return FallbackTextUtils.GetCharPosition(font, _text, index, ref _layout);
+ height = font.GetMaxHeight() / DpiScale;
+ return font.GetCharPosition(_text, index, ref _layout);
}
///
@@ -130,7 +130,7 @@ namespace FlaxEngine.GUI
return 0;
}
- return FallbackTextUtils.HitTestText(font, _text, location, ref _layout);
+ return font.HitTestText(_text, location, ref _layout);
}
///
@@ -169,9 +169,9 @@ namespace FlaxEngine.GUI
// Check if sth is selected to draw selection
if (HasSelection)
{
- var leftEdge = FallbackTextUtils.GetCharPosition(font, _text, SelectionLeft, ref _layout);
- var rightEdge = FallbackTextUtils.GetCharPosition(font, _text, SelectionRight, ref _layout);
- float fontHeight = FallbackTextUtils.GetMaxHeight(font) / DpiScale;
+ var leftEdge = font.GetCharPosition(_text, SelectionLeft, ref _layout);
+ var rightEdge = font.GetCharPosition(_text, SelectionRight, ref _layout);
+ float fontHeight = font.GetMaxHeight() / DpiScale;
// Draw selection background
float alpha = Mathf.Min(1.0f, Mathf.Cos(_animateTime * BackgroundSelectedFlashSpeed) * 0.5f + 1.3f);
@@ -211,11 +211,11 @@ namespace FlaxEngine.GUI
var color = TextColor;
if (!enabled)
color *= 0.6f;
- FallbackTextUtils.DrawText(font, _text, color, ref _layout, TextMaterial);
+ Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
}
else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
{
- FallbackTextUtils.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
}
// Caret
diff --git a/Source/Engine/UI/GUI/Panels/DropPanel.cs b/Source/Engine/UI/GUI/Panels/DropPanel.cs
index 123e0f034..66e7413eb 100644
--- a/Source/Engine/UI/GUI/Panels/DropPanel.cs
+++ b/Source/Engine/UI/GUI/Panels/DropPanel.cs
@@ -374,7 +374,7 @@ namespace FlaxEngine.GUI
textColor *= 0.6f;
}
- FallbackTextUtils.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
+ Render2D.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
if (!_isClosed && EnableContainmentLines)
{
diff --git a/Source/Engine/UI/GUI/Style.cs b/Source/Engine/UI/GUI/Style.cs
index f4fca13eb..6092f0f72 100644
--- a/Source/Engine/UI/GUI/Style.cs
+++ b/Source/Engine/UI/GUI/Style.cs
@@ -69,12 +69,6 @@ namespace FlaxEngine.GUI
set => _fontSmall = new FontReference(value);
}
- ///
- /// The fallback fonts to use if the primary font can't render the char.
- ///
- [EditorOrder(50)]
- public FallbackFonts Fallbacks;
-
///
/// The background color.
///
diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs
index 41d06b017..8d35c21b9 100644
--- a/Source/Engine/UI/GUI/Tooltip.cs
+++ b/Source/Engine/UI/GUI/Tooltip.cs
@@ -234,7 +234,7 @@ namespace FlaxEngine.GUI
Render2D.FillRectangle(new Rectangle(1.1f, 1.1f, Width - 2, Height - 2), style.Background);
// Tooltip text
- FallbackTextUtils.DrawText(
+ Render2D.DrawText(
style.FontMedium,
_currentText,
GetClientArea(),
From 6ab1663a1429591d0678bab1790e3e0b4a9628ca Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Sun, 3 Dec 2023 15:18:27 +0800
Subject: [PATCH 14/16] Add missing xml annotations
---
Source/Engine/Core/Config/GraphicsSettings.h | 4 +--
Source/Engine/Render2D/Render2D.h | 26 ++++++++++++++++++++
Source/Engine/UI/GUI/Style.cs | 1 -
Source/Engine/UI/GUI/Tooltip.cs | 1 -
4 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/Source/Engine/Core/Config/GraphicsSettings.h b/Source/Engine/Core/Config/GraphicsSettings.h
index 7abfbb048..e109a55e4 100644
--- a/Source/Engine/Core/Config/GraphicsSettings.h
+++ b/Source/Engine/Core/Config/GraphicsSettings.h
@@ -121,13 +121,13 @@ public:
PostProcessSettings PostProcessSettings;
///
- ///
+ /// Whether to enable font fallbacking globally.
///
API_FIELD(Attributes = "EditorOrder(12000), EditorDisplay(\"Text Render Settings\", EditorDisplayAttribute.InlineStyle)")
bool EnableFontFallback = true;
///
- ///
+ /// The fallback fonts used for text rendering, ignored if null.
///
API_FIELD(Attributes = "EditorOrder(12005), EditorDisplay(\"Text Render Settings\", EditorDisplayAttribute.InlineStyle)")
FontFallbackList* FallbackFonts;
diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h
index 5813d6f87..6657d8542 100644
--- a/Source/Engine/Render2D/Render2D.h
+++ b/Source/Engine/Render2D/Render2D.h
@@ -281,6 +281,15 @@ public:
}
}
+ ///
+ /// Draws a text, follows the fallback settings defined in .
+ ///
+ /// The font to use.
+ /// The text to render.
+ /// The input text range (substring range of the input text parameter).
+ /// The text color.
+ /// The text location.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr) {
if (EnableFontFallback && FallbackFonts) {
DrawTextInternal(font, FallbackFonts, text, textRange, color, location, customMaterial);
@@ -290,6 +299,14 @@ public:
}
}
+ ///
+ /// Draws a text with formatting, follows the fallback settings defined in .
+ ///
+ /// The font to use.
+ /// The text to render.
+ /// The text color.
+ /// The text layout properties.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr) {
if (EnableFontFallback && FallbackFonts) {
DrawTextInternal(font, FallbackFonts, text, color, layout, customMaterial);
@@ -299,6 +316,15 @@ public:
}
}
+ ///
+ /// Draws a text with formatting, follows the fallback settings defined in .
+ ///
+ /// The font to use.
+ /// The text to render.
+ /// The input text range (substring range of the input text parameter).
+ /// The text color.
+ /// The text layout properties.
+ /// The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.
API_FUNCTION() FORCE_INLINE static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr) {
if (EnableFontFallback && FallbackFonts) {
DrawTextInternal(font, FallbackFonts, text, textRange, color, layout, customMaterial);
diff --git a/Source/Engine/UI/GUI/Style.cs b/Source/Engine/UI/GUI/Style.cs
index 6092f0f72..22b8f52af 100644
--- a/Source/Engine/UI/GUI/Style.cs
+++ b/Source/Engine/UI/GUI/Style.cs
@@ -1,6 +1,5 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
-
namespace FlaxEngine.GUI
{
///
diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs
index 8d35c21b9..734fb078f 100644
--- a/Source/Engine/UI/GUI/Tooltip.cs
+++ b/Source/Engine/UI/GUI/Tooltip.cs
@@ -243,7 +243,6 @@ namespace FlaxEngine.GUI
TextAlignment.Center,
TextWrapping.WrapWords
);
-
}
///
From 360c75355c014bdb7be5051ea41460a777781ba4 Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Sun, 3 Dec 2023 16:04:50 +0800
Subject: [PATCH 15/16] Fix build error under non-windows platforms
---
Source/Engine/Render2D/Font.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp
index 9f28aac01..9a2037b3f 100644
--- a/Source/Engine/Render2D/Font.cpp
+++ b/Source/Engine/Render2D/Font.cpp
@@ -103,7 +103,7 @@ void Font::Invalidate()
_characters.Clear();
}
-inline API_FUNCTION() float Font::GetMaxHeight(FontFallbackList* fallbacks) const
+float Font::GetMaxHeight(FontFallbackList* fallbacks) const
{
float height = GetHeight();
auto& fallbackFonts = fallbacks->GetFontList(GetSize());
From 4497b2ca7d5ee86f67d8ae19cd1db3220fe1464a Mon Sep 17 00:00:00 2001
From: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Date: Tue, 19 Dec 2023 12:36:12 +0800
Subject: [PATCH 16/16] Add fallback settings for control
---
Source/Engine/UI/GUI/Common/Label.cs | 27 ++++++++++++++++--
Source/Engine/UI/GUI/Common/TextBox.cs | 39 ++++++++++++++++++++------
2 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index 3c7c04fb2..8de54fda3 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -182,6 +182,12 @@ namespace FlaxEngine.GUI
set => _autoFitTextRange = value;
}
+ ///
+ /// Gets or sets whether to fallback when the primary font cannot render a char.
+ ///
+ [EditorOrder(120), DefaultValue(true), Tooltip("Whether to fallback when the font cannot render a char.")]
+ public bool EnableFontFallback { get; set; } = true;
+
///
/// Initializes a new instance of the class.
///
@@ -233,7 +239,23 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ if (EnableFontFallback)
+ {
+ Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
+ }
+ else
+ {
+ var layout = new TextLayoutOptions
+ {
+ Bounds = rect,
+ HorizontalAlignment = hAlignment,
+ VerticalAlignment = wAlignment,
+ TextWrapping = Wrapping,
+ Scale = scale,
+ BaseLinesGapScale = BaseLinesGapScale,
+ };
+ Render2D.DrawTextInternal(_font.GetFont(), _text, color, ref layout, Material);
+ }
if (ClipText)
Render2D.PopClip();
@@ -254,7 +276,8 @@ namespace FlaxEngine.GUI
layout.Bounds.Size.X = Width - Margin.Width;
else if (_autoWidth && !_autoHeight)
layout.Bounds.Size.Y = Height - Margin.Height;
- _textSize = font.MeasureText(_text, ref layout);
+ _textSize = EnableFontFallback ?
+ font.MeasureText(_text, ref layout) : font.MeasureTextInternal(_text, ref layout);
_textSize.Y *= BaseLinesGapScale;
// Check if size is controlled via text
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index 3c0d55008..53266a1b2 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -1,6 +1,8 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+using System.ComponentModel;
+
namespace FlaxEngine.GUI
{
///
@@ -65,6 +67,12 @@ namespace FlaxEngine.GUI
[EditorDisplay("Text Style"), EditorOrder(2022), Tooltip("The color of the selection (Transparent if not used).")]
public Color SelectionColor { get; set; }
+ ///
+ /// Gets or sets whether to fallback when the primary font cannot render a char.
+ ///
+ [EditorOrder(120), DefaultValue(true), Tooltip("Whether to fallback when the font cannot render a char.")]
+ public bool EnableFontFallback { get; set; } = true;
+
///
/// Initializes a new instance of the class.
///
@@ -104,7 +112,8 @@ namespace FlaxEngine.GUI
return Float2.Zero;
}
- return font.MeasureText(_text, ref _layout);
+ return EnableFontFallback ? font.MeasureText(_text, ref _layout) :
+ font.MeasureTextInternal(_text, ref _layout);
}
///
@@ -117,8 +126,9 @@ namespace FlaxEngine.GUI
return Float2.Zero;
}
- height = font.GetMaxHeight() / DpiScale;
- return font.GetCharPosition(_text, index, ref _layout);
+ height = (EnableFontFallback ? font.GetMaxHeight() : font.Height) / DpiScale;
+ return EnableFontFallback ? font.GetCharPosition(_text, index, ref _layout) :
+ font.GetCharPositionInternal(_text, index, ref _layout);
}
///
@@ -130,7 +140,8 @@ namespace FlaxEngine.GUI
return 0;
}
- return font.HitTestText(_text, location, ref _layout);
+ return EnableFontFallback ? font.HitTestText(_text, location, ref _layout) :
+ font.HitTestTextInternal(_text, location, ref _layout);
}
///
@@ -169,8 +180,12 @@ namespace FlaxEngine.GUI
// Check if sth is selected to draw selection
if (HasSelection)
{
- var leftEdge = font.GetCharPosition(_text, SelectionLeft, ref _layout);
- var rightEdge = font.GetCharPosition(_text, SelectionRight, ref _layout);
+ var leftEdge = EnableFontFallback ?
+ font.GetCharPosition(_text, SelectionLeft, ref _layout) :
+ font.GetCharPositionInternal(_text, SelectionLeft, ref _layout);
+ var rightEdge = EnableFontFallback ?
+ font.GetCharPosition(_text, SelectionRight, ref _layout) :
+ font.GetCharPositionInternal(_text, SelectionRight, ref _layout);
float fontHeight = font.GetMaxHeight() / DpiScale;
// Draw selection background
@@ -211,11 +226,19 @@ namespace FlaxEngine.GUI
var color = TextColor;
if (!enabled)
color *= 0.6f;
- Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
+ if (EnableFontFallback)
+ Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
+ else
+ // Draw without fallback
+ Render2D.DrawTextInternal(font, _text, color, ref _layout, TextMaterial);
}
else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
{
- Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ if (EnableFontFallback)
+ Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ else
+ // Draw without fallback
+ Render2D.DrawTextInternal(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
}
// Caret