diff --git a/libs/sf2dlib/libsf2d/include/sf2d.h b/libs/sf2dlib/libsf2d/include/sf2d.h index f282d4f..9322ebb 100644 --- a/libs/sf2dlib/libsf2d/include/sf2d.h +++ b/libs/sf2dlib/libsf2d/include/sf2d.h @@ -588,6 +588,24 @@ void sf2d_draw_texture_part_rotate_scale(const sf2d_texture *texture, int x, int */ 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 part of a texture, with rotation, scaling, color and 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 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 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_part_rotate_scale_hotspot_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, float center_x, float center_y, u32 color); + /** * @brief Draws a texture blended in a certain depth * @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 13345e9..12469ed 100644 --- a/libs/sf2dlib/libsf2d/source/sf2d_texture.c +++ b/libs/sf2dlib/libsf2d/source/sf2d_texture.c @@ -599,18 +599,18 @@ void sf2d_draw_texture_part_scale_blend(const sf2d_texture *texture, float x, fl 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) +static inline void sf2d_draw_texture_part_rotate_scale_hotspot_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, float center_x, float center_y) { sf2d_vertex_pos_tex *vertices = sf2d_pool_memalign(4 * sizeof(sf2d_vertex_pos_tex), 8); if (!vertices) return; - int w2 = (tex_w * x_scale)/2.0f; - int h2 = (tex_h * y_scale)/2.0f; + int w = tex_w; + int h = tex_h; - 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 = (sf2d_vector_3f){(float)-center_x * x_scale, (float)-center_y * y_scale, SF2D_DEFAULT_DEPTH}; + vertices[1].position = (sf2d_vector_3f){(float) (w - center_x) * x_scale, (float)-center_y * y_scale, SF2D_DEFAULT_DEPTH}; + vertices[2].position = (sf2d_vector_3f){(float)-center_x * x_scale, (float) (h - center_y) * y_scale, SF2D_DEFAULT_DEPTH}; + vertices[3].position = (sf2d_vector_3f){(float) (w - center_x) * x_scale, (float) h - center_y * y_scale, SF2D_DEFAULT_DEPTH}; float u0 = tex_x/(float)texture->pow2_w; float v0 = tex_y/(float)texture->pow2_h; @@ -650,13 +650,19 @@ static inline void sf2d_draw_texture_part_rotate_scale_generic(const sf2d_textur 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); - sf2d_draw_texture_part_rotate_scale_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale); + sf2d_draw_texture_part_rotate_scale_hotspot_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, tex_w/2.0f, tex_h/2.0f); } 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_bind_texture_color(texture, GPU_TEXUNIT0, color); - sf2d_draw_texture_part_rotate_scale_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale); + sf2d_draw_texture_part_rotate_scale_hotspot_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, tex_w/2.0f, tex_h/2.0f); +} + +void sf2d_draw_texture_part_rotate_scale_hotspot_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, float center_x, float center_y, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_part_rotate_scale_hotspot_generic(texture, x, y, rad, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, center_x, center_y); } static inline void sf2d_draw_texture_depth_generic(const sf2d_texture *texture, int x, int y, signed short z) diff --git a/sdcard/3ds/ctruLua/libs/sprite.lua b/sdcard/3ds/ctruLua/libs/sprite.lua index aec1995..621e4d8 100644 --- a/sdcard/3ds/ctruLua/libs/sprite.lua +++ b/sdcard/3ds/ctruLua/libs/sprite.lua @@ -26,7 +26,7 @@ local function draw(self, x, y, rad) local tsx, tsy = self.texture:getSize() local sx, sy = getBox(tsx, tsy, frame, self.frameSizeX, self.frameSizeY) - self.texture:drawPart(x, y, sx, sy, self.frameSizeX, self.frameSizeY, rad) + self.texture:drawPart(x, y, sx, sy, self.frameSizeX, self.frameSizeY, rad, self.offsetX, self.offsetY) return frame end @@ -52,12 +52,19 @@ local function resetTimer(self) self.frameTimer = ctr.time() end +local function setOffset(self, x, y) + self.offsetX = x or 0 + self.offsetY = y or self.offsetX +end + -- Sprite object constructor function mod.new(texture, fsx, fsy) return { texture = texture, frameSizeX = fsx, frameSizeY = fsy, + offsetX = 0, + offsetY = 0, animations = {}, currentAnimation = 0, currentFrame = 1, @@ -66,6 +73,7 @@ function mod.new(texture, fsx, fsy) draw = draw, addAnimation = addAnimation, setAnimation = setAnimation, + setOffset = setOffset, resetTimer = resetTimer, } end diff --git a/source/texture.c b/source/texture.c index f995386..84467de 100644 --- a/source/texture.c +++ b/source/texture.c @@ -54,10 +54,10 @@ static int texture_load(lua_State *L) { texture_userdata *texture; texture = (texture_userdata *)lua_newuserdata(L, sizeof(*texture)); - + luaL_getmetatable(L, "LTexture"); lua_setmetatable(L, -2); - + if (type==3) type = getType(path); if (type==0) { //PNG texture->texture = sfil_load_PNG_file(path, place); @@ -76,17 +76,17 @@ static int texture_load(lua_State *L) { texture->texture = sf2d_create_texture_mem_RGBA8(data, w, h, TEXFMT_RGBA8, place); free(data); } - + if (texture->texture == NULL) { lua_pushnil(L); lua_pushstring(L, "No such file"); return 2; } - + texture->scaleX = 1.0f; texture->scaleY = 1.0f; texture->blendColor = 0xffffffff; - + return 1; } @@ -102,20 +102,20 @@ static int texture_new(lua_State *L) { int w = luaL_checkinteger(L, 1); int h = luaL_checkinteger(L, 2); u8 place = luaL_checkinteger(L, 3); - + texture_userdata *texture; texture = (texture_userdata *)lua_newuserdata(L, sizeof(*texture)); - + luaL_getmetatable(L, "LTexture"); lua_setmetatable(L, -2); - + texture->texture = sf2d_create_texture(w, h, TEXFMT_RGBA8, place); sf2d_texture_tile32(texture->texture); - + texture->scaleX = 1.0f; texture->scaleY = 1.0f; texture->blendColor = 0xffffffff; - + return 1; } @@ -127,35 +127,41 @@ Texture object /*** Draw a texture. @function :draw -@tparam number x X position -@tparam number y Y position -@tparam[opt=0.0] number rad rotation of the texture (in radians) +@tparam integer x X position +@tparam integer y Y position +@tparam[opt=0.0] number rad rotation of the texture around the hotspot (in radians) +@tparam[opt=0.0] number hotspotX the hostpot X coordinate +@tparam[opt=0.0] number hotspotY the hostpot Y coordinate */ static int texture_draw(lua_State *L) { texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); int x = luaL_checkinteger(L, 2); int y = luaL_checkinteger(L, 3); float rad = luaL_optnumber(L, 4, 0.0f); - + float hotspotX = luaL_optnumber(L, 5, 0.0f); + float hotspotY = luaL_optnumber(L, 6, 0.0f); + if (rad == 0.0f && texture->scaleX == 1.0f && texture->scaleY == 1.0f && texture->blendColor == 0xffffffff) { - sf2d_draw_texture(texture->texture, x, y); + sf2d_draw_texture(texture->texture, x - hotspotX, y - hotspotY); } else { - sf2d_draw_texture_part_rotate_scale_blend(texture->texture, x, y, rad, 0, 0, texture->texture->width, texture->texture->height, texture->scaleX, texture->scaleY, texture->blendColor); + sf2d_draw_texture_rotate_scale_hotspot_blend(texture->texture, x, y, rad, texture->scaleX, texture->scaleY, hotspotX, hotspotY, texture->blendColor); } - + return 0; } /*** Draw a part of the texture @function :drawPart -@tparam number x X position -@tparam number y Y position -@tparam number sx X position of the beginning of the part -@tparam number sy Y position of the beginning of the part -@tparam number w width of the part -@tparam number h height of the part -@tparam[opt=0.0] number rad rotation of the part (in radians) +@tparam integer x X position +@tparam integer y Y position +@tparam integer sx X position of the beginning of the part +@tparam integer sy Y position of the beginning of the part +@tparam integer w width of the part +@tparam integer h height of the part +@tparam[opt=0.0] number rad rotation of the part around the hotspot (in radians) +@tparam[opt=0.0] number hotspotX the hostpot X coordinate +@tparam[opt=0.0] number hotspotY the hostpot Y coordinate */ static int texture_drawPart(lua_State *L) { texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); @@ -166,9 +172,11 @@ static int texture_drawPart(lua_State *L) { int w = luaL_checkinteger(L, 6); int h = luaL_checkinteger(L, 7); int rad = luaL_optnumber(L, 8, 0.0f); - - sf2d_draw_texture_part_rotate_scale_blend(texture->texture, x, y, rad, sx, sy, w, h, texture->scaleX, texture->scaleY, texture->blendColor); - + float hotspotX = luaL_optnumber(L, 9, 0.0f); + float hotspotY = luaL_optnumber(L, 10, 0.0f); + + sf2d_draw_texture_part_rotate_scale_hotspot_blend(texture->texture, x, y, rad, sx, sy, w, h, texture->scaleX, texture->scaleY, hotspotX, hotspotY, texture->blendColor); + return 0; } @@ -193,12 +201,12 @@ Unload a texture. */ static int texture_unload(lua_State *L) { texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); - + if (texture->texture == NULL) return 0; sf2d_free_texture(texture->texture); texture->texture = NULL; - + return 0; } @@ -206,16 +214,16 @@ static int texture_unload(lua_State *L) { Rescale the texture. The default scale is `1.0`. @function :scale @tparam number scaleX new scale of the width -@tparam number scaleY new scale of the height +@tparam[opt=scaleX] number scaleY new scale of the height */ static int texture_scale(lua_State *L) { texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); float sx = luaL_checknumber(L, 2); - float sy = luaL_checknumber(L, 3); - + float sy = luaL_optnumber(L, 3, sx); + texture->scaleX = sx; texture->scaleY = sy; - + return 0; } @@ -230,9 +238,9 @@ static int texture_getPixel(lua_State *L) { texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); int x = luaL_checkinteger(L, 2); int y = luaL_checkinteger(L, 3); - + lua_pushinteger(L, sf2d_get_pixel(texture->texture, x, y)); - + return 1; } @@ -248,9 +256,9 @@ static int texture_setPixel(lua_State *L) { int x = luaL_checkinteger(L, 2); int y = luaL_checkinteger(L, 3); u32 color = luaL_checkinteger(L, 4); - + sf2d_set_pixel(texture->texture, x, y, color); - + return 0; } @@ -262,12 +270,25 @@ Set the blend color of the texture. static int texture_setBlendColor(lua_State *L) { texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); u32 color = luaL_checkinteger(L, 2); - + texture->blendColor = color; - + return 0; } +/*** +Get the blend color of the texture. +@function :getBlendColor +@treturn number the blend color +*/ +static int texture_getBlendColor(lua_State *L) { + texture_userdata *texture = luaL_checkudata(L, 1, "LTexture"); + + lua_pushinteger(L, texture->blendColor); + + return 1; +} + /*** Save a texture to a file. @function :save @@ -357,6 +378,7 @@ static const struct luaL_Reg texture_methods[] = { { "getPixel", texture_getPixel }, { "setPixel", texture_setPixel }, { "setBlendColor", texture_setBlendColor }, + { "getBlendColor", texture_getBlendColor }, { "save", texture_save }, { "__gc", texture_unload }, {NULL, NULL}