mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-27 16:39:29 +00:00
Updated font and fs lib; updated editor; updated sf2dlib
Libs additions: font.load, font:unload, font:getWidth, fs.getDirectory, fs.setDirectory, fs.exists Editor additions: syntaxic coloring and mono font sf2dlib update: you will need the latest version of ctrulib. Also, because of the lib font needs, the sftdlib was modified.
This commit is contained in:
parent
3f995629c0
commit
45f3216ed8
14 changed files with 382 additions and 28 deletions
|
|
@ -151,7 +151,7 @@ void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side)
|
|||
GPU_DepthMap(-1.0f, 0.0f);
|
||||
GPU_SetFaceCulling(GPU_CULL_NONE);
|
||||
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
|
||||
GPU_SetStencilOp(GPU_KEEP, GPU_KEEP, GPU_KEEP);
|
||||
GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
|
||||
GPU_SetBlendingColor(0,0,0,0);
|
||||
GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL);
|
||||
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
|
||||
|
|
|
|||
|
|
@ -78,7 +78,13 @@ sf2d_texture *sf2d_create_texture(int width, int height, sf2d_texfmt pixel_forma
|
|||
texture->data_size = data_size;
|
||||
texture->data = data;
|
||||
|
||||
memset(texture->data, 0, texture->data_size);
|
||||
if (place == SF2D_PLACE_VRAM) {
|
||||
GX_SetMemoryFill(NULL, texture->data, 0x00000000, (u32*)&((u8*)texture->data)[texture->data_size], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH,
|
||||
NULL, 0x00000000, NULL, 0);
|
||||
gspWaitForPSC0();
|
||||
} else {
|
||||
memset(texture->data, 0, texture->data_size);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned
|
|||
*/
|
||||
void sftd_draw_wtextf(sftd_font *font, int x, int y, unsigned int color, unsigned int size, const wchar_t *text, ...);
|
||||
|
||||
// (ctruLua addition) Based on sftd_draw_wtext, returns the width of the text drawn.
|
||||
int sftd_width_wtext(sftd_font *font, unsigned int size, const wchar_t *text);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned
|
|||
&rect, &bitmap_left, &bitmap_top,
|
||||
&advance_x, &advance_y, &glyph_size);
|
||||
|
||||
const float draw_scale = glyph_size/(float)size;
|
||||
const float draw_scale = size/(float)glyph_size;
|
||||
|
||||
sf2d_draw_texture_part_scale_blend(font->tex_atlas->tex,
|
||||
pen_x + bitmap_left * draw_scale,
|
||||
|
|
@ -304,7 +304,7 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned
|
|||
&rect, &bitmap_left, &bitmap_top,
|
||||
&advance_x, &advance_y, &glyph_size);
|
||||
|
||||
const float draw_scale = (float)size/glyph_size;
|
||||
const float draw_scale = size/(float)glyph_size;
|
||||
|
||||
sf2d_draw_texture_part_scale_blend(font->tex_atlas->tex,
|
||||
pen_x + bitmap_left * draw_scale,
|
||||
|
|
@ -332,3 +332,62 @@ void sftd_draw_wtextf(sftd_font *font, int x, int y, unsigned int color, unsigne
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
// (ctruLua addition) Based on sftd_draw_wtext, returns the width of the text drawn.
|
||||
int sftd_width_wtext(sftd_font *font, unsigned int size, const wchar_t *text)
|
||||
{
|
||||
FTC_FaceID face_id = (FTC_FaceID)font;
|
||||
FT_Face face;
|
||||
FTC_Manager_LookupFace(ftcmanager, face_id, &face);
|
||||
|
||||
FT_Int charmap_index;
|
||||
charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||
|
||||
FT_Glyph glyph;
|
||||
FT_Bool use_kerning = FT_HAS_KERNING(face);
|
||||
FT_UInt glyph_index, previous = 0;
|
||||
int pen_x = 0;
|
||||
|
||||
FTC_ScalerRec scaler;
|
||||
scaler.face_id = face_id;
|
||||
scaler.width = size;
|
||||
scaler.height = size;
|
||||
scaler.pixel = 1;
|
||||
|
||||
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||
|
||||
while (*text) {
|
||||
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
||||
|
||||
if (use_kerning && previous && glyph_index) {
|
||||
FT_Vector delta;
|
||||
FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
|
||||
pen_x += delta.x >> 6;
|
||||
}
|
||||
|
||||
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, size)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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, &glyph_size);
|
||||
|
||||
const float draw_scale = size/(float)glyph_size;
|
||||
|
||||
pen_x += (advance_x >> 16) * draw_scale;
|
||||
|
||||
previous = glyph_index;
|
||||
text++;
|
||||
}
|
||||
|
||||
return pen_x;
|
||||
}
|
||||
BIN
sdcard/3ds/ctruLua/editor/VeraMono.ttf
Normal file
BIN
sdcard/3ds/ctruLua/editor/VeraMono.ttf
Normal file
Binary file not shown.
|
|
@ -1,6 +1,16 @@
|
|||
-- Colors based on the Monokai theme
|
||||
return {
|
||||
background = 0x272822FF,
|
||||
default = 0xF8F8F2FF,
|
||||
cursor = 0xFF0000FF
|
||||
-- General
|
||||
["background"] = 0x272822FF,
|
||||
["cursor"] = 0xF8F8F0FF,
|
||||
["default"] = 0xF8F8F2FF,
|
||||
|
||||
-- Syntax
|
||||
["comment"] = 0x75715EFF,
|
||||
["string"] = 0xE6DB74FF,
|
||||
["constant.numeric"] = 0xAE81FFFF,
|
||||
["constant.language"] = 0xAE81FFFF,
|
||||
["keyword.control"] = 0xF92672FF,
|
||||
["keyword.operator"] = 0xF92672FF,
|
||||
["support.function"] = 0x66D9EFFF
|
||||
}
|
||||
|
|
@ -5,27 +5,45 @@ local gfx = require("ctr.gfx")
|
|||
-- Open libs
|
||||
local keyboard = dofile("sdmc:/3ds/ctruLua/keyboard.lua")
|
||||
local openfile = dofile("sdmc:/3ds/ctruLua/openfile.lua")
|
||||
local color = dofile("sdmc:/3ds/ctruLua/editor/color.lua")
|
||||
local color = dofile("color.lua")
|
||||
local syntax = dofile("syntax.lua")
|
||||
|
||||
-- Load data
|
||||
local font = gfx.font.load("VeraMono.ttf")
|
||||
|
||||
-- Open file
|
||||
local path, status = openfile("Choose a file to edit", "/3ds/ctruLua/", nil, "any")
|
||||
if not path then return end
|
||||
local lineEnding
|
||||
local lines = {}
|
||||
if status == "exist" then
|
||||
for line in io.lines(path) do table.insert(lines, line) end
|
||||
for line in io.lines(path, "L") do
|
||||
if not lineEnding then lineEnding = line:match("([\n\r]+)$") end
|
||||
table.insert(lines, line:match("^(.-)[\n\r]*$"))
|
||||
end
|
||||
else
|
||||
lineEnding = "\n"
|
||||
lines = { "" }
|
||||
end
|
||||
|
||||
-- Syntax coloring
|
||||
local coloredLines = syntax(lines, color)
|
||||
|
||||
-- Variables
|
||||
local lineHeight = 10
|
||||
local cursorX, cursorY = 1, 1
|
||||
local scrollX, scrollY = 0, 0
|
||||
|
||||
-- Helper functions
|
||||
local function displayedText(text)
|
||||
return text:gsub("\t", " ")
|
||||
end
|
||||
|
||||
-- Set defaults
|
||||
gfx.set3D(false)
|
||||
gfx.color.setDefault(color.default)
|
||||
gfx.color.setBackground(color.background)
|
||||
gfx.font.setDefault(font)
|
||||
|
||||
while ctr.run() do
|
||||
hid.read()
|
||||
|
|
@ -75,10 +93,10 @@ while ctr.run() do
|
|||
until t + 5 < os.time()
|
||||
else
|
||||
for i = 1, #lines, 1 do
|
||||
file:write(lines[i].."\n")
|
||||
file:write(lines[i]..lineEnding)
|
||||
gfx.startFrame(gfx.GFX_TOP)
|
||||
gfx.rectangle(0, 0, math.ceil(i/#lines*gfx.TOP_WIDTH), gfx.TOP_HEIGHT, 0, 0xFFFFFFFF)
|
||||
gfx.color.setDefault(0x000000FF)
|
||||
gfx.color.setDefault(color.background)
|
||||
gfx.text(gfx.TOP_WIDTH/2, gfx.TOP_HEIGHT/2, math.ceil(i/#lines*100).."%")
|
||||
gfx.color.setDefault(color.default)
|
||||
gfx.endFrame()
|
||||
|
|
@ -122,6 +140,7 @@ while ctr.run() do
|
|||
-- Draw
|
||||
gfx.startFrame(gfx.GFX_TOP)
|
||||
|
||||
-- Lines
|
||||
local sI = math.floor(scrollY / lineHeight)
|
||||
if sI < 1 then sI = 1 end
|
||||
|
||||
|
|
@ -129,25 +148,36 @@ while ctr.run() do
|
|||
if eI > #lines then eI = #lines end
|
||||
|
||||
for i = sI, eI, 1 do
|
||||
local line = lines[i]
|
||||
local x = -scrollX
|
||||
local y = -scrollY+ (i-1)*lineHeight
|
||||
|
||||
if cursorY == i then
|
||||
gfx.color.setDefault(color.cursor)
|
||||
gfx.text(-scrollX, y, line:sub(1, (utf8.offset(line, cursorX) or 0)-1):gsub("\t", " ").."|", nil) -- TODO: color doesn't work
|
||||
gfx.color.setDefault(color.default)
|
||||
end
|
||||
for _,colored in ipairs(coloredLines[i]) do
|
||||
local str = displayedText(colored[1])
|
||||
|
||||
gfx.text(-scrollX, y, line:gsub("\t", " "), nil)
|
||||
gfx.color.setDefault(colored[2])
|
||||
gfx.text(x, y, str)
|
||||
gfx.color.setDefault(color.default)
|
||||
|
||||
x = x + font:width(str)
|
||||
end
|
||||
end
|
||||
|
||||
-- Cursor
|
||||
local curline = lines[cursorY]
|
||||
gfx.rectangle(-scrollX+ font:width(displayedText(curline:sub(1, (utf8.offset(curline, cursorX) or 0)-1))),
|
||||
-scrollY+ (cursorY-1)*lineHeight, 1, lineHeight, 0, color.cursor)
|
||||
|
||||
gfx.endFrame()
|
||||
|
||||
gfx.startFrame(gfx.GFX_BOTTOM)
|
||||
|
||||
gfx.text(3, 3, "FPS: "..math.ceil(gfx.getFPS()))
|
||||
|
||||
keyboard.draw(5, 115)
|
||||
|
||||
gfx.endFrame()
|
||||
|
||||
gfx.render()
|
||||
end
|
||||
|
||||
font:unload()
|
||||
90
sdcard/3ds/ctruLua/editor/syntax.lua
Normal file
90
sdcard/3ds/ctruLua/editor/syntax.lua
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
-- Each pattern should return 3 captures : start position, the string to colorize, and the end position.
|
||||
local syntax = {
|
||||
{ "comment", { "()(%-%-.*)()$" } },
|
||||
|
||||
--["string"] = { "()(%'.*%f[%\\]%')()", "()(%\".*%f[%\\]%\")()" },
|
||||
{ "string", { "()(%'[^%']*%')()", "()(%\"[^%\"]*%\")()" } },
|
||||
|
||||
{ "constant.numeric", {
|
||||
"%f[%d%w%.]()(0x[a-fA-F%d]+)()%f[^%d%w%.]",
|
||||
"%f[%d%w%.]()([%d% ]+%.[%d% ]+)()%f[^%d%w%.]",
|
||||
"%f[%d%w%.]()([%d% ]+)()%f[^%d%w%.]"
|
||||
}
|
||||
},
|
||||
|
||||
{ "constant.language", {
|
||||
"%f[%w]()(false)()%f[%W]", "%f[%w]()(nil)()%f[%W]", "%f[%w]()(true)()%f[%W]", "%f[%w]()(_G)()%f[%W]",
|
||||
"%f[%w]()(_VERSION)()%f[%W]", "%f[%w]()(math.pi)()%f[%W]", "%f[%w]()(math.huge)()%f[%W]", "%f[%w]()(%.%.%.)()%f[%W]"
|
||||
}
|
||||
},
|
||||
|
||||
{ "keyword.control", {
|
||||
"%f[%w]()(break)()%f[%W]", "%f[%w]()(goto)()%f[%W]", "%f[%w]()(do)()%f[%W]", "%f[%w]()(else)()%f[%W]",
|
||||
"%f[%w]()(for)()%f[%W]", "%f[%w]()(if)()%f[%W]", "%f[%w]()(elseif)()%f[%W]", "%f[%w]()(return)()%f[%W]",
|
||||
"%f[%w]()(then)()%f[%W]", "%f[%w]()(repeat)()%f[%W]", "%f[%w]()(while)()%f[%W]", "%f[%w]()(until)()%f[%W]",
|
||||
"%f[%w]()(end)()%f[%W]", "%f[%w]()(function)()%f[%W]", "%f[%w]()(local)()%f[%W]", "%f[%w]()(in)()%f[%W]"
|
||||
}
|
||||
},
|
||||
|
||||
{ "keyword.operator", {
|
||||
"%f[%w]()(and)()%f[%W]", "%f[%w]()(or)()%f[%W]", "%f[%w]()(not)()%f[%W]",
|
||||
"()(%+)()", "()(%-)()", "()(%%)()", "()(%#)()", "()(%*)()", "()(%/%/?)()", "()(%^)()", "()(%=%=?)()", "()(%~%=?)()",
|
||||
"()(%.%.)()", "()(%<%=?)()", "()(%>%=?)()", "()(%&)()", "()(%|)()", "()(%<%<)()", "()(%>%>)()",
|
||||
}
|
||||
},
|
||||
|
||||
{ "support.function", {
|
||||
"[^%.%:]()(assert)()[%( %{]", "[^%.%:]()(collectgarbage)()[%( %{]", "[^%.%:]()(dofile)()[%( %{]",
|
||||
"[^%.%:]()(error)()[%( %{]", "[^%.%:]()(getfenv)()[%( %{]", "[^%.%:]()(getmetatable)()[%( %{]",
|
||||
"[^%.%:]()(ipairs)()[%( %{]", "[^%.%:]()loadfile)()[%( %{]", "[^%.%:]()(loadstring)()[%( %{]",
|
||||
"[^%.%:]()(module)()[%( %{]", "[^%.%:]()(next)()[%( %{]", "[^%.%:]()(pairs)()[%( %{]",
|
||||
"[^%.%:]()(pcall)()[%( %{]", "[^%.%:]()(print)()[%( %{]", "[^%.%:]()(rawequal)()[%( %{]",
|
||||
"[^%.%:]()(rawget)()[%( %{]", "[^%.%:]()(rawset)()[%( %{]", "[^%.%:]()(require)()[%( %{]",
|
||||
"[^%.%:]()(select)()[%( %{]", "[^%.%:]()(setfenv)()[%( %{]", "[^%.%:]()(setmetatable)()[%( %{]",
|
||||
"[^%.%:]()(tonumber)()[%( %{]", "[^%.%:]()(tostring)()[%( %{]", "[^%.%:]()(type)()[%( %{]",
|
||||
"[^%.%:]()(unpack)()[%( %{]", "[^%.%:]()(xpcall)()[%( %{]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return function(lines, color)
|
||||
local ret = {}
|
||||
|
||||
for _,line in ipairs(lines) do
|
||||
local colored = { { line, color.default } }
|
||||
|
||||
for _, patterns in ipairs(syntax) do
|
||||
local name = patterns[1]
|
||||
|
||||
for _, pattern in ipairs(patterns[2]) do
|
||||
local i = 1
|
||||
while i <= #colored do
|
||||
local oldcolor = colored[i][2]
|
||||
|
||||
if oldcolor == color.default then
|
||||
local part = colored[i][1]
|
||||
|
||||
local starti, match, endi = part:match(pattern)
|
||||
if starti then
|
||||
table.remove(colored, i)
|
||||
if starti > 1 then
|
||||
table.insert(colored, i, { part:sub(1, starti-1), oldcolor })
|
||||
i = i + 1
|
||||
end
|
||||
table.insert(colored, i, { match, color[name] or color.default })
|
||||
if endi <= #part then
|
||||
table.insert(colored, i+1, { part:sub(endi, -1), oldcolor })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(ret, colored)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
local fs = require("ctr.fs")
|
||||
|
||||
repeat
|
||||
local file = dofile("sdmc:/3ds/ctruLua/openfile.lua")("Choose a Lua file to execute", "/3ds/ctruLua/", ".lua", "exist")
|
||||
if file then dofile(file) end
|
||||
fs.setDirectory("sdmc:/3ds/ctruLua")
|
||||
local file = dofile("openfile.lua")("Choose a Lua file to execute", "/3ds/ctruLua/", ".lua", "exist")
|
||||
if file then
|
||||
fs.setDirectory(file:match("^(.-)[^/]*$"))
|
||||
dofile(file)
|
||||
end
|
||||
until not file
|
||||
|
|
@ -29,9 +29,11 @@ return function(title, curdir, exts, type)
|
|||
--local was3D = gfx.get3D() TODO: implement this thing in ctruLua
|
||||
local wasDefault = gfx.color.getDefault()
|
||||
local wasBackground = gfx.color.getBackground()
|
||||
local wasFont = gfx.font.getDefault()
|
||||
gfx.set3D(false)
|
||||
gfx.color.setDefault(0xFFFFFFFF)
|
||||
gfx.color.setBackground(0x000000FF)
|
||||
gfx.font.setDefault()
|
||||
|
||||
while ctr.run() do
|
||||
ctr.hid.read()
|
||||
|
|
@ -130,6 +132,7 @@ return function(title, curdir, exts, type)
|
|||
--gfx.set3D(was3D)
|
||||
gfx.color.setDefault(wasDefault)
|
||||
gfx.color.setBackground(wasBackground)
|
||||
gfx.font.setDefault(wasFont)
|
||||
|
||||
if ret then
|
||||
return table.unpack(ret)
|
||||
|
|
|
|||
105
source/font.c
105
source/font.c
|
|
@ -1,27 +1,126 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sftd.h>
|
||||
#include "vera_ttf.h"
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
sftd_font *font_default;
|
||||
#include "font.h"
|
||||
|
||||
static int font_load(lua_State *L) {
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
|
||||
font_userdata *font = lua_newuserdata(L, sizeof(*font));
|
||||
luaL_getmetatable(L, "LFont");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
font->font = sftd_load_font_file(path);
|
||||
|
||||
// SFTD doesn't actually check if the file exist, so we have to do this ourselves.
|
||||
if (font->font == NULL || access(path, F_OK) != 0) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "No valid font file at %s", path);
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int font_setDefault(lua_State *L) {
|
||||
if (luaL_testudata(L, 1, "LFont") == NULL) {
|
||||
font_userdata *font = lua_newuserdata(L, sizeof(*font));
|
||||
luaL_getmetatable(L, "LFont");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
font->font = sftd_load_font_mem(vera_ttf, vera_ttf_size);
|
||||
}
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "LFontDefault");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int font_getDefault(lua_State *L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LFontDefault");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int font_object_width(lua_State *L) {
|
||||
font_userdata *font = luaL_checkudata(L, 1, "LFont");
|
||||
if (font->font == NULL) luaL_error(L, "The font object was unloaded");
|
||||
|
||||
size_t len;
|
||||
const char *text = luaL_checklstring(L, 2, &len);
|
||||
|
||||
int size = luaL_optinteger(L, 3, 9);
|
||||
|
||||
// Wide caracters support. (wchar = UTF32 on 3DS.)
|
||||
wchar_t wtext[len];
|
||||
len = mbstowcs(wtext, text, len);
|
||||
*(wtext+len) = 0x0; // text end
|
||||
|
||||
lua_pushinteger(L, sftd_width_wtext(font->font, size, wtext));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int font_object_unload(lua_State *L) {
|
||||
font_userdata *font = luaL_checkudata(L, 1, "LFont");
|
||||
if (font->font == NULL) return 0;
|
||||
|
||||
sftd_free_font(font->font);
|
||||
font->font = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Font object methods
|
||||
static const struct luaL_Reg font_object_methods[] = {
|
||||
{ "width", font_object_width },
|
||||
{ "unload", font_object_unload },
|
||||
{ "__gc", font_object_unload },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
// Library functions
|
||||
static const struct luaL_Reg font_lib[] = {
|
||||
{ "load", font_load },
|
||||
{ "setDefault", font_setDefault },
|
||||
{ "getDefault", font_getDefault },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int luaopen_font_lib(lua_State *L) {
|
||||
luaL_newmetatable(L, "LFont");
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
luaL_setfuncs(L, font_object_methods, 0);
|
||||
|
||||
luaL_newlib(L, font_lib);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void load_font_lib(lua_State *L) {
|
||||
font_default = sftd_load_font_mem(vera_ttf, vera_ttf_size); // Load default font
|
||||
// Load default font
|
||||
font_userdata *font = lua_newuserdata(L, sizeof(*font));
|
||||
luaL_getmetatable(L, "LFont");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
font->font = sftd_load_font_mem(vera_ttf, vera_ttf_size);
|
||||
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "LFontDefault");
|
||||
|
||||
// Load lib
|
||||
luaL_requiref(L, "ctr.gfx.font", luaopen_font_lib, false);
|
||||
}
|
||||
|
||||
void unload_font_lib(lua_State *L) {
|
||||
sftd_free_font(font_default); // Unload current font
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LFontDefault");
|
||||
|
||||
if (luaL_testudata(L, -1, "LFont") != NULL)
|
||||
sftd_free_font(((font_userdata *)lua_touserdata(L, -1))->font); // Unload current font
|
||||
}
|
||||
8
source/font.h
Normal file
8
source/font.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef FONT_H
|
||||
#define FONT_H
|
||||
|
||||
typedef struct {
|
||||
sftd_font *font;
|
||||
} font_userdata;
|
||||
|
||||
#endif
|
||||
38
source/fs.c
38
source/fs.c
|
|
@ -1,3 +1,5 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <3ds/types.h>
|
||||
#include <3ds/util/utf.h>
|
||||
#include <3ds/services/fs.h>
|
||||
|
|
@ -8,7 +10,7 @@
|
|||
Handle *fsuHandle;
|
||||
FS_archive sdmcArchive;
|
||||
|
||||
int fs_list(lua_State *L) {
|
||||
static int fs_list(lua_State *L) {
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
|
||||
lua_newtable(L);
|
||||
|
|
@ -60,8 +62,40 @@ int fs_list(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int fs_exists(lua_State *L) {
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
|
||||
lua_pushboolean(L, access(path, F_OK) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fs_getDirectory(lua_State *L) {
|
||||
char cwd[256];
|
||||
|
||||
lua_pushstring(L, getcwd(cwd, 256));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fs_setDirectory(lua_State *L) {
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
|
||||
int result = chdir(path);
|
||||
|
||||
if (result == 0)
|
||||
lua_pushboolean(L, true);
|
||||
else
|
||||
lua_pushboolean(L, false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg fs_lib[] = {
|
||||
{ "list", fs_list },
|
||||
{ "list", fs_list },
|
||||
{ "exists", fs_exists },
|
||||
{ "getDirectory", fs_getDirectory },
|
||||
{ "setDirectory", fs_setDirectory },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
|||
13
source/gfx.c
13
source/gfx.c
|
|
@ -8,6 +8,8 @@
|
|||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "font.h"
|
||||
|
||||
bool isGfxInitialised = false;
|
||||
|
||||
void load_color_lib(lua_State *L);
|
||||
|
|
@ -18,7 +20,6 @@ void load_map_lib(lua_State *L);
|
|||
void unload_font_lib(lua_State *L);
|
||||
|
||||
u32 color_default;
|
||||
sftd_font *font_default;
|
||||
|
||||
static int gfx_startFrame(lua_State *L) {
|
||||
u8 screen = luaL_checkinteger(L, 1);
|
||||
|
|
@ -124,14 +125,20 @@ static int gfx_text(lua_State *L) {
|
|||
|
||||
int size = luaL_optinteger(L, 4, 9);
|
||||
u32 color = luaL_optinteger(L, 5, color_default);
|
||||
// todo : font selection
|
||||
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_default, x, y, color, size, wtext);
|
||||
sftd_draw_wtext(font->font, x, y, color, size, wtext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue