Mercurial > repos > blastem
comparison nuklear_ui/blastem_nuklear.c @ 1623:18a946ec74c8
Pull current controller config in binding UI from whatever the actual binding code would end up using
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 24 Oct 2018 21:10:12 -0700 |
parents | 9c8f58740450 |
children | 7bbe0bfedb58 |
comparison
equal
deleted
inserted
replaced
1622:4bb2c8b78b4a | 1623:18a946ec74c8 |
---|---|
13 #include "../blastem.h" | 13 #include "../blastem.h" |
14 #include "../config.h" | 14 #include "../config.h" |
15 #include "../io.h" | 15 #include "../io.h" |
16 #include "../png.h" | 16 #include "../png.h" |
17 #include "../controller_info.h" | 17 #include "../controller_info.h" |
18 #include "../bindings.h" | |
18 | 19 |
19 static struct nk_context *context; | 20 static struct nk_context *context; |
20 | 21 |
21 typedef void (*view_fun)(struct nk_context *); | 22 typedef void (*view_fun)(struct nk_context *); |
22 static view_fun current_view; | 23 static view_fun current_view; |
512 #define AXIS 0x40000000 | 513 #define AXIS 0x40000000 |
513 #define STICKDIR 0x30000000 | 514 #define STICKDIR 0x30000000 |
514 #define LEFTSTICK 0x10000000 | 515 #define LEFTSTICK 0x10000000 |
515 #define RIGHTSTICK 0x20000000 | 516 #define RIGHTSTICK 0x20000000 |
516 enum { | 517 enum { |
517 UP,DOWN,LEFT,RIGHT | 518 UP,DOWN,RIGHT,LEFT,NUM_AXIS_DIRS |
518 }; | 519 }; |
519 | 520 |
520 static char * config_ps_names[] = { | 521 static char * config_ps_names[] = { |
521 [SDL_CONTROLLER_BUTTON_A] = "cross", | 522 [SDL_CONTROLLER_BUTTON_A] = "cross", |
522 [SDL_CONTROLLER_BUTTON_B] = "circle", | 523 [SDL_CONTROLLER_BUTTON_B] = "circle", |
528 [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "r1", | 529 [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "r1", |
529 [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "l3", | 530 [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "l3", |
530 [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "r3", | 531 [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "r3", |
531 }; | 532 }; |
532 | 533 |
533 static void binding_box(struct nk_context *context, char *name, float x, float y, float width, int num_binds, int *binds) | 534 typedef struct { |
535 const char *button_binds[SDL_CONTROLLER_BUTTON_MAX]; | |
536 const char *left_stick[NUM_AXIS_DIRS]; | |
537 const char *right_stick[NUM_AXIS_DIRS]; | |
538 const char *triggers[2]; | |
539 } pad_bind_config; | |
540 | |
541 static void binding_box(struct nk_context *context, pad_bind_config *bindings, char *name, float x, float y, float width, int num_binds, int *binds) | |
534 { | 542 { |
535 const struct nk_user_font *font = context->style.font; | 543 const struct nk_user_font *font = context->style.font; |
536 float row_height = font->height * 2; | 544 float row_height = font->height * 2; |
537 | 545 |
538 char const **labels = calloc(sizeof(char *), num_binds); | 546 char const **labels = calloc(sizeof(char *), num_binds); |
539 char **conf_keys = calloc(sizeof(char *), num_binds); | 547 char const **conf_vals = calloc(sizeof(char *), num_binds); |
540 float max_width = 0.0f; | 548 float max_width = 0.0f; |
541 | 549 |
542 static const char base_path[] = "bindings\0pads"; | |
543 static const char buttons[] = "buttons"; | |
544 static const char dpads[] = "dpads\00"; | |
545 static const char axes[] = "axes"; | |
546 static const char positive[] = ".positive"; | |
547 static const char negative[] = ".negative"; | |
548 char padkey[] = {'0' + selected_controller, 0}; | |
549 int skipped = 0; | 550 int skipped = 0; |
550 for (int i = 0; i < num_binds; i++) | 551 for (int i = 0; i < num_binds; i++) |
551 { | 552 { |
552 if (binds[i] & AXIS) { | 553 if (binds[i] & AXIS) { |
553 labels[i] = get_axis_label(&selected_controller_info, binds[i] & ~AXIS); | 554 labels[i] = get_axis_label(&selected_controller_info, binds[i] & ~AXIS); |
554 const char *axname = SDL_GameControllerGetStringForAxis(binds[i] & ~AXIS); | 555 conf_vals[i] = bindings->triggers[(binds[i] & ~AXIS) - SDL_CONTROLLER_AXIS_TRIGGERLEFT]; |
555 size_t namelen = strlen(axname); | |
556 conf_keys[i] = malloc(sizeof(base_path) + sizeof(padkey) + sizeof(axes) + namelen + 2); | |
557 memcpy(conf_keys[i], base_path, sizeof(base_path)); | |
558 memcpy(conf_keys[i] + sizeof(base_path), padkey, sizeof(padkey)); | |
559 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey), axes, sizeof(axes)); | |
560 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey) + sizeof(axes), axname, namelen+1); | |
561 conf_keys[i][sizeof(base_path) + sizeof(padkey) + sizeof(axes) + namelen + 1] = 0; | |
562 } else if (binds[i] & STICKDIR) { | 556 } else if (binds[i] & STICKDIR) { |
563 static char const * dirs[] = {"Up", "Down", "Left", "Right"}; | 557 static char const * dirs[] = {"Up", "Down", "Right", "Left"}; |
564 labels[i] = dirs[binds[i] & 3]; | 558 labels[i] = dirs[binds[i] & 3]; |
565 uint8_t is_pos = (binds[i] & 3) == 3 || !(binds[i] & 3); | 559 conf_vals[i] = (binds[i] & LEFTSTICK ? bindings->left_stick : bindings->right_stick)[binds[i] & 3]; |
566 int sdl_axis = (binds[i] & LEFTSTICK ? SDL_CONTROLLER_AXIS_LEFTX : SDL_CONTROLLER_AXIS_RIGHTX) + !(binds[i] & 2); | |
567 const char *axname = SDL_GameControllerGetStringForAxis(sdl_axis); | |
568 size_t namelen = strlen(axname); | |
569 conf_keys[i] = malloc(sizeof(base_path) + sizeof(padkey) + sizeof(axes) + namelen + sizeof(positive) + 1); | |
570 memcpy(conf_keys[i], base_path, sizeof(base_path)); | |
571 memcpy(conf_keys[i] + sizeof(base_path), padkey, sizeof(padkey)); | |
572 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey), axes, sizeof(axes)); | |
573 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey) + sizeof(axes), axname, namelen); | |
574 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey) + sizeof(axes) + namelen, is_pos ? positive : negative, sizeof(positive)); | |
575 conf_keys[i][sizeof(base_path) + sizeof(padkey) + sizeof(axes) + namelen + sizeof(positive)] = 0; | |
576 } else { | 560 } else { |
577 labels[i] = get_button_label(&selected_controller_info, binds[i]); | 561 labels[i] = get_button_label(&selected_controller_info, binds[i]); |
578 static const char* dpdirs[] = {"up", "down", "left", "right"}; | 562 conf_vals[i] = bindings->button_binds[binds[i]]; |
579 const char *but_name, *mid; | |
580 size_t midsz; | |
581 if (binds[i] < SDL_CONTROLLER_BUTTON_DPAD_UP) { | |
582 but_name = SDL_GameControllerGetStringForButton(binds[i]); | |
583 mid = buttons; | |
584 midsz = sizeof(buttons); | |
585 } else { | |
586 but_name = dpdirs[binds[i] - SDL_CONTROLLER_BUTTON_DPAD_UP]; | |
587 mid = dpads; | |
588 midsz = sizeof(dpads); | |
589 } | |
590 size_t namelen = strlen(but_name); | |
591 conf_keys[i] = malloc(sizeof(base_path) + sizeof(padkey) + midsz + namelen + 2); | |
592 memcpy(conf_keys[i], base_path, sizeof(base_path)); | |
593 memcpy(conf_keys[i] + sizeof(base_path), padkey, sizeof(padkey)); | |
594 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey), mid, midsz); | |
595 | |
596 memcpy(conf_keys[i] + sizeof(base_path) + sizeof(padkey) + midsz, but_name, namelen+1); | |
597 conf_keys[i][sizeof(base_path) + sizeof(padkey) + sizeof(buttons) + namelen + 1] = 0; | |
598 } | 563 } |
599 if (!labels[i]) { | 564 if (!labels[i]) { |
600 skipped++; | 565 skipped++; |
601 continue; | 566 continue; |
602 } | 567 } |
612 { | 577 { |
613 if (!labels[i]) { | 578 if (!labels[i]) { |
614 continue; | 579 continue; |
615 } | 580 } |
616 nk_label(context, labels[i], NK_TEXT_LEFT); | 581 nk_label(context, labels[i], NK_TEXT_LEFT); |
617 if (conf_keys[i]) { | 582 nk_button_label(context, conf_vals[i] ? conf_vals[i] : "None"); |
618 char *assigned = tern_find_path(config, conf_keys[i], TVAL_PTR).ptrval; | 583 } |
619 if (!assigned) { | 584 free(labels); |
620 assigned = "None"; | 585 free(conf_vals); |
621 } else if (!memcmp("gamepads.", assigned, strlen("gamepads."))) { | |
622 assigned += strlen("gamepads.0."); | |
623 } | |
624 nk_button_label(context, assigned); | |
625 } else { | |
626 nk_button_label(context, i & 1 ? "Internal Screenshot" : "A"); | |
627 } | |
628 free(conf_keys[i]); | |
629 } | |
630 nk_group_end(context); | 586 nk_group_end(context); |
631 } | 587 } |
632 | 588 |
589 static void button_iter(char *key, tern_val val, uint8_t valtype, void *data) | |
590 { | |
591 pad_bind_config *bindings = data; | |
592 if (valtype != TVAL_PTR) { | |
593 return; | |
594 } | |
595 int button = render_lookup_button(key); | |
596 if (button != SDL_CONTROLLER_BUTTON_INVALID) { | |
597 bindings->button_binds[button] = val.ptrval; | |
598 } | |
599 } | |
600 | |
601 static void axis_iter(char *key, tern_val val, uint8_t valtype, void *data) | |
602 { | |
603 pad_bind_config *bindings = data; | |
604 if (valtype != TVAL_PTR) { | |
605 return; | |
606 } | |
607 int axis; | |
608 uint8_t is_negative = 0; | |
609 char *period = strchr(key, '.'); | |
610 if (period) { | |
611 char *tmp = malloc(period-key + 1); | |
612 memcpy(tmp, key, period-key); | |
613 tmp[period-key] = 0; | |
614 axis = render_lookup_axis(key); | |
615 free(tmp); | |
616 is_negative = strcmp(period+1, "negative") == 0; | |
617 } else { | |
618 axis = render_lookup_axis(key); | |
619 } | |
620 switch (axis) | |
621 { | |
622 case SDL_CONTROLLER_AXIS_LEFTX: | |
623 case SDL_CONTROLLER_AXIS_LEFTY: | |
624 bindings->left_stick[(axis - SDL_CONTROLLER_AXIS_LEFTX) * 2 + is_negative] = val.ptrval; | |
625 break; | |
626 case SDL_CONTROLLER_AXIS_RIGHTX: | |
627 case SDL_CONTROLLER_AXIS_RIGHTY: | |
628 bindings->right_stick[(axis - SDL_CONTROLLER_AXIS_RIGHTX) * 2 + is_negative] = val.ptrval; | |
629 break; | |
630 case SDL_CONTROLLER_AXIS_TRIGGERLEFT: | |
631 case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: | |
632 bindings->triggers[axis-SDL_CONTROLLER_AXIS_TRIGGERLEFT] = val.ptrval; | |
633 break; | |
634 } | |
635 } | |
636 | |
633 void view_controller_bindings(struct nk_context *context) | 637 void view_controller_bindings(struct nk_context *context) |
634 { | 638 { |
639 static pad_bind_config *bindings; | |
635 if (nk_begin(context, "Controller Bindings", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) { | 640 if (nk_begin(context, "Controller Bindings", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) { |
641 if (!bindings) { | |
642 bindings = calloc(1, sizeof(*bindings)); | |
643 tern_node *pad = get_binding_node_for_pad(selected_controller); | |
644 if (pad) { | |
645 tern_foreach(tern_find_node(pad, "buttons"), button_iter, bindings); | |
646 tern_foreach(tern_find_node(pad, "axes"), axis_iter, bindings); | |
647 } | |
648 } | |
649 | |
636 float orig_height = def_font->handle.height; | 650 float orig_height = def_font->handle.height; |
637 def_font->handle.height *= 0.5f; | 651 def_font->handle.height *= 0.5f; |
638 | 652 |
639 uint32_t avail_height = render_height() - 2 * orig_height; | 653 uint32_t avail_height = render_height() - 2 * orig_height; |
640 float desired_width = render_width() * 0.5f, desired_height = avail_height * 0.5f; | 654 float desired_width = render_width() * 0.5f, desired_height = avail_height * 0.5f; |
684 bind_box_left = img_right; | 698 bind_box_left = img_right; |
685 } else { | 699 } else { |
686 bind_box_left = img_right + (render_width() - img_right) / 2.0f - bind_box_width / 2.0f; | 700 bind_box_left = img_right + (render_width() - img_right) / 2.0f - bind_box_width / 2.0f; |
687 } | 701 } |
688 | 702 |
689 binding_box(context, "Action Buttons", bind_box_left, img_top, bind_box_width, 4, (int[]){ | 703 binding_box(context, bindings, "Action Buttons", bind_box_left, img_top, bind_box_width, 4, (int[]){ |
690 SDL_CONTROLLER_BUTTON_A, | 704 SDL_CONTROLLER_BUTTON_A, |
691 SDL_CONTROLLER_BUTTON_B, | 705 SDL_CONTROLLER_BUTTON_B, |
692 SDL_CONTROLLER_BUTTON_X, | 706 SDL_CONTROLLER_BUTTON_X, |
693 SDL_CONTROLLER_BUTTON_Y | 707 SDL_CONTROLLER_BUTTON_Y |
694 }); | 708 }); |
695 | 709 |
696 binding_box(context, "Right Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){ | 710 binding_box(context, bindings, "Right Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){ |
697 SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, | 711 SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, |
698 AXIS | SDL_CONTROLLER_AXIS_TRIGGERRIGHT | 712 AXIS | SDL_CONTROLLER_AXIS_TRIGGERRIGHT |
699 }); | 713 }); |
700 | 714 |
701 binding_box(context, "Misc Buttons", (render_width() - bind_box_width) / 2, font->height/2, bind_box_width, 3, (int[]){ | 715 binding_box(context, bindings, "Misc Buttons", (render_width() - bind_box_width) / 2, font->height/2, bind_box_width, 3, (int[]){ |
702 SDL_CONTROLLER_BUTTON_BACK, | 716 SDL_CONTROLLER_BUTTON_BACK, |
703 SDL_CONTROLLER_BUTTON_GUIDE, | 717 SDL_CONTROLLER_BUTTON_GUIDE, |
704 SDL_CONTROLLER_BUTTON_START | 718 SDL_CONTROLLER_BUTTON_START |
705 }); | 719 }); |
706 | 720 |
707 binding_box(context, "Right Stick", img_right - desired_width/3, img_bot, bind_box_width, 5, (int[]){ | 721 binding_box(context, bindings, "Right Stick", img_right - desired_width/3, img_bot, bind_box_width, 5, (int[]){ |
708 RIGHTSTICK | UP, | 722 RIGHTSTICK | UP, |
709 RIGHTSTICK | DOWN, | 723 RIGHTSTICK | DOWN, |
710 RIGHTSTICK | LEFT, | 724 RIGHTSTICK | LEFT, |
711 RIGHTSTICK | RIGHT, | 725 RIGHTSTICK | RIGHT, |
712 SDL_CONTROLLER_BUTTON_RIGHTSTICK | 726 SDL_CONTROLLER_BUTTON_RIGHTSTICK |
713 }); | 727 }); |
714 | 728 |
715 | 729 |
716 bind_box_left -= img_right; | 730 bind_box_left -= img_right; |
717 binding_box(context, "Left Stick", bind_box_left, img_top, bind_box_width, 5, (int[]){ | 731 binding_box(context, bindings, "Left Stick", bind_box_left, img_top, bind_box_width, 5, (int[]){ |
718 LEFTSTICK | UP, | 732 LEFTSTICK | UP, |
719 LEFTSTICK | DOWN, | 733 LEFTSTICK | DOWN, |
720 LEFTSTICK | LEFT, | 734 LEFTSTICK | LEFT, |
721 LEFTSTICK | RIGHT, | 735 LEFTSTICK | RIGHT, |
722 SDL_CONTROLLER_BUTTON_LEFTSTICK | 736 SDL_CONTROLLER_BUTTON_LEFTSTICK |
723 }); | 737 }); |
724 | 738 |
725 binding_box(context, "Left Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){ | 739 binding_box(context, bindings, "Left Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){ |
726 SDL_CONTROLLER_BUTTON_LEFTSHOULDER, | 740 SDL_CONTROLLER_BUTTON_LEFTSHOULDER, |
727 AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT | 741 AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT |
728 }); | 742 }); |
729 | 743 |
730 binding_box(context, "D-pad", img_left - desired_width/6, img_bot + font->height * 1.5, bind_box_width, 4, (int[]){ | 744 binding_box(context, bindings, "D-pad", img_left - desired_width/6, img_bot + font->height * 1.5, bind_box_width, 4, (int[]){ |
731 SDL_CONTROLLER_BUTTON_DPAD_UP, | 745 SDL_CONTROLLER_BUTTON_DPAD_UP, |
732 SDL_CONTROLLER_BUTTON_DPAD_DOWN, | 746 SDL_CONTROLLER_BUTTON_DPAD_DOWN, |
733 SDL_CONTROLLER_BUTTON_DPAD_LEFT, | 747 SDL_CONTROLLER_BUTTON_DPAD_LEFT, |
734 SDL_CONTROLLER_BUTTON_DPAD_RIGHT | 748 SDL_CONTROLLER_BUTTON_DPAD_RIGHT |
735 }); | 749 }); |