remove dependency to AscSprite from AscText

Fri, 11 Jul 2025 00:48:08 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 11 Jul 2025 00:48:08 +0200
changeset 196
ac2ade047d5b
parent 195
f9e9b7425ed3
child 197
a1f7c4f858d9

remove dependency to AscSprite from AscText

src/Makefile file | annotate | diff | comparison | revisions
src/ascension/constants.h file | annotate | diff | comparison | revisions
src/ascension/sprite.h file | annotate | diff | comparison | revisions
src/ascension/ui/text.h file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
test/snake/Makefile file | annotate | diff | comparison | revisions
--- a/src/Makefile	Thu Jul 10 22:19:48 2025 +0200
+++ b/src/Makefile	Fri Jul 11 00:48:08 2025 +0200
@@ -141,14 +141,14 @@
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
-$(BUILD_DIR)/text.o: text.c ascension/error.h ascension/context.h \
+$(BUILD_DIR)/text.o: text.c ascension/ui/text.h ascension/ui/font.h \
+ ascension/ui/../mesh.h ascension/ui/../datatypes.h \
+ ascension/ui/../texture.h ascension/ui/../scene_node.h \
+ ascension/ui/../transform.h ascension/error.h ascension/context.h \
  ascension/datatypes.h ascension/window.h ascension/glcontext.h \
- ascension/scene.h ascension/scene_node.h ascension/transform.h \
- ascension/camera.h ascension/input.h ascension/ui/font.h \
- ascension/ui/text.h ascension/ui/font.h ascension/ui/../sprite.h \
- ascension/ui/../scene_node.h ascension/ui/../mesh.h \
- ascension/ui/../datatypes.h ascension/ui/../texture.h \
- ascension/ui/../camera.h
+ ascension/scene.h ascension/scene_node.h ascension/camera.h \
+ ascension/input.h ascension/ui/font.h ascension/shader.h \
+ ascension/constants.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
@@ -161,13 +161,12 @@
 	$(CC) -o $@ $(CFLAGS) -c $<
 
 $(BUILD_DIR)/ui.o: ui.c ascension/ui.h ascension/ui/text.h \
- ascension/ui/font.h ascension/ui/../sprite.h \
- ascension/ui/../scene_node.h ascension/ui/../datatypes.h \
- ascension/ui/../transform.h ascension/ui/../mesh.h \
- ascension/ui/../texture.h ascension/ui/../camera.h ascension/context.h \
- ascension/datatypes.h ascension/window.h ascension/glcontext.h \
- ascension/scene.h ascension/scene_node.h ascension/camera.h \
- ascension/input.h ascension/ui/font.h ascension/scene.h
+ ascension/ui/font.h ascension/ui/../mesh.h ascension/ui/../datatypes.h \
+ ascension/ui/../texture.h ascension/ui/../scene_node.h \
+ ascension/ui/../transform.h ascension/context.h ascension/datatypes.h \
+ ascension/window.h ascension/glcontext.h ascension/scene.h \
+ ascension/scene_node.h ascension/camera.h ascension/input.h \
+ ascension/ui/font.h ascension/scene.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 
--- a/src/ascension/constants.h	Thu Jul 10 22:19:48 2025 +0200
+++ b/src/ascension/constants.h	Fri Jul 11 00:48:08 2025 +0200
@@ -45,6 +45,7 @@
 #define ASC_SHADER_ELLIPSIS_DRAW                ASC_SHADER_INTERNAL_ID(10)
 #define ASC_SHADER_ELLIPSIS_FILL                ASC_SHADER_INTERNAL_ID(11)
 #define ASC_SHADER_ELLIPSIS_FILL_BORDER         ASC_SHADER_INTERNAL_ID(12)
+#define ASC_SHADER_TEXT                         ASC_SHADER_INTERNAL_ID(20)
 
 
 #endif // ASC_CONSTANTS_H
