From 5a60c94c7682b423aa1513230347cc495c9781fd Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Sat, 14 Oct 2017 20:15:52 +0500 Subject: [PATCH] Implemented Reading/Writing keybindings using new parser object --- README.md | 3 +- src/common/log.c | 9 +- src/common/parser.c | 2 + src/common/parser.h | 1 + src/game/platform.c | 4 +- src/libsymmetry/input.c | 521 ++++++++++++++++++++-------------------- src/libsymmetry/input.h | 20 +- 7 files changed, 288 insertions(+), 272 deletions(-) diff --git a/README.md b/README.md index b3c042f..c00ee5d 100644 --- a/README.md +++ b/README.md @@ -155,8 +155,6 @@ - ## TODO - - Add array support to variant - - Read/Write keybindings using new parser object - Store Materials in new format supported by parser - Add model description file which has the same syntax supported by parser and modify old blender exporter to conform to new standards - Implement sound/listener loading from scene file @@ -331,3 +329,4 @@ * Modify entity loading logic to use the new parsing code by parsing all entity properties into a hashmap first then recreating entity from that * Implmented writing to file through the new Parser and Parser_Objects * Changed Config to read/write using new Parser and Parser_Objects + * Implemented Reading/Writing keybindings using new parser object diff --git a/src/common/log.c b/src/common/log.c index b515f97..66e7143 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -53,7 +53,14 @@ void log_init(const char* log_file_name, const char* user_directory) void log_cleanup(void) { - if(log_file) fclose(log_file); + if(log_file) + { + time_t current_time; + time(¤t_time); + fprintf(log_file, "\nLog closing at %s\n", ctime(¤t_time)); + fflush(log_file); + fclose(log_file); + } } diff --git a/src/common/parser.c b/src/common/parser.c index 4ed35d5..b75ed09 100644 --- a/src/common/parser.c +++ b/src/common/parser.c @@ -242,6 +242,7 @@ int parser_object_type_from_str(const char* str) else if(strncmp(str, "Model", HASH_MAX_KEY_LEN) == 0) object_type = PO_MODEL; else if(strncmp(str, "Material", HASH_MAX_KEY_LEN) == 0) object_type = PO_MATERIAL; else if(strncmp(str, "Config", HASH_MAX_KEY_LEN) == 0) object_type = PO_CONFIG; + else if(strncmp(str, "Key", HASH_MAX_KEY_LEN) == 0) object_type = PO_KEY; return object_type; } @@ -254,6 +255,7 @@ const char* parser_object_type_to_str(int type) case PO_MODEL: return "Model"; case PO_MATERIAL: return "Material"; case PO_CONFIG: return "Config"; + case PO_KEY: return "Key"; case PO_UNKNOWN: return "Unknown"; default: return "Unknown"; } diff --git a/src/common/parser.h b/src/common/parser.h index 999b6e9..13212b9 100644 --- a/src/common/parser.h +++ b/src/common/parser.h @@ -9,6 +9,7 @@ enum Parser_Object_Type PO_ENTITY, PO_MATERIAL, PO_MODEL, + PO_KEY, PO_UNKNOWN }; diff --git a/src/game/platform.c b/src/game/platform.c index 3f16965..a377843 100644 --- a/src/game/platform.c +++ b/src/game/platform.c @@ -431,8 +431,8 @@ int platform_key_from_name(const char* key_name) strncpy(trimmed_key_name, &key_name[start], (end - start) + 1); int key = SDL_GetKeyFromName(trimmed_key_name); - if(key == SDLK_UNKNOWN) - log_error("platform:key_from_name", "Unrecognized key '%s', SDL (%s)", trimmed_key_name, SDL_GetError()); + /*if(key == SDLK_UNKNOWN) + log_error("platform:key_from_name", "Unrecognized key '%s', SDL (%s)", trimmed_key_name, SDL_GetError());*/ return key; } diff --git a/src/libsymmetry/input.c b/src/libsymmetry/input.c index 5149cea..45207f6 100644 --- a/src/libsymmetry/input.c +++ b/src/libsymmetry/input.c @@ -7,22 +7,16 @@ #include "gui.h" #include "../common/string_utils.h" #include "../common/common.h" +#include "../common/hashmap.h" +#include "../common/variant.h" #include "../common/parser.h" -struct Input_Map -{ - char* name; - struct Key_Combination* keys; - int state; -}; - static void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); static void input_on_mousebutton(int button, int state, int x, int y, int8 num_clicks); static void input_on_mousemotion(int x, int y, int xrel, int yrel); static void input_on_mousewheel(int x, int y); -static int map_find(const char* name); -static void on_parser_assign(const char* key, const char* value, const char* filename, int current_line); -static struct Input_Map* input_map_list = NULL; + +static struct Hashmap* key_bindings = NULL; void input_init(void) { @@ -31,192 +25,227 @@ void input_init(void) platform->mousemotion_callback_set(&input_on_mousemotion); platform->mousewheel_callback_set(&input_on_mousewheel); - input_map_list = array_new(struct Input_Map); - if(!input_keybinds_load("keybindings.cfg", DIRT_USER)) + key_bindings = hashmap_new(); + + /* Default keys for fallback */ + struct Key_Binding forward_keys = {KEY_W, KMOD_NONE, KEY_UP, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding backward_keys = {KEY_S, KMOD_NONE, KEY_DOWN, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding up_keys = {KEY_Q, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding down_keys = {KEY_E, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding left_keys = {KEY_A, KMOD_NONE, KEY_LEFT, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding right_keys = {KEY_D, KMOD_NONE, KEY_RIGHT, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding turn_right_keys = {KEY_L, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding turn_left_keys = {KEY_J, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding turn_up_keys = {KEY_I, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding turn_down_keys = {KEY_K, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding sprint_keys = {KEY_LSHIFT, KMOD_NONE, KEY_RSHIFT, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding ed_toggle_keys = {KEY_F1, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding win_fullscr_keys = {KEY_F11, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding win_max_keys = {KEY_F12, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + struct Key_Binding reload_game_keys = {KEY_F5, KMOD_NONE, KEY_NONE, KMOD_NONE, KS_INACTIVE}; + input_map_create("Move_Forward", forward_keys); + input_map_create("Move_Backward", backward_keys); + input_map_create("Move_Up", up_keys); + input_map_create("Move_Down", down_keys); + input_map_create("Move_Left", left_keys); + input_map_create("Move_Right", right_keys); + input_map_create("Turn_Right", turn_right_keys); + input_map_create("Turn_Left", turn_left_keys); + input_map_create("Turn_Up", turn_up_keys); + input_map_create("Turn_Down", turn_down_keys); + input_map_create("Sprint", sprint_keys); + input_map_create("Editor_Toggle", ed_toggle_keys); + input_map_create("Window_Fullscreen", win_fullscr_keys); + input_map_create("Window_Maximize", win_max_keys); + input_map_create("Reload_Game_Lib", reload_game_keys); + + if(!input_keybinds_load("keybindings.symtres", DIRT_USER)) { log_error("input:init", "Failed to load keybindings"); log_message("Reverting to default keybindings"); - if(!input_keybinds_load("keybindings.cfg", DIRT_INSTALL)) + if(!input_keybinds_load("keybindings.symtres", DIRT_INSTALL)) { log_error("input:init", "Failed to load default keybindings"); + input_keybinds_save("keybindings.symtres", DIRT_INSTALL); } - else - { - input_keybinds_save("keybindings.cfg"); - } - } - /* Default keys for fallback */ - struct Key_Combination forward_keys[2] = {{KEY_W, KMD_NONE}, {KEY_UP, KMD_ALT | KMD_SHIFT}}; - struct Key_Combination backward_keys[2] = {{KEY_S, KMD_NONE}, {KEY_DOWN, KMD_NONE}}; - struct Key_Combination up_keys[2] = {{KEY_Q}}; - struct Key_Combination down_keys[2] = {{KEY_E}}; - struct Key_Combination left_keys[2] = {{KEY_A}, {KEY_LEFT}}; - struct Key_Combination right_keys[2] = {{KEY_D}, {KEY_RIGHT}}; - struct Key_Combination turn_right_keys[1] = {{KEY_L}}; - struct Key_Combination turn_left_keys[1] = {{KEY_J}}; - struct Key_Combination turn_up_keys[1] = {{KEY_I}}; - struct Key_Combination turn_down_keys[1] = {{KEY_K}}; - struct Key_Combination sprint_keys[2] = {{KEY_LSHIFT}, {KEY_RSHIFT}}; - struct Key_Combination ed_toggle_keys[1] = {{KEY_F1}}; - struct Key_Combination win_fullscr_keys[1] = {{KEY_F11}}; - struct Key_Combination win_max_keys[1] = {{KEY_F12}}; - struct Key_Combination reload_game_keys[1] = {{KEY_F5}}; - input_map_create("Move_Forward", forward_keys, 2); - input_map_create("Move_Backward", backward_keys, 2); - input_map_create("Move_Up", up_keys, 1); - input_map_create("Move_Down", down_keys, 1); - input_map_create("Move_Left", left_keys, 2); - input_map_create("Move_Right", right_keys, 2); - input_map_create("Turn_Right", turn_right_keys, 1); - input_map_create("Turn_Left", turn_left_keys, 1); - input_map_create("Turn_Up", turn_up_keys, 1); - input_map_create("Turn_Down", turn_down_keys, 1); - input_map_create("Sprint", sprint_keys, 2); - input_map_create("Editor_Toggle", ed_toggle_keys, 1); - input_map_create("Window_Fullscreen", win_fullscr_keys, 1); - input_map_create("Window_Maximize", win_max_keys, 1); - input_map_create("Reload_Game_Lib", reload_game_keys, 1); + input_keybinds_save("keybindings.symtres", DIRT_USER); + } } void input_cleanup(void) { - for(int i = 0; i < array_len(input_map_list); i++) + char* key = NULL; + struct Variant* value = NULL; + HASHMAP_FOREACH(key_bindings, key, value) { - struct Input_Map* map = &input_map_list[i]; - if(map->name) free(map->name); - array_free(map->keys); + free(value->val_voidptr); } - array_free(input_map_list); - input_map_list = NULL; + + hashmap_free(key_bindings); } -void on_parser_assign(const char* key, const char* value, const char* filename, int current_line) +bool input_keybinds_load(const char* filename, int directory_type) { - char* value_copy = str_new(value); - //value_copy[strlen(value_copy) - 1] = '\0'; - char* val = strtok(value_copy, ","); - if(!val) + FILE* key_file = platform->file.open(directory_type, filename, "rb"); + if(!key_file) { - log_warning("Unable to parse keys for keybinding %s in file %s, line %d", key, filename, current_line); - free(value_copy); - return; + log_error("input:keybinds_load", "Could not open %s", filename); + return false; } - while(val) + struct Parser* parser = parser_load_objects(key_file, filename); + if(!parser) { -#define max_key_str_len 20 - /* Check if there are any Modifiers */ - int modifiers = KMD_NONE; - char* keys = strstr(val, "-"); - char* start_loc = val; - char key_name[max_key_str_len]; - int skip_to_next = 0; - while(keys) - { - memset(key_name, '\0', max_key_str_len); - strncpy(key_name, start_loc, (keys - start_loc)); + log_error("input:keybinds_load", "Failed to parse %s", filename); + fclose(key_file); + return false; + } - int key_modifier = platform->key_from_name(key_name); + for(int i = 0; i < array_len(parser->objects); i++) + { + struct Parser_Object* object = &parser->objects[i]; - if(key_modifier == KEY_UNKNOWN) + const char* name_temp = NULL; + struct Key_Binding key_binding = + { + .state = KS_INACTIVE, + .key_primary = KEY_NONE, + .mods_primary = KMD_NONE, + .key_secondary = KEY_NONE, + .mods_secondary = KMD_NONE + }; + + if(hashmap_value_exists(object->data, "name")) name_temp = hashmap_str_get(object->data, "name"); + if(hashmap_value_exists(object->data, "key_primary")) + { + int key = platform->key_from_name(hashmap_str_get(object->data, "key_primary")); + if(key != KEY_UNKNOWN) { - log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); - skip_to_next = true; - break; + key_binding.key_primary = key; } + } - switch(key_modifier) + if(hashmap_value_exists(object->data, "key_secondary")) + { + int key = platform->key_from_name(hashmap_str_get(object->data, "key_secondary")); + if(key != KEY_UNKNOWN) { - case KEY_LSHIFT: case KEY_RSHIFT: modifiers |= KMD_SHIFT; break; - case KEY_LCTRL: case KEY_RCTRL: modifiers |= KMD_CTRL; break; - case KEY_LALT: case KEY_RALT: modifiers |= KMD_ALT; break; - }; - - ++keys; - start_loc = keys; - keys = strstr(keys, "-"); + key_binding.key_secondary = key; + } } - - if(skip_to_next) + + if(hashmap_value_exists(object->data, "mods_primary_ctrl")) { - val = strtok(NULL, ","); - continue; + if(hashmap_bool_get(object->data, "mods_primary_ctrl")) + key_binding.mods_primary |= KMD_CTRL; } - - /* Copy the last key after the hyphen */ - strncpy(key_name, start_loc, max_key_str_len); - int key_code = platform->key_from_name(key_name); - if(key_code == KEY_UNKNOWN) + + if(hashmap_value_exists(object->data, "mods_primary_shift")) { - log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); - val = strtok(NULL, ","); - continue; + if(hashmap_bool_get(object->data, "mods_primary_shift")) + key_binding.mods_primary |= KMD_SHIFT; } - struct Key_Combination key_comb = { .key = key_code, .mods = modifiers}; - input_map_create(key, &key_comb, 1); - - val = strtok(NULL, ","); + if(hashmap_value_exists(object->data, "mods_primary_alt")) + { + if(hashmap_bool_get(object->data, "mods_primary_alt")) + key_binding.mods_primary |= KMD_ALT; + } + + if(hashmap_value_exists(object->data, "mods_secondary_ctrl")) + { + if(hashmap_bool_get(object->data, "mods_secondary_ctrl")) + key_binding.mods_secondary |= KMD_CTRL; + } + + if(hashmap_value_exists(object->data, "mods_secondary_shift")) + { + if(hashmap_bool_get(object->data, "mods_secondary_shift")) + key_binding.mods_secondary = KMD_SHIFT; + } + + if(hashmap_value_exists(object->data, "mods_secondary_alt")) + { + if(hashmap_bool_get(object->data, "mods_secondary_alt")) + key_binding.mods_secondary = KMD_ALT; + } + + input_map_create(name_temp, key_binding); } - free(value_copy); + + parser_free(parser); + fclose(key_file); + return true; } -bool input_keybinds_load(const char* filename, int directory_type) +bool input_keybinds_save(const char* filename, int directory_type) { - bool success = false; - FILE* config_file = platform->file.open(directory_type, filename, "r"); - if(!config_file) + struct Parser* parser = parser_new(); + if(!parser) { - log_error("input:keybinds_load", "Could not open %s", filename); - return success; + log_error("input:keybinds_save", "Could not create Parser"); + return false; } - if(!parser_load(config_file, filename, &on_parser_assign, false, 0)) - { - log_error("input:keybinds_load", "Failed to parse file %s", filename); - } - else + + char* key = NULL; + struct Variant* value = NULL; + + HASHMAP_FOREACH(key_bindings, key, value) { - log_message("Loaded keybindings from %s", filename); - success = true; + struct Key_Binding* key_binding = (struct Key_Binding*)value->val_voidptr; + struct Parser_Object* object = parser_object_new(parser, PO_KEY); + if(!object) + { + log_error("input:keybinds_save", "Failed to create Parser_object for Map '%s'", key); + continue; + } + bool mods_primary_ctrl = ((key_binding->mods_primary & KMD_CTRL) == KMD_CTRL) ? true : false; + bool mods_primary_shift = ((key_binding->mods_primary & KMD_SHIFT) == KMD_SHIFT) ? true : false; + bool mods_primary_alt = ((key_binding->mods_primary & KMD_ALT) == KMD_ALT) ? true : false; + + bool mods_secondary_ctrl = ((key_binding->mods_secondary & KMD_CTRL) == KMD_CTRL) ? true : false; + bool mods_secondary_shift = ((key_binding->mods_secondary & KMD_SHIFT) == KMD_SHIFT) ? true : false; + bool mods_secondary_alt = ((key_binding->mods_secondary & KMD_ALT) == KMD_ALT) ? true : false; + + hashmap_str_set(object->data, "name", key); + hashmap_str_set(object->data, "key_primary", key_binding->key_primary == KEY_NONE ? "NONE" : platform->key_name_get(key_binding->key_primary)); + hashmap_bool_set(object->data, "mods_primary_ctrl", mods_primary_ctrl); + hashmap_bool_set(object->data, "mods_primary_shift", mods_primary_shift); + hashmap_bool_set(object->data, "mods_primary_alt", mods_primary_alt); + + hashmap_str_set(object->data, "key_secondary", key_binding->key_secondary == KEY_NONE ? "NONE" : platform->key_name_get(key_binding->key_secondary)); + hashmap_bool_set(object->data, "mods_secondary_ctrl", mods_secondary_ctrl); + hashmap_bool_set(object->data, "mods_secondary_shift", mods_secondary_shift); + hashmap_bool_set(object->data, "mods_secondary_alt", mods_secondary_alt); } - - fclose(config_file); - return success; -} -bool input_keybinds_save(const char* filename) -{ - bool success = false; + log_message("Keybindings saved to %s", filename); + - FILE* config_file = platform->file.open(DIRT_USER, filename, "w"); - if(!config_file) + bool write_success = false; + FILE* key_file = platform->file.open(directory_type, filename, "w"); + if(!key_file) { log_error("input:keybinds_save", "Could not open %s", filename); - return success; } - - for(int i = 0; i < array_len(input_map_list); i++) + else { - struct Input_Map* map = &input_map_list[i]; - fprintf(config_file, "%s : ", map->name); - for(int j = 0; j < array_len(map->keys); j++) + if(parser_write_objects(parser, key_file, filename)) + { + log_message("Input Maps written to %s", filename); + write_success = true; + } + else { - if(j != 0) fprintf(config_file, ", "); - struct Key_Combination* key_comb = &map->keys[j]; - if((key_comb->mods & KMD_ALT) == KMD_ALT) fprintf(config_file, "%s-", platform->key_name_get(KEY_LALT)); - if((key_comb->mods & KMD_SHIFT) == KMD_SHIFT) fprintf(config_file, "%s-", platform->key_name_get(KEY_LSHIFT)); - if((key_comb->mods & KMD_CTRL) == KMD_CTRL) fprintf(config_file, "%s-", platform->key_name_get(KEY_LCTRL)); - fprintf(config_file, "%s", platform->key_name_get(key_comb->key)); + log_error("Failed to write Input Maps to %s", filename); } - fprintf(config_file, "\n"); } - fprintf(config_file, "\n"); - fclose(config_file); - log_message("Keybindings saved to %s", filename); - success = true; - return success; + + parser_free(parser); + fclose(key_file); + return write_success; } void input_on_mousemotion(int x, int y, int xrel, int yrel) @@ -248,31 +277,34 @@ void input_on_key(int key, int scancode, int state, int repeat, int mod_ctrl, in if(mod_ctrl) mods |= KMD_CTRL; if(mod_shift) mods |= KMD_SHIFT; if(mod_alt) mods |= KMD_ALT; - for(int i = 0; i < array_len(input_map_list); i++) + + char* map_key = NULL; + struct Variant* value = NULL; + HASHMAP_FOREACH(key_bindings, map_key, value) { - struct Input_Map* map = &input_map_list[i]; - for(int j = 0; j < array_len(map->keys); j++) + struct Key_Binding* key_binding = (struct Key_Binding*)value->val_voidptr; + //Check with primary key + if(key_binding->key_primary == key && (key_binding->mods_primary & mods) == key_binding->mods_primary) { - /* if(map->state == KS_PRESSED && */ - /* state == KS_RELEASED && */ - /* ((map->keys[j].mods & mods) == map->keys[j].mods)) */ - /* { */ - /* map->state = state; */ - /* } */ - if(map->keys[j].key == key && ((map->keys[j].mods & mods) == map->keys[j].mods)) - { - map->state = state; - break; - } + key_binding->state = state; + break; + } + + //If not, then check with secondary key + if(key_binding->key_secondary == key && (key_binding->mods_secondary & mods) == key_binding->mods_secondary) + { + key_binding->state = state; + break; } } + /* TODO: This is temporary. After proper event loop is added this code should not be here */ gui_handle_keyboard_event(key, state, mod_ctrl, mod_shift); } void input_on_mousebutton(int button, int state, int x, int y, int8 num_clicks) { - /* Probably add 'mouse maps', same as input maps for keyboard but with buttons + /* Probably add 'mouse maps', same as input maps for keyboard but with buttons. Do we even need that? */ /* TODO: This is temporary. After proper event loop is added this code should not be here */ @@ -284,25 +316,38 @@ void input_mouse_mode_set(enum Mouse_Mode mode) platform->mouse_relative_mode_set(mode == MM_NORMAL ? 0 : 1); } -bool input_map_state_get(const char* map_name, int state) +bool input_map_state_get(const char* name, int state) { - int current_state = KS_INACTIVE; - for(int i = 0; i < array_len(input_map_list); i++) + struct Key_Binding* key_binding = (struct Key_Binding*)hashmap_ptr_get(key_bindings, name); + if(!key_binding) { - struct Input_Map* map = &input_map_list[i]; - if(strcmp(map->name, map_name) == 0) - { - current_state = map->state; - break; - } + log_error("input:map_state_get", "Map '%s' not found", name); + return false; } - bool result = false; - if(current_state == state) - { - result = true; - } - return result; + return (key_binding->state == state); +} + +bool input_map_create(const char* name, struct Key_Binding key_combination) +{ + //Check if a key map already exists + if(hashmap_value_exists(key_bindings, name)) + { + log_warning("Removing existing Map '%s' and replacing with new one", name); + input_map_remove(name); + } + + struct Key_Binding* new_keybinding = malloc(sizeof(*new_keybinding)); + if(!new_keybinding) + { + log_error("input:map_create", "Out of memory"); + return false; + } + + memcpy(new_keybinding, &key_combination, sizeof(key_combination)); + hashmap_ptr_set(key_bindings, name, new_keybinding); + log_message("Created new input map '%s'", name); + return true; } bool input_is_key_pressed(int key) @@ -316,110 +361,66 @@ bool input_mousebutton_state_get(uint button, int state_type) return state_type == current_state ? true : false; } -void input_map_create(const char* name, struct Key_Combination* keys, int num_keys) -{ - assert(name && keys && num_keys > 0); - int index = map_find(name); - if(index > -1) - { - struct Input_Map* map = &input_map_list[index]; - for(int i = 0; i < num_keys; i++) - { - struct Key_Combination* new_comb = array_grow(map->keys, struct Key_Combination); - new_comb->mods = KMD_NONE; - *new_comb = keys[i]; - log_message("Added new Key combination to input map : %s", name); - } - } - else - { - struct Input_Map* new_map = array_grow(input_map_list, struct Input_Map); - new_map->name = str_new(name); - new_map->keys = array_new_cap(struct Key_Combination, num_keys); - new_map->state = KS_INACTIVE; - for(int i = 0; i < num_keys; i++) - { - new_map->keys[i].mods = KMD_NONE; - new_map->keys[i] = keys[i]; - } - log_message("Created Input Map : %s", name); - } -} - void input_update(void) { - for(int i = 0; i < array_len(input_map_list); i++) + struct Variant* value = NULL; + char* key = NULL; + HASHMAP_FOREACH(key_bindings, key, value) { - struct Input_Map* map = &input_map_list[i]; - if(map->state == KS_RELEASED) - map->state = KS_INACTIVE; + struct Key_Binding* key_binding = (struct Key_Binding*)value->val_voidptr; + if(key_binding->state == KS_RELEASED) + key_binding->state = KS_INACTIVE; } } bool input_map_remove(const char* name) { assert(name); - bool success = false; - int index = map_find(name); - if(index > -1) - { - array_remove_at(input_map_list, (int)index); - success = true; - } - if(!success) log_error("input:map_remove", "Map %s not found", name); - return success; -} - -bool input_map_keys_set(const char* name, struct Key_Combination* keys, int num_keys) -{ - assert(name && keys && num_keys > 0); - bool success = false; - int index = map_find(name); - if(index > -1) + if(hashmap_value_exists(key_bindings, name)) { - struct Input_Map* map = &input_map_list[index]; - if(array_len(map->keys) != num_keys) - array_reset(map->keys, num_keys); - for(int i = 0; i < num_keys; i++) - map->keys[i] = keys[i]; - - map->state = KS_INACTIVE; - success = true; + struct Key_Binding* current_key = (struct Key_Binding*)hashmap_ptr_get(key_bindings, name); + free(current_key); + hashmap_value_remove(key_bindings, name); } - if(!success) - log_error("input:map_keys_set", "Map %s not found", name); - return success; + else + { + log_error("input:map_remove", "Map '%s' not found", name); + return false; + } + + return true; } -bool input_map_name_set(const char* name, const char* new_name) +bool input_map_keys_set(const char* name, struct Key_Binding key_combination) { - assert(name && new_name); - bool success = false; - int index = map_find(name); - if(index > -1) + assert(name); + struct Key_Binding* existing_combination = (struct Key_Binding*)hashmap_ptr_get(key_bindings, name); + if(!existing_combination) { - struct Input_Map* map = &input_map_list[index]; - map->name = str_new(new_name); - success = true; + log_error("input:map_keys_set", "Map '%s' not found", name); + return false; } - if(!success) log_error("input:map_name_set", "Map %s not found", name); - return success; + + memcpy(existing_combination, &key_combination, sizeof(key_combination)); + existing_combination->state = KS_INACTIVE; + return true; } -int map_find(const char* name) +bool input_map_name_set(const char* name, const char* new_name) { - int index = -1; - for(int i = 0; i < array_len(input_map_list); i++) - { - struct Input_Map* map = &input_map_list[i]; - if(strcmp(name, map->name) == 0) - { - index = i; - break; - } - } - return index; + //assert(name && new_name); + //bool success = false; + //int index = map_find(name); + //if(index > -1) + //{ + // struct Key_Binding* map = &key_bindings[index]; + // map->name = str_new(new_name); + // success = true; + //} + //if(!success) log_error("input:map_name_set", "Map %s not found", name); + //return success; + return false; } int input_mouse_mode_get(void) diff --git a/src/libsymmetry/input.h b/src/libsymmetry/input.h index 1475f11..141bbdc 100644 --- a/src/libsymmetry/input.h +++ b/src/libsymmetry/input.h @@ -6,10 +6,15 @@ #include -struct Key_Combination +struct Key_Binding { - int key; - int mods; + int key_primary; + int mods_primary; + + int key_secondary; + int mods_secondary; + + int state; }; enum Key_Mod @@ -156,7 +161,8 @@ enum Keyboard_Key KEY_RCTRL = SDLK_RCTRL, KEY_LALT = SDLK_LALT, KEY_RALT = SDLK_RALT, - KEY_UNKNOWN = SDLK_UNKNOWN + KEY_UNKNOWN = SDLK_UNKNOWN, + KEY_NONE = -1 }; enum Keyboard_Scancode @@ -410,7 +416,7 @@ enum Keyboard_Scancode void input_init(void); bool input_keybinds_load(const char* filename, int directory_type); -bool input_keybinds_save(const char* filename); +bool input_keybinds_save(const char* filename, int directory_type); void input_cleanup(void); bool input_mousebutton_state_get(uint button, int state_type); bool input_is_key_pressed(int key); @@ -421,8 +427,8 @@ void input_mouse_mode_set(enum Mouse_Mode mode); int input_mouse_mode_get(void); void input_update(void); bool input_map_state_get(const char* map_name, int state); -void input_map_create(const char* name, struct Key_Combination* keys, int num_keys); -bool input_map_keys_set(const char* name, struct Key_Combination* keys, int num_keys); +bool input_map_create(const char* name, struct Key_Binding key_combination); +bool input_map_keys_set(const char* name, struct Key_Binding key_combination); bool input_map_remove(const char* name); bool input_map_name_set(const char* name, const char* new_name);