summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt24
-rw-r--r--docs/input-handling.md1
-rw-r--r--include/engine/engine.h1
-rw-r--r--include/engine/input.h30
-rw-r--r--include/engine/state.h9
-rw-r--r--src/engine.c6
-rw-r--r--src/input.c2
-rw-r--r--src/state.c120
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