--- a/src/ascension/sprite.h	Thu Jul 10 22:19:48 2025 +0200
+++ b/src/ascension/sprite.h	Fri Jul 11 00:48:08 2025 +0200
@@ -34,7 +34,7 @@
 #include "camera.h"
 
 typedef struct asc_sprite_s {
-    AscSceneNode data;
+    AscSceneNode base;
     AscMesh mesh;
     unsigned width;
     unsigned height;
@@ -71,7 +71,4 @@
 
 void asc_sprite_set_size(AscSprite *sprite, asc_vec2u size);
 
-// TODO: can be removed once AscText does no longer depend on AscSprite
-void asc_sprite_draw(const AscCamera *camera, const AscSceneNode *node);
-
 #endif //ASCENSION_SPRITE_H
--- a/src/ascension/ui/text.h	Thu Jul 10 22:19:48 2025 +0200
+++ b/src/ascension/ui/text.h	Fri Jul 11 00:48:08 2025 +0200
@@ -29,13 +29,17 @@
 #define ASCENSION_UI_TEXT_H
 
 #include "font.h"
-#include "../sprite.h"
+// TODO: clean up these messy include paths
+#include "../mesh.h"
+#include "../texture.h"
+#include "../scene_node.h"
 
 #include <cx/string.h>
 
 typedef struct asc_text_s {
-    // TODO: try to remove the explicit dependency to a sprite
-    AscSprite base;
+    AscSceneNode base;
+    AscMesh mesh;
+    AscTexture *texture;
     cxmutstr text;
     AscFont font;
     asc_col4i color;
--- a/src/text.c	Thu Jul 10 22:19:48 2025 +0200
+++ b/src/text.c	Fri Jul 11 00:48:08 2025 +0200
@@ -25,18 +25,48 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "ascension/ui/text.h"
+
 #include "ascension/error.h"
 #include "ascension/context.h"
-#include "ascension/ui/text.h"
+#include "ascension/shader.h"
+#include "ascension/constants.h"
 
 #include <assert.h>
 #include <cx/printf.h>
 
-#include <GL/glew.h>
+typedef struct asc_text_shader_s {
+    AscShaderProgram program;
+    asc_uniform_loc tex;
+} AscTextShader;
+
+AscShaderProgram *asc_text_shader_create(cx_attr_unused int unused) {
+    AscShaderCodes codes;
+    // TODO: with more advanced feature we want to create specific text shaders
+    if (asc_shader_load_code_files((AscShaderCodeInfo){
+        .files.vtx = "sprite_vtx.glsl",
+        .files.frag = "sprite_frag.glsl",
+        .defines.frag = "#define USE_RECT",
+    }, &codes)) {
+        asc_error("Loading text shader failed.");
+        return NULL;
+    }
+    AscShaderProgram *shader = asc_shader_create(codes, sizeof(*shader));
+    if (asc_shader_invalid(shader)) {
+        asc_shader_free_codes(codes);
+        return shader;
+    }
+    asc_ptr_cast(AscTextShader, text_shader, shader);
+    text_shader->tex = asc_shader_get_uniform_loc(shader, "tex");
+    asc_shader_free_codes(codes);
+
+    asc_error_catch_all_gl();
+
+    return shader;
+}
 
 static void asc_text_update(AscSceneNode *node) {
-    AscSprite *sprite = (AscSprite*) node;
-    AscText *text = (AscText*) node;
+    asc_ptr_cast(AscText, text, node);
 
     // Render text onto a surface
     TTF_Font *font = asc_font_load(text->font);
@@ -47,7 +77,7 @@
             TTF_WRAPPED_ALIGN_RIGHT
     };
     TTF_SetFontWrappedAlign(
-            font, alignments[text->base.data.flags & ASC_TEXT_ALIGNMENT_MASK]);
+            font, alignments[text->base.flags & ASC_TEXT_ALIGNMENT_MASK]);
     SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped(
             font, text->text.ptr, asc_col_sdl(text->color), text->max_width
     );
@@ -55,21 +85,21 @@
         asc_error("Rendering TTF surface failed: %s", SDL_GetError());
         return;
     }
