Add font fallback
Note: All the `First()` in the code are temperary workarounds to make it work and require refractoring
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
using FlaxEditor.GUI.Drag;
|
using FlaxEditor.GUI.Drag;
|
||||||
using FlaxEditor.GUI.Tree;
|
using FlaxEditor.GUI.Tree;
|
||||||
@@ -140,8 +141,8 @@ namespace FlaxEditor.Content
|
|||||||
var textRect = TextRect;
|
var textRect = TextRect;
|
||||||
for (int i = 0; i < ranges.Length; i++)
|
for (int i = 0; i < ranges.Length; i++)
|
||||||
{
|
{
|
||||||
var start = font.GetCharPosition(text, ranges[i].StartIndex);
|
var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
|
||||||
var end = font.GetCharPosition(text, ranges[i].EndIndex);
|
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));
|
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
|
||||||
}
|
}
|
||||||
isThisVisible = true;
|
isThisVisible = true;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.Actions;
|
using FlaxEditor.Actions;
|
||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
@@ -42,7 +43,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
// Add script button
|
// Add script button
|
||||||
var buttonText = "Add script";
|
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;
|
float addScriptButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
|
||||||
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
|
var buttonHeight = (textSize.Y < 18) ? 18 : textSize.Y + 4;
|
||||||
_addScriptsButton = new Button
|
_addScriptsButton = new Button
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
// Info
|
// Info
|
||||||
var info = new Label(0, title.Bottom, DialogWidth, InfoHeight)
|
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",
|
Text = "Shift: also set bounds\nControl: also set pivot",
|
||||||
Parent = this
|
Parent = this
|
||||||
};
|
};
|
||||||
@@ -423,7 +423,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
// Set control type button
|
// Set control type button
|
||||||
var space = layout.Space(20);
|
var space = layout.Space(20);
|
||||||
var buttonText = "Set Type";
|
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;
|
float setTypeButtonWidth = (textSize.X < 60.0f) ? 60.0f : textSize.X + 4;
|
||||||
var setTypeButton = new Button
|
var setTypeButton = new Button
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Editors
|
namespace FlaxEditor.CustomEditors.Editors
|
||||||
{
|
{
|
||||||
@@ -100,7 +101,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
_linkButton.Clicked += ToggleLink;
|
_linkButton.Clicked += ToggleLink;
|
||||||
ToggleEnabled();
|
ToggleEnabled();
|
||||||
SetLinkStyle();
|
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;
|
_linkButton.LocalX += textSize.X + 10;
|
||||||
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
|
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -631,7 +631,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
TooltipText = "Edit...",
|
TooltipText = "Edit...",
|
||||||
Parent = _label,
|
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)
|
if (textSize.Y > button.Width)
|
||||||
button.Width = textSize.Y + 2;
|
button.Width = textSize.Y + 2;
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ namespace FlaxEditor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
|
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
|
||||||
|
|
||||||
|
public static string CJKFont = "Editor/Fonts/NotoSansSC-Medium";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Inconsolata Regular font.
|
/// The Inconsolata Regular font.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ namespace FlaxEditor.GUI
|
|||||||
MaximumItemsInViewCount = 20;
|
MaximumItemsInViewCount = 20;
|
||||||
|
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
Font = new FontReference(style.FontMedium);
|
Font = new FontReference(style.FontMedium.First());
|
||||||
TextColor = style.Foreground;
|
TextColor = style.Foreground;
|
||||||
BackgroundColor = style.BackgroundNormal;
|
BackgroundColor = style.BackgroundNormal;
|
||||||
BackgroundColorHighlighted = BackgroundColor;
|
BackgroundColorHighlighted = BackgroundColor;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
@@ -233,11 +234,11 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
float width = 20;
|
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))
|
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);
|
return Mathf.Max(width, base.MinimumWidth);
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ namespace FlaxEditor.GUI
|
|||||||
_contentsColor = style.Background.RGBMultiplied(0.7f);
|
_contentsColor = style.Background.RGBMultiplied(0.7f);
|
||||||
_linesColor = style.ForegroundDisabled.RGBMultiplied(0.7f);
|
_linesColor = style.ForegroundDisabled.RGBMultiplied(0.7f);
|
||||||
_labelsColor = style.ForegroundDisabled;
|
_labelsColor = style.ForegroundDisabled;
|
||||||
_labelsFont = style.FontSmall;
|
_labelsFont = style.FontSmall.First();
|
||||||
|
|
||||||
_mainPanel = new Panel(ScrollBars.Both)
|
_mainPanel = new Panel(ScrollBars.Both)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using FlaxEngine;
|
|||||||
using FlaxEngine.Assertions;
|
using FlaxEngine.Assertions;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEditor.Options;
|
using FlaxEditor.Options;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEditor.GUI.Docking
|
namespace FlaxEditor.GUI.Docking
|
||||||
{
|
{
|
||||||
@@ -488,7 +489,7 @@ namespace FlaxEditor.GUI.Docking
|
|||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
if (style?.FontMedium != null)
|
if (style?.FontMedium != null)
|
||||||
_titleSize = style.FontMedium.MeasureText(_title);
|
_titleSize = style.FontMedium.First().MeasureText(_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
base.PerformLayoutBeforeChildren();
|
base.PerformLayoutBeforeChildren();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEditor.GUI.Input;
|
using FlaxEditor.GUI.Input;
|
||||||
using FlaxEditor.Utilities;
|
using FlaxEditor.Utilities;
|
||||||
@@ -86,8 +87,8 @@ namespace FlaxEditor.GUI
|
|||||||
var font = style.FontSmall;
|
var font = style.FontSmall;
|
||||||
for (int i = 0; i < ranges.Length; i++)
|
for (int i = 0; i < ranges.Length; i++)
|
||||||
{
|
{
|
||||||
var start = font.GetCharPosition(Name, ranges[i].StartIndex);
|
var start = font.First().GetCharPosition(Name, ranges[i].StartIndex);
|
||||||
var end = font.GetCharPosition(Name, ranges[i].EndIndex);
|
var end = font.First().GetCharPosition(Name, ranges[i].EndIndex);
|
||||||
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
|
_highlights.Add(new Rectangle(start.X + 2, 0, end.X - start.X, Height));
|
||||||
}
|
}
|
||||||
Visible = true;
|
Visible = true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEditor.GUI
|
namespace FlaxEditor.GUI
|
||||||
{
|
{
|
||||||
@@ -101,8 +102,8 @@ namespace FlaxEditor.GUI
|
|||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
float width = 18;
|
float width = 18;
|
||||||
|
|
||||||
if (style.FontMedium)
|
if (style.FontMedium.First())
|
||||||
width += style.FontMedium.MeasureText(Text).X;
|
width += style.FontMedium.First().MeasureText(Text).X;
|
||||||
|
|
||||||
Width = width;
|
Width = width;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEditor.GUI
|
namespace FlaxEditor.GUI
|
||||||
{
|
{
|
||||||
@@ -65,9 +66,9 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
var style = Style.Current;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
@@ -38,8 +39,8 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
Depth = -1;
|
Depth = -1;
|
||||||
|
|
||||||
if (Height < Style.Current.FontMedium.Height)
|
if (Height < Style.Current.FontMedium.First().Height)
|
||||||
Height = Style.Current.FontMedium.Height + 4;
|
Height = Style.Current.FontMedium.First().Height + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
@@ -129,7 +130,7 @@ namespace FlaxEditor.GUI
|
|||||||
Render2D.FillRectangle(rect, column.TitleBackgroundColor);
|
Render2D.FillRectangle(rect, column.TitleBackgroundColor);
|
||||||
|
|
||||||
var style = Style.Current;
|
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);
|
Render2D.DrawText(font, column.Title, rect, column.TitleColor, TextAlignment.Center, TextAlignment.Center);
|
||||||
|
|
||||||
if (columnIndex < _columns.Length - 1)
|
if (columnIndex < _columns.Length - 1)
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
|
|||||||
if (_previewValue != null)
|
if (_previewValue != null)
|
||||||
{
|
{
|
||||||
// Based on Track.Draw for track text placement
|
// 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)
|
if (Icon.IsValid)
|
||||||
left += 18;
|
left += 18;
|
||||||
if (IsExpanded)
|
if (IsExpanded)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
@@ -150,8 +151,8 @@ namespace FlaxEditor.GUI
|
|||||||
|
|
||||||
if (hasSprite)
|
if (hasSprite)
|
||||||
width += iconSize;
|
width += iconSize;
|
||||||
if (!string.IsNullOrEmpty(_text) && style.FontMedium)
|
if (!string.IsNullOrEmpty(_text) && style.FontMedium.First())
|
||||||
width += style.FontMedium.MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
|
width += style.FontMedium.First().MeasureText(_text).X + (hasSprite ? DefaultMargin : 0);
|
||||||
|
|
||||||
Width = width;
|
Width = width;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
@@ -317,7 +318,7 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
BackgroundColorSelected = style.BackgroundSelected;
|
BackgroundColorSelected = style.BackgroundSelected;
|
||||||
BackgroundColorHighlighted = style.BackgroundHighlighted;
|
BackgroundColorHighlighted = style.BackgroundHighlighted;
|
||||||
BackgroundColorSelectedUnfocused = style.LightBackground;
|
BackgroundColorSelectedUnfocused = style.LightBackground;
|
||||||
TextFont = new FontReference(style.FontSmall);
|
TextFont = new FontReference(style.FontSmall.First());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -237,12 +237,18 @@ namespace FlaxEditor.Options
|
|||||||
public int NumberOfGameClientsToLaunch = 1;
|
public int NumberOfGameClientsToLaunch = 1;
|
||||||
|
|
||||||
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
||||||
|
private static FontAsset _cjkFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.CJKFont);
|
||||||
private FontReference _titleFont = new FontReference(DefaultFont, 18);
|
private FontReference _titleFont = new FontReference(DefaultFont, 18);
|
||||||
private FontReference _largeFont = new FontReference(DefaultFont, 14);
|
private FontReference _largeFont = new FontReference(DefaultFont, 14);
|
||||||
private FontReference _mediumFont = new FontReference(DefaultFont, 9);
|
private FontReference _mediumFont = new FontReference(DefaultFont, 9);
|
||||||
private FontReference _smallFont = new FontReference(DefaultFont, 9);
|
private FontReference _smallFont = new FontReference(DefaultFont, 9);
|
||||||
private FontReference _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont), 10);
|
private FontReference _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont), 10);
|
||||||
|
|
||||||
|
public FontReference CJKFont
|
||||||
|
{
|
||||||
|
get => new FontReference(_cjkFont, 9);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the title font for editor UI.
|
/// Gets or sets the title font for editor UI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -261,8 +261,9 @@ namespace FlaxEditor.Options
|
|||||||
// Fonts
|
// Fonts
|
||||||
FontTitle = options.Interface.TitleFont.GetFont(),
|
FontTitle = options.Interface.TitleFont.GetFont(),
|
||||||
FontLarge = options.Interface.LargeFont.GetFont(),
|
FontLarge = options.Interface.LargeFont.GetFont(),
|
||||||
FontMedium = options.Interface.MediumFont.GetFont(),
|
FontMedium = new Font[] { options.Interface.MediumFont.GetFont(), options.Interface.CJKFont.GetFont() },
|
||||||
FontSmall = options.Interface.SmallFont.GetFont(),
|
FontSmall = new Font[] { options.Interface.SmallFont.GetFont(), options.Interface.CJKFont.GetFont() },
|
||||||
|
FontCJK = options.Interface.CJKFont.GetFont(),
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
ArrowDown = Editor.Icons.ArrowDown12,
|
ArrowDown = Editor.Icons.ArrowDown12,
|
||||||
@@ -314,8 +315,8 @@ namespace FlaxEditor.Options
|
|||||||
// Fonts
|
// Fonts
|
||||||
FontTitle = options.Interface.TitleFont.GetFont(),
|
FontTitle = options.Interface.TitleFont.GetFont(),
|
||||||
FontLarge = options.Interface.LargeFont.GetFont(),
|
FontLarge = options.Interface.LargeFont.GetFont(),
|
||||||
FontMedium = options.Interface.MediumFont.GetFont(),
|
FontMedium = new Font[] { options.Interface.MediumFont.GetFont(), options.Interface.CJKFont.GetFont() },
|
||||||
FontSmall = options.Interface.SmallFont.GetFont(),
|
FontSmall = new Font[] { options.Interface.SmallFont.GetFont(), options.Interface.CJKFont.GetFont() },
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
ArrowDown = Editor.Icons.ArrowDown12,
|
ArrowDown = Editor.Icons.ArrowDown12,
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ namespace FlaxEditor.SceneGraph.GUI
|
|||||||
var textRect = TextRect;
|
var textRect = TextRect;
|
||||||
for (int i = 0; i < ranges.Length; i++)
|
for (int i = 0; i < ranges.Length; i++)
|
||||||
{
|
{
|
||||||
var start = font.GetCharPosition(text, ranges[i].StartIndex);
|
var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
|
||||||
var end = font.GetCharPosition(text, ranges[i].EndIndex);
|
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));
|
_highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
|
||||||
}
|
}
|
||||||
isThisVisible = true;
|
isThisVisible = true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.CustomEditors.Dedicated;
|
using FlaxEditor.CustomEditors.Dedicated;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEditor.GUI.Drag;
|
using FlaxEditor.GUI.Drag;
|
||||||
@@ -100,7 +101,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
|
_debugRelevant = Behavior.GetNodeDebugRelevancy(instance, behavior);
|
||||||
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
|
_debugInfo = Behavior.GetNodeDebugInfo(instance, behavior);
|
||||||
if (!string.IsNullOrEmpty(_debugInfo))
|
if (!string.IsNullOrEmpty(_debugInfo))
|
||||||
_debugInfoSize = Style.Current.FontSmall.MeasureText(_debugInfo);
|
_debugInfoSize = Style.Current.FontSmall.First().MeasureText(_debugInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,8 +200,8 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
var font = style.FontSmall;
|
var font = style.FontSmall;
|
||||||
for (int i = 0; i < ranges.Length; i++)
|
for (int i = 0; i < ranges.Length; i++)
|
||||||
{
|
{
|
||||||
var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
|
var start = font.First().GetCharPosition(_archetype.Title, ranges[i].StartIndex);
|
||||||
var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
|
var end = font.First().GetCharPosition(_archetype.Title, ranges[i].EndIndex);
|
||||||
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
|
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
|
||||||
|
|
||||||
if (ranges[i].StartIndex <= 0)
|
if (ranges[i].StartIndex <= 0)
|
||||||
@@ -222,8 +222,8 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
_highlights.Clear();
|
_highlights.Clear();
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var font = style.FontSmall;
|
var font = style.FontSmall;
|
||||||
var start = font.GetCharPosition(_archetype.Title, 0);
|
var start = font.First().GetCharPosition(_archetype.Title, 0);
|
||||||
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
|
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));
|
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
|
||||||
_isFullMatch = true;
|
_isFullMatch = true;
|
||||||
Visible = true;
|
Visible = true;
|
||||||
@@ -237,8 +237,8 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
_highlights.Clear();
|
_highlights.Clear();
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
var font = style.FontSmall;
|
var font = style.FontSmall;
|
||||||
var start = font.GetCharPosition(_archetype.Title, 0);
|
var start = font.First().GetCharPosition(_archetype.Title, 0);
|
||||||
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
|
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));
|
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
|
||||||
Visible = true;
|
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);
|
Render2D.DrawText(style.FontSmall, _archetype.Title, textRect, Enabled ? style.Foreground : style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
|
||||||
if (_archetype.SubTitle != null)
|
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);
|
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);
|
Render2D.DrawText(style.FontSmall, _archetype.SubTitle, subTitleRect, style.ForegroundDisabled, TextAlignment.Near, TextAlignment.Center);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1428,7 +1428,7 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
|
|
||||||
if (_defaultValueEditor != null)
|
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))
|
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];
|
_editor = DefaultValueEditors[i];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Surface.Elements;
|
using FlaxEditor.Surface.Elements;
|
||||||
using FlaxEditor.Surface.Undo;
|
using FlaxEditor.Surface.Undo;
|
||||||
@@ -199,7 +200,7 @@ namespace FlaxEditor.Surface
|
|||||||
continue;
|
continue;
|
||||||
if (child is InputBox inputBox)
|
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)
|
if (inputBox.DefaultValueEditor != null)
|
||||||
boxWidth += inputBox.DefaultValueEditor.Width + 4;
|
boxWidth += inputBox.DefaultValueEditor.Width + 4;
|
||||||
leftWidth = Mathf.Max(leftWidth, boxWidth);
|
leftWidth = Mathf.Max(leftWidth, boxWidth);
|
||||||
@@ -207,7 +208,7 @@ namespace FlaxEditor.Surface
|
|||||||
}
|
}
|
||||||
else if (child is OutputBox outputBox)
|
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);
|
rightHeight = Mathf.Max(rightHeight, outputBox.Archetype.Position.Y - Constants.NodeMarginY - Constants.NodeHeaderSize + 20.0f);
|
||||||
}
|
}
|
||||||
else if (child is Control control)
|
else if (child is Control control)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI.Tabs;
|
using FlaxEditor.GUI.Tabs;
|
||||||
using FlaxEditor.Modules;
|
using FlaxEditor.Modules;
|
||||||
using FlaxEditor.SceneGraph.Actors;
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
@@ -147,7 +148,7 @@ namespace FlaxEditor.Tools.Foliage
|
|||||||
Parent = _noFoliagePanel,
|
Parent = _noFoliagePanel,
|
||||||
Enabled = false
|
Enabled = false
|
||||||
};
|
};
|
||||||
var textSize = Style.Current.FontMedium.MeasureText(buttonText);
|
var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
|
||||||
if (_createNewFoliage.Width < textSize.X)
|
if (_createNewFoliage.Width < textSize.X)
|
||||||
{
|
{
|
||||||
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
|
_createNewFoliage.LocalX -= (textSize.X - _createNewFoliage.Width) / 2;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI.Tabs;
|
using FlaxEditor.GUI.Tabs;
|
||||||
using FlaxEditor.Modules;
|
using FlaxEditor.Modules;
|
||||||
using FlaxEditor.SceneGraph.Actors;
|
using FlaxEditor.SceneGraph.Actors;
|
||||||
@@ -105,7 +106,7 @@ namespace FlaxEditor.Tools.Terrain
|
|||||||
Parent = _noTerrainPanel,
|
Parent = _noTerrainPanel,
|
||||||
Enabled = false
|
Enabled = false
|
||||||
};
|
};
|
||||||
var textSize = Style.Current.FontMedium.MeasureText(buttonText);
|
var textSize = Style.Current.FontMedium.First().MeasureText(buttonText);
|
||||||
if (_createTerrainButton.Width < textSize.X)
|
if (_createTerrainButton.Width < textSize.X)
|
||||||
{
|
{
|
||||||
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
|
_createTerrainButton.LocalX -= (textSize.X - _createTerrainButton.Width) / 2;
|
||||||
|
|||||||
@@ -548,9 +548,9 @@ namespace FlaxEditor.Viewport
|
|||||||
#region Camera settings widget
|
#region Camera settings widget
|
||||||
|
|
||||||
var largestText = "Relative Panning";
|
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 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
|
// Camera Settings Widget
|
||||||
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
||||||
@@ -801,7 +801,7 @@ namespace FlaxEditor.Viewport
|
|||||||
#region View mode widget
|
#region View mode widget
|
||||||
|
|
||||||
largestText = "Brightness";
|
largestText = "Brightness";
|
||||||
textSize = Style.Current.FontMedium.MeasureText(largestText);
|
textSize = Style.Current.FontMedium.First().MeasureText(largestText);
|
||||||
xLocationForExtras = textSize.X + 5;
|
xLocationForExtras = textSize.X + 5;
|
||||||
|
|
||||||
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
|
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
@@ -162,8 +163,8 @@ namespace FlaxEditor.Viewport.Widgets
|
|||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
|
|
||||||
if (style != null && style.FontMedium)
|
if (style != null && style.FontMedium.First())
|
||||||
Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.MeasureText(_text).X, Icon.IsValid);
|
Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.First().MeasureText(_text).X, Icon.IsValid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI.Dialogs;
|
using FlaxEditor.GUI.Dialogs;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
@@ -53,7 +54,7 @@ namespace FlaxEditor.Windows
|
|||||||
Parent = this
|
Parent = this
|
||||||
};
|
};
|
||||||
var buttonText = "Copy version info";
|
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)
|
var copyVersionButton = new Button(Width - fontSize.X - 8, 6, fontSize.X + 4, 20)
|
||||||
{
|
{
|
||||||
Text = buttonText,
|
Text = buttonText,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEditor.Windows.Profiler
|
namespace FlaxEditor.Windows.Profiler
|
||||||
{
|
{
|
||||||
@@ -84,8 +85,8 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
Render2D.FillRectangle(bounds, color);
|
Render2D.FillRectangle(bounds, color);
|
||||||
Render2D.DrawRectangle(bounds, color * 0.5f);
|
Render2D.DrawRectangle(bounds, color * 0.5f);
|
||||||
|
|
||||||
if (_nameLength < 0 && style.FontMedium)
|
if (_nameLength < 0 && style.FontMedium.First())
|
||||||
_nameLength = style.FontMedium.MeasureText(_name).X;
|
_nameLength = style.FontMedium.First().MeasureText(_name).X;
|
||||||
|
|
||||||
if (_nameLength < bounds.Width + 4)
|
if (_nameLength < bounds.Width + 4)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI.Input;
|
using FlaxEditor.GUI.Input;
|
||||||
using FlaxEditor.GUI.Tabs;
|
using FlaxEditor.GUI.Tabs;
|
||||||
using FlaxEditor.GUI.Tree;
|
using FlaxEditor.GUI.Tree;
|
||||||
@@ -272,8 +273,8 @@ namespace FlaxEditor.Windows
|
|||||||
var textRect = item.TextRect;
|
var textRect = item.TextRect;
|
||||||
for (int i = 0; i < ranges.Length; i++)
|
for (int i = 0; i < ranges.Length; i++)
|
||||||
{
|
{
|
||||||
var start = font.GetCharPosition(text, ranges[i].StartIndex);
|
var start = font.First().GetCharPosition(text, ranges[i].StartIndex);
|
||||||
var end = font.GetCharPosition(text, ranges[i].EndIndex);
|
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));
|
highlights.Add(new Rectangle(start.X + textRect.X, textRect.Y, end.X - start.X, textRect.Height));
|
||||||
}
|
}
|
||||||
item.SetHighlights(highlights);
|
item.SetHighlights(highlights);
|
||||||
|
|||||||
@@ -283,6 +283,206 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Font::ProcessText(const Array<Font*>& fonts, const StringView& text, Array<FontLineCache>& 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<float>(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)
|
Float2 Font::MeasureText(const StringView& text, const TextLayoutOptions& layout)
|
||||||
{
|
{
|
||||||
// Check if there is no need to do anything
|
// 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<float>((lines.Count() - 1) * baseLinesDistance));
|
return rootOffset + Float2(lines.Last().Size.X, static_cast<float>((lines.Count() - 1) * baseLinesDistance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Font::ContainsChar(Char c)
|
||||||
|
{
|
||||||
|
return FT_Get_Char_Index(GetAsset()->GetFTFace(), c) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Font::FlushFaceSize() const
|
void Font::FlushFaceSize() const
|
||||||
{
|
{
|
||||||
// Set the character size
|
// Set the character size
|
||||||
|
|||||||
@@ -339,6 +339,15 @@ public:
|
|||||||
/// <param name="outputLines">The output lines list.</param>
|
/// <param name="outputLines">The output lines list.</param>
|
||||||
void ProcessText(const StringView& text, Array<FontLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
|
void ProcessText(const StringView& text, Array<FontLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes text to get cached lines for rendering.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The font list.</param>
|
||||||
|
/// <param name="text">The input text.</param>
|
||||||
|
/// <param name="layout">The layout properties.</param>
|
||||||
|
/// <param name="outputLines">The output lines list.</param>
|
||||||
|
static void ProcessText(const Array<Font*>& fonts, const StringView& text, Array<FontLineCache>& outputLines, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes text to get cached lines for rendering.
|
/// Processes text to get cached lines for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -395,6 +404,15 @@ public:
|
|||||||
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
||||||
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
|
API_FUNCTION() Float2 MeasureText(const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Measures minimum size of the rectangle that will be needed to draw given text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to render with.</param>
|
||||||
|
/// <param name="text">The input text to test.</param>
|
||||||
|
/// <param name="layout">The layout properties.</param>
|
||||||
|
/// <returns>The minimum size for that text and fot to render properly.</returns>
|
||||||
|
API_FUNCTION() static Float2 MeasureText(const Array<Font*>& fonts, const StringView& text, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -482,6 +500,16 @@ public:
|
|||||||
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
||||||
API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
|
API_FUNCTION() Float2 GetCharPosition(const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates character position for given text and character index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use.</param>
|
||||||
|
/// <param name="text">The input text to test.</param>
|
||||||
|
/// <param name="index">The text position to get coordinates of.</param>
|
||||||
|
/// <param name="layout">The text layout properties.</param>
|
||||||
|
/// <returns>The character position (upper left corner which can be used for a caret position).</returns>
|
||||||
|
API_FUNCTION() static Float2 GetCharPosition(const Array<Font*>& fonts, const StringView& text, int32 index, API_PARAM(Ref) const TextLayoutOptions& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates character position for given text and character index.
|
/// Calculates character position for given text and character index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -518,6 +546,13 @@ public:
|
|||||||
return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
|
return GetCharPosition(textRange.Substring(text), index, TextLayoutOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the font contains the glyph of a char
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="c">The char to test.</param>
|
||||||
|
/// <returns>True if the font contains the glyph of the char, otherwise false.</returns>
|
||||||
|
API_FUNCTION() FORCE_INLINE bool ContainsChar(Char c);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flushes the size of the face with the Free Type library backend.
|
/// Flushes the size of the face with the Free Type library backend.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -155,6 +155,9 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
|
|||||||
|
|
||||||
// Get the index to the glyph in the font face
|
// Get the index to the glyph in the font face
|
||||||
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
|
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
|
// Load the glyph
|
||||||
const FT_Error error = FT_Load_Glyph(face, glyphIndex, glyphFlags);
|
const FT_Error error = FT_Load_Glyph(face, glyphIndex, glyphFlags);
|
||||||
|
|||||||
@@ -27,11 +27,11 @@
|
|||||||
|
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
#define RENDER2D_CHECK_RENDERING_STATE \
|
#define RENDER2D_CHECK_RENDERING_STATE \
|
||||||
if (!Render2D::IsRendering()) \
|
if (!Render2D::IsRendering()) \
|
||||||
{ \
|
{ \
|
||||||
LOG(Error, "Calling Render2D is only valid during rendering."); \
|
LOG(Error, "Calling Render2D is only valid during rendering."); \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define RENDER2D_CHECK_RENDERING_STATE
|
#define RENDER2D_CHECK_RENDERING_STATE
|
||||||
#endif
|
#endif
|
||||||
@@ -54,7 +54,7 @@ const bool DownsampleForBlur = false;
|
|||||||
|
|
||||||
PACK_STRUCT(struct Data {
|
PACK_STRUCT(struct Data {
|
||||||
Matrix ViewProjection;
|
Matrix ViewProjection;
|
||||||
});
|
});
|
||||||
|
|
||||||
PACK_STRUCT(struct BlurData {
|
PACK_STRUCT(struct BlurData {
|
||||||
Float2 InvBufferSize;
|
Float2 InvBufferSize;
|
||||||
@@ -62,7 +62,7 @@ PACK_STRUCT(struct BlurData {
|
|||||||
float Dummy0;
|
float Dummy0;
|
||||||
Float4 Bounds;
|
Float4 Bounds;
|
||||||
Float4 WeightAndOffsets[RENDER2D_BLUR_MAX_SAMPLES / 2];
|
Float4 WeightAndOffsets[RENDER2D_BLUR_MAX_SAMPLES / 2];
|
||||||
});
|
});
|
||||||
|
|
||||||
enum class DrawCallType : byte
|
enum class DrawCallType : byte
|
||||||
{
|
{
|
||||||
@@ -1174,7 +1174,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
|
|||||||
drawCall.AsChar.Mat = nullptr;
|
drawCall.AsChar.Mat = nullptr;
|
||||||
}
|
}
|
||||||
Float2 pointer = location;
|
Float2 pointer = location;
|
||||||
for (int32 currentIndex = 0; currentIndex <= text.Length(); currentIndex++)
|
for (int32 currentIndex = 0; currentIndex < text.Length(); currentIndex++)
|
||||||
{
|
{
|
||||||
// Cache current character
|
// Cache current character
|
||||||
const Char currentChar = text[currentIndex];
|
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);
|
DrawText(font, textRange.Substring(text), color, layout, customMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Render2D::DrawText(const Array<Font*>& 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<float>(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<Font*>& 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<Font*>& 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<float>(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<Font*>& 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)
|
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
|
||||||
{
|
{
|
||||||
return (color.A * TintLayersStack.Peek().A) < 1.0f;
|
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<Float2>& vertices, const Span<Float2>& uvs)
|
void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span<Float2>& vertices, const Span<Float2>& uvs)
|
||||||
{
|
{
|
||||||
RENDER2D_CHECK_RENDERING_STATE;
|
RENDER2D_CHECK_RENDERING_STATE;
|
||||||
CHECK(vertices.Length() == uvs.Length())
|
CHECK(vertices.Length() == uvs.Length());
|
||||||
|
|
||||||
Render2DDrawCall& drawCall = DrawCalls.AddOne();
|
Render2DDrawCall& drawCall = DrawCalls.AddOne();
|
||||||
drawCall.Type = DrawCallType::FillTexture;
|
drawCall.Type = DrawCallType::FillTexture;
|
||||||
@@ -1977,7 +2289,7 @@ void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span<uint16>& indices,
|
|||||||
drawCall.StartIB = IBIndex;
|
drawCall.StartIB = IBIndex;
|
||||||
drawCall.CountIB = indices.Length();
|
drawCall.CountIB = indices.Length();
|
||||||
drawCall.AsTexture.Ptr = t;
|
drawCall.AsTexture.Ptr = t;
|
||||||
|
|
||||||
for (int32 i = 0; i < indices.Length();)
|
for (int32 i = 0; i < indices.Length();)
|
||||||
{
|
{
|
||||||
const uint16 i0 = indices.Get()[i++];
|
const uint16 i0 = indices.Get()[i++];
|
||||||
|
|||||||
@@ -152,6 +152,59 @@ namespace FlaxEngine
|
|||||||
DrawText(font, text, color, ref layout, customMaterial);
|
DrawText(font, text, color, ref layout, customMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
||||||
|
/// <param name="text">The text to render.</param>
|
||||||
|
/// <param name="layoutRect">The size and position of the area in which the text is drawn.</param>
|
||||||
|
/// <param name="color">The text color.</param>
|
||||||
|
/// <param name="horizontalAlignment">The horizontal alignment of the text in a layout rectangle.</param>
|
||||||
|
/// <param name="verticalAlignment">The vertical alignment of the text in a layout rectangle.</param>
|
||||||
|
/// <param name="textWrapping">Describes how wrap text inside a layout rectangle.</param>
|
||||||
|
/// <param name="baseLinesGapScale">The scale for distance one baseline from another. Default is 1.</param>
|
||||||
|
/// <param name="scale">The text drawing scale. Default is 1.</param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
||||||
|
/// <param name="customMaterial">Custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
|
/// <param name="text">The text to render.</param>
|
||||||
|
/// <param name="layoutRect">The size and position of the area in which the text is drawn.</param>
|
||||||
|
/// <param name="color">The text color.</param>
|
||||||
|
/// <param name="horizontalAlignment">The horizontal alignment of the text in a layout rectangle.</param>
|
||||||
|
/// <param name="verticalAlignment">The vertical alignment of the text in a layout rectangle.</param>
|
||||||
|
/// <param name="textWrapping">Describes how wrap text inside a layout rectangle.</param>
|
||||||
|
/// <param name="baseLinesGapScale">The scale for distance one baseline from another. Default is 1.</param>
|
||||||
|
/// <param name="scale">The text drawing scale. Default is 1.</param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls drawing GUI to the texture.
|
/// Calls drawing GUI to the texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The rendering features and options flags.
|
/// The rendering features and options flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_ENUM(Attributes="Flags") enum class RenderingFeatures
|
API_ENUM(Attributes = "Flags") enum class RenderingFeatures
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The none.
|
/// The none.
|
||||||
@@ -215,6 +215,49 @@ public:
|
|||||||
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
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 DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
||||||
|
/// <param name="text">The text to render.</param>
|
||||||
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
|
/// <param name="color">The text color.</param>
|
||||||
|
/// <param name="location">The text location.</param>
|
||||||
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
|
API_FUNCTION() static void DrawText(const Array<Font*, HeapAllocation>& fonts, const StringView& text, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a text with formatting.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
||||||
|
/// <param name="text">The text to render.</param>
|
||||||
|
/// <param name="color">The text color.</param>
|
||||||
|
/// <param name="layout">The text layout properties.</param>
|
||||||
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
|
API_FUNCTION() static void DrawText(const Array<Font*, HeapAllocation>& fonts, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Float2& location, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a text with formatting.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
||||||
|
/// <param name="text">The text to render.</param>
|
||||||
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
|
/// <param name="color">The text color.</param>
|
||||||
|
/// <param name="layout">The text layout properties.</param>
|
||||||
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
|
API_FUNCTION() static void DrawText(const Array<Font*, HeapAllocation>& fonts, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws a text with formatting.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fonts">The fonts to use, ordered by priority.</param>
|
||||||
|
/// <param name="text">The text to render.</param>
|
||||||
|
/// <param name="textRange">The input text range (substring range of the input text parameter).</param>
|
||||||
|
/// <param name="color">The text color.</param>
|
||||||
|
/// <param name="layout">The text layout properties.</param>
|
||||||
|
/// <param name="customMaterial">The custom material for font characters rendering. It must contain texture parameter named Font used to sample font texture.</param>
|
||||||
|
API_FUNCTION() static void DrawText(const Array<Font*, HeapAllocation>& fonts, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills a rectangle area.
|
/// Fills a rectangle area.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -295,12 +295,13 @@ namespace FlaxEngine
|
|||||||
|
|
||||||
// Use optionally bundled default font (matches Editor)
|
// Use optionally bundled default font (matches Editor)
|
||||||
var defaultFont = Content.LoadAsyncInternal<FontAsset>("Editor/Fonts/Roboto-Regular");
|
var defaultFont = Content.LoadAsyncInternal<FontAsset>("Editor/Fonts/Roboto-Regular");
|
||||||
|
var cjkFont = Content.LoadAsyncInternal<FontAsset>("NotoSansSC-Medium");
|
||||||
if (defaultFont)
|
if (defaultFont)
|
||||||
{
|
{
|
||||||
style.FontTitle = defaultFont.CreateFont(18);
|
style.FontTitle = defaultFont.CreateFont(18);
|
||||||
style.FontLarge = defaultFont.CreateFont(14);
|
style.FontLarge = defaultFont.CreateFont(14);
|
||||||
style.FontMedium = defaultFont.CreateFont(9);
|
style.FontMedium = new Font[] { defaultFont.CreateFont(9), cjkFont.CreateFont(9) };
|
||||||
style.FontSmall = defaultFont.CreateFont(9);
|
style.FontSmall = new Font[] { defaultFont.CreateFont(9), cjkFont.CreateFont(9) };
|
||||||
}
|
}
|
||||||
|
|
||||||
Style.Current = style;
|
Style.Current = style;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -155,7 +156,7 @@ namespace FlaxEngine.GUI
|
|||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
if (style != null)
|
if (style != null)
|
||||||
{
|
{
|
||||||
_font = new FontReference(style.FontMedium);
|
_font = new FontReference(style.FontMedium.First());
|
||||||
TextColor = style.Foreground;
|
TextColor = style.Foreground;
|
||||||
BackgroundColor = style.BackgroundNormal;
|
BackgroundColor = style.BackgroundNormal;
|
||||||
BorderColor = style.BorderNormal;
|
BorderColor = style.BorderNormal;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -358,7 +359,7 @@ namespace FlaxEngine.GUI
|
|||||||
: base(0, 0, 120, 18.0f)
|
: base(0, 0, 120, 18.0f)
|
||||||
{
|
{
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
Font = new FontReference(style.FontMedium);
|
Font = new FontReference(style.FontMedium.First());
|
||||||
TextColor = style.Foreground;
|
TextColor = style.Foreground;
|
||||||
BackgroundColor = style.BackgroundNormal;
|
BackgroundColor = style.BackgroundNormal;
|
||||||
BackgroundColorHighlighted = BackgroundColor;
|
BackgroundColorHighlighted = BackgroundColor;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using FlaxEditor.Options;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -190,7 +192,7 @@ namespace FlaxEngine.GUI
|
|||||||
{
|
{
|
||||||
AutoFocus = false;
|
AutoFocus = false;
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
Font = new FontReference(style.FontMedium);
|
Font = new FontReference(style.FontMedium.First());
|
||||||
TextColor = style.Foreground;
|
TextColor = style.Foreground;
|
||||||
TextColorHighlighted = style.Foreground;
|
TextColorHighlighted = style.Foreground;
|
||||||
}
|
}
|
||||||
@@ -201,7 +203,7 @@ namespace FlaxEngine.GUI
|
|||||||
{
|
{
|
||||||
AutoFocus = false;
|
AutoFocus = false;
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
Font = new FontReference(style.FontMedium);
|
Font = new FontReference(style.FontMedium.First());
|
||||||
TextColor = style.Foreground;
|
TextColor = style.Foreground;
|
||||||
TextColorHighlighted = 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)
|
if (ClipText)
|
||||||
Render2D.PopClip();
|
Render2D.PopClip();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -45,7 +46,7 @@ namespace FlaxEngine.GUI
|
|||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
_textStyle = new TextBlockStyle
|
_textStyle = new TextBlockStyle
|
||||||
{
|
{
|
||||||
Font = new FontReference(style.FontMedium),
|
Font = new FontReference(style.FontMedium.First()),
|
||||||
Color = style.Foreground,
|
Color = style.Foreground,
|
||||||
BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected),
|
BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -88,7 +90,7 @@ namespace FlaxEngine.GUI
|
|||||||
_layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
|
_layout.Bounds = new Rectangle(DefaultMargin, 1, Width - 2 * DefaultMargin, Height - 2);
|
||||||
|
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
Font = new FontReference(style.FontMedium);
|
Font = new FontReference(style.FontMedium.First());
|
||||||
TextColor = style.Foreground;
|
TextColor = style.Foreground;
|
||||||
WatermarkTextColor = style.ForegroundDisabled;
|
WatermarkTextColor = style.ForegroundDisabled;
|
||||||
SelectionColor = style.BackgroundSelected;
|
SelectionColor = style.BackgroundSelected;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -237,7 +238,7 @@ namespace FlaxEngine.GUI
|
|||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
HeaderColor = style.BackgroundNormal;
|
HeaderColor = style.BackgroundNormal;
|
||||||
HeaderColorMouseOver = style.BackgroundHighlighted;
|
HeaderColorMouseOver = style.BackgroundHighlighted;
|
||||||
HeaderTextFont = new FontReference(style.FontMedium);
|
HeaderTextFont = new FontReference(style.FontMedium.First());
|
||||||
HeaderTextColor = style.Foreground;
|
HeaderTextColor = style.Foreground;
|
||||||
ArrowImageOpened = new SpriteBrush(style.ArrowDown);
|
ArrowImageOpened = new SpriteBrush(style.ArrowDown);
|
||||||
ArrowImageClosed = new SpriteBrush(style.ArrowRight);
|
ArrowImageClosed = new SpriteBrush(style.ArrowRight);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -12,6 +14,14 @@ namespace FlaxEngine.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static Style Current { get; set; }
|
public static Style Current { get; set; }
|
||||||
|
|
||||||
|
public Font FontCJK
|
||||||
|
{
|
||||||
|
get => _fontCJK?.GetFont();
|
||||||
|
set => _fontCJK = new FontReference(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FontReference _fontCJK;
|
||||||
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
private FontReference _fontTitle;
|
private FontReference _fontTitle;
|
||||||
|
|
||||||
@@ -41,31 +51,31 @@ namespace FlaxEngine.GUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
private FontReference _fontMedium;
|
private FontReference[] _fontMedium;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The font medium.
|
/// The font medium.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NoSerialize]
|
[NoSerialize]
|
||||||
[EditorOrder(30)]
|
[EditorOrder(30)]
|
||||||
public Font FontMedium
|
public Font[] FontMedium
|
||||||
{
|
{
|
||||||
get => _fontMedium?.GetFont();
|
get => _fontMedium?.Select((x)=>x.GetFont()).ToArray();
|
||||||
set => _fontMedium = new FontReference(value);
|
set => _fontMedium = value.Select((x)=>new FontReference(x)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
private FontReference _fontSmall;
|
private FontReference[] _fontSmall;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The font small.
|
/// The font small.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NoSerialize]
|
[NoSerialize]
|
||||||
[EditorOrder(40)]
|
[EditorOrder(40)]
|
||||||
public Font FontSmall
|
public Font[] FontSmall
|
||||||
{
|
{
|
||||||
get => _fontSmall?.GetFont();
|
get => _fontSmall?.Select((x) => x.GetFont()).ToArray();
|
||||||
set => _fontSmall = new FontReference(value);
|
set => _fontSmall = value.Select((x) => new FontReference(x)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -255,14 +256,14 @@ namespace FlaxEngine.GUI
|
|||||||
|
|
||||||
// Calculate size of the tooltip
|
// Calculate size of the tooltip
|
||||||
var size = Float2.Zero;
|
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;
|
var layout = TextLayoutOptions.Default;
|
||||||
layout.Bounds = new Rectangle(0, 0, MaxWidth, 10000000);
|
layout.Bounds = new Rectangle(0, 0, MaxWidth, 10000000);
|
||||||
layout.HorizontalAlignment = TextAlignment.Center;
|
layout.HorizontalAlignment = TextAlignment.Center;
|
||||||
layout.VerticalAlignment = TextAlignment.Center;
|
layout.VerticalAlignment = TextAlignment.Center;
|
||||||
layout.TextWrapping = TextWrapping.WrapWords;
|
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++)
|
for (int i = 0; i < items.Length; i++)
|
||||||
{
|
{
|
||||||
ref var item = ref items[i];
|
ref var item = ref items[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user