diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp index df75bbb87..30335aee3 100644 --- a/Source/Engine/UI/TextRender.cpp +++ b/Source/Engine/UI/TextRender.cpp @@ -6,6 +6,7 @@ #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Models/Types.h" #include "Engine/Graphics/RenderView.h" +#include "Engine/Graphics/RenderTask.h" #include "Engine/Level/Scene/SceneRendering.h" #include "Engine/Render2D/Font.h" #include "Engine/Render2D/FontAsset.h" @@ -16,7 +17,7 @@ #include "Engine/Content/Assets/MaterialInstance.h" #include "Engine/Content/Content.h" #include "Engine/Core/Types/Variant.h" -#include "Engine/Graphics/RenderTask.h" +#include "Engine/Localization/Localization.h" #if USE_EDITOR #include "Editor/Editor.h" #endif @@ -45,7 +46,12 @@ TextRender::TextRender(const SpawnParams& params) Material.Changed.Bind(this); } -void TextRender::SetText(const StringView& value) +const LocalizedString& TextRender::GetText() const +{ + return _text; +} + +void TextRender::SetText(const LocalizedString& value) { if (_text != value) { @@ -54,6 +60,11 @@ void TextRender::SetText(const StringView& value) } } +Color TextRender::GetColor() const +{ + return _color; +} + void TextRender::SetColor(const Color& value) { if (_color != value) @@ -63,6 +74,11 @@ void TextRender::SetColor(const Color& value) } } +int32 TextRender::GetFontSize() const +{ + return _size; +} + void TextRender::SetFontSize(int32 value) { value = Math::Clamp(value, 1, 1024); @@ -84,9 +100,6 @@ void TextRender::SetLayoutOptions(TextLayoutOptions& value) void TextRender::UpdateLayout() { - if (!_isDirty) - return; - // Clear _ib.Clear(); _vb0.Clear(); @@ -111,8 +124,28 @@ void TextRender::UpdateLayout() _isDirty = false; // Skip if no need to calculate the layout - if (_text.IsEmpty()) - return; + String textData; + String* textPtr = &_text.Value; + if (textPtr->IsEmpty()) + { + if (_text.Id.IsEmpty()) + return; + textData = Localization::GetString(_text.Id); + textPtr = &textData; + if (!_isLocalized) + { + _isLocalized = true; + Localization::LocalizationChanged.Bind(this); + } + if (textPtr->IsEmpty()) + return; + } + else if (_isLocalized) + { + _isLocalized = false; + Localization::LocalizationChanged.Unbind(this); + } + const String& text = *textPtr; // Pick a font (remove DPI text scale as the text is being placed in the world) auto font = Font->CreateFont(_size); @@ -126,13 +159,13 @@ void TextRender::UpdateLayout() // Perform layout Array lines; - font->ProcessText(_text, lines, _layoutOptions); + font->ProcessText(text, lines, _layoutOptions); // Prepare buffers capacity - _ib.Data.EnsureCapacity(_text.Length() * 6 * sizeof(uint16)); - _vb0.Data.EnsureCapacity(_text.Length() * 4 * sizeof(VB0ElementType)); - _vb1.Data.EnsureCapacity(_text.Length() * 4 * sizeof(VB1ElementType)); - _vb2.Data.EnsureCapacity(_text.Length() * 4 * sizeof(VB2ElementType)); + _ib.Data.EnsureCapacity(text.Length() * 6 * sizeof(uint16)); + _vb0.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB0ElementType)); + _vb1.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB1ElementType)); + _vb2.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB2ElementType)); _buffersDirty = true; // Init draw chunks data @@ -155,7 +188,7 @@ void TextRender::UpdateLayout() // Render all characters from the line for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex; charIndex++) { - const Char c = _text[charIndex]; + const Char c = text[charIndex]; if (c != '\n') { font->GetCharacter(c, entry); @@ -198,7 +231,7 @@ void TextRender::UpdateLayout() const auto param = drawChunk.Material->Params.Get(FontParamName); if (param && param->GetParameterType() == MaterialParameterType::Texture) { - param->SetValue(fontAtlas); + param->SetValue(Variant(fontAtlas)); param->SetIsOverride(true); } } @@ -305,7 +338,10 @@ bool TextRender::HasContentLoaded() const void TextRender::Draw(RenderContext& renderContext) { - UpdateLayout(); + if (_isDirty) + { + UpdateLayout(); + } GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, _world); @@ -449,11 +485,19 @@ void TextRender::OnEnable() // Base Actor::OnEnable(); - UpdateLayout(); + if (_isDirty) + { + UpdateLayout(); + } } void TextRender::OnDisable() { + if (_isLocalized) + { + _isLocalized = false; + Localization::LocalizationChanged.Unbind(this); + } GetSceneRendering()->RemoveGeometry(this); // Base diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h index 07bfcfbe0..fff3915a5 100644 --- a/Source/Engine/UI/TextRender.h +++ b/Source/Engine/UI/TextRender.h @@ -11,6 +11,7 @@ #include "Engine/Content/Assets/MaterialInstance.h" #include "Engine/Graphics/DynamicBuffer.h" #include "Engine/Graphics/Models/Config.h" +#include "Engine/Localization/LocalizedString.h" #if USE_PRECISE_MESH_INTERSECTS #include "Engine/Graphics/Models/CollisionProxy.h" #endif @@ -34,7 +35,8 @@ private: bool _isDirty = false; bool _buffersDirty = false; - String _text; + bool _isLocalized = false; + LocalizedString _text; Color _color; TextLayoutOptions _layoutOptions; int32 _size; @@ -56,25 +58,19 @@ public: /// /// Gets the text. /// - API_PROPERTY(Attributes="EditorOrder(0), DefaultValue(\"\"), MultilineText, EditorDisplay(\"Text\")") - FORCE_INLINE const String& GetText() const - { - return _text; - } + API_PROPERTY(Attributes="EditorOrder(0), EditorDisplay(\"Text\")") + const LocalizedString& GetText() const; /// /// Sets the text. /// - API_PROPERTY() void SetText(const StringView& value); + API_PROPERTY() void SetText(const LocalizedString& value); /// /// Gets the color of the text. /// API_PROPERTY(Attributes="EditorOrder(10), DefaultValue(typeof(Color), \"1,1,1,1\"), EditorDisplay(\"Text\")") - FORCE_INLINE Color GetColor() const - { - return _color; - } + Color GetColor() const; /// /// Sets the color of the text. @@ -97,10 +93,7 @@ public: /// Gets the font characters size. /// API_PROPERTY(Attributes="EditorOrder(40), DefaultValue(32), Limit(1, 1000), EditorDisplay(\"Text\")") - FORCE_INLINE int32 GetFontSize() const - { - return _size; - } + int32 GetFontSize() const; /// /// Sets the font characters size. @@ -123,7 +116,7 @@ public: /// Gets the layout options. Layout is defined in local space of the object (on XY plane). /// API_PROPERTY(Attributes="EditorOrder(100), EditorDisplay(\"Text\")") - FORCE_INLINE TextLayoutOptions GetLayoutOptions() const + FORCE_INLINE const TextLayoutOptions& GetLayoutOptions() const { return _layoutOptions; } diff --git a/Source/Engine/UI/UI.Build.cs b/Source/Engine/UI/UI.Build.cs index 86c6f23c8..b72b7ca01 100644 --- a/Source/Engine/UI/UI.Build.cs +++ b/Source/Engine/UI/UI.Build.cs @@ -1,10 +1,18 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using Flax.Build; +using Flax.Build.NativeCpp; /// /// User Interface module. /// public class UI : EngineModule { + /// + public override void Setup(BuildOptions options) + { + base.Setup(options); + + options.PublicDependencies.Add("Localization"); + } }