centralize draw functions

Wed, 14 Aug 2024 21:09:52 +0200

author
Mike Becker <universe@uap-core.de>
date
Wed, 14 Aug 2024 21:09:52 +0200
changeset 71
baa73a0be3ce
parent 70
81a089a47eff
child 72
84472fb3adbd

centralize draw functions

src/ascension/scene.h file | annotate | diff | comparison | revisions
src/ascension/ui/text.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
--- a/src/ascension/scene.h	Sun Aug 11 16:29:09 2024 +0200
+++ b/src/ascension/scene.h	Wed Aug 14 21:09:52 2024 +0200
@@ -31,6 +31,7 @@
 #include "datatypes.h"
 #include "transform.h"
 #include "camera.h"
+#include "texture.h"
 
 #include <cx/list.h>
 
@@ -38,7 +39,6 @@
 
 typedef void(*asc_scene_free_func)(AscSceneNode*);
 typedef void(*asc_scene_update_func)(AscSceneNode*);
-typedef void(*asc_scene_draw_func)(AscSceneNode const*);
 
 enum AscRenderGroup {
     ASC_RENDER_GROUP_SPRITE_OPAQUE,
@@ -54,7 +54,6 @@
     CxList *behaviors;
     asc_scene_free_func free_func;
     asc_scene_update_func update_func;
-    asc_scene_draw_func draw_func;
     unsigned depth; // TODO: do we really need this bullshit?
     asc_vec3f position;
     asc_vec3f rotation;
@@ -69,6 +68,11 @@
     uint32_t flags;
 };
 
+typedef struct AscSprite {
+    AscSceneNode data;
+    AscTexture tex;
+} AscSprite;
+
 /**
  * The reserved bits for general flags.
  */
@@ -95,11 +99,6 @@
 #define ASC_SCENE_NODE_HIDDEN                 0x80000000
 
 /**
- * Place this as first member of a structure that shall be used as a scene node.
- */
-#define extend_asc_scene_node AscSceneNode base
-
-/**
  * Draws the scene with the specified root node.
  *
  * @param root the root node of the scene graph
--- a/src/ascension/ui/text.h	Sun Aug 11 16:29:09 2024 +0200
+++ b/src/ascension/ui/text.h	Wed Aug 14 21:09:52 2024 +0200
@@ -30,19 +30,17 @@
 
 #include "font.h"
 #include "../scene.h"
-#include "../texture.h"
 #include "../utils.h"
 
 #include <cx/string.h>
 
 typedef struct AscText {
-    extend_asc_scene_node;
+    AscSprite base;
     cxmutstr text;
     AscFont font;
     asc_col4i color;
     unsigned short max_width;
     unsigned short offx;
-    AscTexture tex;
 } AscText;
 
 enum asc_text_alignment {
@@ -155,11 +153,4 @@
         ...
 );
 
-/**
- * Releases all the memory of this node.
- *
- * @param node the text node
- */
-void asc_text_free(AscText *node);
-
 #endif //ASCENSION_UI_TEXT_H
--- a/src/scene.c	Sun Aug 11 16:29:09 2024 +0200
+++ b/src/scene.c	Wed Aug 14 21:09:52 2024 +0200
@@ -58,22 +58,29 @@
     );
 }
 
-struct asc_render_group_entry {
-    asc_scene_draw_func draw;
-    AscSceneNode const *node;
-};
+static void asc_sprite_draw(AscSprite const *node) {
+    // Obtain shader
+    AscShaderSprite *shader = &asc_active_window->glctx.shader.sprite;
+
+    // Upload model matrix
+    glUniformMatrix4fv(shader->base.model, 1,
+                       GL_FALSE, node->data.world_transform);
 
-#define asc_draw_render_group(iter) \
-    cx_foreach(struct asc_render_group_entry*, entry, iter) { \
-        entry->draw(entry->node); \
-    }
+    // Bind texture
+    asc_texture_bind(&node->tex, shader->tex, 0);
+
+    // Apply depth
+    glUniform1f(shader->depth, (float)(node->data.depth));
+
+    // Draw mesh
+    asc_primitives_draw_plane();
+}
 
 void asc_scene_draw(AscSceneNode *root, asc_recti viewport, AscCamera *camera) {
     // create render groups
     CxList *render_group[ASC_RENDER_GROUP_COUNT];
     cx_for_n(i, ASC_RENDER_GROUP_COUNT) {
-        render_group[i] = cxArrayListCreateSimple(
-                sizeof(struct asc_render_group_entry), 32);
+        render_group[i] = cxArrayListCreateSimple(CX_STORE_POINTERS, 32);
     }
 
     // skip the root node deliberately, we know it's just the container
@@ -126,12 +133,7 @@
         }
 
         // add to render group
-        if (node->draw_func != NULL) {
-            struct asc_render_group_entry entry = {
-                    node->draw_func, node
-            };
-            cxListAdd(render_group[node->render_group], &entry);
-        }
+        cxListAdd(render_group[node->render_group], node);
     }
 
     // set the viewport (in OpenGL we need to invert the Y axis)
@@ -164,13 +166,17 @@
     // render opaque sprites from front to back
     glDisable(GL_BLEND);
     render_iter = cxListBackwardsIterator(render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE]);
