#include "scripting.h" #include "util.h" #include "context.h" #include #include #include #include #include #include static void msgbox(UmkaStackSlot *params, UmkaStackSlot *result) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, params[1].ptrVal, params[0].ptrVal, NULL); } static void umka_log_info(UmkaStackSlot *params, UmkaStackSlot *result) { log_info(params[0].ptrVal); } static void umka_log_critical(UmkaStackSlot *params, UmkaStackSlot *result) { log_critical(params[0].ptrVal); } static void umka_log_warn(UmkaStackSlot *params, UmkaStackSlot *result) { log_warn(params[0].ptrVal); } static void is_action_pressed(UmkaStackSlot *params, UmkaStackSlot *result) { struct state *state = params[1].ptrVal; t_ctx *ctx = state->hidden_ptr; bool value = input_is_action_pressed(&ctx->input, params[0].ptrVal); result->uintVal = value; } static void is_action_just_pressed(UmkaStackSlot *params, UmkaStackSlot *result) { struct state *state = params[1].ptrVal; t_ctx *ctx = state->hidden_ptr; bool value = input_is_action_just_pressed(&ctx->input, params[0].ptrVal); result->uintVal = value; } static void is_action_just_released(UmkaStackSlot *params, UmkaStackSlot *result) { struct state *state = params[1].ptrVal; t_ctx *ctx = state->hidden_ptr; bool value = input_is_action_just_released(&ctx->input, params[0].ptrVal); result->uintVal = value; } static void get_action_position(UmkaStackSlot *params, UmkaStackSlot *result) { struct state *state = params[2].ptrVal; t_ctx *ctx = state->hidden_ptr; t_fvec2 *position = params[0].ptrVal; *position = input_get_action_position(&ctx->input, params[1].ptrVal); // the result is in a hidden result pointer allocated by Umka result->ptrVal = params[0].ptrVal; } static void register_api(void *umka) { umkaAddFunc(umka, "msgbox", msgbox); umkaAddFunc(umka, "logInfo", umka_log_info); umkaAddFunc(umka, "logCritical", umka_log_critical); umkaAddFunc(umka, "logWarn", umka_log_warn); umkaAddFunc(umka, "cImplIsActionPressed", is_action_pressed); umkaAddFunc(umka, "cImplIsActionJustPressed", is_action_just_pressed); umkaAddFunc(umka, "cImplIsActionJustReleased", is_action_just_released); umkaAddFunc(umka, "getActionPosition", get_action_position); } bool scripting_init(t_ctx *ctx) { if (!PHYSFS_exists("/scripts/main.um")) { CRY("Failed to initialize scripting", "Could not find a main.um (we need it)"); return false; } ctx->umka = umkaAlloc(); char *main_script = file_to_str("/scripts/main.um"); bool umka_ok = umkaInit(ctx->umka, "main.um", main_script, UMKA_STACK_SIZE, NULL, ctx->argc, ctx->argv, false, false, NULL); free(main_script); if (!umka_ok) { CRY("Failed to initialize scripting", "Unknown Umka error"); return false; } /* all Umka files are compiled even if they're never used */ char **dir_file_names = PHYSFS_enumerateFiles("/scripts"); for (char **i = dir_file_names; *i != NULL; ++i) { char *file_name = *i; if (!strends(file_name, ".um")) continue; /* got this one already */ if (strcmp(file_name, "main.um") == 0) continue; /* need to figure out the actual path (as opposed to the lone file name) */ const char *path_prefix = "/scripts/"; size_t path_size = snprintf(NULL, 0, "%s%s", path_prefix, file_name) + 1; char *path = cmalloc(path_size); snprintf(path, path_size, "%s%s", path_prefix, file_name); char *contents = file_to_str(path); umkaAddModule(ctx->umka, file_name, contents); free(path); free(contents); } PHYSFS_freeList(dir_file_names); register_api(ctx->umka); if (!umkaCompile(ctx->umka)) { cry_umka(ctx->umka); return false; } return true; } void scripting_deinit(t_ctx *ctx) { umkaFree(ctx->umka); }