Cogs.Core
TextSystem.cpp
1#include "Rendering/ICapabilities.h"
2
3#include "TextSystem.h"
4
5#include "Context.h"
6
7
8#include "Systems/Core/TransformSystem.h"
9#include "Systems/Core/SpriteRenderSystem.h"
10
11#include "Resources/MaterialManager.h"
12#include "Resources/FontManager.h"
13#include "Resources/Texture.h"
14
16{
18
19 if (context->device->getCapabilities()->getDeviceCapabilities().GeometryShaders) {
20 textMaterial = context->materialManager->loadMaterial("Materials/TextMaterial.material");
21 }
22 else {
23 textMaterial = context->materialManager->loadMaterial("Materials/TextNoGsMaterial.material");
24 }
25 context->materialManager->processLoading();
26
28 textMaterial->options.depthWriteEnabled = false;
29
30 spriteMaterial = context->spriteRenderSystem->registerSpriteMaterial(textMaterial);
31}
32
34{
35 for (auto & component : pool) {
36 if (!component.transformComponent) {
37 component.transformComponent = component.getComponentHandle<TransformComponent>();
38 component.spriteRenderComponent = component.getComponentHandle<SpriteRenderComponent>();
39 }
40 }
41
42 auto fontManager = context->fontManager;
43 auto sprites = context->spriteRenderSystem;
44 for (auto & textComponent : pool) {
45 if (!textComponent.texts.size()) continue;
46 if (!textComponent.spriteRenderComponent) continue;
47
48 auto spriteRenderer = textComponent.spriteRenderComponent.resolveComponent<SpriteRenderComponent>();
49
50 if (!spriteRenderer->isVisible()) continue;
51
52 auto font = textComponent.fontHandle.resolve();
53 if (!font) font = context->fontManager->getHandle(context->fontManager->DefaultRegularFont).resolve();
54
55 if (!font || !font->isActive()) continue;
56 if (!font->texture) continue;
57 if (!font->texture->isActive()) continue;
58
59 auto batch = sprites->begin(spriteMaterial,
60 font->sdf ? "Sdf" : "",
61 textComponent.positionMode,
63 font->texture,
64 textComponent.color);
65
66#ifdef EMSCRIPTEN
67 batch->blendMode = BlendMode::Blend;
68#else
69 batch->blendMode = BlendMode::PremultipliedBlend;
70#endif
71
72 const bool useOffsets = textComponent.positions.size() == textComponent.texts.size();
73 const auto transformComponent = textComponent.transformComponent.resolveComponent<TransformComponent>();
74
75 for (size_t i = 0; i < textComponent.texts.size(); ++i) {
76 auto & text = textComponent.texts[i];
77
78 if (textComponent.colors.size() == textComponent.texts.size()) {
79 batch = sprites->begin(spriteMaterial,
80 font->sdf ? "Sdf" : "",
81 textComponent.positionMode,
83 font->texture,
84 textComponent.colors[i]);
85 batch->blendMode = BlendMode::PremultipliedBlend;
86 }
87
88 const glm::vec3 offset = useOffsets ? textComponent.positions[i] : glm::vec3(0.0f);
89 glm::vec3 startPosition = glm::vec3(0.0f);
90 float depth = -1;
91
92 if (textComponent.positionMode == PositionMode::World) {
93 auto & localToWorld = context->transformSystem->getLocalToWorld(transformComponent);
94 auto position = glm::vec3(localToWorld * glm::vec4(0, 0, 0, 1));
95 startPosition = glm::vec4(position + offset, 1);
96 } else if (textComponent.positionMode == PositionMode::Local) {
97 startPosition = glm::vec4(offset, 1);
98 batch->transform = context->transformSystem->getLocalToWorld(transformComponent);
99 } else {
100 startPosition += transformComponent->position + offset;
101 }
102
103 batch->depth = std::max(batch->depth, depth);
104
105 const float factor = 0.72f;
106 float verticalOffset = 0.0f;
107 switch (textComponent.verticalAlignment) {
109 verticalOffset = (font->size / 2.0f) * factor;
110 break;
112 verticalOffset = (font->size) * factor;
113 break;
114 default:
115 break;
116 }
117
118 float x = 0;
119 float y = 0;
120
121 if (textComponent.horizontalJustification == HorizontalJustification::Left) {
122 for (size_t ii = 0; ii < text.size(); ++ii) {
124 fontManager->getBakedCharacter(font, text[ii], x, y, q);
125
126 glm::vec2 offset2 = {
127 (q.x0 + q.x1) * 0.5f,
128 (q.y0 + q.y1) * -0.5f - verticalOffset,
129 };
130
131 glm::vec2 size = {
132 q.x1 - q.x0,
133 q.y1 - q.y0
134 };
135
136 glm::vec4 uv = {
137 q.s0,
138 q.t1,
139 q.s1,
140 q.t0,
141 };
142
143 sprites->addSprite(spriteRenderer, startPosition, offset2, size, uv);
144 }
145 } else if(textComponent.horizontalJustification == HorizontalJustification::Right) {
146 const float startX = x;
147
148 for (size_t ii = 0; ii < text.size(); ++ii) {
150 fontManager->getBakedCharacter(font, text[text.size() - 1 - ii], x, y, q);
151
152 const float width = q.x1 - q.x0;
153 const float start = startX - (q.x0 - startX);
154
155 glm::vec2 offset2 = {
156 start - width * 0.5f,
157 (q.y0 + q.y1) * -0.5f - verticalOffset,
158 };
159
160 glm::vec2 size = {
161 q.x1 - q.x0,
162 q.y1 - q.y0
163 };
164
165 glm::vec4 uv = {
166 q.s0,
167 q.t1,
168 q.s1,
169 q.t0,
170 };
171
172 sprites->addSprite(spriteRenderer, startPosition, offset2, size, uv);
173 }
174 }
175 else {
177 fontManager->getBakedCharacter(font, text[0], x, y, q0);
178 Font::BakedCharacter qn = q0;
179
180 for (size_t ii = 1; ii < text.size(); ++ii)
181 fontManager->getBakedCharacter(font, text[ii], x, y, qn);
182 x = 0;
183 y = 0;
184 const float horizontalOffset = (qn.x1 - q0.x0) * 0.5f;
185
186 for (size_t ii = 0; ii < text.size(); ++ii) {
188 fontManager->getBakedCharacter(font, text[ii], x, y, q);
189
190 glm::vec2 offset_ = {
191 (q.x0 + q.x1) * 0.5f - horizontalOffset,
192 (q.y0 + q.y1) * -0.5f - verticalOffset,
193 };
194
195 glm::vec2 size = {
196 q.x1 - q.x0,
197 q.y1 - q.y0
198 };
199
200 glm::vec4 uv = {
201 q.s0,
202 q.t1,
203 q.s1,
204 q.t0,
205 };
206
207 sprites->addSprite(spriteRenderer, startPosition, offset_, size, uv);
208 }
209 }
210
211 if (batch->positionMode >= PositionMode::World) {
212 batch->flags |= RenderItemFlags::CalculateDepth;
213 }
214 }
215 }
216}
ComponentHandle getComponentHandle() const
Definition: Component.h:177
Context * context
Pointer to the Context instance the system lives in.
virtual void initialize(Context *context)
Initialize the system.
void update()
Updates the system state to that of the current frame.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
void initialize(Context *context) override
Initialize the system.
Definition: TextSystem.cpp:15
Defines a 4x4 transformation matrix for the entity and a global offset for root entities.
@ World
Position given in world space coordinates.
@ Right
The rightmost character is placed to the left of the screen position.
@ Left
The leftmost character is placed to the right of the screen position.
@ Blend
Render with regular alpha blending.
@ Pixels
Size given in screen pixels.
@ Bottom
Align the text towards the bottom, making the position minus the font height the baseline of the text...
@ Center
Center the text on the screen position.
Defines a quad with locations in screen space defined by [x0, y0] and [x1, y1].
Definition: Font.h:48
BlendMode blendMode
Blend mode to use when rendering geometry with the material instance.
bool depthWriteEnabled
If depth writes should be enabled rendering the geometry with the material instance.
MaterialOptions options
Material rendering options.
Definition: Material.h:383