From bc77340569cb284b7a9668e0d8a353801252db27 Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Mon, 9 Oct 2023 17:55:46 -0500
Subject: [PATCH] Added text alignment support.

---
 src/dawn/scene/components/ui/text/UILabel.cpp | 53 +++++++++++++++++++
 src/dawn/scene/components/ui/text/UILabel.hpp |  2 +
 .../shader/ShaderParameterBufferTypes.hpp     |  7 +++
 .../display/shader/shaders/FontShader.cpp     |  5 +-
 .../display/shader/shaders/FontShader.hpp     |  1 +
 5 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/dawn/scene/components/ui/text/UILabel.cpp b/src/dawn/scene/components/ui/text/UILabel.cpp
index 6f9107ab..a9a3bc93 100644
--- a/src/dawn/scene/components/ui/text/UILabel.cpp
+++ b/src/dawn/scene/components/ui/text/UILabel.cpp
@@ -22,12 +22,65 @@ void UILabel::onStart() {
   this->shaderBuffer.init();
 
   useEvent([&]{
+    // TODO: I believe I only need to rebuffer here if maxWidth is not -1
     this->rebufferQuads(this->texts);
   }, eventAlignmentUpdated);
 
   useEffect([&]{
     this->rebufferQuads(this->texts);
   }, lineHeight);
+  
+  useEvent([&]{
+    this->updateTextAlignments();
+  }, eventTextChanged);
+
+  useEffect([&]{
+    this->updateTextAlignments();
+  }, this->textAlign);
+}
+
+void UILabel::updateTextAlignments() {
+  struct FontShaderBufferData data;
+
+  switch(this->textAlign) {
+    case UI_LABEL_TEXT_ALIGN_LEFT: {
+      auto itLine = lines.begin();
+      int32_t i = 0;
+      while(itLine != lines.end()) {
+        data.linePositions[i] = glm::vec2(0, 0);
+        ++itLine;
+      }
+      break;
+    }
+    
+    case UI_LABEL_TEXT_ALIGN_RIGHT: {
+      float_t widthBased = this->getWidth();
+      auto itLine = lines.begin();
+      int32_t i = 0;
+      while(itLine != lines.end()) {
+        data.linePositions[i] = glm::vec2(widthBased - itLine->width, 0);
+        ++itLine;
+      }
+      break;
+    }
+
+    case UI_LABEL_TEXT_ALIGN_CENTER: {
+      float_t widthBased = this->getWidth();
+      auto itLine = lines.begin();
+      int32_t i = 0;
+      while(itLine != lines.end()) {
+        float_t x = (widthBased - itLine->width) / 2.0f;
+        data.linePositions[i] = glm::vec2(x, 0);
+        ++itLine;
+      }
+      break;
+    }
+
+    default:
+      assertUnreachable("UILabel::updateTextAlignments: TextAlign invalid");
+  }
+
+  this->shaderBuffer.buffer(&data, &data.linePositions);
 }
 
 std::vector<struct ShaderPassItem> UILabel::getUIRenderPasses() {
diff --git a/src/dawn/scene/components/ui/text/UILabel.hpp b/src/dawn/scene/components/ui/text/UILabel.hpp
index 0e881fcc..8ca3a0bd 100644
--- a/src/dawn/scene/components/ui/text/UILabel.hpp
+++ b/src/dawn/scene/components/ui/text/UILabel.hpp
@@ -59,6 +59,8 @@ namespace Dawn {
       bool_t ignoreAlignmentUpdate = false;
       bool_t hasDecorations = false;
 
+      void updateTextAlignments();
+
     public:
       int32_t quadStart = 0;
       int32_t quadCount = -1;
diff --git a/src/dawnopengl/display/shader/ShaderParameterBufferTypes.hpp b/src/dawnopengl/display/shader/ShaderParameterBufferTypes.hpp
index 1d200a68..0f5e9b1b 100644
--- a/src/dawnopengl/display/shader/ShaderParameterBufferTypes.hpp
+++ b/src/dawnopengl/display/shader/ShaderParameterBufferTypes.hpp
@@ -43,5 +43,12 @@
 #define SHADER_PARAMETER_BUFFER_MAT4(name) \
   glm::mat4 name;
 
+// VEC2
+#define SHADER_PARAMETER_BUFFER_VEC2(name) \
+  glm::vec2 name;
+
+#define SHADER_PARAMETER_BUFFER_VEC2_ARRAY(name, size) \
+  glm::vec2 name[size];
+
 // EOF Fix
 #define NOTHING "Fixes an error with EOF"
\ No newline at end of file
diff --git a/src/dawnopengl/display/shader/shaders/FontShader.cpp b/src/dawnopengl/display/shader/shaders/FontShader.cpp
index 12b59379..7ef2dc0f 100644
--- a/src/dawnopengl/display/shader/shaders/FontShader.cpp
+++ b/src/dawnopengl/display/shader/shaders/FontShader.cpp
@@ -28,6 +28,7 @@ void FontShader::compile() {
       "layout (shared) uniform ub_Font {\n"
         "vec4 u_FontColors[" MACRO_STRINGIFY(FONT_SHADER_PARTS_MAX) "];\n"
         "int u_FontTextures[" MACRO_STRINGIFY(FONT_SHADER_PARTS_MAX) "];\n"
+        "vec2 u_FontLinePositions[" MACRO_STRINGIFY(FONT_SHADER_PARTS_MAX) "];\n"
         "int u_FontQuadMappings[" MACRO_STRINGIFY(FONT_SHADER_QUADS_MAX) "];\n"
       "};\n"
 
@@ -37,10 +38,12 @@ void FontShader::compile() {
       "flat out int o_TextIndex;\n"
 
       "void main() {\n"
-        "gl_Position = u_Projection * u_View * u_Model * vec4(aPos.xy, 0, 1.0);\n"
         "o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
         "int quadIndex = gl_VertexID / " MACRO_STRINGIFY(QUAD_VERTICE_COUNT) ";\n"
         "int partIndex = u_FontQuadMappings[quadIndex];\n"
+        "gl_Position = u_Projection * u_View * u_Model * (\n"
+          "vec4(aPos.xy, 0, 1.0) + vec4(u_FontLinePositions[partIndex], 0, 0)\n"
+        ");\n"
         "o_VertColor = u_FontColors[partIndex];\n"
         "o_TextIndex = u_FontTextures[partIndex];\n"
       "}",
diff --git a/src/dawnopengl/display/shader/shaders/FontShader.hpp b/src/dawnopengl/display/shader/shaders/FontShader.hpp
index 66eb90b0..0bcd5b4e 100644
--- a/src/dawnopengl/display/shader/shaders/FontShader.hpp
+++ b/src/dawnopengl/display/shader/shaders/FontShader.hpp
@@ -15,6 +15,7 @@ namespace Dawn {
   SHADER_PARAMETER_BUFFER_DEFINE(FontShaderBuffer, \
     SHADER_PARAMETER_BUFFER_COLOR_ARRAY(colors, FONT_SHADER_PARTS_MAX);
     SHADER_PARAMETER_BUFFER_INTEGER_ARRAY(textures, FONT_SHADER_PARTS_MAX);
+    SHADER_PARAMETER_BUFFER_VEC2_ARRAY(linePositions, FONT_SHADER_PARTS_MAX);
     SHADER_PARAMETER_BUFFER_INTEGER_ARRAY(quadMappings, FONT_SHADER_QUADS_MAX);
   );