32 |
32 |
33 #include <cx/printf.h> |
33 #include <cx/printf.h> |
34 |
34 |
35 #include <GL/glew.h> |
35 #include <GL/glew.h> |
36 |
36 |
37 static void asc_text_draw(AscText const *node) { |
37 static void asc_text_update(AscSceneNode *node) { |
38 // Obtain shader |
38 AscSprite *sprite = (AscSprite*) node; |
39 AscShaderSprite *shader = &asc_active_window->glctx.shader.sprite; |
39 AscText *text = (AscText*) node; |
40 |
40 |
41 // Upload model matrix |
|
42 glUniformMatrix4fv(shader->base.model, 1, |
|
43 GL_FALSE, node->base.world_transform); |
|
44 |
|
45 // Bind texture |
|
46 asc_texture_bind(&node->tex, shader->tex, 0); |
|
47 |
|
48 // Apply depth |
|
49 glUniform1f(shader->depth, (float)(node->base.depth)); |
|
50 |
|
51 // Draw mesh |
|
52 asc_primitives_draw_plane(); |
|
53 } |
|
54 |
|
55 static void asc_text_update(AscText *node) { |
|
56 // Generate new texture, if required |
41 // Generate new texture, if required |
57 if (asc_texture_uninitialized(&node->tex)) { |
42 if (asc_texture_uninitialized(&sprite->tex)) { |
58 asc_texture_init_rectangle(&node->tex); |
43 asc_texture_init_rectangle(&sprite->tex); |
59 } |
44 } |
60 |
45 |
61 // Render text onto a surface |
46 // Render text onto a surface |
62 TTF_Font *font = asc_font_load(node->font); |
47 TTF_Font *font = asc_font_load(text->font); |
63 static int alignments[] = { |
48 static int alignments[] = { |
64 TTF_WRAPPED_ALIGN_LEFT, |
49 TTF_WRAPPED_ALIGN_LEFT, |
65 TTF_WRAPPED_ALIGN_CENTER, |
50 TTF_WRAPPED_ALIGN_CENTER, |
66 TTF_WRAPPED_ALIGN_RIGHT |
51 TTF_WRAPPED_ALIGN_RIGHT |
67 }; |
52 }; |
68 TTF_SetFontWrappedAlign( |
53 TTF_SetFontWrappedAlign( |
69 font, alignments[node->base.flags & ASC_TEXT_ALIGNMENT_MASK]); |
54 font, alignments[text->base.data.flags & ASC_TEXT_ALIGNMENT_MASK]); |
70 SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( |
55 SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( |
71 font, node->text.ptr, asc_col_sdl(node->color), node->max_width |
56 font, text->text.ptr, asc_col_sdl(text->color), text->max_width |
72 ); |
57 ); |
73 if (surface == NULL) { |
58 if (surface == NULL) { |
74 asc_error(SDL_GetError()); |
59 asc_error(SDL_GetError()); |
75 return; |
60 return; |
76 } |
61 } |
77 asc_set_scale2d(&node->base, surface->w, surface->h); |
62 asc_set_scale2d(node, surface->w, surface->h); |
78 if (asc_test_flag(node->base.flags, ASC_TEXT_CENTERED_FLAG)) { |
63 if (asc_test_flag(text->base.data.flags, ASC_TEXT_CENTERED_FLAG)) { |
79 unsigned short newoffx = surface->w / 2; |
64 unsigned short newoffx = surface->w / 2; |
80 asc_vec2i pos = asc_get_position2d(&node->base); |
65 asc_vec2i pos = asc_get_position2d(node); |
81 asc_set_position2d(&node->base, pos.x + node->offx - newoffx, pos.y); |
66 asc_set_position2d(node, pos.x + text->offx - newoffx, pos.y); |
82 node->offx = newoffx; |
67 text->offx = newoffx; |
83 } |
68 } |
84 |
69 |
85 // Transfer Image Data |
70 // Transfer Image Data |
86 asc_texture_from_surface(&node->tex, surface); |
71 asc_texture_from_surface(&sprite->tex, surface); |
87 |
72 |
88 // Free the surface |
73 // Free the surface |
89 SDL_FreeSurface(surface); |
74 SDL_FreeSurface(surface); |
90 } |
75 } |
91 |
76 |
|
77 static void asc_text_free(AscSceneNode *node) { |
|
78 AscText *text = (AscText*) node; |
|
79 AscSprite *sprite = (AscSprite*) node; |
|
80 asc_texture_destroy(&sprite->tex); |
|
81 cx_strfree(&text->text); |
|
82 free(node); |
|
83 } |
|
84 |
92 AscSceneNode *asc_text_create(struct asc_text_create_args args) { |
85 AscSceneNode *asc_text_create(struct asc_text_create_args args) { |
93 AscText *node = calloc(1, sizeof(AscText)); |
86 AscText *text = calloc(1, sizeof(AscText)); |
|
87 AscSceneNode *node = (AscSceneNode*) text; |
94 |
88 |
95 node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND; |
89 node->render_group = ASC_RENDER_GROUP_SPRITE_BLEND; |
96 node->base.free_func = (asc_scene_free_func) asc_text_free; |
90 node->free_func = asc_text_free; |
97 node->base.update_func = (asc_scene_update_func) asc_text_update; |
91 node->update_func = asc_text_update; |
98 node->base.draw_func = (asc_scene_draw_func) asc_text_draw; |
|
99 |
92 |
100 node->base.flags = args.alignment; |
93 node->flags = args.alignment; |
101 node->base.position.x = (float) args.x; |
94 node->position.x = (float) args.x; |
102 node->base.position.y = (float) args.y; |
95 node->position.y = (float) args.y; |
103 node->max_width = args.max_width; |
96 text->max_width = args.max_width; |
104 node->font = asc_active_font; |
97 text->font = asc_active_font; |
105 node->color = asc_context.ink; |
98 text->color = asc_context.ink; |
106 if (args.text == NULL) { |
99 if (args.text == NULL) { |
107 node->text = cx_mutstr(strdup(" ")); |
100 text->text = cx_mutstr(strdup(" ")); |
108 } else { |
101 } else { |
109 node->text = cx_mutstr(strdup(args.text)); |
102 text->text = cx_mutstr(strdup(args.text)); |
110 } |
103 } |
111 |
104 |
112 // initialize |
105 // initialize |
113 asc_text_update(node); |
106 asc_text_update(node); |
114 |
107 |
115 return &node->base; |
108 return node; |
116 } |
|
117 |
|
118 void asc_text_free(AscText *node) { |
|
119 asc_texture_destroy(&node->tex); |
|
120 cx_strfree(&node->text); |
|
121 free(node); |
|
122 } |
109 } |
123 |
110 |
124 void asc_text_printf( |
111 void asc_text_printf( |
125 AscSceneNode *node, |
112 AscSceneNode *node, |
126 char const* format, |
113 char const* format, |