diff options
| -rw-r--r-- | CMakeLists.txt | 24 | ||||
| -rw-r--r-- | docs/input-handling.md | 1 | ||||
| -rw-r--r-- | include/engine/engine.h | 1 | ||||
| -rw-r--r-- | include/engine/input.h | 30 | ||||
| -rw-r--r-- | include/engine/state.h | 9 | ||||
| -rw-r--r-- | src/engine.c | 6 | ||||
| -rw-r--r-- | src/input.c | 2 | ||||
| -rw-r--r-- | src/state.c | 120 |
8 files changed, 169 insertions, 24 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e93f70..7e3c2fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,16 @@ if(DAW_BUILD_UBSAN AND DAW_BUILD_ASAN) message(FATAL_ERROR "You cannot build both asan and ubsan") endif() +if(DAW_BUILD_DEBUG) + set(BUILD_OPTS -Og -ggdb3 -fno-omit-frame-pointer) +else() + set(BUILD_OPTS -O2 -flto=auto -fuse-linker-plugin -ffat-lto-objects + -funroll-loops -ffast-math -fno-signed-zeros -fno-trapping-math + -ffunction-sections -fdata-sections) +endif() + +## + set(ENGINE_SOURCES src/btree.c src/dltools.c @@ -76,6 +86,9 @@ set(ENGINE_SOURCES src/vector.c ) +add_compile_options(${RELEASE_OPTS}) +add_link_options(${RELEASE_OPTS}) + add_library(daw ${ENGINE_SOURCES}) @@ -102,17 +115,6 @@ if(DAW_BUILD_UBSAN AND NOT C_COMPILER_ID STREQUAL MSVC) add_link_options(-fsanitize=undefined -fsanitize-undefined-trap-on-error -fno-sanitize-recover) endif() -if(DAW_BUILD_DEBUG) - set(BUILD_OPTS -Og -ggdb3 -fno-omit-frame-pointer) -else() - set(BUILD_OPTS -O2 -flto=auto -fuse-linker-plugin -ffat-lto-objects - -funroll-loops -ffast-math -fno-signed-zeros -fno-trapping-math - -ffunction-sections -fdata-sections) -endif() - -add_compile_options(${RELEASE_OPTS}) -add_link_options(${RELEASE_OPTS}) - target_compile_options(${PROJECT_NAME} PUBLIC $<$<NOT:$<C_COMPILER_ID:MSVC>>:-Wall -Wextra> # Dont be pedantic when using hot reloading. diff --git a/docs/input-handling.md b/docs/input-handling.md index effb69c..9355122 100644 --- a/docs/input-handling.md +++ b/docs/input-handling.md @@ -5,6 +5,7 @@ _This document serves as a low-level explanation of how the input system works_ ```C typedef enum InputType InputType; enum InputType { + InputType_error, // fire once, ie. keydown. stuff like spells, semi-automatic InputType_action, // active while pressed, deactivate once released. Ignore key-repeat. stuff like running diff --git a/include/engine/engine.h b/include/engine/engine.h index cf2283f..d3c3e87 100644 --- a/include/engine/engine.h +++ b/include/engine/engine.h @@ -84,6 +84,7 @@ void engine_stop(Platform *p); void engine_fps_max(u64 cap); void engine_input_ctx_push(i_ctx *ctx); void engine_input_ctx_pop(void); +void engine_input_ctx_reset(void); void render_set_zoom(f32 new_zoom); void render_adjust_zoom(f32 diff); diff --git a/include/engine/input.h b/include/engine/input.h index d200e62..918312e 100644 --- a/include/engine/input.h +++ b/include/engine/input.h @@ -48,7 +48,7 @@ typedef struct i_ctx { } i_ctx; void i_flush_bindings(usize numcalls, void* state_mem, input_callback_t* c[]); -action_t i_get_action(const i_ctx *ctx, u32 time, scancode_t scancode); +action_t i_get_action(const i_ctx *restrict ctx, u32 time, scancode_t scancode); #define BindAction(key, altkey, f_action) \ (binding_t){\ @@ -76,4 +76,32 @@ action_t i_get_action(const i_ctx *ctx, u32 time, scancode_t scancode); .since_last_activation = 0\ } +// Lazy binds, used internally +#define BindActionLazy(key, altkey, action_str) \ + (binding_t){\ + .action = (action_t){.action = {\ + .type = InputType_action,\ + .callback = NULL,\ + .callback_str = action_str,\ + }},\ + .scancode = key,\ + .scancode_alt = altkey,\ + .since_last_activation = 0\ +} + +#define BindStateLazy(key, altkey, _activate_str , _deactivate_str) \ + (binding_t){\ + .action = (action_t){.state = {\ + .type = InputType_state,\ + .activate = NULL,\ + .deactivate = NULL,\ + .activate_str = _activate_str,\ + .deactivate_str = _deactivate_str,\ + }},\ + .scancode = key,\ + .scancode_alt = altkey,\ + .since_last_activation = 0\ +} + + #endif diff --git a/include/engine/state.h b/include/engine/state.h index 68228b1..9c832f5 100644 --- a/include/engine/state.h +++ b/include/engine/state.h @@ -22,14 +22,11 @@ StateType State_update(StateType type, memory *mem); /* Reloads shared object file associated with state */ #ifdef DAW_BUILD_HOTRELOAD -bool State_reload(StateType type); - -#define get_statelib_var(type) libstate_##name -#define State_load_binding(type, function_name) dynamic_library_get_symbol(get_statelib_var(type), #function_name) +#include <engine/input.h> +bool State_reload(StateType type, i_ctx **ctx, usize ctx_len); #else -#define State_reload(_) true -#define State_load_binding(_, __) true +#define State_reload(_, _0, _1) true #endif #endif diff --git a/src/engine.c b/src/engine.c index 677cb3f..d6064de 100644 --- a/src/engine.c +++ b/src/engine.c @@ -379,7 +379,7 @@ Platform *engine_init( #ifdef DAW_BUILD_HOTRELOAD #define State(name) \ -if (!State_reload(STATE_##name)) { \ +if (!State_reload(STATE_##name, p->bindings, p->bindings_len)) { \ ERROR("Failed to reload shared object file for state %s", #name ); \ }; @@ -579,7 +579,7 @@ i32 engine_run(Platform *p, StateType initial_state) { case SDL_KEYDOWN: if (e[i].key.keysym.sym == SDLK_F7) { INFO("Reloading %s", StateTypeStr[state]); - if (!State_reload(state)) { + if (! State_reload(state, p->bindings, p->bindings_len) ) { ERROR("Failed to reload state library!"); } else { update_func = State_updateFunc(state); @@ -648,7 +648,7 @@ i32 engine_run(Platform *p, StateType initial_state) { State_free(state, mem); memory_clear(mem); - p->bindings_len = 0; + engine_input_ctx_reset(); state = next_state; update_func = State_updateFunc(state); diff --git a/src/input.c b/src/input.c index 6b02ad7..d53e7ed 100644 --- a/src/input.c +++ b/src/input.c @@ -74,7 +74,7 @@ void i_flush_bindings(usize numcalls, void* state_mem, input_callback_t* c[]) { } } -action_t i_get_action(const i_ctx *ctx, u32 time, scancode_t scancode) { +action_t i_get_action(const i_ctx *restrict ctx, u32 time, scancode_t scancode) { isize idx = 0; if (ctx == NULL) { diff --git a/src/state.c b/src/state.c index baf67c6..bfc4416 100644 --- a/src/state.c +++ b/src/state.c @@ -1,6 +1,9 @@ +#include <string.h> + #include <engine/state.h> #include <engine/logging.h> #include <engine/dltools.h> +#include <engine/input.h> typedef StateType state_update_t(void*); @@ -132,8 +135,117 @@ StateType State_update(StateType type, memory *mem) { return next_state; } +bool state_refresh_input_ctx(void *lib, i_ctx **ctx, usize ctx_len) { + if (ctx == NULL) return true; + if (ctx_len > 0 && ctx[0] == NULL) return false; + if (lib == NULL) return false; + + for (usize c = 0; c < ctx_len; c++) { + LOG("ctx[%d]->len = %d", c, ctx[c]->len); + for (isize b = 0; b < ctx[c]->len; b++) { + switch (ctx[c]->bindings[b].action.type) { + case InputType_error: + break; + case InputType_action: + if (strcmp("NULL", ctx[c]->bindings[b].action.action.callback_str) != 0) { + + ctx[c]->bindings[b].action.action.callback = + (input_callback_t*)dynamic_library_get_symbol(lib, ctx[c]->bindings[b].action.action.callback_str); + + if (ctx[c]->bindings[b].action.action.callback == NULL) { + ERROR("Failed to get binding for %s: %s", + ctx[c]->bindings[b].action.action.callback_str, + dynamic_library_get_error()); + return false; + } + } + break; + case InputType_state: + if (strcmp("NULL", ctx[c]->bindings[b].action.state.activate_str) != 0) { + + ctx[c]->bindings[b].action.state.activate = + (input_callback_t*)dynamic_library_get_symbol(lib, ctx[c]->bindings[b].action.state.activate_str); + + if (ctx[c]->bindings[b].action.state.activate == NULL) { + ERROR("Failed to get binding for %s: %s", + ctx[c]->bindings[b].action.state.activate_str, + dynamic_library_get_error()); + return false; + } + } + + if (strcmp("NULL", ctx[c]->bindings[b].action.state.deactivate_str) != 0) { + + ctx[c]->bindings[b].action.state.deactivate = + (input_callback_t*)dynamic_library_get_symbol(lib, ctx[c]->bindings[b].action.state.deactivate_str); + + if (ctx[c]->bindings[b].action.state.deactivate == NULL) { + ERROR("Failed to get binding for %s: %s", + ctx[c]->bindings[b].action.state.deactivate_str, + dynamic_library_get_error()); + return false; + } + } + break; + case InputType_range: + default: + break; + } + } + } + + return true; +} + +/* IMPLEMENT CPY(dst,src) FOR THE SAME TYPE, SO WE CAN OVERRIDE THE OLD ONE AND + * FREE UP `ret->bindings` AND `ret` */ +i_ctx* i_ctx_dup(i_ctx **ctx, usize ctx_len) { + usize num_binds = 0; + for (usize c = 0; c < ctx_len; c++) { + num_binds += ctx[c]->len; + } + + binding_t *bb = calloc(num_binds, sizeof(binding_t)); + i_ctx *ret = calloc(ctx_len, sizeof(i_ctx)); + + usize cumsum = 0; + for (usize c = 0; c < ctx_len; c++) { + binding_t *b = ctx[c]->bindings; + ret[c].len = ctx[c]->len; + ret[c].bindings = &bb[cumsum]; + + for (isize i = 0; i < ctx[c]->len; i++) { + switch (b[i].action.type) { + case InputType_error: + break; + case InputType_action: + bb[cumsum] = BindActionLazy( + b[i].scancode, + b[i].scancode_alt, + b[i].action.action.callback_str); + break; + case InputType_state: + bb[cumsum] = BindStateLazy( + b[i].scancode, + b[i].scancode_alt, + b[i].action.state.activate_str, + b[i].action.state.deactivate_str); + break; + case InputType_range: + default: + break; + } + cumsum++; + } + } + return ret; +} + #ifdef DAW_BUILD_HOTRELOAD -bool State_reload(StateType type) { +bool State_reload(StateType type, i_ctx **ctx, usize ctx_len) { + void* libptr = NULL; + //i_ctx* ctx_cpy = i_ctx_dup(ctx, ctx_len); + switch (type) { #define State(name) \ case (STATE_##name): { \ @@ -153,6 +265,7 @@ bool State_reload(StateType type) { name##_init = (state_##name##_init_t*)dynamic_library_get_symbol(libstate_##name, STR( name##_init ) ); \ name##_free = (state_##name##_free_t*)dynamic_library_get_symbol(libstate_##name, STR( name##_free ) ); \ name##_update = (state_##name##_update_t*)dynamic_library_get_symbol(libstate_##name, STR( name##_update ) ); \ + libptr = libstate_##name; \ break; \ } #include <states/list_of_states.h> @@ -161,10 +274,13 @@ bool State_reload(StateType type) { case STATE_quit: ERROR("Invalid state"); DEBUG("Got %s state.\n", StateTypeStr[type]); - break; + return false; default: exit(EXIT_FAILURE); } + state_refresh_input_ctx(libptr, ctx, ctx_len); + //state_refresh_input_ctx(libptr, &ctx_cpy, ctx_len); + //ctx = &ctx_cpy; return true; } #endif |
