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 });