-    asc_draw_render_group(render_iter);
+    cx_foreach(AscSprite const *, node, render_iter) {
+        asc_sprite_draw(node);
+    }
 
     // render sprites with alpha value from back to front
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     render_iter = cxListIterator(render_group[ASC_RENDER_GROUP_SPRITE_BLEND]);
-    asc_draw_render_group(render_iter);
+    cx_foreach(AscSprite const *, node, render_iter) {
+        asc_sprite_draw(node);
+    }
 
     // destroy render groups
     cx_for_n(i, ASC_RENDER_GROUP_COUNT) {
--- a/src/text.c	Sun Aug 11 16:29:09 2024 +0200
+++ b/src/text.c	Wed Aug 14 21:09:52 2024 +0200
@@ -34,91 +34,78 @@
 
 #include <GL/glew.h>
 
-static void asc_text_draw(AscText const *node) {
-    // Obtain shader
-    AscShaderSprite *shader = &asc_active_window->glctx.shader.sprite;
-
-    // Upload model matrix
-    glUniformMatrix4fv(shader->base.model, 1,
-                       GL_FALSE, node->base.world_transform);
-
-    // Bind texture
-    asc_texture_bind(&node->tex, shader->tex, 0);
+static void asc_text_update(AscSceneNode *node) {
+    AscSprite *sprite = (AscSprite*) node;
+    AscText *text = (AscText*) node;
 
-    // Apply depth
-    glUniform1f(shader->depth, (float)(node->base.depth));
-
-    // Draw mesh
-    asc_primitives_draw_plane();
-}
-
-static void asc_text_update(AscText *node) {
     // Generate new texture, if required
-    if (asc_texture_uninitialized(&node->tex)) {
-        asc_texture_init_rectangle(&node->tex);
+    if (asc_texture_uninitialized(&sprite->tex)) {
+        asc_texture_init_rectangle(&sprite->tex);
     }
 
     // Render text onto a surface
-    TTF_Font *font = asc_font_load(node->font);
+    TTF_Font *font = asc_font_load(text->font);
     static int alignments[] = {
             TTF_WRAPPED_ALIGN_LEFT,
             TTF_WRAPPED_ALIGN_CENTER,
             TTF_WRAPPED_ALIGN_RIGHT
     };
     TTF_SetFontWrappedAlign(
-            font, alignments[node->base.flags & ASC_TEXT_ALIGNMENT_MASK]);
+            font, alignments[text->base.data.flags & ASC_TEXT_ALIGNMENT_MASK]);
     SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped(
-            font, node->text.ptr, asc_col_sdl(node->color), node->max_width
+            font, text->text.ptr, asc_col_sdl(text->color), text->max_width
     );
     if (surface == NULL) {
         asc_error(SDL_GetError());
         return;
     }
-    asc_set_scale2d(&node->base, surface->w, surface->h);
-    if (asc_test_flag(node->base.flags, ASC_TEXT_CENTERED_FLAG)) {
+    asc_set_scale2d(node, surface->w, surface->h);
+    if (asc_test_flag(text->base.data.flags, ASC_TEXT_CENTERED_FLAG)) {
         unsigned short newoffx = surface->w / 2;
-        asc_vec2i pos = asc_get_position2d(&node->base);
-        asc_set_position2d(&node->base, pos.x + node->offx - newoffx, pos.y);
-        node->offx = newoffx;
+        asc_vec2i pos = asc_get_position2d(node);
+        asc_set_position2d(node, pos.x + text->offx - newoffx, pos.y);
+        text->offx = newoffx;
     }
 
     // Transfer Image Data
-    asc_texture_from_surface(&node->tex, surface);
+    asc_texture_from_surface(&sprite->tex, surface);
 
     // Free the surface
     SDL_FreeSurface(surface);
 }
 
-AscSceneNode *asc_text_create(struct asc_text_create_args args) {
-    AscText *node = calloc(1, sizeof(AscText));
+static void asc_text_free(AscSceneNode *node) {
+    AscText *text = (AscText*) node;
+    AscSprite *sprite = (AscSprite*) node;
+    asc_texture_destroy(&sprite->tex);
+    cx_strfree(&text->text);
+    free(node);
+}
 
-    node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND;
-    node->base.free_func = (asc_scene_free_func) asc_text_free;
-    node->base.update_func = (asc_scene_update_func) asc_text_update;
-    node->base.draw_func = (asc_scene_draw_func) asc_text_draw;
+AscSceneNode *asc_text_create(struct asc_text_create_args args) {
+    AscText *text = calloc(1, sizeof(AscText));
+    AscSceneNode *node = (AscSceneNode*) text;
 
-    node->base.flags = args.alignment;
-    node->base.position.x = (float) args.x;
-    node->base.position.y = (float) args.y;
-    node->max_width = args.max_width;
-    node->font = asc_active_font;
-    node->color = asc_context.ink;
+    node->render_group = ASC_RENDER_GROUP_SPRITE_BLEND;
+    node->free_func = asc_text_free;
+    node->update_func = asc_text_update;
+
+    node->flags = args.alignment;
+    node->position.x = (float) args.x;
+    node->position.y = (float) args.y;
+    text->max_width = args.max_width;
+    text->font = asc_active_font;
+    text->color = asc_context.ink;
     if (args.text == NULL) {
-        node->text = cx_mutstr(strdup(" "));
+        text->text = cx_mutstr(strdup(" "));
     } else {
-        node->text = cx_mutstr(strdup(args.text));
+        text->text = cx_mutstr(strdup(args.text));
     }
 
     // initialize
     asc_text_update(node);
 
-    return &node->base;
-}
-
-void asc_text_free(AscText *node) {
-    asc_texture_destroy(&node->tex);
-    cx_strfree(&node->text);
-    free(node);
+    return node;
 }
 
 void asc_text_printf(

mercurial