![]() | tremblin's Blog... |
2026-05-13
Example of how to use the x_info functions to add/get access to assets. This is the full font library including the font_info function. All the other assets are basically identical, except the struct stored in the black box may have more information (see headers.)
// All of the predefined assets have a x_info that is almost identical to this.
// The type returned can be viewed in the header files
Font_Info *font_info(Program *prg)
{
Font_Info *info = (Font_Info *)booboo::get_black_box(prg, "com.nooskewl.booboo.font");
if (info == nullptr) {
info = new Font_Info;
info->font_id = 0;
booboo::set_black_box(prg, "com.nooskewl.booboo.font", info);
}
return info;
}
// The main magic is in the load/create functions, which stuffs a value into the black box
// and returns a handle
static void exprfunc_font_load(Program *prg, const std::vector<Token> &v)
{
MIN_ARGS(3)
std::string name = as_string(prg, v[0]);
int size = as_number(prg, v[1]);
bool smooth = as_number(prg, v[2]);
Font_Info *info = font_info(prg);
int sheet_size = 512;
if (v.size() > 3) {
sheet_size = as_number(prg, v[3]);
}
bool load_from_filesystem = false;
if (v.size() > 4) {
load_from_filesystem = as_number(prg, v[4]);
}
prg->result.type = Variable::NUMBER;
try {
gfx::TTF *font = new gfx::TTF(name, size, sheet_size, load_from_filesystem);
font->set_smooth(smooth);
prg->result.n = info->font_id;
info->fonts[info->font_id++] = font;
}
catch (util::Error &e) {
prg->result.n = -1;
}
}
// These functions just access the info struct with a handle
static bool fontfunc_destroy(Program *prg, const std::vector<Token> &v)
{
COUNT_ARGS(1)
int id = as_number(prg, v[0]);
Font_Info *info = font_info(prg);
INFO_EXISTS(info->fonts, id)
delete info->fonts[id];
info->fonts.erase(info->fonts.find(id));
return true;
}
static bool fontfunc_draw(Program *prg, const std::vector<Token> &v)
{
MIN_ARGS(8)
int id = as_number(prg, v[0]);
double r = as_number(prg, v[1]);
double g = as_number(prg, v[2]);
double b = as_number(prg, v[3]);
double a = as_number(prg, v[4]);
std::string text = as_string(prg, v[5]);
double x = as_number(prg, v[6]);
double y = as_number(prg, v[7]);
bool interpret_codes;
bool rtl;
if (v.size() > 8) {
interpret_codes = as_number(prg, v[8]);
}
else {
interpret_codes = false;
}
if (v.size() > 9) {
rtl = as_number(prg, v[9]);
}
else {
rtl = false;
}
Font_Info *info = font_info(prg);
INFO_EXISTS(info->fonts, id)
gfx::TTF *font = info->fonts[id];
SDL_Color c;
c.r = r;
c.g = g;
c.b = b;
c.a = a;
font->draw(c, text, util::Point<float>(x, y), interpret_codes, false, interpret_codes, rtl);
return true;
}
static void exprfunc_font_width(Program *prg, const std::vector<Token> &v)
{
COUNT_ARGS(2)
int id = as_number(prg, v[0]);
std::string text = as_string(prg, v[1]);
Font_Info *info = font_info(prg);
INFO_EXISTS(info->fonts, id)
gfx::TTF *font = info->fonts[id];
int w = font->get_text_width(text);
prg->result.type = Variable::NUMBER;
prg->result.n = w;
}
static void exprfunc_font_height(Program *prg, const std::vector<Token> &v)
{
COUNT_ARGS(1)
int id = as_number(prg, v[0]);
Font_Info *info = font_info(prg);
INFO_EXISTS(info->fonts, id)
gfx::TTF *font = info->fonts[id];
int h = font->get_height();
prg->result.type = Variable::NUMBER;
prg->result.n = h;
}
static bool fontfunc_add_extra_glyph(Program *prg, const std::vector<Token> &v)
{
COUNT_ARGS(3)
int id = as_number(prg, v[0]);
int glyph_id = as_number(prg, v[1]);
int image_id = as_number(prg, v[2]);
Font_Info *info = font_info(prg);
INFO_EXISTS(info->fonts, id)
gfx::TTF *font = info->fonts[id];
Image_Info *iinfo = image_info(prg);
INFO_EXISTS(iinfo->images, image_id)
gfx::Image *image = iinfo->images[image_id]->image;
font->add_extra_glyph(glyph_id, image);
return true;
}
// After defining the function, you just register them like this:
add_expression_handler("font_load", exprfunc_font_load);
add_instruction("font_destroy", fontfunc_destroy);
add_instruction("font_draw", fontfunc_draw);
add_expression_handler("font_width", exprfunc_font_width);
add_expression_handler("font_height", exprfunc_font_height);
add_instruction("font_add_extra_glyph", fontfunc_add_extra_glyph);