mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Font renderer improvements + component for scripting
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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....
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)]
|
||||
|
||||
Reference in New Issue
Block a user