From 378f91b70c54cc111684f4a3a8f2b868af570fd8 Mon Sep 17 00:00:00 2001 From: 0scar Date: Wed, 2 Aug 2023 16:17:17 +0200 Subject: Add reloading of state-specific keybindings bindings --- src/engine.c | 6 +-- src/input.c | 2 +- src/state.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 122 insertions(+), 6 deletions(-) (limited to 'src') 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 + #include #include #include +#include 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 @@ -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 -- cgit v1.3