diff --git a/libs/sf2dlib/libsf2d/include/sf2d.h b/libs/sf2dlib/libsf2d/include/sf2d.h index 8d85e02..9df8d08 100644 --- a/libs/sf2dlib/libsf2d/include/sf2d.h +++ b/libs/sf2dlib/libsf2d/include/sf2d.h @@ -280,6 +280,8 @@ void sf2d_draw_fill_circle(int x, int y, int radius, u32 color); * @param pixel_format the pixel_format of the texture * @param place where to allocate the texture * @return a pointer to the newly created texture + * @note Before drawing the texture, it needs to be tiled + * by calling sf2d_texture_tile32. */ sf2d_texture *sf2d_create_texture(int width, int height, sf2d_texfmt pixel_format, sf2d_place place); @@ -343,7 +345,40 @@ void sf2d_bind_texture_parameters(const sf2d_texture *texture, GPU_TEXUNIT unit, void sf2d_draw_texture(const sf2d_texture *texture, int x, int y); /** - * @brief Draws a texture with rotation + * @brief Draws a texture blended with a color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color); + +/** + * @brief Draws a texture with rotation around a hotspot + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param rad rotation (in radians) to draw the texture + * @param center_x the x position of the hotspot + * @param center_y the y position of the hotspot + */ +void sf2d_draw_texture_rotate_hotspot(const sf2d_texture *texture, int x, int y, float rad, float center_x, float center_y); + +/** + * @brief Draws a texture with rotation around a hotspot with a color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param rad rotation (in radians) to draw the texture + * @param center_x the x position of the hotspot + * @param center_y the y position of the hotspot + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_rotate_hotspot_blend(const sf2d_texture *texture, int x, int y, float rad, float center_x, float center_y, u32 color); + + +/** + * @brief Draws a texture with rotation around its center * @param texture the texture to draw * @param x the x coordinate to draw the texture to * @param y the y coordinate to draw the texture to @@ -351,6 +386,16 @@ void sf2d_draw_texture(const sf2d_texture *texture, int x, int y); */ void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad); +/** + * @brief Draws a texture with rotation around its center with color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param rad rotation (in radians) to draw the texture + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_rotate_blend(const sf2d_texture *texture, int x, int y, float rad, u32 color); + /** * @brief Draws a part of a texture * @param texture the texture to draw @@ -363,6 +408,19 @@ void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float r */ void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h); +/** + * @brief Draws a part of a texture with color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param tex_x the starting point (x coordinate) where to start drawing + * @param tex_y the starting point (y coordinate) where to start drawing + * @param tex_w the width to draw from the starting point + * @param tex_h the height to draw from the starting point + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color); + /** * @brief Draws a texture with scaling * @param texture the texture to draw @@ -373,6 +431,46 @@ void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x */ void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale); +/** + * @brief Draws a texture with scaling with color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param x_scale the x scale + * @param y_scale the y scale + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_scale_blend(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale, u32 color); + +/** + * @brief Draws a part of a texture, with scaling + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param tex_x the starting point (x coordinate) where to start drawing + * @param tex_y the starting point (y coordinate) where to start drawing + * @param tex_w the width to draw from the starting point + * @param tex_h the height to draw from the starting point + * @param x_scale the x scale + * @param y_scale the y scale + */ +void sf2d_draw_texture_part_scale(const sf2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale); + +/** + * @brief Draws a part of a texture, with scaling, with color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param tex_x the starting point (x coordinate) where to start drawing + * @param tex_y the starting point (y coordinate) where to start drawing + * @param tex_w the width to draw from the starting point + * @param tex_h the height to draw from the starting point + * @param x_scale the x scale + * @param y_scale the y scale + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_part_scale_blend(const sf2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, u32 color); + /** * @brief Draws a part of a texture, with rotation and scaling * @param texture the texture to draw @@ -386,29 +484,23 @@ void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_ * @param x_scale the x scale * @param y_scale the y scale */ -void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale); +void sf2d_draw_texture_part_rotate_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale); /** - * @brief Draws a texture blended with a color - * @param texture the texture to draw - * @param x the x coordinate to draw the texture to - * @param y the y coordinate to draw the texture to - * @param color the color to blend with the texture - */ -void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color); - -/** - * @brief Draws a part of a texture blended with a color + * @brief Draws a part of a texture, with rotation, scaling and color * @param texture the texture to draw * @param x the x coordinate to draw the texture to * @param y the y coordinate to draw the texture to + * @param rad rotation (in radians) to draw the texture * @param tex_x the starting point (x coordinate) where to start drawing * @param tex_y the starting point (y coordinate) where to start drawing * @param tex_w the width to draw from the starting point * @param tex_h the height to draw from the starting point + * @param x_scale the x scale + * @param y_scale the y scale * @param color the color to blend with the texture */ -void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color); +void sf2d_draw_texture_part_rotate_scale_blend(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale, u32 color); /** * @brief Draws a texture blended in a certain depth @@ -425,6 +517,22 @@ void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int */ void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed short z); +/** + * @brief Draws a texture blended in a certain depth + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param z the depth to draw the texture to + * @param color the color to blend with the texture + * @note The z parameter is a value in the [-32768, +32767] range, + * where -32768 is the deepest and +32767 the toppest. + * By default, the textures are drawn at z = 0. + * Keep in mind that this function won't do + * Order-independent transparency (OIT), so you should use fully + * opaque textures to get good results. + */ +void sf2d_draw_texture_depth_blend(const sf2d_texture *texture, int x, int y, signed short z, u32 color); + /** * @brief Draws a texture using custom texture coordinates and parameters * @param texture the texture to draw diff --git a/libs/sf2dlib/libsf2d/source/sf2d_texture.c b/libs/sf2dlib/libsf2d/source/sf2d_texture.c index 6397a9e..c9368c7 100644 --- a/libs/sf2dlib/libsf2d/source/sf2d_texture.c +++ b/libs/sf2dlib/libsf2d/source/sf2d_texture.c @@ -1,5 +1,6 @@ #include #include +#include #include "sf2d.h" #include "sf2d_private.h" @@ -191,7 +192,7 @@ void sf2d_bind_texture_parameters(const sf2d_texture *texture, GPU_TEXUNIT unit, ); } -void sf2d_draw_texture(const sf2d_texture *texture, int x, int y) +static inline void sf2d_draw_texture_generic(const sf2d_texture *texture, int x, int y) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); if (!vertices) return; @@ -212,8 +213,6 @@ void sf2d_draw_texture(const sf2d_texture *texture, int x, int y) vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; - sf2d_bind_texture(texture, GPU_TEXUNIT0); - GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), @@ -229,39 +228,60 @@ void sf2d_draw_texture(const sf2d_texture *texture, int x, int y) GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); } -void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad) +void sf2d_draw_texture(const sf2d_texture *texture, int x, int y) +{ + sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_generic(texture, x, y); +} + +void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_generic(texture, x, y); +} + +static inline void sf2d_draw_texture_rotate_hotspot_generic(const sf2d_texture *texture, int x, int y, float rad, float center_x, float center_y) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); if (!vertices) return; - int w2 = texture->width/2.0f; - int h2 = texture->height/2.0f; + const float w = texture->width; + const float h = texture->height; - vertices[0].position = (sf2d_vector_3f){(float)-w2, (float)-h2, SF2D_DEFAULT_DEPTH}; - vertices[1].position = (sf2d_vector_3f){(float) w2, (float)-h2, SF2D_DEFAULT_DEPTH}; - vertices[2].position = (sf2d_vector_3f){(float)-w2, (float) h2, SF2D_DEFAULT_DEPTH}; - vertices[3].position = (sf2d_vector_3f){(float) w2, (float) h2, SF2D_DEFAULT_DEPTH}; + vertices[0].position.x = -center_x; + vertices[0].position.y = -center_y; + vertices[0].position.z = SF2D_DEFAULT_DEPTH; - float u = texture->width/(float)texture->pow2_w; - float v = texture->height/(float)texture->pow2_h; + vertices[1].position.x = w - center_x; + vertices[1].position.y = -center_y; + vertices[1].position.z = SF2D_DEFAULT_DEPTH; + + vertices[2].position.x = -center_x; + vertices[2].position.y = h - center_y; + vertices[2].position.z = SF2D_DEFAULT_DEPTH; + + vertices[3].position.x = w - center_x; + vertices[3].position.y = h - center_y; + vertices[3].position.z = SF2D_DEFAULT_DEPTH; + + float u = w/(float)texture->pow2_w; + float v = h/(float)texture->pow2_h; vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; - float m[4*4]; - matrix_set_z_rotation(m, rad); - sf2d_vector_3f rot[4]; - + const float c = cosf(rad); + const float s = sinf(rad); int i; - for (i = 0; i < 4; i++) { - vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]); - vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z}; + for (i = 0; i < 4; ++i) { // Rotate and translate + float _x = vertices[i].position.x; + float _y = vertices[i].position.y; + vertices[i].position.x = _x*c - _y*s + x; + vertices[i].position.y = _x*s + _y*c + y; } - sf2d_bind_texture(texture, GPU_TEXUNIT0); - GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), @@ -277,7 +297,34 @@ void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float r GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); } -void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h) +void sf2d_draw_texture_rotate_hotspot(const sf2d_texture *texture, int x, int y, float rad, float center_x, float center_y) +{ + sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_rotate_hotspot_generic(texture, x, y, rad, center_x, center_y); +} + +void sf2d_draw_texture_rotate_hotspot_blend(const sf2d_texture *texture, int x, int y, float rad, float center_x, float center_y, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_rotate_hotspot_generic(texture, x, y, rad, center_x, center_y); +} + +void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float rad) +{ + sf2d_draw_texture_rotate_hotspot(texture, x, y, rad, + texture->width/2.0f, + texture->height/2.0f); +} + +void sf2d_draw_texture_rotate_blend(const sf2d_texture *texture, int x, int y, float rad, u32 color) +{ + sf2d_draw_texture_rotate_hotspot_blend(texture, x, y, rad, + texture->width/2.0f, + texture->height/2.0f, + color); +} + +static inline void sf2d_draw_texture_part_generic(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); if (!vertices) return; @@ -297,8 +344,6 @@ void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; - sf2d_bind_texture(texture, GPU_TEXUNIT0); - GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), @@ -314,7 +359,19 @@ void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); } -void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale) +void sf2d_draw_texture_part(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h) +{ + sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_part_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h); +} + +void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_part_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h); +} + +static inline void sf2d_draw_texture_scale_generic(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); if (!vertices) return; @@ -335,7 +392,55 @@ void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_ vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; + GPU_SetAttributeBuffers( + 2, // number of attributes + (u32*)osConvertVirtToPhys((u32)vertices), + GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), + 0xFFFC, //0b1100 + 0x10, + 1, //number of buffers + (u32[]){0x0}, // buffer offsets (placeholders) + (u64[]){0x10}, // attribute permutations for each buffer + (u8[]){2} // number of attributes for each buffer + ); + + GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); +} + +void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale) +{ sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_scale_generic(texture, x, y, x_scale, y_scale); +} + +void sf2d_draw_texture_scale_blend(const sf2d_texture *texture, int x, int y, float x_scale, float y_scale, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_scale_generic(texture, x, y, x_scale, y_scale); +} + +static inline void sf2d_draw_texture_part_scale_generic(const sf2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale) +{ + sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); + if (!vertices) return; + + float u0 = tex_x/(float)texture->pow2_w; + float v0 = tex_y/(float)texture->pow2_h; + float u1 = (tex_x+tex_w)/(float)texture->pow2_w; + float v1 = (tex_y+tex_h)/(float)texture->pow2_h; + + vertices[0].texcoord = (sf2d_vector_2f){u0, v0}; + vertices[1].texcoord = (sf2d_vector_2f){u1, v0}; + vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; + vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; + + tex_w *= x_scale; + tex_h *= y_scale; + + vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH}; + vertices[1].position = (sf2d_vector_3f){(float)x+tex_w, (float)y, SF2D_DEFAULT_DEPTH}; + vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+tex_h, SF2D_DEFAULT_DEPTH}; + vertices[3].position = (sf2d_vector_3f){(float)x+tex_w, (float)y+tex_h, SF2D_DEFAULT_DEPTH}; GPU_SetAttributeBuffers( 2, // number of attributes @@ -352,14 +457,23 @@ void sf2d_draw_texture_scale(const sf2d_texture *texture, int x, int y, float x_ GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); } -void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale) +void sf2d_draw_texture_part_scale(const sf2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale) +{ + sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_part_scale_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale); +} + +void sf2d_draw_texture_part_scale_blend(const sf2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_part_scale_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale); +} + +static inline void sf2d_draw_texture_part_rotate_scale_generic(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); if (!vertices) return; - //Don't even try to understand what I'm doing here (because I don't even understand it). - //Matrices are boring. - int w2 = (tex_w * x_scale)/2.0f; int h2 = (tex_h * y_scale)/2.0f; @@ -378,109 +492,44 @@ void sf2d_draw_texture_rotate_cut_scale(const sf2d_texture *texture, int x, int vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; - float m[4*4]; - matrix_set_z_rotation(m, rad); - sf2d_vector_3f rot[4]; - + const float c = cosf(rad); + const float s = sinf(rad); int i; - for (i = 0; i < 4; i++) { - vector_mult_matrix4x4(m, &vertices[i].position, &rot[i]); - vertices[i].position = (sf2d_vector_3f){rot[i].x + x + w2, rot[i].y + y + h2, rot[i].z}; + for (i = 0; i < 4; ++i) { // Rotate and translate + float _x = vertices[i].position.x; + float _y = vertices[i].position.y; + vertices[i].position.x = _x*c - _y*s + x; + vertices[i].position.y = _x*s + _y*c + y; } + GPU_SetAttributeBuffers( + 2, // number of attributes + (u32*)osConvertVirtToPhys((u32)vertices), + GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), + 0xFFFC, //0b1100 + 0x10, + 1, //number of buffers + (u32[]){0x0}, // buffer offsets (placeholders) + (u64[]){0x10}, // attribute permutations for each buffer + (u8[]){2} // number of attributes for each buffer + ); + + GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); +} + +void sf2d_draw_texture_part_rotate_scale(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale) +{ sf2d_bind_texture(texture, GPU_TEXUNIT0); - - GPU_SetAttributeBuffers( - 2, // number of attributes - (u32*)osConvertVirtToPhys((u32)vertices), - GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), - 0xFFFC, //0b1100 - 0x10, - 1, //number of buffers - (u32[]){0x0}, // buffer offsets (placeholders) - (u64[]){0x10}, // attribute permutations for each buffer - (u8[]){2} // number of attributes for each buffer - ); - - GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); + sf2d_draw_texture_part_rotate_scale_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale); } -void sf2d_draw_texture_blend(const sf2d_texture *texture, int x, int y, u32 color) +void sf2d_draw_texture_part_rotate_scale_blend(const sf2d_texture *texture, int x, int y, float rad, int tex_x, int tex_y, int tex_w, int tex_h, float x_scale, float y_scale, u32 color) { - sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); - if (!vertices) return; - - int w = texture->width; - int h = texture->height; - - vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH}; - vertices[1].position = (sf2d_vector_3f){(float)x+w, (float)y, SF2D_DEFAULT_DEPTH}; - vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+h, SF2D_DEFAULT_DEPTH}; - vertices[3].position = (sf2d_vector_3f){(float)x+w, (float)y+h, SF2D_DEFAULT_DEPTH}; - - float u = texture->width/(float)texture->pow2_w; - float v = texture->height/(float)texture->pow2_h; - - vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; - vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; - vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; - vertices[3].texcoord = (sf2d_vector_2f){u, v}; - sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); - - GPU_SetAttributeBuffers( - 2, // number of attributes - (u32*)osConvertVirtToPhys((u32)vertices), - GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), - 0xFFFC, //0b1100 - 0x10, - 1, //number of buffers - (u32[]){0x0}, // buffer offsets (placeholders) - (u64[]){0x10}, // attribute permutations for each buffer - (u8[]){2} // number of attributes for each buffer - ); - - GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); + sf2d_draw_texture_part_rotate_scale_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale); } -void sf2d_draw_texture_part_blend(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h, u32 color) -{ - sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); - if (!vertices) return; - - vertices[0].position = (sf2d_vector_3f){(float)x, (float)y, SF2D_DEFAULT_DEPTH}; - vertices[1].position = (sf2d_vector_3f){(float)x+tex_w, (float)y, SF2D_DEFAULT_DEPTH}; - vertices[2].position = (sf2d_vector_3f){(float)x, (float)y+tex_h, SF2D_DEFAULT_DEPTH}; - vertices[3].position = (sf2d_vector_3f){(float)x+tex_w, (float)y+tex_h, SF2D_DEFAULT_DEPTH}; - - float u0 = tex_x/(float)texture->pow2_w; - float v0 = tex_y/(float)texture->pow2_h; - float u1 = (tex_x+tex_w)/(float)texture->pow2_w; - float v1 = (tex_y+tex_h)/(float)texture->pow2_h; - - vertices[0].texcoord = (sf2d_vector_2f){u0, v0}; - vertices[1].texcoord = (sf2d_vector_2f){u1, v0}; - vertices[2].texcoord = (sf2d_vector_2f){u0, v1}; - vertices[3].texcoord = (sf2d_vector_2f){u1, v1}; - - sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); - - GPU_SetAttributeBuffers( - 2, // number of attributes - (u32*)osConvertVirtToPhys((u32)vertices), - GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), - 0xFFFC, //0b1100 - 0x10, - 1, //number of buffers - (u32[]){0x0}, // buffer offsets (placeholders) - (u64[]){0x10}, // attribute permutations for each buffer - (u8[]){2} // number of attributes for each buffer - ); - - GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); -} - -void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed short z) +static inline void sf2d_draw_texture_depth_generic(const sf2d_texture *texture, int x, int y, signed short z) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); if (!vertices) return; @@ -502,8 +551,6 @@ void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed s vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; vertices[3].texcoord = (sf2d_vector_2f){u, v}; - sf2d_bind_texture(texture, GPU_TEXUNIT0); - GPU_SetAttributeBuffers( 2, // number of attributes (u32*)osConvertVirtToPhys((u32)vertices), @@ -519,6 +566,19 @@ void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed s GPU_DrawArray(GPU_TRIANGLE_STRIP, 4); } +void sf2d_draw_texture_depth(const sf2d_texture *texture, int x, int y, signed short z) +{ + sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_depth_generic(texture, x, y, z); +} + +void sf2d_draw_texture_depth_blend(const sf2d_texture *texture, int x, int y, signed short z, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_depth_generic(texture, x, y, z); +} + + void sf2d_draw_quad_uv(const sf2d_texture *texture, float left, float top, float right, float bottom, float u0, float v0, float u1, float v1, unsigned int params) { sf2d_vertex_pos_tex *vertices = sf2d_pool_malloc(4 * sizeof(sf2d_vertex_pos_tex)); diff --git a/libs/sf2dlib/sample/source/main.c b/libs/sf2dlib/sample/source/main.c index 09dde4d..fb96559 100644 --- a/libs/sf2dlib/sample/source/main.c +++ b/libs/sf2dlib/sample/source/main.c @@ -59,13 +59,13 @@ int main() sf2d_draw_rectangle_rotate(260, 20, 40, 40, RGBA8(0xFF, 0xFF, 0x00, 0xFF), -2.0f*rad); sf2d_draw_rectangle(20, 60, 40, 40, RGBA8(0xFF, 0x00, 0x00, 0xFF)); sf2d_draw_rectangle(5, 5, 30, 30, RGBA8(0x00, 0xFF, 0xFF, 0xFF)); - sf2d_draw_texture_rotate(tex1, 320/2-tex1->width/2 + circle.dx, 240/2-tex1->height/2 - circle.dy, rad); + sf2d_draw_texture_rotate(tex1, 400/2 + circle.dx, 240/2 - circle.dy, rad); sf2d_end_frame(); sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_draw_rectangle_rotate(190, 160, 70, 60, RGBA8(0xFF, 0xFF, 0xFF, 0xFF), 3.0f*rad); sf2d_draw_rectangle(30, 100, 40, 60, RGBA8(0xFF, 0x00, 0xFF, 0xFF)); - sf2d_draw_texture_rotate(tex2, touch_x-tex1->width/2, touch_y-tex1->height/2, -rad); + sf2d_draw_texture_rotate(tex2, touch_x, touch_y, -rad); sf2d_draw_rectangle(160-15 + cosf(rad)*50.0f, 120-15 + sinf(rad)*50.0f, 30, 30, RGBA8(0x00, 0xFF, 0xFF, 0xFF)); sf2d_draw_fill_circle(40, 40, 35, RGBA8(0x00, 0xFF, 0x00, 0xFF)); sf2d_end_frame(); diff --git a/libs/sftdlib/libsftd/include/texture_atlas.h b/libs/sftdlib/libsftd/include/texture_atlas.h index e973939..cc5ba06 100644 --- a/libs/sftdlib/libsftd/include/texture_atlas.h +++ b/libs/sftdlib/libsftd/include/texture_atlas.h @@ -15,6 +15,7 @@ typedef struct atlas_htab_entry { int bitmap_top; int advance_x; int advance_y; + int glyph_size; } atlas_htab_entry; typedef struct texture_atlas { @@ -25,9 +26,9 @@ typedef struct texture_atlas { texture_atlas *texture_atlas_create(int width, int height, sf2d_texfmt format, sf2d_place place); void texture_atlas_free(texture_atlas *atlas); -int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const void *image, int width, int height, int bitmap_left, int bitmap_top, int advance_x, int advance_y); +int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const void *image, int width, int height, int bitmap_left, int bitmap_top, int advance_x, int advance_y, int glyph_size); int texture_atlas_exists(texture_atlas *atlas, unsigned int character); -void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectangle *rect, int *bitmap_left, int *bitmap_top, int *advance_x, int *advance_y); +void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectangle *rect, int *bitmap_left, int *bitmap_top, int *advance_x, int *advance_y, int *glyph_size); #ifdef __cplusplus } diff --git a/libs/sftdlib/libsftd/source/sftd.c b/libs/sftdlib/libsftd/source/sftd.c index 0df867f..dd9ea02 100644 --- a/libs/sftdlib/libsftd/source/sftd.c +++ b/libs/sftdlib/libsftd/source/sftd.c @@ -147,7 +147,7 @@ void sftd_free_font(sftd_font *font) } } -static int atlas_add_glyph(texture_atlas *atlas, unsigned int glyph_index, const FT_BitmapGlyph bitmap_glyph) +static int atlas_add_glyph(texture_atlas *atlas, unsigned int glyph_index, const FT_BitmapGlyph bitmap_glyph, int glyph_size) { const FT_Bitmap *bitmap = &bitmap_glyph->bitmap; @@ -171,7 +171,8 @@ static int atlas_add_glyph(texture_atlas *atlas, unsigned int glyph_index, const int ret = texture_atlas_insert(atlas, glyph_index, buffer, bitmap->width, bitmap->rows, bitmap_glyph->left, bitmap_glyph->top, - bitmap_glyph->root.advance.x, bitmap_glyph->root.advance.y); + bitmap_glyph->root.advance.x, bitmap_glyph->root.advance.y, + glyph_size); free(buffer); @@ -213,7 +214,7 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned if (!texture_atlas_exists(font->tex_atlas, glyph_index)) { FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph)) { + if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph, size)) { continue; } } @@ -221,25 +222,29 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned bp2d_rectangle rect; int bitmap_left, bitmap_top; int advance_x, advance_y; + int glyph_size; texture_atlas_get(font->tex_atlas, glyph_index, &rect, &bitmap_left, &bitmap_top, - &advance_x, &advance_y); + &advance_x, &advance_y, &glyph_size); - sf2d_draw_texture_part_blend(font->tex_atlas->tex, - pen_x + bitmap_left, - pen_y - bitmap_top, + const float draw_scale = glyph_size/(float)size; + + sf2d_draw_texture_part_scale_blend(font->tex_atlas->tex, + pen_x + bitmap_left * draw_scale, + pen_y - bitmap_top * draw_scale, rect.x, rect.y, rect.w, rect.h, + draw_scale, + draw_scale, color); - pen_x += advance_x >> 16; - pen_y += advance_y >> 16; + pen_x += (advance_x >> 16) * draw_scale; + pen_y += (advance_y >> 16) * draw_scale; previous = glyph_index; text++; } } - void sftd_draw_textf(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const char *text, ...) { char buffer[256]; @@ -285,7 +290,7 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned if (!texture_atlas_exists(font->tex_atlas, glyph_index)) { FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL); - if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph)) { + if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph, size)) { continue; } } @@ -293,19 +298,24 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned bp2d_rectangle rect; int bitmap_left, bitmap_top; int advance_x, advance_y; + int glyph_size; texture_atlas_get(font->tex_atlas, glyph_index, &rect, &bitmap_left, &bitmap_top, - &advance_x, &advance_y); + &advance_x, &advance_y, &glyph_size); - sf2d_draw_texture_part_blend(font->tex_atlas->tex, - pen_x + bitmap_left, - pen_y - bitmap_top, + const float draw_scale = (float)size/glyph_size; + + sf2d_draw_texture_part_scale_blend(font->tex_atlas->tex, + pen_x + bitmap_left * draw_scale, + pen_y - bitmap_top * draw_scale, rect.x, rect.y, rect.w, rect.h, + draw_scale, + draw_scale, color); - pen_x += advance_x >> 16; - pen_y += advance_y >> 16; + pen_x += (advance_x >> 16) * draw_scale; + pen_y += (advance_y >> 16) * draw_scale; previous = glyph_index; text++; diff --git a/libs/sftdlib/libsftd/source/texture_atlas.c b/libs/sftdlib/libsftd/source/texture_atlas.c index dc46fac..c877c59 100644 --- a/libs/sftdlib/libsftd/source/texture_atlas.c +++ b/libs/sftdlib/libsftd/source/texture_atlas.c @@ -31,7 +31,7 @@ void texture_atlas_free(texture_atlas *atlas) free(atlas); } -int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const void *image, int width, int height, int bitmap_left, int bitmap_top, int advance_x, int advance_y) +int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const void *image, int width, int height, int bitmap_left, int bitmap_top, int advance_x, int advance_y, int glyph_size) { bp2d_size size; size.w = width; @@ -51,6 +51,7 @@ int texture_atlas_insert(texture_atlas *atlas, unsigned int character, const voi entry->bitmap_top = bitmap_top; entry->advance_x = advance_x; entry->advance_y = advance_y; + entry->glyph_size = glyph_size; int_htab_insert(atlas->htab, character, entry); @@ -71,7 +72,7 @@ int texture_atlas_exists(texture_atlas *atlas, unsigned int character) return int_htab_find(atlas->htab, character) != NULL; } -void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectangle *rect, int *bitmap_left, int *bitmap_top, int *advance_x, int *advance_y) +void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectangle *rect, int *bitmap_left, int *bitmap_top, int *advance_x, int *advance_y, int *glyph_size) { atlas_htab_entry *entry = int_htab_find(atlas->htab, character); @@ -83,4 +84,5 @@ void texture_atlas_get(texture_atlas *atlas, unsigned int character, bp2d_rectan *bitmap_top = entry->bitmap_top; *advance_x = entry->advance_x; *advance_y = entry->advance_y; + *glyph_size = entry->glyph_size; } diff --git a/libs/sftdlib/sample/data/FreeSans.ttf b/libs/sftdlib/sample/data/FreeSans.ttf new file mode 100644 index 0000000..9db9585 Binary files /dev/null and b/libs/sftdlib/sample/data/FreeSans.ttf differ diff --git a/libs/sftdlib/sample/data/airstrike.ttf b/libs/sftdlib/sample/data/airstrike.ttf deleted file mode 100644 index 2a751aa..0000000 Binary files a/libs/sftdlib/sample/data/airstrike.ttf and /dev/null differ diff --git a/libs/sftdlib/sample/source/main.c b/libs/sftdlib/sample/source/main.c index 19977ad..c402119 100644 --- a/libs/sftdlib/sample/source/main.c +++ b/libs/sftdlib/sample/source/main.c @@ -4,19 +4,17 @@ #include <3ds.h> #include #include -#include "airstrike_ttf.h" +#include "FreeSans_ttf.h" int main() { sf2d_init(); sf2d_set_clear_color(RGBA8(0x40, 0x40, 0x40, 0xFF)); - - consoleInit(GFX_BOTTOM, NULL); - printf("sftd sample\n"); + sf2d_set_vblank_wait(0); // Font loading sftd_init(); - sftd_font *font = sftd_load_font_mem(airstrike_ttf, airstrike_ttf_size); + sftd_font *font = sftd_load_font_mem(FreeSans_ttf, FreeSans_ttf_size); while (aptMainLoop()) { @@ -25,8 +23,32 @@ int main() sf2d_start_frame(GFX_TOP, GFX_LEFT); - sftd_draw_text(font, 10, 10, RGBA8(255, 0, 0, 255), 20, "Font drawing on the top screen!"); - sftd_draw_textf(font, 10, 40, RGBA8(0, 255, 0, 255), 20, "FPS %f", sf2d_get_fps()); + sftd_draw_textf(font, 10, 10, RGBA8(0, 255, 0, 255), 20, "FPS %f", sf2d_get_fps()); + + sftd_draw_text(font, 10, 30, RGBA8(255, 0, 0, 255), 20, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 50, RGBA8(0, 255, 0, 255), 15, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 68, RGBA8(0, 0, 255, 255), 25, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 90, RGBA8(255, 255, 0, 255), 10, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 105, RGBA8(255, 0, 255, 255), 8, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 120, RGBA8(0, 255, 255, 255), 30, "Font drawing on the top screen!"); + + sftd_draw_text(font, 10, 155, RGBA8(255, 0, 0, 255), 20, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 170, RGBA8(0, 255, 0, 255), 2, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 180, RGBA8(0, 0, 255, 255), 10, "Font drawing on the top screen!"); + sftd_draw_text(font, 10, 205, RGBA8(255, 255, 0, 255), 170, "Font drawing on the top screen!"); + + sf2d_end_frame(); + + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + + sftd_draw_text(font, 10, 10, RGBA8(0, 255, 0, 255), 20, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 30, RGBA8(255, 0, 0, 255), 10, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 50, RGBA8(0, 255, 0, 255), 15, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 70, RGBA8(0, 0, 255, 255), 5, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 90, RGBA8(255, 255, 0, 255), 25, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 120, RGBA8(255, 0, 255, 255), 20, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 140, RGBA8(0, 255, 255, 255), 12, "Font drawing on the bot. screen!"); + sftd_draw_text(font, 10, 150, RGBA8(255, 0, 0, 255), 28, "Font drawing on the bot. screen!"); sf2d_end_frame(); diff --git a/sdcard/3ds/ctruLua/example.lua b/sdcard/3ds/ctruLua/example.lua index cf4ebc6..8ab85b6 100644 --- a/sdcard/3ds/ctruLua/example.lua +++ b/sdcard/3ds/ctruLua/example.lua @@ -66,7 +66,7 @@ while ctr.run() do gfx.text(5, 17, "Hello world, from Lua ! éàçù", 20, gfx.color.RGBA8(0, 0, 0)) gfx.text(5, 50, "Time: "..os.date()) - texture1:draw(240, 10, angle); + texture1:draw(280, 80, angle); local cx, cy = hid.circle() gfx.rectangle(40, 90, 60, 60, 0, 0xDDDDDDFF) diff --git a/source/texture.c b/source/texture.c index d2680ac..53d23db 100644 --- a/source/texture.c +++ b/source/texture.c @@ -59,7 +59,7 @@ static int texture_draw(lua_State *L) { if (rad == 0.0f && texture->scaleX == 1.0f && texture->scaleY == 1.0f) { sf2d_draw_texture(texture->texture, x, y); } else { - sf2d_draw_texture_rotate_cut_scale(texture->texture, x, y, rad, 0, 0, texture->texture->width, texture->texture->height, texture->scaleX, texture->scaleY); + sf2d_draw_texture_part_rotate_scale(texture->texture, x, y, rad, 0, 0, texture->texture->width, texture->texture->height, texture->scaleX, texture->scaleY); } return 0; @@ -75,7 +75,7 @@ static int texture_drawPart(lua_State *L) { int h = luaL_checkinteger(L, 7); int rad = luaL_optnumber(L, 8, 0.0f); - sf2d_draw_texture_rotate_cut_scale(texture->texture, x, y, rad, sx, sy, w, h, texture->scaleX, texture->scaleY); + sf2d_draw_texture_part_rotate_scale(texture->texture, x, y, rad, sx, sy, w, h, texture->scaleX, texture->scaleY); return 0; }