Font renderer improvements + component for scripting

This commit is contained in:
Simon Lübeß
2024-03-17 20:29:52 +01:00
parent 930d289565
commit d28426478b
8 changed files with 170 additions and 11 deletions
@@ -481,7 +481,7 @@ namespace GlitchyEditor.EditWindows
{
StartNewProperty("Rich text");
ImGui.AttachTooltip("If checked, the text will be interpreted as rich text. This means, that you can use tags to change the style of the text.");
ImGui.AttachTooltip("If checked, the text will be interpreted as rich text.");
bool isRichText = textRendererComponent.IsRichText;
-3
View File
@@ -117,9 +117,6 @@ namespace GlitchyEngine.Renderer.Text
{
Debug.Profiler.ProfileResourceFunction!();
// Make sure the fontrenderer is initialized (Font only cares about freetype)
FontRenderer.Init();
// Set default sampler
Sampler = null;
@@ -84,6 +84,18 @@ namespace GlitchyEngine.Renderer.Text
}
public static readonly Self Empty = new Self(null) ~ _.ReleaseRef();
/// Optimizes rendering of the text by sorting the glyphs
public void Optimize()
{
// Sort by texture -> render all glyphs with same font at once
Glyphs.Sort((lhs, rhs) => (int)Internal.UnsafeCastToPtr(lhs.Font._atlas) - (int)Internal.UnsafeCastToPtr(rhs.Font._atlas));
}
public void Clear()
{
Glyphs.Clear();
}
}
/*
public class PreparedLine
@@ -178,11 +190,11 @@ namespace GlitchyEngine.Renderer.Text
}
}
public static PreparedText PrepareText(Font font, StringView text, float fontSize, Color fontColor = .White, Color bitmapColor = .White, float lineSpaceScale = 1.0f, TextDirection direction = .LeftToRight)
public static void PrepareText(PreparedText preparedText, Font font, StringView text, float fontSize, Color fontColor = .White, Color bitmapColor = .White, float lineSpaceScale = 1.0f, TextDirection direction = .LeftToRight)
{
Debug.Profiler.ProfileRendererFunction!();
PreparedText preparedText = new PreparedText(font);
preparedText.Clear();
float scale = fontSize / (float)font._fontSize;
@@ -476,7 +488,7 @@ namespace GlitchyEngine.Renderer.Text
preparedText.AdvanceY = baseline;
return preparedText;
preparedText.Optimize();
}
public static void DrawText(PreparedText text, float x, float y, Color fontColor = .White)
@@ -497,6 +509,7 @@ namespace GlitchyEngine.Renderer.Text
Renderer2D.Flush();
// TODO: this is very not good!
// At some point we will support using materials with the 2D renderer. At that point we can simply bind different materials with fonts (or glyphs?) and don't need this hack anymore. One day...
var lastEffect = Renderer2D.[Friend]s_currentQuadEffect;
Renderer2D.[Friend]s_currentQuadEffect = _msdfEffect;
// TODO: oh no....
+56
View File
@@ -91,6 +91,7 @@ static class ScriptGlue
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.Physics.Rigidbody2D");
RegisterComponent<CameraComponent>("GlitchyEngine.Core.Camera");
RegisterComponent<CircleRendererComponent>("GlitchyEngine.Graphics.CircleRenderer");
RegisterComponent<TextRendererComponent>("GlitchyEngine.Graphics.TextRenderer");
}
[RegisterMethod]
@@ -996,6 +997,61 @@ static class ScriptGlue
#endregion
#region TextRenderer
[RegisterCall("ScriptGlue::TextRenderer_SetIsRichText")]
static bool TextRenderer_SetIsRichText(UUID entityId)
{
return GetComponentSafe<TextRendererComponent>(entityId).IsRichText;
}
[RegisterCall("ScriptGlue::TextRenderer_SetIsRichText")]
static void TextRenderer_SetIsRichText(UUID entityId, bool isRichText)
{
TextRendererComponent* textComponent = GetComponentSafe<TextRendererComponent>(entityId);
textComponent.IsRichText = isRichText;
textComponent.NeedsRebuild = true;
}
[RegisterCall("ScriptGlue::TextRenderer_GetText")]
static void TextRenderer_GetText(UUID entityId, out MonoString* text)
{
TextRendererComponent* textComponent = GetComponentSafe<TextRendererComponent>(entityId);
text = Mono.mono_string_new_len(ScriptEngine.[Friend]s_AppDomain, textComponent.Text.Ptr, (uint32)textComponent.Text.Length);
}
[RegisterCall("ScriptGlue::TextRenderer_SetText")]
static void TextRenderer_SetText(UUID entityId, MonoString* text)
{
TextRendererComponent* textComponent = GetComponentSafe<TextRendererComponent>(entityId);
char8* rawText = Mono.mono_string_to_utf8(text);
textComponent.Text = StringView(rawText);
textComponent.NeedsRebuild = true;
Mono.mono_free(rawText);
}
[RegisterCall("ScriptGlue::TextRenderer_GetColor")]
static void TextRenderer_GetColor(UUID entityId, out ColorRGBA color)
{
color = default;
return;
}
[RegisterCall("ScriptGlue::TextRenderer_SetColor")]
static void TextRenderer_SetColor(UUID entityId, ColorRGBA color)
{
return;
}
#endregion
#region Math
private static void RegisterMathFunctions()
+10 -2
View File
@@ -799,10 +799,18 @@ namespace GlitchyEngine.World
{
if (textRenderer.NeedsRebuild || textRenderer.PreparedText == null)
{
using (PreparedText preparedText = FontRenderer.PrepareText(_font, textRenderer.Text, 24, .Black))
if (textRenderer.PreparedText == null)
{
textRenderer.PreparedText = preparedText;
textRenderer.PreparedText = new FontRenderer.PreparedText(_font);
}
else
{
textRenderer.PreparedText.AddRef();
}
FontRenderer.PrepareText(textRenderer.PreparedText, _font, textRenderer.Text, 24, .Black);
textRenderer.PreparedText.ReleaseRef();
textRenderer.NeedsRebuild = false;
}
+16 -2
View File
@@ -118,15 +118,29 @@ class SceneRenderer
// Sprite renderer
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront);
for (var (entity, transform, sprite) in Scene._ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent>())
for (var (entity, transform, sprite, editorFlags) in Scene._ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent, EditorFlagsComponent>())
{
if (editorFlags.Flags.HasFlag(.HideInScene))
continue;
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
}
for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
for (var (entity, transform, circle, editorFlags) in Scene._ecsWorld.Enumerate<TransformComponent, CircleRendererComponent, EditorFlagsComponent>())
{
if (editorFlags.Flags.HasFlag(.HideInScene))
continue;
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
}
for (var (entity, transform, text, editorFlags) in Scene._ecsWorld.Enumerate<TransformComponent, TextRendererComponent, EditorFlagsComponent>())
{
if (editorFlags.Flags.HasFlag(.HideInScene) || text.PreparedText == null)
continue;
FontRenderer.DrawText(text.PreparedText, transform.WorldTransform * Matrix.Scaling(1.0f / 24.0f));
}
Renderer2D.EndScene();
+49
View File
@@ -0,0 +1,49 @@
using GlitchyEngine.Core;
using GlitchyEngine.Math;
namespace GlitchyEngine.Graphics;
/// <summary>
/// Renders text.
/// </summary>
public class TextRenderer : Component
{
/// <summary>
/// Gets or sets whether the text is rich text.<br/>
/// If <see langword="true"/>, the text will be parsed for rich text tags; if <see langword="false"/>, the text will be rendered as plain text.
/// </summary>
public bool IsRichText
{
get => ScriptGlue.TextRenderer_GetIsRichText(_uuid);
set => ScriptGlue.TextRenderer_SetIsRichText(_uuid, value);
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string Text
{
get
{
ScriptGlue.TextRenderer_GetText(_uuid, out string text);
return text;
}
set => ScriptGlue.TextRenderer_SetText(_uuid, value);
}
/// <summary>
/// The color that will be used to render the text. This color can be overridden by rich text tags.
/// </summary>
public ColorRGBA Color
{
get
{
ScriptGlue.TextRenderer_GetColor(_uuid, out ColorRGBA color);
return color;
}
set => ScriptGlue.TextRenderer_SetColor(_uuid, value);
}
// TODO: PreparedText component
}
+22
View File
@@ -255,6 +255,28 @@ internal static class ScriptGlue
#endregion
#region TextRenderer
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool TextRenderer_GetIsRichText(UUID entityId);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void TextRenderer_SetIsRichText(UUID entityId, bool isRichText);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void TextRenderer_GetText(UUID entityId, out string text);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void TextRenderer_SetText(UUID entityId, string text);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void TextRenderer_GetColor(UUID entityId, out ColorRGBA color);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void TextRenderer_SetColor(UUID entityId, ColorRGBA color);
#endregion
#region Math
[MethodImpl(MethodImplOptions.InternalCall)]