Fri, 11 Jul 2025 00:48:08 +0200
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 $<