-    if (asc_test_flag(text->base.data.flags, ASC_TEXT_CENTERED_FLAG)) {
+    if (asc_test_flag(text->base.flags, ASC_TEXT_CENTERED_FLAG)) {
         unsigned short newoffx = surface->w / 2;
         asc_transform_translate2f(node->transform, ASC_VEC2F(text->offx - newoffx, 0));
         text->offx = newoffx;
     }
 
     // Transfer Image Data
-    asc_texture_from_surface(sprite->texture, surface);
+    asc_texture_from_surface(text->texture, surface);
 
     // If dimensions changed, update the mesh
     if (text->dimension.x != (unsigned)surface->w || text->dimension.y != (unsigned)surface->h) {
         text->dimension.x = surface->w;
         text->dimension.y = surface->h;
-        const asc_vec2f uv_scale = asc_texture_calculate_uv_scale(sprite->texture, text->dimension, ASC_VEC2F_1);
-        asc_mesh_plane_2d(&text->base.mesh,
+        const asc_vec2f uv_scale = asc_texture_calculate_uv_scale(text->texture, text->dimension, ASC_VEC2F_1);
+        asc_mesh_plane_2d(&text->mesh,
             .size = ASC_VEC2F(surface->w, surface->h),
             .uv_scale = uv_scale
         );
@@ -82,26 +112,45 @@
     asc_node_update_transform(node);
 }
 
+static void asc_text_draw(const AscCamera *camera, const AscSceneNode *node) {
+    asc_cptr_cast(AscText, text, node);
+
+    // Activate shader
+    // TODO: scene should know which shader we are going to activate s.t. it can pre-sort nodes
+    const AscShaderProgram *shader = asc_shader_lookup_or_create(
+            ASC_SHADER_TEXT, asc_text_shader_create, 0);
+    if (asc_shader_use(shader, camera)) return;
+    asc_cptr_cast(AscTextShader, text_shader, shader);
+
+    // Upload model matrix
+    asc_shader_upload_model_matrix(shader, node);
+
+    // Bind texture
+    asc_texture_bind(text->texture, text_shader->tex, 0);
+
+    // Draw mesh
+    asc_mesh_draw_triangle_strip(&text->mesh);
+}
+
 static void asc_text_destroy(AscSceneNode *node) {
-    AscText *text = (AscText*) node;
-    AscSprite *sprite = (AscSprite*) node;
-    asc_mesh_destroy(&sprite->mesh);
-    asc_texture_destroy(sprite->texture, 1);
-    assert(sprite->texture->refcount == 0);
-    cxFreeDefault(sprite->texture);
+    asc_ptr_cast(AscText, text, node);
+    asc_mesh_destroy(&text->mesh);
+    asc_texture_destroy(text->texture, 1);
+    assert(text->texture->refcount == 0);
+    cxFreeDefault(text->texture);
     cx_strfree(&text->text);
 }
 
 AscSceneNode *asc_text_create(struct asc_text_create_args args) {
     AscText *text = cxZallocDefault(sizeof(AscText));
-    AscSceneNode *node = &text->base.data;
+    AscSceneNode *node = &text->base;
 
     // node properties
     asc_scene_node_name(node, args.name);
     node->render_group = ASC_RENDER_GROUP_2D_BLEND;
     node->destroy_func = asc_text_destroy;
     node->update_func = asc_text_update;
-    node->draw_func = asc_sprite_draw;
+    node->draw_func = asc_text_draw;
     asc_transform_identity(node->transform);
     asc_transform_translate3f(node->transform,
         ASC_VEC3F(args.x, args.y, ASC_SCENE_2D_DEPTH_OFFSET));
@@ -119,8 +168,8 @@
 
     // initialize texture
     // mesh will be created in the update func
-    text->base.texture = cxMallocDefault(sizeof(AscTexture));
-    asc_texture_init_rectangle(text->base.texture, 1);
+    text->texture = cxMallocDefault(sizeof(AscTexture));
+    asc_texture_init_rectangle(text->texture, 1);
     asc_text_update(node);
 
     return node;
--- a/test/snake/Makefile	Thu Jul 10 22:19:48 2025 +0200
+++ b/test/snake/Makefile	Fri Jul 11 00:48:08 2025 +0200
@@ -52,12 +52,12 @@
  ../../src/ascension/camera.h ../../src/ascension/input.h \
  ../../src/ascension/ui/font.h ../../src/ascension/behavior.h \
  ../../src/ascension/ui.h ../../src/ascension/ui/text.h \
- ../../src/ascension/ui/font.h ../../src/ascension/ui/../sprite.h \
- ../../src/ascension/ui/../scene_node.h ../../src/ascension/ui/../mesh.h \
+ ../../src/ascension/ui/font.h ../../src/ascension/ui/../mesh.h \
  ../../src/ascension/ui/../datatypes.h \
- ../../src/ascension/ui/../texture.h ../../src/ascension/ui/../camera.h \
- ../../src/ascension/sprite.h ../../src/ascension/2d.h \
- ../../src/ascension/mesh.h
+ ../../src/ascension/ui/../texture.h \
+ ../../src/ascension/ui/../scene_node.h ../../src/ascension/sprite.h \
+ ../../src/ascension/mesh.h ../../src/ascension/texture.h \
+ ../../src/ascension/2d.h
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 

mercurial