mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-28 00:39:30 +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_DepthMap(-1.0f, 0.0f);
|
||||||
GPU_SetFaceCulling(GPU_CULL_NONE);
|
GPU_SetFaceCulling(GPU_CULL_NONE);
|
||||||
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
|
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_SetBlendingColor(0,0,0,0);
|
||||||
GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL);
|
GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL);
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
|
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_size = data_size;
|
||||||
texture->data = data;
|
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;
|
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, ...);
|
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
|
#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,
|
&rect, &bitmap_left, &bitmap_top,
|
||||||
&advance_x, &advance_y, &glyph_size);
|
&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,
|
sf2d_draw_texture_part_scale_blend(font->tex_atlas->tex,
|
||||||
pen_x + bitmap_left * draw_scale,
|
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,
|
&rect, &bitmap_left, &bitmap_top,
|
||||||
&advance_x, &advance_y, &glyph_size);
|
&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,
|
sf2d_draw_texture_part_scale_blend(font->tex_atlas->tex,
|
||||||
pen_x + bitmap_left * draw_scale,
|
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);
|
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
|
-- Colors based on the Monokai theme
|
||||||
return {
|
return {
|
||||||
background = 0x272822FF,
|
-- General
|
||||||
default = 0xF8F8F2FF,
|
["background"] = 0x272822FF,
|
||||||
cursor = 0xFF0000FF
|
["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
|
-- Open libs
|
||||||
local keyboard = dofile("sdmc:/3ds/ctruLua/keyboard.lua")
|
local keyboard = dofile("sdmc:/3ds/ctruLua/keyboard.lua")
|
||||||
local openfile = dofile("sdmc:/3ds/ctruLua/openfile.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
|
-- Open file
|
||||||
local path, status = openfile("Choose a file to edit", "/3ds/ctruLua/", nil, "any")
|
local path, status = openfile("Choose a file to edit", "/3ds/ctruLua/", nil, "any")
|
||||||
if not path then return end
|
if not path then return end
|
||||||
|
local lineEnding
|
||||||
local lines = {}
|
local lines = {}
|
||||||
if status == "exist" then
|
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
|
else
|
||||||
|
lineEnding = "\n"
|
||||||
lines = { "" }
|
lines = { "" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Syntax coloring
|
||||||
|
local coloredLines = syntax(lines, color)
|
||||||
|
|
||||||
-- Variables
|
-- Variables
|
||||||
local lineHeight = 10
|
local lineHeight = 10
|
||||||
local cursorX, cursorY = 1, 1
|
local cursorX, cursorY = 1, 1
|
||||||
local scrollX, scrollY = 0, 0
|
local scrollX, scrollY = 0, 0
|
||||||
|
|
||||||
|
-- Helper functions
|
||||||
|
local function displayedText(text)
|
||||||
|
return text:gsub("\t", " ")
|
||||||
|
end
|
||||||
|
|
||||||
-- Set defaults
|
-- Set defaults
|
||||||
gfx.set3D(false)
|
gfx.set3D(false)
|
||||||
gfx.color.setDefault(color.default)
|
gfx.color.setDefault(color.default)
|
||||||
gfx.color.setBackground(color.background)
|
gfx.color.setBackground(color.background)
|
||||||
|
gfx.font.setDefault(font)
|
||||||
|
|
||||||
while ctr.run() do
|
while ctr.run() do
|
||||||
hid.read()
|
hid.read()
|
||||||
|
|
@ -75,10 +93,10 @@ while ctr.run() do
|
||||||
until t + 5 < os.time()
|
until t + 5 < os.time()
|
||||||
else
|
else
|
||||||
for i = 1, #lines, 1 do
|
for i = 1, #lines, 1 do
|
||||||
file:write(lines[i].."\n")
|
file:write(lines[i]..lineEnding)
|
||||||
gfx.startFrame(gfx.GFX_TOP)
|
gfx.startFrame(gfx.GFX_TOP)
|
||||||
gfx.rectangle(0, 0, math.ceil(i/#lines*gfx.TOP_WIDTH), gfx.TOP_HEIGHT, 0, 0xFFFFFFFF)
|
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.text(gfx.TOP_WIDTH/2, gfx.TOP_HEIGHT/2, math.ceil(i/#lines*100).."%")
|
||||||
gfx.color.setDefault(color.default)
|
gfx.color.setDefault(color.default)
|
||||||
gfx.endFrame()
|
gfx.endFrame()
|
||||||
|
|
@ -122,6 +140,7 @@ while ctr.run() do
|
||||||
-- Draw
|
-- Draw
|
||||||
gfx.startFrame(gfx.GFX_TOP)
|
gfx.startFrame(gfx.GFX_TOP)
|
||||||
|
|
||||||
|
-- Lines
|
||||||
local sI = math.floor(scrollY / lineHeight)
|
local sI = math.floor(scrollY / lineHeight)
|
||||||
if sI < 1 then sI = 1 end
|
if sI < 1 then sI = 1 end
|
||||||
|
|
||||||
|
|
@ -129,21 +148,30 @@ while ctr.run() do
|
||||||
if eI > #lines then eI = #lines end
|
if eI > #lines then eI = #lines end
|
||||||
|
|
||||||
for i = sI, eI, 1 do
|
for i = sI, eI, 1 do
|
||||||
local line = lines[i]
|
local x = -scrollX
|
||||||
local y = -scrollY+ (i-1)*lineHeight
|
local y = -scrollY+ (i-1)*lineHeight
|
||||||
|
|
||||||
if cursorY == i then
|
for _,colored in ipairs(coloredLines[i]) do
|
||||||
gfx.color.setDefault(color.cursor)
|
local str = displayedText(colored[1])
|
||||||
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(colored[2])
|
||||||
|
gfx.text(x, y, str)
|
||||||
gfx.color.setDefault(color.default)
|
gfx.color.setDefault(color.default)
|
||||||
|
|
||||||
|
x = x + font:width(str)
|
||||||
end
|
end
|
||||||
|
|
||||||
gfx.text(-scrollX, y, line:gsub("\t", " "), nil)
|
|
||||||
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.endFrame()
|
||||||
|
|
||||||
gfx.startFrame(gfx.GFX_BOTTOM)
|
gfx.startFrame(gfx.GFX_BOTTOM)
|
||||||
|
|
||||||
|
gfx.text(3, 3, "FPS: "..math.ceil(gfx.getFPS()))
|
||||||
|
|
||||||
keyboard.draw(5, 115)
|
keyboard.draw(5, 115)
|
||||||
|
|
||||||
|
|
@ -151,3 +179,5 @@ while ctr.run() do
|
||||||
|
|
||||||
gfx.render()
|
gfx.render()
|
||||||
end
|
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
|
repeat
|
||||||
local file = dofile("sdmc:/3ds/ctruLua/openfile.lua")("Choose a Lua file to execute", "/3ds/ctruLua/", ".lua", "exist")
|
fs.setDirectory("sdmc:/3ds/ctruLua")
|
||||||
if file then dofile(file) end
|
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
|
until not file
|
||||||
|
|
@ -29,9 +29,11 @@ return function(title, curdir, exts, type)
|
||||||
--local was3D = gfx.get3D() TODO: implement this thing in ctruLua
|
--local was3D = gfx.get3D() TODO: implement this thing in ctruLua
|
||||||
local wasDefault = gfx.color.getDefault()
|
local wasDefault = gfx.color.getDefault()
|
||||||
local wasBackground = gfx.color.getBackground()
|
local wasBackground = gfx.color.getBackground()
|
||||||
|
local wasFont = gfx.font.getDefault()
|
||||||
gfx.set3D(false)
|
gfx.set3D(false)
|
||||||
gfx.color.setDefault(0xFFFFFFFF)
|
gfx.color.setDefault(0xFFFFFFFF)
|
||||||
gfx.color.setBackground(0x000000FF)
|
gfx.color.setBackground(0x000000FF)
|
||||||
|
gfx.font.setDefault()
|
||||||
|
|
||||||
while ctr.run() do
|
while ctr.run() do
|
||||||
ctr.hid.read()
|
ctr.hid.read()
|
||||||
|
|
@ -130,6 +132,7 @@ return function(title, curdir, exts, type)
|
||||||
--gfx.set3D(was3D)
|
--gfx.set3D(was3D)
|
||||||
gfx.color.setDefault(wasDefault)
|
gfx.color.setDefault(wasDefault)
|
||||||
gfx.color.setBackground(wasBackground)
|
gfx.color.setBackground(wasBackground)
|
||||||
|
gfx.font.setDefault(wasFont)
|
||||||
|
|
||||||
if ret then
|
if ret then
|
||||||
return table.unpack(ret)
|
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 <sftd.h>
|
||||||
#include "vera_ttf.h"
|
#include "vera_ttf.h"
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.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[] = {
|
static const struct luaL_Reg font_lib[] = {
|
||||||
|
{ "load", font_load },
|
||||||
|
{ "setDefault", font_setDefault },
|
||||||
|
{ "getDefault", font_getDefault },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
int luaopen_font_lib(lua_State *L) {
|
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);
|
luaL_newlib(L, font_lib);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_font_lib(lua_State *L) {
|
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);
|
luaL_requiref(L, "ctr.gfx.font", luaopen_font_lib, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unload_font_lib(lua_State *L) {
|
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/types.h>
|
||||||
#include <3ds/util/utf.h>
|
#include <3ds/util/utf.h>
|
||||||
#include <3ds/services/fs.h>
|
#include <3ds/services/fs.h>
|
||||||
|
|
@ -8,7 +10,7 @@
|
||||||
Handle *fsuHandle;
|
Handle *fsuHandle;
|
||||||
FS_archive sdmcArchive;
|
FS_archive sdmcArchive;
|
||||||
|
|
||||||
int fs_list(lua_State *L) {
|
static int fs_list(lua_State *L) {
|
||||||
const char *path = luaL_checkstring(L, 1);
|
const char *path = luaL_checkstring(L, 1);
|
||||||
|
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
@ -60,8 +62,40 @@ int fs_list(lua_State *L) {
|
||||||
return 1;
|
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[] = {
|
static const struct luaL_Reg fs_lib[] = {
|
||||||
{ "list", fs_list },
|
{ "list", fs_list },
|
||||||
|
{ "exists", fs_exists },
|
||||||
|
{ "getDirectory", fs_getDirectory },
|
||||||
|
{ "setDirectory", fs_setDirectory },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
13
source/gfx.c
13
source/gfx.c
|
|
@ -8,6 +8,8 @@
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
bool isGfxInitialised = false;
|
bool isGfxInitialised = false;
|
||||||
|
|
||||||
void load_color_lib(lua_State *L);
|
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);
|
void unload_font_lib(lua_State *L);
|
||||||
|
|
||||||
u32 color_default;
|
u32 color_default;
|
||||||
sftd_font *font_default;
|
|
||||||
|
|
||||||
static int gfx_startFrame(lua_State *L) {
|
static int gfx_startFrame(lua_State *L) {
|
||||||
u8 screen = luaL_checkinteger(L, 1);
|
u8 screen = luaL_checkinteger(L, 1);
|
||||||
|
|
@ -124,14 +125,20 @@ static int gfx_text(lua_State *L) {
|
||||||
|
|
||||||
int size = luaL_optinteger(L, 4, 9);
|
int size = luaL_optinteger(L, 4, 9);
|
||||||
u32 color = luaL_optinteger(L, 5, color_default);
|
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.)
|
// Wide caracters support. (wchar = UTF32 on 3DS.)
|
||||||
wchar_t wtext[len];
|
wchar_t wtext[len];
|
||||||
len = mbstowcs(wtext, text, len);
|
len = mbstowcs(wtext, text, len);
|
||||||
*(wtext+len) = 0x0; // text end
|
*(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue