#include "input.h" #include "debug.h" #include <stdint.h> typedef struct InputAction { const uint8_t* positive; const uint8_t* negative; int last; InputActionDelegate delegate; } InputAction; static InputAction* _actions = NULL; static size_t _actions_len = 0; static size_t _actions_cap = 0; static const uint8_t* _keys; void input_init() { _actions = malloc(8 * sizeof(InputAction)); if(_actions == NULL) { LOG_ERROR("Failed to allocate memory for input actions array"); return; } _actions_cap = 8; _keys = SDL_GetKeyboardState(NULL); } void input_clean() { free(_actions); _actions_len = 0; _actions_cap = 0; } static void _key_changed_event(SDL_Event evt) { const uint8_t* keyptr = _keys + evt.key.keysym.scancode; for(InputAction* action = _actions; action < _actions + _actions_len; ++action) { if(keyptr == action->positive || keyptr == action->negative) { int val = *action->positive - *action->negative; if(val != action->last) { action->last = val; action->delegate(val); } } } } void input_handle_event(SDL_Event event) { switch(event.type) { default:return; case SDL_KEYDOWN: case SDL_KEYUP: _key_changed_event(event); break; } } static void _resize_actions_if_needed(size_t needed_amount) { if(_actions_cap > needed_amount) return; size_t next_amount = _actions_cap; while(next_amount <= needed_amount) { next_amount *= 2; } InputAction* new = realloc(_actions, next_amount); if(new == NULL) { LOG_ERROR("Failed to allocate enough space for adding a new input actions"); return; } _actions = new; _actions_cap = next_amount; } void input_add_axis_action(SDL_Scancode negative, SDL_Scancode positive, InputActionDelegate delegate) { _resize_actions_if_needed(_actions_len + 1); _actions[_actions_len] = (InputAction){ .negative = _keys + negative, .positive = _keys + positive, .delegate = delegate }; ++_actions_len; } void input_add_key_action(SDL_Scancode key, InputActionDelegate delegate) { _resize_actions_if_needed(_actions_len + 1); _actions[_actions_len] = (InputAction) { .negative = _keys + SDL_SCANCODE_UNKNOWN, .positive = _keys + key, .delegate = delegate }; ++_actions_len; } static void _remove_element(InputAction* item) { InputAction* next = item + 1; if(next < _actions + _actions_len) { memmove(item, next, (_actions + _actions_len) - next); } --_actions_len; } void input_remove_actions(InputActionDelegate delegate) { for(InputAction* action = _actions; action < _actions + _actions_len; ++action) { if(action->delegate == delegate) { _remove_element(action); } } }