add ui module

This commit is contained in:
asrael 2025-10-04 11:55:04 -05:00
parent 1744e689b5
commit 6008ebf5ed
12 changed files with 703 additions and 215 deletions

View file

@ -11,12 +11,14 @@
#include "pxl8_macros.h"
#include "pxl8_script.h"
#include "pxl8_ui.h"
#include "pxl8_vfx.h"
struct pxl8_script {
lua_State* L;
pxl8_gfx* gfx;
pxl8_input_state* input;
pxl8_ui* ui;
char last_error[1024];
char main_path[256];
char watch_dir[256];
@ -35,7 +37,7 @@ static const char* pxl8_ffi_cdefs =
"typedef float f32;\n"
"typedef double f64;\n"
"typedef struct pxl8_gfx pxl8_gfx;\n"
"typedef struct { int x, y, w, h; } pxl8_rect;\n"
"typedef struct { int x, y, w, h; } pxl8_bounds;\n"
"typedef struct { int x, y; } pxl8_point;\n"
"\n"
"i32 pxl8_gfx_get_height(pxl8_gfx* ctx);\n"
@ -145,7 +147,30 @@ static const char* pxl8_ffi_cdefs =
"pxl8_mat4 pxl8_mat4_rotate_y(float angle);\n"
"pxl8_mat4 pxl8_mat4_rotate_z(float angle);\n"
"pxl8_mat4 pxl8_mat4_scale(float x, float y, float z);\n"
"pxl8_mat4 pxl8_mat4_translate(float x, float y, float z);\n";
"pxl8_mat4 pxl8_mat4_translate(float x, float y, float z);\n"
"\n"
"typedef struct pxl8_ui pxl8_ui;\n"
"typedef struct { unsigned char bg_color; unsigned int sprite_id; int corner_size; int edge_size; int padding; } pxl8_frame_theme;\n"
"typedef struct { bool enabled; const char* label; } pxl8_menu_item;\n"
"pxl8_ui* pxl8_ui_create(pxl8_gfx* gfx);\n"
"void pxl8_ui_destroy(pxl8_ui* ui);\n"
"void pxl8_ui_frame_begin(pxl8_ui* ui);\n"
"void pxl8_ui_frame_end(pxl8_ui* ui);\n"
"void pxl8_ui_input_keydown(pxl8_ui* ui, int key);\n"
"void pxl8_ui_input_keyup(pxl8_ui* ui, int key);\n"
"void pxl8_ui_input_mousedown(pxl8_ui* ui, int x, int y, int button);\n"
"void pxl8_ui_input_mousemove(pxl8_ui* ui, int x, int y);\n"
"void pxl8_ui_input_mouseup(pxl8_ui* ui, int x, int y, int button);\n"
"void pxl8_ui_input_scroll(pxl8_ui* ui, int x, int y);\n"
"void pxl8_ui_input_text(pxl8_ui* ui, const char* text);\n"
"bool pxl8_ui_button(pxl8_ui* ui, const char* label);\n"
"void pxl8_ui_label(pxl8_ui* ui, const char* text);\n"
"void pxl8_ui_layout_row(pxl8_ui* ui, int item_count, const int* widths, int height);\n"
"int pxl8_ui_menu(pxl8_ui* ui, pxl8_menu_item* items, int item_count);\n"
"void pxl8_ui_panel(pxl8_ui* ui, pxl8_bounds rect, pxl8_frame_theme* theme);\n"
"bool pxl8_ui_window_begin(pxl8_ui* ui, const char* title, pxl8_bounds rect, int options);\n"
"void pxl8_ui_window_end(pxl8_ui* ui);\n"
"pxl8_frame_theme pxl8_ui_theme_default(void);\n";
void pxl8_lua_info(const char* msg) {
pxl8_info("%s", msg);
@ -249,12 +274,19 @@ void pxl8_script_set_input(pxl8_script* script, pxl8_input_state* input) {
}
}
pxl8_result pxl8_script_run_file(pxl8_script* script, const char* filename) {
if (!script || !script->L || !filename) return PXL8_ERROR_NULL_POINTER;
void pxl8_script_set_ui(pxl8_script* script, pxl8_ui* ui) {
if (!script) return;
script->ui = ui;
if (script->L && ui) {
lua_pushlightuserdata(script->L, ui);
lua_setglobal(script->L, "_pxl8_ui");
}
}
static pxl8_result pxl8_script_prepare_path(pxl8_script* script, const char* filename, char** out_basename) {
char* filename_copy = strdup(filename);
char* last_slash = strrchr(filename_copy, '/');
const char* basename = filename;
*out_basename = (char*)filename;
if (last_slash) {
*last_slash = '\0';
@ -263,12 +295,22 @@ pxl8_result pxl8_script_run_file(pxl8_script* script, const char* filename) {
if (script_dir && original_cwd) {
chdir(script_dir);
pxl8_script_set_cart_path(script, script_dir, original_cwd);
basename = last_slash + 1;
*out_basename = strdup(last_slash + 1);
}
free(script_dir);
free(original_cwd);
}
free(filename_copy);
return PXL8_OK;
}
pxl8_result pxl8_script_run_file(pxl8_script* script, const char* filename) {
if (!script || !script->L || !filename) return PXL8_ERROR_NULL_POINTER;
char* basename;
pxl8_script_prepare_path(script, filename, &basename);
pxl8_result result = PXL8_OK;
if (luaL_dofile(script->L, basename) != 0) {
pxl8_script_set_error(script, lua_tostring(script->L, -1));
@ -278,8 +320,7 @@ pxl8_result pxl8_script_run_file(pxl8_script* script, const char* filename) {
script->last_error[0] = '\0';
}
free(filename_copy);
if (basename != filename) free(basename);
return result;
}
@ -320,28 +361,14 @@ void pxl8_script_set_cart_path(pxl8_script* script, const char* cart_path, const
pxl8_result pxl8_script_run_fennel_file(pxl8_script* script, const char* filename) {
if (!script || !script->L || !filename) return PXL8_ERROR_NULL_POINTER;
char* filename_copy = strdup(filename);
char* last_slash = strrchr(filename_copy, '/');
const char* basename = filename;
if (last_slash) {
*last_slash = '\0';
char* script_dir = realpath(filename_copy, NULL);
char* original_cwd = getcwd(NULL, 0);
if (script_dir && original_cwd) {
chdir(script_dir);
pxl8_script_set_cart_path(script, script_dir, original_cwd);
basename = last_slash + 1;
}
free(script_dir);
free(original_cwd);
}
char* basename;
pxl8_script_prepare_path(script, filename, &basename);
lua_getglobal(script->L, "fennel");
if (lua_isnil(script->L, -1)) {
pxl8_script_set_error(script, "Fennel not loaded");
lua_pop(script->L, 1);
free(filename_copy);
if (basename != filename) free(basename);
return PXL8_ERROR_SCRIPT_ERROR;
}
@ -358,7 +385,7 @@ pxl8_result pxl8_script_run_fennel_file(pxl8_script* script, const char* filenam
}
lua_pop(script->L, 1);
free(filename_copy);
if (basename != filename) free(basename);
return result;
}