refactor SDL out of core files
This commit is contained in:
parent
82ed6b4ea9
commit
9d183341ae
21 changed files with 1419 additions and 1028 deletions
513
src/pxl8.c
513
src/pxl8.c
|
|
@ -4,197 +4,33 @@
|
|||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linenoise.h>
|
||||
|
||||
#define SDL_MAIN_USE_CALLBACKS
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
#include "pxl8_cart.h"
|
||||
#include "pxl8_game.h"
|
||||
#include "pxl8_hal.h"
|
||||
#include "pxl8_macros.h"
|
||||
#include "pxl8_script.h"
|
||||
#include "pxl8_sdl3.h"
|
||||
#include "pxl8_types.h"
|
||||
#include "pxl8_ui.h"
|
||||
|
||||
#define PXL8_MAX_REPL_COMMANDS 4096
|
||||
|
||||
typedef struct pxl8_repl_command {
|
||||
char buffer[PXL8_MAX_REPL_COMMANDS];
|
||||
struct pxl8_repl_command* next;
|
||||
} pxl8_repl_command;
|
||||
|
||||
typedef struct pxl8_repl_state {
|
||||
pthread_t thread;
|
||||
pthread_mutex_t mutex;
|
||||
pxl8_repl_command* queue_head;
|
||||
pxl8_repl_command* queue_tail;
|
||||
bool running;
|
||||
} pxl8_repl_state;
|
||||
|
||||
typedef struct pxl8_state {
|
||||
pxl8_cart* cart;
|
||||
pxl8_color_mode color_mode;
|
||||
pxl8_gfx* gfx;
|
||||
pxl8_repl_state repl;
|
||||
pxl8_resolution resolution;
|
||||
pxl8_script* script;
|
||||
pxl8_ui* ui;
|
||||
|
||||
i32 frame_count;
|
||||
u64 last_time;
|
||||
f32 time;
|
||||
|
||||
bool repl_mode;
|
||||
bool running;
|
||||
bool script_loaded;
|
||||
char script_path[256];
|
||||
|
||||
pxl8_input_state input;
|
||||
} pxl8_state;
|
||||
|
||||
static void pxl8_repl_completion(const char* buf, linenoiseCompletions* lc) {
|
||||
const char* fennel_keywords[] = {
|
||||
"fn", "let", "var", "set", "global", "local",
|
||||
"if", "when", "do", "while", "for", "each",
|
||||
"lambda", "λ", "partial", "macro", "macros",
|
||||
"require", "include", "import-macros",
|
||||
"values", "select", "table", "length",
|
||||
".", "..", ":", "->", "->>", "-?>", "-?>>",
|
||||
"doto", "match", "case", "pick-values",
|
||||
"collect", "icollect", "accumulate"
|
||||
};
|
||||
|
||||
const char* pxl8_functions[] = {
|
||||
"pxl8.clr", "pxl8.pixel", "pxl8.get_pixel",
|
||||
"pxl8.line", "pxl8.rect", "pxl8.rect_fill",
|
||||
"pxl8.circle", "pxl8.circle_fill", "pxl8.text",
|
||||
"pxl8.get_screen", "pxl8.info", "pxl8.warn",
|
||||
"pxl8.error", "pxl8.debug", "pxl8.trace"
|
||||
};
|
||||
|
||||
auto buf_len = strlen(buf);
|
||||
|
||||
for (size_t i = 0; i < sizeof(fennel_keywords) / sizeof(fennel_keywords[0]); i++) {
|
||||
if (strncmp(buf, fennel_keywords[i], buf_len) == 0) {
|
||||
linenoiseAddCompletion(lc, fennel_keywords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(pxl8_functions) / sizeof(pxl8_functions[0]); i++) {
|
||||
if (strncmp(buf, pxl8_functions[i], buf_len) == 0) {
|
||||
linenoiseAddCompletion(lc, pxl8_functions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char* pxl8_repl_hints(const char* buf, int* color, int* bold) {
|
||||
if (strncmp(buf, "pxl8.", 5) == 0 && strlen(buf) == 5) {
|
||||
*color = 35;
|
||||
*bold = 0;
|
||||
return "clr|pixel|line|rect|circle|text|get_screen";
|
||||
}
|
||||
|
||||
if (strcmp(buf, "(fn") == 0) {
|
||||
*color = 36;
|
||||
*bold = 0;
|
||||
return " [args] body)";
|
||||
}
|
||||
|
||||
if (strcmp(buf, "(let") == 0) {
|
||||
*color = 36;
|
||||
*bold = 0;
|
||||
return " [bindings] body)";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* pxl8_repl_stdin_thread(void* user_data) {
|
||||
pxl8_repl_state* repl = (pxl8_repl_state*)user_data;
|
||||
char* line;
|
||||
const char* history_file = ".pxl8_history";
|
||||
|
||||
linenoiseHistorySetMaxLen(100);
|
||||
linenoiseSetMultiLine(1);
|
||||
linenoiseSetCompletionCallback(pxl8_repl_completion);
|
||||
linenoiseSetHintsCallback(pxl8_repl_hints);
|
||||
linenoiseHistoryLoad(history_file);
|
||||
|
||||
while (repl->running && (line = linenoise(">> "))) {
|
||||
if (strlen(line) > 0) {
|
||||
linenoiseHistoryAdd(line);
|
||||
linenoiseHistorySave(history_file);
|
||||
|
||||
pxl8_repl_command* cmd = (pxl8_repl_command*)SDL_malloc(sizeof(pxl8_repl_command));
|
||||
if (cmd) {
|
||||
strncpy(cmd->buffer, line, PXL8_MAX_REPL_COMMANDS - 1);
|
||||
cmd->buffer[PXL8_MAX_REPL_COMMANDS - 1] = '\0';
|
||||
cmd->next = NULL;
|
||||
|
||||
pthread_mutex_lock(&repl->mutex);
|
||||
if (repl->queue_tail) {
|
||||
repl->queue_tail->next = cmd;
|
||||
repl->queue_tail = cmd;
|
||||
} else {
|
||||
repl->queue_head = repl->queue_tail = cmd;
|
||||
}
|
||||
pthread_mutex_unlock(&repl->mutex);
|
||||
}
|
||||
}
|
||||
linenoiseFree(line);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pxl8_repl_init(pxl8_repl_state* repl) {
|
||||
repl->queue_head = NULL;
|
||||
repl->queue_tail = NULL;
|
||||
repl->running = true;
|
||||
pthread_mutex_init(&repl->mutex, NULL);
|
||||
pthread_create(&repl->thread, NULL, pxl8_repl_stdin_thread, repl);
|
||||
}
|
||||
|
||||
static void pxl8_repl_shutdown(pxl8_repl_state* repl) {
|
||||
repl->running = false;
|
||||
pthread_join(repl->thread, NULL);
|
||||
pthread_mutex_destroy(&repl->mutex);
|
||||
|
||||
pxl8_repl_command* cmd = repl->queue_head;
|
||||
while (cmd) {
|
||||
pxl8_repl_command* next = cmd->next;
|
||||
SDL_free(cmd);
|
||||
cmd = next;
|
||||
}
|
||||
}
|
||||
|
||||
static pxl8_repl_command* pxl8_repl_pop_command(pxl8_repl_state* repl) {
|
||||
pthread_mutex_lock(&repl->mutex);
|
||||
pxl8_repl_command* cmd = repl->queue_head;
|
||||
if (cmd) {
|
||||
repl->queue_head = cmd->next;
|
||||
if (!repl->queue_head) {
|
||||
repl->queue_tail = NULL;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&repl->mutex);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
||||
static pxl8_state app = {0};
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) {
|
||||
pxl8_error("SDL_Init failed: %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
pxl8_game_result pxl8_init(pxl8_game* game, i32 argc, char* argv[]) {
|
||||
if (!game) {
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
app.color_mode = PXL8_COLOR_MODE_MEGA;
|
||||
app.resolution = PXL8_RESOLUTION_640x360;
|
||||
if (!game->hal) {
|
||||
pxl8_error("HAL must be set before calling pxl8_init");
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
game->color_mode = PXL8_COLOR_MODE_MEGA;
|
||||
game->resolution = PXL8_RESOLUTION_640x360;
|
||||
|
||||
const char* script_arg = NULL;
|
||||
bool pack_mode = false;
|
||||
|
|
@ -203,7 +39,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
|
||||
for (i32 i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--repl") == 0) {
|
||||
app.repl_mode = true;
|
||||
game->repl_mode = true;
|
||||
} else if (strcmp(argv[i], "--pack") == 0) {
|
||||
pack_mode = true;
|
||||
if (i + 2 < argc) {
|
||||
|
|
@ -211,7 +47,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
pack_output = argv[++i];
|
||||
} else {
|
||||
pxl8_error("--pack requires <folder> <output.pxc>");
|
||||
return SDL_APP_FAILURE;
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
} else if (!script_arg) {
|
||||
script_arg = argv[i];
|
||||
|
|
@ -220,39 +56,39 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
|
||||
if (pack_mode) {
|
||||
pxl8_result result = pxl8_cart_pack(pack_input, pack_output);
|
||||
return (result == PXL8_OK) ? SDL_APP_SUCCESS : SDL_APP_FAILURE;
|
||||
return (result == PXL8_OK) ? PXL8_GAME_SUCCESS : PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (app.repl_mode) {
|
||||
fprintf(stderr, "\033[38;2;184;187;38m[pxl8]\033[0m Starting in REPL mode with script: %s\n", app.script_path);
|
||||
if (game->repl_mode) {
|
||||
fprintf(stderr, "\033[38;2;184;187;38m[pxl8]\033[0m Starting in REPL mode with script: %s\n", game->script_path);
|
||||
}
|
||||
|
||||
pxl8_info("Starting up");
|
||||
|
||||
app.gfx = pxl8_gfx_create(app.color_mode, app.resolution, "pxl8", 1280, 720);
|
||||
if (!app.gfx) {
|
||||
game->gfx = pxl8_gfx_create(game->hal, game->color_mode, game->resolution, "pxl8", 1280, 720);
|
||||
if (!game->gfx) {
|
||||
pxl8_error("Failed to create graphics context");
|
||||
return SDL_APP_FAILURE;
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
if (pxl8_gfx_load_font_atlas(app.gfx) != PXL8_OK) {
|
||||
if (pxl8_gfx_load_font_atlas(game->gfx) != PXL8_OK) {
|
||||
pxl8_error("Failed to load font atlas");
|
||||
return SDL_APP_FAILURE;
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
app.ui = pxl8_ui_create(app.gfx);
|
||||
if (!app.ui) {
|
||||
game->ui = pxl8_ui_create(game->gfx);
|
||||
if (!game->ui) {
|
||||
pxl8_error("Failed to create UI");
|
||||
pxl8_gfx_destroy(app.gfx);
|
||||
return SDL_APP_FAILURE;
|
||||
pxl8_gfx_destroy(game->gfx);
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
app.script = pxl8_script_create();
|
||||
if (!app.script) {
|
||||
pxl8_error("Failed to initialize scripting: %s", pxl8_script_get_last_error(app.script));
|
||||
pxl8_gfx_destroy(app.gfx);
|
||||
return SDL_APP_FAILURE;
|
||||
game->script = pxl8_script_create();
|
||||
if (!game->script) {
|
||||
pxl8_error("Failed to initialize scripting: %s", pxl8_script_get_last_error(game->script));
|
||||
pxl8_gfx_destroy(game->gfx);
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
const char* cart_path = script_arg ? script_arg : "demo";
|
||||
|
|
@ -263,244 +99,181 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
|||
|
||||
if (is_cart) {
|
||||
char* original_cwd = getcwd(NULL, 0);
|
||||
app.cart = pxl8_cart_create();
|
||||
if (!app.cart) {
|
||||
game->cart = pxl8_cart_create();
|
||||
if (!game->cart) {
|
||||
pxl8_error("Failed to create cart");
|
||||
return false;
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
if (pxl8_cart_load(app.cart, cart_path) == PXL8_OK) {
|
||||
pxl8_script_set_cart_path(app.script, pxl8_cart_get_base_path(app.cart), original_cwd);
|
||||
pxl8_cart_mount(app.cart);
|
||||
strcpy(app.script_path, "main.fnl");
|
||||
pxl8_info("Loaded cart: %s", pxl8_cart_get_name(app.cart));
|
||||
if (pxl8_cart_load(game->cart, cart_path) == PXL8_OK) {
|
||||
pxl8_script_set_cart_path(game->script, pxl8_cart_get_base_path(game->cart), original_cwd);
|
||||
pxl8_cart_mount(game->cart);
|
||||
strcpy(game->script_path, "main.fnl");
|
||||
pxl8_info("Loaded cart: %s", pxl8_cart_get_name(game->cart));
|
||||
} else {
|
||||
pxl8_error("Failed to load cart: %s", cart_path);
|
||||
return SDL_APP_FAILURE;
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
free(original_cwd);
|
||||
} else if (script_arg) {
|
||||
strncpy(app.script_path, script_arg, sizeof(app.script_path) - 1);
|
||||
app.script_path[sizeof(app.script_path) - 1] = '\0';
|
||||
strncpy(game->script_path, script_arg, sizeof(game->script_path) - 1);
|
||||
game->script_path[sizeof(game->script_path) - 1] = '\0';
|
||||
}
|
||||
|
||||
pxl8_script_set_gfx(app.script, app.gfx);
|
||||
pxl8_script_set_input(app.script, &app.input);
|
||||
pxl8_script_set_ui(app.script, app.ui);
|
||||
pxl8_script_set_gfx(game->script, game->gfx);
|
||||
pxl8_script_set_input(game->script, &game->input);
|
||||
pxl8_script_set_ui(game->script, game->ui);
|
||||
|
||||
if (app.script_path[0] != '\0') {
|
||||
pxl8_result result = pxl8_script_load_main(app.script, app.script_path);
|
||||
app.script_loaded = (result == PXL8_OK);
|
||||
if (game->script_path[0] != '\0') {
|
||||
pxl8_result result = pxl8_script_load_main(game->script, game->script_path);
|
||||
game->script_loaded = (result == PXL8_OK);
|
||||
}
|
||||
|
||||
if (app.repl_mode) {
|
||||
pxl8_repl_init(&app.repl);
|
||||
fprintf(stderr, "\033[38;2;184;187;38m[pxl8 REPL]\033[0m Fennel %s - Tab for completions, Ctrl-C to exit\n", "1.5.1");
|
||||
if (game->repl_mode) {
|
||||
game->repl = pxl8_script_repl_create();
|
||||
if (game->repl) {
|
||||
pxl8_script_repl_init(game->repl);
|
||||
fprintf(stderr, "\033[38;2;184;187;38m[pxl8 REPL]\033[0m Fennel %s - Tab for completions, Ctrl-C to exit\n", "1.5.1");
|
||||
|
||||
if (pxl8_script_load_module(app.script, "pxl8") != PXL8_OK) {
|
||||
fprintf(stderr, "Warning: Failed to setup pxl8 global: %s\n", pxl8_script_get_last_error(app.script));
|
||||
if (pxl8_script_load_module(game->script, "pxl8") != PXL8_OK) {
|
||||
fprintf(stderr, "Warning: Failed to setup pxl8 global: %s\n", pxl8_script_get_last_error(game->script));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.last_time = SDL_GetTicksNS();
|
||||
app.running = true;
|
||||
game->last_time = game->hal->get_ticks();
|
||||
game->running = true;
|
||||
|
||||
*appstate = &app;
|
||||
return SDL_APP_CONTINUE;
|
||||
|
||||
return PXL8_GAME_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppIterate(void* appstate) {
|
||||
pxl8_state* app = (pxl8_state*)appstate;
|
||||
pxl8_bounds bounds = pxl8_gfx_get_bounds(app->gfx);
|
||||
pxl8_game_result pxl8_update(pxl8_game* game) {
|
||||
if (!game) {
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
u64 current_time = SDL_GetTicksNS();
|
||||
f32 dt = (f32)(current_time - app->last_time) / 1000000000.0f;
|
||||
u64 current_time = game->hal->get_ticks();
|
||||
f32 dt = (f32)(current_time - game->last_time) / 1000000000.0f;
|
||||
|
||||
app->last_time = current_time;
|
||||
app->time += dt;
|
||||
|
||||
pxl8_script_check_reload(app->script);
|
||||
|
||||
if (app->repl_mode) {
|
||||
pxl8_repl_command* cmd = pxl8_repl_pop_command(&app->repl);
|
||||
game->last_time = current_time;
|
||||
game->time += dt;
|
||||
|
||||
pxl8_script_check_reload(game->script);
|
||||
|
||||
if (game->repl_mode && game->repl) {
|
||||
pxl8_script_repl_command* cmd = pxl8_script_repl_pop_command(game->repl);
|
||||
if (cmd) {
|
||||
pxl8_result result = pxl8_script_eval(app->script, cmd->buffer);
|
||||
pxl8_result result = pxl8_script_eval(game->script, pxl8_script_repl_command_buffer(cmd));
|
||||
if (result != PXL8_OK) {
|
||||
pxl8_error("%s", pxl8_script_get_last_error(app->script));
|
||||
pxl8_error("%s", pxl8_script_get_last_error(game->script));
|
||||
}
|
||||
SDL_free(cmd);
|
||||
pxl8_script_repl_command_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (app->ui) {
|
||||
pxl8_ui_input_mousemove(app->ui, app->input.mouse_x, app->input.mouse_y);
|
||||
if (app->input.mouse_wheel_x != 0 || app->input.mouse_wheel_y != 0) {
|
||||
pxl8_ui_input_scroll(app->ui, app->input.mouse_wheel_x * 10, -app->input.mouse_wheel_y * 10);
|
||||
if (game->ui) {
|
||||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(game->resolution, &render_width, &render_height);
|
||||
|
||||
pxl8_ui_input_mousemove(game->ui, game->input.mouse_x, game->input.mouse_y);
|
||||
|
||||
if (game->input.mouse_wheel_x != 0 || game->input.mouse_wheel_y != 0) {
|
||||
pxl8_ui_input_scroll(game->ui, game->input.mouse_wheel_x * 10, -game->input.mouse_wheel_y * 10);
|
||||
}
|
||||
|
||||
pxl8_ui_frame_begin(app->ui);
|
||||
|
||||
for (i32 i = 0; i < 3; i++) {
|
||||
if (app->input.mouse_buttons_pressed[i]) {
|
||||
pxl8_ui_input_mousedown(app->ui, app->input.mouse_x, app->input.mouse_y, i + 1);
|
||||
if (game->input.mouse_buttons_pressed[i]) {
|
||||
pxl8_ui_input_mousedown(game->ui, game->input.mouse_x, game->input.mouse_y, i + 1);
|
||||
}
|
||||
if (app->input.mouse_buttons_released[i]) {
|
||||
pxl8_ui_input_mouseup(app->ui, app->input.mouse_x, app->input.mouse_y, i + 1);
|
||||
if (game->input.mouse_buttons_released[i]) {
|
||||
pxl8_ui_input_mouseup(game->ui, game->input.mouse_x, game->input.mouse_y, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i32 key = 0; key < 256; key++) {
|
||||
if (app->input.keys_pressed[key]) {
|
||||
pxl8_ui_input_keydown(app->ui, key);
|
||||
if (game->input.keys_pressed[key]) {
|
||||
pxl8_ui_input_keydown(game->ui, key);
|
||||
}
|
||||
if (!app->input.keys_down[key] && app->input.keys_pressed[key]) {
|
||||
pxl8_ui_input_keyup(app->ui, key);
|
||||
if (!game->input.keys_down[key] && game->input.keys_pressed[key]) {
|
||||
pxl8_ui_input_keyup(game->ui, key);
|
||||
}
|
||||
}
|
||||
|
||||
pxl8_ui_frame_begin(game->ui);
|
||||
}
|
||||
|
||||
if (app->script_loaded) {
|
||||
pxl8_script_call_function_f32(app->script, "update", dt);
|
||||
if (game->script_loaded) {
|
||||
pxl8_script_call_function_f32(game->script, "update", dt);
|
||||
}
|
||||
|
||||
pxl8_result frame_result = pxl8_script_call_function(app->script, "frame");
|
||||
return PXL8_GAME_CONTINUE;
|
||||
}
|
||||
|
||||
pxl8_game_result pxl8_frame(pxl8_game* game) {
|
||||
if (!game) {
|
||||
return PXL8_GAME_FAILURE;
|
||||
}
|
||||
|
||||
pxl8_bounds bounds = pxl8_gfx_get_bounds(game->gfx);
|
||||
|
||||
if (game->script_loaded) {
|
||||
pxl8_result frame_result = pxl8_script_call_function(game->script, "frame");
|
||||
if (frame_result == PXL8_ERROR_SCRIPT_ERROR) {
|
||||
pxl8_error("Error calling frame: %s", pxl8_script_get_last_error(app->script));
|
||||
pxl8_error("Error calling frame: %s", pxl8_script_get_last_error(game->script));
|
||||
}
|
||||
} else {
|
||||
pxl8_clr(app->gfx, 32);
|
||||
pxl8_clr(game->gfx, 32);
|
||||
|
||||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(app->resolution, &render_width, &render_height);
|
||||
pxl8_gfx_get_resolution_dimensions(game->resolution, &render_width, &render_height);
|
||||
|
||||
for (i32 y = 0; y < render_height; y += 24) {
|
||||
for (i32 x = 0; x < render_width; x += 32) {
|
||||
u32 color = ((x / 32) + (y / 24) + (i32)(app->time * 2)) % 8;
|
||||
pxl8_rect_fill(app->gfx, x, y, 31, 23, color);
|
||||
u32 color = ((x / 32) + (y / 24) + (i32)(game->time * 2)) % 8;
|
||||
pxl8_rect_fill(game->gfx, x, y, 31, 23, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(app->resolution, &render_width, &render_height);
|
||||
pxl8_gfx_get_resolution_dimensions(game->resolution, &render_width, &render_height);
|
||||
|
||||
if (app->ui) {
|
||||
pxl8_ui_frame_end(app->ui);
|
||||
if (game->ui) {
|
||||
pxl8_ui_frame_end(game->ui);
|
||||
}
|
||||
|
||||
pxl8_gfx_set_viewport(app->gfx, pxl8_gfx_viewport(bounds, render_width, render_height));
|
||||
pxl8_gfx_upload_framebuffer(app->gfx);
|
||||
pxl8_gfx_upload_atlas(app->gfx);
|
||||
pxl8_gfx_present(app->gfx);
|
||||
pxl8_gfx_set_viewport(game->gfx, pxl8_gfx_viewport(bounds, render_width, render_height));
|
||||
pxl8_gfx_upload_framebuffer(game->gfx);
|
||||
pxl8_gfx_upload_atlas(game->gfx);
|
||||
pxl8_gfx_present(game->gfx);
|
||||
|
||||
SDL_memset(app->input.keys_pressed, 0, sizeof(app->input.keys_pressed));
|
||||
SDL_memset(app->input.keys_released, 0, sizeof(app->input.keys_released));
|
||||
SDL_memset(app->input.mouse_buttons_pressed, 0, sizeof(app->input.mouse_buttons_pressed));
|
||||
SDL_memset(app->input.mouse_buttons_released, 0, sizeof(app->input.mouse_buttons_released));
|
||||
app->input.mouse_wheel_x = 0;
|
||||
app->input.mouse_wheel_y = 0;
|
||||
memset(game->input.keys_pressed, 0, sizeof(game->input.keys_pressed));
|
||||
memset(game->input.keys_released, 0, sizeof(game->input.keys_released));
|
||||
memset(game->input.mouse_buttons_pressed, 0, sizeof(game->input.mouse_buttons_pressed));
|
||||
memset(game->input.mouse_buttons_released, 0, sizeof(game->input.mouse_buttons_released));
|
||||
game->input.mouse_wheel_x = 0;
|
||||
game->input.mouse_wheel_y = 0;
|
||||
|
||||
return app->running ? SDL_APP_CONTINUE : SDL_APP_SUCCESS;
|
||||
return game->running ? PXL8_GAME_CONTINUE : PXL8_GAME_SUCCESS;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
|
||||
pxl8_state* app = (pxl8_state*)appstate;
|
||||
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_QUIT:
|
||||
app->running = false;
|
||||
return SDL_APP_SUCCESS;
|
||||
|
||||
case SDL_EVENT_KEY_DOWN: {
|
||||
if (event->key.key == SDLK_ESCAPE) {
|
||||
app->running = false;
|
||||
return SDL_APP_SUCCESS;
|
||||
}
|
||||
void pxl8_quit(pxl8_game* game) {
|
||||
if (!game) return;
|
||||
|
||||
SDL_Scancode scancode = event->key.scancode;
|
||||
if (scancode < 256) {
|
||||
if (!app->input.keys_down[scancode]) {
|
||||
app->input.keys_pressed[scancode] = true;
|
||||
}
|
||||
app->input.keys_down[scancode] = true;
|
||||
app->input.keys_released[scancode] = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pxl8_info("Shutting down");
|
||||
|
||||
case SDL_EVENT_KEY_UP: {
|
||||
SDL_Scancode scancode = event->key.scancode;
|
||||
if (scancode < 256) {
|
||||
app->input.keys_down[scancode] = false;
|
||||
app->input.keys_pressed[scancode] = false;
|
||||
app->input.keys_released[scancode] = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||
u8 button = event->button.button - 1;
|
||||
if (button < 3) {
|
||||
if (!app->input.mouse_buttons_down[button]) {
|
||||
app->input.mouse_buttons_pressed[button] = true;
|
||||
}
|
||||
app->input.mouse_buttons_down[button] = true;
|
||||
app->input.mouse_buttons_released[button] = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||
u8 button = event->button.button - 1;
|
||||
if (button < 3) {
|
||||
app->input.mouse_buttons_down[button] = false;
|
||||
app->input.mouse_buttons_pressed[button] = false;
|
||||
app->input.mouse_buttons_released[button] = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_MOTION: {
|
||||
i32 window_mouse_x = (i32)event->motion.x;
|
||||
i32 window_mouse_y = (i32)event->motion.y;
|
||||
|
||||
i32 render_width, render_height;
|
||||
pxl8_gfx_get_resolution_dimensions(app->resolution, &render_width, &render_height);
|
||||
pxl8_viewport vp = pxl8_gfx_viewport(pxl8_gfx_get_bounds(app->gfx), render_width, render_height);
|
||||
|
||||
app->input.mouse_x = (i32)((window_mouse_x - vp.offset_x) / vp.scale);
|
||||
app->input.mouse_y = (i32)((window_mouse_y - vp.offset_y) / vp.scale);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_WHEEL: {
|
||||
app->input.mouse_wheel_x = (i32)event->wheel.x;
|
||||
app->input.mouse_wheel_y = (i32)event->wheel.y;
|
||||
break;
|
||||
}
|
||||
if (game->repl_mode && game->repl) {
|
||||
pxl8_script_repl_shutdown(game->repl);
|
||||
pxl8_script_repl_destroy(game->repl);
|
||||
}
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
void SDL_AppQuit(void* appstate, SDL_AppResult result) {
|
||||
pxl8_state* app = (pxl8_state*)appstate;
|
||||
(void)result;
|
||||
|
||||
if (app) {
|
||||
pxl8_info("Shutting down");
|
||||
if (app->repl_mode) {
|
||||
pxl8_repl_shutdown(&app->repl);
|
||||
}
|
||||
if (app->cart) {
|
||||
pxl8_cart_unload(app->cart);
|
||||
free(app->cart);
|
||||
app->cart = NULL;
|
||||
}
|
||||
pxl8_script_destroy(app->script);
|
||||
if (app->ui) {
|
||||
pxl8_ui_destroy(app->ui);
|
||||
}
|
||||
pxl8_gfx_destroy(app->gfx);
|
||||
if (game->cart) {
|
||||
pxl8_cart_unload(game->cart);
|
||||
free(game->cart);
|
||||
game->cart = NULL;
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
pxl8_gfx_destroy(game->gfx);
|
||||
pxl8_script_destroy(game->script);
|
||||
if (game->ui) pxl8_ui_destroy(game->ui);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue