1
0
Fork 0
mirror of https://github.com/ctruLua/ctruLua.git synced 2025-10-27 16:39:29 +00:00
ctruLua/source/gfx.c
Reuh 0773992b68 Fully documented ctr and ctr.gfx in the C source
The documentation can be built using LDoc : run make build-doc

However, there's still a bunch of things to document.
2015-09-12 13:35:21 +02:00

357 lines
8.2 KiB
C

/***
The `gfx` module.
@module ctr.gfx
@usage local gfx = require("ctr.gfx")
*/
#include <stdlib.h>
#include <sf2d.h>
#include <sftd.h>
#include <3ds/vram.h>
#include <lua.h>
#include <lauxlib.h>
#include "font.h"
bool isGfxInitialised = false;
/***
The `ctr.gfx.color` module.
@table color
@see ctr.gfx.color
*/
void load_color_lib(lua_State *L);
u32 color_default;
/***
The `ctr.gfx.font` module.
@table font
@see ctr.gfx.font
*/
void load_font_lib(lua_State *L);
void unload_font_lib(lua_State *L);
/***
The `ctr.gfx.texture` module.
@table texture
@see ctr.gfx.texture
*/
void load_texture_lib(lua_State *L);
/***
The `ctr.gfx.map` module.
@table map
@see ctr.gfx.map
*/
void load_map_lib(lua_State *L);
/***
Start drawing to a screen.
Must be called before any draw operation.
@function startFrame
@tparam number screen the screen to draw to (`GFX_TOP` or `GFX_BOTTOM`)
@tparam[opt=GFX_LEFT] number eye the eye to draw to (`GFX_LEFT` or `GFX_RIGHT`)
*/
static int gfx_startFrame(lua_State *L) {
u8 screen = luaL_checkinteger(L, 1);
u8 eye = luaL_optinteger(L, 2, GFX_LEFT);
sf2d_start_frame(screen, eye);
return 0;
}
/***
End drawing to a screen.
Must be called after your draw operations.
@function endFrame
*/
static int gfx_endFrame(lua_State *L) {
sf2d_end_frame();
return 0;
}
/***
Display any drawn pixel.
@function render
*/
static int gfx_render(lua_State *L) {
sf2d_swapbuffers();
return 0;
}
/***
Get the current number of frame per second.
@function getFPS
@treturn number number of frame per seconds
*/
static int gfx_getFPS(lua_State *L) {
float fps = sf2d_get_fps();
lua_pushnumber(L, fps);
return 1;
}
/***
Enable or disable the stereoscopic 3D on the top screen.
@function set3D
@tparam boolean enable true to enable, false to disable
*/
static int gfx_set3D(lua_State *L) {
bool enable = lua_toboolean(L, 1);
sf2d_set_3D(enable);
return 0;
}
/***
Get free VRAM space.
@function vramSpaceFree
@treturn integer free VRAM in bytes
*/
static int gfx_vramSpaceFree(lua_State *L) {
lua_pushinteger(L, vramSpaceFree());
return 1;
}
/***
Draw a line on the current screen.
@function line
@tparam integer x1 line's starting point horizontal coordinate, in pixels
@tparam integer y1 line's starting point vertical coordinate, in pixels
@tparam integer x2 line's endpoint horizontal coordinate, in pixels
@tparam integer y2 line's endpoint vertical coordinate, in pixels
@tparam[opt=default color] integer color drawing color
*/
static int gfx_line(lua_State *L) {
int x1 = luaL_checkinteger(L, 1);
int y1 = luaL_checkinteger(L, 2);
int x2 = luaL_checkinteger(L, 3);
int y2 = luaL_checkinteger(L, 4);
u32 color = luaL_optinteger(L, 5, color_default);
sf2d_draw_line(x1, y1, x2, y2, color);
return 0;
}
/***
Draw a point, a single pixel, on the current screen.
@function point
@tparam integer x point horizontal coordinate, in pixels
@tparam integer y point vertical coordinate, in pixels
@tparam[opt=default color] integer color drawing color
*/
static int gfx_point(lua_State *L) {
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
u32 color = luaL_optinteger(L, 3, color_default);
sf2d_draw_rectangle(x, y, 1, 1, color); // well, it looks like a point
return 0;
}
/***
Draw a rectangle on the current screen.
@function rectangle
@tparam integer x rectangle origin horizontal coordinate, in pixels
@tparam integer y rectangle origin vertical coordinate, in pixels
@tparam integer width rectangle width, in pixels
@tparam integer height rectangle height, in pixels
@tparam[opt=0] number angle rectangle rotation, in radians
@tparam[opt=default color] integer color drawing color
*/
static int gfx_rectangle(lua_State *L) {
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int width = luaL_checkinteger(L, 3);
int height = luaL_checkinteger(L, 4);
float angle = luaL_optnumber(L, 5, 0);
u32 color = luaL_optinteger(L, 6, color_default);
if (angle == 0)
sf2d_draw_rectangle(x, y, width, height, color);
else
sf2d_draw_rectangle_rotate(x, y, width, height, color, angle);
return 0;
}
/***
Draw a circle on the current screen.
@function circle
@tparam integer x circle center horizontal coordinate, in pixels
@tparam integer y circle center vertical coordinate, in pixels
@tparam integer radius circle radius, in pixels
@tparam[opt=default color] integer color drawing color
*/
static int gfx_circle(lua_State *L) {
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
int radius = luaL_checkinteger(L, 3);
u32 color = luaL_optinteger(L, 4, color_default);
sf2d_draw_fill_circle(x, y, radius, color);
return 0;
}
/***
Draw a text on the current screen.
@function text
@tparam integer x text drawing origin horizontal coordinate, in pixels
@tparam integer y text drawing origin vertical coordinate, in pixels
@tparam string text the text to draw
@tparam[opt=9] integer size drawing size, in pixels
@tparam[opt=default color] integer color drawing color
@tparam[opt=default font] font font to use
*/
static int gfx_text(lua_State *L) {
int x = luaL_checkinteger(L, 1);
int y = luaL_checkinteger(L, 2);
size_t len;
const char *text = luaL_checklstring(L, 3, &len);
int size = luaL_optinteger(L, 4, 9);
u32 color = luaL_optinteger(L, 5, color_default);
font_userdata *font = luaL_testudata(L, 6, "LFont");
if (font == NULL) {
lua_getfield(L, LUA_REGISTRYINDEX, "LFontDefault");
font = luaL_testudata(L, -1, "LFont");
if (font == NULL) luaL_error(L, "No default font set and no font object passed");
}
if (font->font == NULL) luaL_error(L, "The font object was unloaded");
// Wide caracters support. (wchar = UTF32 on 3DS.)
wchar_t wtext[len];
len = mbstowcs(wtext, text, len);
*(wtext+len) = 0x0; // text end
sftd_draw_wtext(font->font, x, y, color, size, wtext);
return 0;
}
// Functions
static const struct luaL_Reg gfx_lib[] = {
{ "startFrame", gfx_startFrame },
{ "endFrame", gfx_endFrame },
{ "render", gfx_render },
{ "getFPS", gfx_getFPS },
{ "set3D", gfx_set3D },
{ "vramSpaceFree", gfx_vramSpaceFree },
{ "line", gfx_line },
{ "point", gfx_point },
{ "rectangle", gfx_rectangle },
{ "circle", gfx_circle },
{ "text", gfx_text },
{ NULL, NULL }
};
// Constants
struct { char *name; int value; } gfx_constants[] = {
/***
Constant used to select the top screen.
It is equal to `0`.
@field GFX_TOP
*/
{ "GFX_TOP", GFX_TOP },
/***
Constant used to select the bottom screen.
It is equal to `1`.
@field GFX_BOTTOM
*/
{ "GFX_BOTTOM", GFX_BOTTOM },
/***
Constant used to select the left eye.
It is equal to `0`.
@field GFX_LEFT
*/
{ "GFX_LEFT", GFX_LEFT },
/***
Constant used to select the right eye.
It is equal to `1`.
@field GFX_RIGHT
*/
{ "GFX_RIGHT", GFX_RIGHT },
/***
The top screen height, in pixels.
It is equal to `240`.
@field TOP_HEIGHT
*/
{ "TOP_HEIGHT", 240 },
/***
The top screen width, in pixels.
It is equal to `400`.
@field TOP_WIDTH
*/
{ "TOP_WIDTH", 400 },
/***
The bottom screen height, in pixels.
It is equal to `240`.
@field BOTTOM_HEIGHT
*/
{ "BOTTOM_HEIGHT", 240 },
/***
The bottom screen width, in pixels.
It is equal to `320`.
@field BOTTOM_WIDTH
*/
{ "BOTTOM_WIDTH", 320 },
{ NULL, 0 }
};
// Subtables
struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } gfx_libs[] = {
{ "color", load_color_lib, NULL },
{ "font", load_font_lib, unload_font_lib },
{ "texture", load_texture_lib, NULL },
{ "map", load_map_lib, NULL },
{ NULL, NULL }
};
int luaopen_gfx_lib(lua_State *L) {
luaL_newlib(L, gfx_lib);
for (int i = 0; gfx_constants[i].name; i++) {
lua_pushinteger(L, gfx_constants[i].value);
lua_setfield(L, -2, gfx_constants[i].name);
}
for (int i = 0; gfx_libs[i].name; i++) {
gfx_libs[i].load(L);
lua_setfield(L, -2, gfx_libs[i].name);
}
return 1;
}
void load_gfx_lib(lua_State *L) {
sf2d_init();
sftd_init();
isGfxInitialised = true;
luaL_requiref(L, "ctr.gfx", luaopen_gfx_lib, 0);
}
void unload_gfx_lib(lua_State *L) {
for (int i = 0; gfx_libs[i].name; i++) {
if (gfx_libs[i].unload) gfx_libs[i].unload(L);
}
sftd_fini();
sf2d_fini();
}