From: Lukas Krickl Date: Sun, 1 Mar 2026 15:04:29 +0000 (+0100) Subject: input: Added basic input mapping system from platform backend to engine X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=1f287b473ac9ce4c0cb04cbc4d9a48e34024c846;p=lrts%2F.git input: Added basic input mapping system from platform backend to engine This allows a generic action struct to keep the user input state. The platform is currently in charge of setting the button states based on scan codes and modifier keys. A history of previous states is kept to allow detection of keys being just pressed or held. Added mouse cursor postion. --- diff --git a/src/i_input.c b/src/i_input.c index 24d0ecd..903d97b 100644 --- a/src/i_input.c +++ b/src/i_input.c @@ -1,7 +1,91 @@ #include "i_input.h" -struct i_cursor i_cursor; -struct i_keyboard i_keyboard; +/* TODO: change api so that this calls the platform backend + * with specific actions that are expected */ + +struct i_input_map i_input_map; void i_input_init(void) { + p_input_set_default_map(); + + + /* TODO read key map from config file */ +} + +struct i_input_map_ent* i_input_find_ent(u16 scan_code, lrts_bool mod_shift, + lrts_bool mod_alt, lrts_bool mod_ctrl, lrts_bool mod_super) { + u32 i = 0; + struct i_input_map_ent *ent = LRTS_NULL; + for (i = 0; i < I_INPUT_ACTION_LEN; i++) { + ent = &i_input_map.inputs[i]; + + if (ent->scan_code == scan_code + && ent->mod_shift == mod_shift + && ent->mod_alt == mod_alt + && ent->mod_ctrl == mod_ctrl + && ent->mod_super == mod_super) { + return ent; + } + } + + return LRTS_NULL; +} + +void i_input_set(u16 scan_code, lrts_bool mod_shift, lrts_bool mod_alt, lrts_bool mod_ctrl, lrts_bool mod_super) { + struct i_input_map_ent *ent = i_input_find_ent(scan_code, mod_shift, mod_alt, mod_ctrl, mod_super); + if (ent == LRTS_NULL) { + return; + } + ent->held = 1; +} + +void i_input_unset(u16 scan_code, lrts_bool mod_shift, lrts_bool mod_alt, lrts_bool mod_ctrl, lrts_bool mod_super) { + struct i_input_map_ent *ent = i_input_find_ent(scan_code, mod_shift, mod_alt, mod_ctrl, mod_super); + if (ent == LRTS_NULL) { + return; + } + ent->held = 0; +} + +void i_input_update(void) { + u32 i = 0; + /* move all pressed events over one position */ + for (i = 0; i < I_INPUT_ACTION_LEN; i++) { + i_input_map.inputs[i].pressed <<= 1; + i_input_map.inputs[i].pressed |= i_input_map.inputs[i].held; + } +} + +void i_input_cursor_set(i32 x, i32 y) { + i_input_map.cursor_x = x; + i_input_map.cursor_y = y; +} + +void i_input_cursor_click_set(void) { + i_input_map.inputs[I_INPUT_ACTION_CURSOR_CLICK].held = 1; +} + +void i_input_cursor_drag_set(void) { + i_input_map.inputs[I_INPUT_ACTION_CURSOR_DRAG].held = 1; +} + +void i_input_cursor_action_set(void) { + i_input_map.inputs[I_INPUT_ACTION_CURSOR_ACTION].held = 1; +} + +void i_input_cursor_click_unset(void) { + i_input_map.inputs[I_INPUT_ACTION_CURSOR_CLICK].held = 0; +} + +void i_input_cursor_drag_unset(void) { + i_input_map.inputs[I_INPUT_ACTION_CURSOR_DRAG].held = 0; +} + +void i_input_cursor_action_unset(void) { + i_input_map.inputs[I_INPUT_ACTION_CURSOR_ACTION].held = 0; +} + +void i_input_poll(void) { + p_poll_events(); + i_input_update(); } diff --git a/src/i_input.h b/src/i_input.h index 9c166ac..b9a1204 100644 --- a/src/i_input.h +++ b/src/i_input.h @@ -9,67 +9,92 @@ * be translated to action commands. */ -#define I_CURSOR_BUTTONS 3 -#define I_KEYBOARD_KEYS 128 - -enum i_button_state { - I_BUTTON_RELEASE = 0, - I_BUTTON_JUST_PRESSED = 1, - I_BUTTON_HELD = 2 +/* describes all possible input actions */ +enum i_input_actions { + I_INPUT_ACTION_CAMERA_UP, + I_INPUT_ACTION_CAMERA_DOWN, + I_INPUT_ACTION_CAMERA_LEFT, + I_INPUT_ACTION_CAMERA_RIGHT, + + /* left click on target */ + I_INPUT_ACTION_CURSOR_CLICK, + /* primary action when right clicking */ + I_INPUT_ACTION_CURSOR_ACTION, + + /* middle mouse drag */ + I_INPUT_ACTION_CURSOR_DRAG, + + /* not a real entry just the length of the action list */ + I_INPUT_ACTION_LEN }; - -/* describes the current cursor state */ -struct i_cursor { - struct u_vec2 pos; - - enum i_button_state buttons[I_CURSOR_BUTTONS]; +/* input entry */ +struct i_input_map_ent { + /* this is a platform specific button + * code to this input action + */ + u16 scan_code; + + /* possible modifiers for the input map entry */ + lrts_bool mod_shift; + lrts_bool mod_alt; + lrts_bool mod_ctrl; + lrts_bool mod_super; + + /* bit field for pressed state + * every frame this is shifted over by 1 bit + * the most recent state is in the rightmost bit + */ + u16 pressed; + u16 held; }; -enum i_arrow_keys { - I_ARROW_UP = 0, - I_ARROW_DOWN, - I_ARROW_LEFT, - I_ARROW_RIGHT, - I_ARROW_LEN +/* map of all input actions to scanscodes */ +struct i_input_map { + struct i_input_map_ent inputs[I_INPUT_ACTION_LEN]; + + /* screen position of cursor */ + i32 cursor_x; + i32 cursor_y; }; -#define I_FKEYS_LEN 12 +extern struct i_input_map i_input_map; -struct i_keyboard { - enum i_button_state esc; - enum i_button_state shift; - enum i_button_state ctrl; - enum i_button_state alt; - enum i_button_state super; - enum i_button_state enter; - enum i_button_state space; - enum i_button_state backspace; - enum i_button_state arrow[I_ARROW_LEN]; +void i_input_init(void); - enum i_button_state del; - enum i_button_state home; - enum i_button_state end; - enum i_button_state pgup; - enum i_button_state pgdown; - enum i_button_state insert; +/* sets an input to held + * the scancode and modifiers have to match + * if no event map is present the event is dropped + * This should be called by the platforms event polling function + * to pass events as inputs to the engine + * should be called by p_poll_events + */ +void i_input_set(u16 scan_code, lrts_bool mod_shift, lrts_bool mod_alt, lrts_bool mod_ctrl, lrts_bool mod_super); - enum i_button_state tab; +/* unsets held state + */ +void i_input_unset(u16 scan_code, lrts_bool mod_shift, lrts_bool mod_alt, lrts_bool mod_ctrl, lrts_bool mod_super); - enum i_button_state print; - enum i_button_state pause; +/* updates input history by shifting pressed bitfield over by 1 and oring it with the held state */ +void i_input_update(void); - enum i_button_state fkey[I_FKEYS_LEN]; +/* sets cursor positon + * should be called by p_poll_events + */ +void i_input_cursor_set(i32 x, i32 y); - /* ascii table for all other keys */ - enum i_button_state keys[I_KEYBOARD_KEYS]; -}; +void i_input_cursor_click_set(void); +void i_input_cursor_drag_set(void); +void i_input_cursor_action_set(void); -/* primary IO devices */ -extern struct i_cursor i_cursor; -extern struct i_keyboard i_keyboard; +void i_input_cursor_click_unset(void); +void i_input_cursor_drag_unset(void); +void i_input_cursor_action_unset(void); -void i_input_init(void); +/* polls input from system backend + * and translates the input to commands + */ +void i_input_poll(void); #endif diff --git a/src/lrts.c b/src/lrts.c index aebc6e3..9a7f5ec 100644 --- a/src/lrts.c +++ b/src/lrts.c @@ -106,7 +106,7 @@ int lrts_main(int argc, char **argv) { p_render_init_framebuffer(); while (!lrts_cfg()->exit) { - p_poll_events(); + i_input_poll(); t_sim_update(); r_render_frame(); } diff --git a/src/p_platform.h b/src/p_platform.h index dd50baa..2817e0f 100644 --- a/src/p_platform.h +++ b/src/p_platform.h @@ -62,7 +62,17 @@ void p_delay(u64 time); /** * polls input events * should be called once a frame + * + * should call: + * i_input_cursor_set + * i_input_set */ int p_poll_events(); +/** + * Allow the platform to set up a default + * keymap + */ +void p_input_set_default_map(); + #endif diff --git a/src/p_r_sdl/p_window.c b/src/p_r_sdl/p_window.c index 249e54a..ecc1d2b 100644 --- a/src/p_r_sdl/p_window.c +++ b/src/p_r_sdl/p_window.c @@ -1,15 +1,66 @@ SDL_Window *p_main_window; #include "../u_defs.h" +#include "../i_input.h" SDL_Surface *r_target; +void p_input_set_default_map() { + i_input_map.inputs[I_INPUT_ACTION_CAMERA_UP].scan_code = SDL_SCANCODE_UP; + i_input_map.inputs[I_INPUT_ACTION_CAMERA_DOWN].scan_code = SDL_SCANCODE_DOWN; + i_input_map.inputs[I_INPUT_ACTION_CAMERA_LEFT].scan_code = SDL_SCANCODE_LEFT; + i_input_map.inputs[I_INPUT_ACTION_CAMERA_RIGHT].scan_code = SDL_SCANCODE_RIGHT; +} + int p_poll_events() { SDL_Event e; + float x, y; + while (SDL_PollEvent(&e)) { - if (e.type == SDL_EVENT_QUIT) { - lrts_cfg()->exit = LRTS_TRUE; + switch (e.type) { + case SDL_EVENT_QUIT: + lrts_cfg()->exit = LRTS_TRUE; + break; + case SDL_EVENT_KEY_DOWN: + i_input_set(e.key.scancode, + (e.key.mod & (SDL_KMOD_LSHIFT | SDL_KMOD_RSHIFT)) != 0, + (e.key.mod & (SDL_KMOD_LALT | SDL_KMOD_RALT)) != 0, + (e.key.mod & (SDL_KMOD_LCTRL | SDL_KMOD_RCTRL)) != 0, + (e.key.mod & (SDL_KMOD_LGUI | SDL_KMOD_RGUI)) != 0 + ); + break; + case SDL_EVENT_KEY_UP: + i_input_unset(e.key.scancode, + (e.key.mod & (SDL_KMOD_LSHIFT | SDL_KMOD_RSHIFT)) != 0, + (e.key.mod & (SDL_KMOD_LALT | SDL_KMOD_RALT)) != 0, + (e.key.mod & (SDL_KMOD_LCTRL | SDL_KMOD_RCTRL)) != 0, + (e.key.mod & (SDL_KMOD_LGUI | SDL_KMOD_RGUI)) != 0 + ); + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + if (e.button.button == SDL_BUTTON_LEFT) { + i_input_cursor_click_set(); + } else if (e.button.button == SDL_BUTTON_MIDDLE) { + i_input_cursor_drag_set(); + } else if (e.button.button == SDL_BUTTON_RIGHT) { + i_input_cursor_action_set(); + } + break; + case SDL_EVENT_MOUSE_BUTTON_UP: + if (e.button.button == SDL_BUTTON_LEFT) { + i_input_cursor_click_unset(); + } else if (e.button.button == SDL_BUTTON_MIDDLE) { + i_input_cursor_drag_unset(); + } else if (e.button.button == SDL_BUTTON_RIGHT) { + i_input_cursor_action_unset(); + } + break; } + } + + SDL_GetMouseState(&x, &y); + i_input_cursor_set(x, y); + return 0; }