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.
#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();
}
* 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
p_render_init_framebuffer();
while (!lrts_cfg()->exit) {
- p_poll_events();
+ i_input_poll();
t_sim_update();
r_render_frame();
}
/**
* 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
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;
}