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];