# HG changeset patch # User Michael Pavone # Date 1517985736 28800 # Node ID 63659fb92db4b8e600adae52715172f574bc727b # Parent a51721408c15b5a67d9365c16b8ade679c13b33c Key binding menu is now functional diff -r a51721408c15 -r 63659fb92db4 Makefile --- a/Makefile Mon Feb 05 23:39:14 2018 -0800 +++ b/Makefile Tue Feb 06 22:42:16 2018 -0800 @@ -65,8 +65,8 @@ endif #Windows ifdef DEBUG -CFLAGS:=-ggdb $(CFLAGS) -LDFLAGS:=-ggdb $(LDFLAGS) +CFLAGS:=-g3 $(CFLAGS) +LDFLAGS:=-g3 $(LDFLAGS) else ifdef NOLTO CFLAGS:=-O2 $(CFLAGS) diff -r a51721408c15 -r 63659fb92db4 nuklear_ui/blastem_nuklear.c --- a/nuklear_ui/blastem_nuklear.c Mon Feb 05 23:39:14 2018 -0800 +++ b/nuklear_ui/blastem_nuklear.c Tue Feb 06 22:42:16 2018 -0800 @@ -235,6 +235,7 @@ *binding_lookup = tern_insert_ptr(*binding_lookup, val.ptrval, strdup(key)); } +static int32_t keycode; static const char *set_binding; char *set_label; void binding_group(struct nk_context *context, char *name, const char **binds, const char **bind_names, uint32_t num_binds, tern_node *binding_lookup) @@ -254,6 +255,7 @@ if (nk_button_label(context, tern_find_ptr_default(binding_lookup, binds[i], "Not Set"))) { set_binding = binds[i]; set_label = strdup(label); + keycode = 0; } if (label_alloc) { free(label_alloc); @@ -263,6 +265,61 @@ } } +static char *get_key_name(int32_t keycode) +{ + char *name = NULL; + if (keycode > ' ' && keycode < 0x80) { + //key corresponds to a printable non-whitespace character + name = malloc(2); + name[0] = keycode; + name[1] = 0; + } else { + switch (keycode) + { + case RENDERKEY_UP: name = "up"; break; + case RENDERKEY_DOWN: name = "down"; break; + case RENDERKEY_LEFT: name = "left"; break; + case RENDERKEY_RIGHT: name = "right"; break; + case '\r': name = "enter"; break; + case ' ': name = "space"; break; + case '\t': name = "tab"; break; + case '\b': name = "backspace"; break; + case RENDERKEY_ESC: name = "esc"; break; + case RENDERKEY_DEL: name = "delete"; break; + case RENDERKEY_LSHIFT: name = "lshift"; break; + case RENDERKEY_RSHIFT: name = "rshift"; break; + case RENDERKEY_LCTRL: name = "lctrl"; break; + case RENDERKEY_RCTRL: name = "rctrl"; break; + case RENDERKEY_LALT: name = "lalt"; break; + case RENDERKEY_RALT: name = "ralt"; break; + case RENDERKEY_HOME: name = "home"; break; + case RENDERKEY_END: name = "end"; break; + case RENDERKEY_PAGEUP: name = "pageup"; break; + case RENDERKEY_PAGEDOWN: name = "pagedown"; break; + case RENDERKEY_F1: name = "f1"; break; + case RENDERKEY_F2: name = "f2"; break; + case RENDERKEY_F3: name = "f3"; break; + case RENDERKEY_F4: name = "f4"; break; + case RENDERKEY_F5: name = "f5"; break; + case RENDERKEY_F6: name = "f6"; break; + case RENDERKEY_F7: name = "f7"; break; + case RENDERKEY_F8: name = "f8"; break; + case RENDERKEY_F9: name = "f9"; break; + case RENDERKEY_F10: name = "f10"; break; + case RENDERKEY_F11: name = "f11"; break; + case RENDERKEY_F12: name = "f12"; break; + case RENDERKEY_SELECT: name = "select"; break; + case RENDERKEY_PLAY: name = "play"; break; + case RENDERKEY_SEARCH: name = "search"; break; + case RENDERKEY_BACK: name = "back"; break; + } + if (name) { + name = strdup(name); + } + } + return name; +} + void view_key_bindings(struct nk_context *context) { const char *controller1_binds[] = { @@ -282,7 +339,7 @@ "ui.screenshot", "ui.sms_pause", "ui.toggle_keyboard_cpatured", "ui.release_mouse" }; const char *general_names[] = { - "Show Menu", "Quick Save", "Toggle Fullscreen", "Soft Reset", "Reload Media" + "Show Menu", "Quick Save", "Toggle Fullscreen", "Soft Reset", "Reload Media", "Internal Screenshot", "SMS Pause", "Capture Keyboard", "Release Mouse" }; const char *speed_binds[] = { @@ -331,6 +388,36 @@ if (nk_button_label(context, "Cancel")) { free(set_label); set_binding = set_label = NULL; + } else if (keycode) { + char *name = get_key_name(keycode); + if (name) { + uint32_t prefix_len = strlen("bindings") + strlen("keys") + 2; + char * old = tern_find_ptr(binding_lookup, set_binding); + if (old) { + uint32_t suffix_len = strlen(old) + 1; + char *old_path = malloc(prefix_len + suffix_len + 1); + memcpy(old_path, "bindings\0keys\0", prefix_len); + memcpy(old_path + prefix_len, old, suffix_len); + old_path[prefix_len + suffix_len] = 0; + tern_val old_val; + if (tern_delete_path(&config, old_path, &old_val) == TVAL_PTR) { + free(old_val.ptrval); + } + } + uint32_t suffix_len = strlen(name) + 1; + char *path = malloc(prefix_len + suffix_len + 1); + memcpy(path, "bindings\0keys\0", prefix_len); + memcpy(path + prefix_len, name, suffix_len); + path[prefix_len + suffix_len] = 0; + + config = tern_insert_path(config, path, (tern_val){.ptrval = strdup(set_binding)}, TVAL_PTR); + free(path); + free(name); + tern_free(binding_lookup); + binding_lookup = NULL; + } + free(set_label); + set_binding = set_label = NULL; } nk_end(context); } @@ -753,6 +840,9 @@ } static void handle_event(SDL_Event *event) { + if (event->type == SDL_KEYDOWN) { + keycode = event->key.keysym.sym; + } nk_sdl_handle_event(event); } diff -r a51721408c15 -r 63659fb92db4 tern.c --- a/tern.c Mon Feb 05 23:39:14 2018 -0800 +++ b/tern.c Tue Feb 06 22:42:16 2018 -0800 @@ -138,6 +138,39 @@ return NULL; } +uint8_t tern_delete(tern_node **head, char const *key, tern_val *out) +{ + tern_node *cur = *head, **last = head; + while (cur) + { + if (cur->el == *key) { + if (*key) { + last = &cur->straight.next; + cur = cur->straight.next; + key++; + } else { + break; + } + } else if (*key < cur->el) { + last = &cur->left; + cur = cur->left; + } else { + last = &cur->right; + cur = cur->right; + } + } + if (!cur) { + return TVAL_NONE; + } + *last = cur->right; + uint8_t valtype = cur->valtype; + if (out) { + *out = cur->straight.value; + } + free(cur); + return valtype; +} + tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype) { tern_val ret; @@ -193,6 +226,25 @@ } } +uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out) +{ + const char *next_key = key + strlen(key) + 1; + if (*next_key) { + tern_node *child = tern_find_node(*head, key); + if (!child) { + return TVAL_NONE; + } + tern_node *tmp = child; + uint8_t valtype = tern_delete_path(&tmp, next_key, out); + if (tmp != child) { + *head = tern_insert_node(*head, key, tmp); + } + return valtype; + } else { + return tern_delete(head, key, out); + } +} + uint32_t tern_count(tern_node *head) { uint32_t count = 0; @@ -220,7 +272,7 @@ if (head->left) { tern_foreach_int(head->left, fun, data, keybuf, pos); } - if (head->el) { + if (head->el && head->straight.next) { if (pos == MAX_ITER_KEY) { fatal_error("tern_foreach_int: exceeded maximum key size"); } diff -r a51721408c15 -r 63659fb92db4 tern.h --- a/tern.h Mon Feb 05 23:39:14 2018 -0800 +++ b/tern.h Tue Feb 06 22:42:16 2018 -0800 @@ -43,8 +43,10 @@ void * tern_find_ptr_default(tern_node * head, char const * key, void * def); void * tern_find_ptr(tern_node * head, char const * key); tern_node *tern_find_node(tern_node *head, char const *key); +uint8_t tern_delete(tern_node **head, char const *key, tern_val *out); tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype); tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype); +uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out); tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value); tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value); tern_node *tern_insert_path(tern_node *head, char const *key, tern_val val, uint8_t valtype);