comparison bindings.c @ 2317:e836cf11783b

Make deadzones configurable and bump up the default value
author Michael Pavone <pavone@retrodev.com>
date Sun, 02 Apr 2023 23:21:39 -0700
parents 59fd8aa352e2
children f8ce89498e11
comparison
equal deleted inserted replaced
2316:523ab225815b 2317:e836cf11783b
62 62
63 typedef struct { 63 typedef struct {
64 keybinding positive; 64 keybinding positive;
65 keybinding negative; 65 keybinding negative;
66 int16_t value; 66 int16_t value;
67 int16_t deadzone;
67 } joyaxis; 68 } joyaxis;
68 69
69 typedef struct { 70 typedef struct {
70 keybinding *buttons; 71 keybinding *buttons;
71 joydpad *dpads; 72 joydpad *dpads;
142 break; 143 break;
143 } 144 }
144 } 145 }
145 } 146 }
146 147
147 void bind_axis(int joystick, int axis, int positive, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b) 148 void bind_axis(int joystick, int axis, int positive, int deadzone, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b)
148 { 149 {
149 if (joystick >= MAX_JOYSTICKS) { 150 if (joystick >= MAX_JOYSTICKS) {
150 return; 151 return;
151 } 152 }
152 if (!joysticks[joystick].axes) { 153 if (!joysticks[joystick].axes) {
157 uint32_t old_capacity = joysticks[joystick].num_axes; 158 uint32_t old_capacity = joysticks[joystick].num_axes;
158 joysticks[joystick].num_axes *= 2; 159 joysticks[joystick].num_axes *= 2;
159 joysticks[joystick].axes = realloc(joysticks[joystick].axes, sizeof(joyaxis) * joysticks[joystick].num_axes); 160 joysticks[joystick].axes = realloc(joysticks[joystick].axes, sizeof(joyaxis) * joysticks[joystick].num_axes);
160 memset(joysticks[joystick].axes + old_capacity, 0, (joysticks[joystick].num_axes - old_capacity) * sizeof(joyaxis)); 161 memset(joysticks[joystick].axes + old_capacity, 0, (joysticks[joystick].num_axes - old_capacity) * sizeof(joyaxis));
161 } 162 }
163 joysticks[joystick].axes[axis].deadzone = deadzone;
162 if (positive) { 164 if (positive) {
163 do_bind(&joysticks[joystick].axes[axis].positive, bind_type, subtype_a, subtype_b); 165 do_bind(&joysticks[joystick].axes[axis].positive, bind_type, subtype_a, subtype_b);
164 } else { 166 } else {
165 do_bind(&joysticks[joystick].axes[axis].negative, bind_type, subtype_a, subtype_b); 167 do_bind(&joysticks[joystick].axes[axis].negative, bind_type, subtype_a, subtype_b);
166 } 168 }
533 handle_binding_up(dpad->bindings + i); 535 handle_binding_up(dpad->bindings + i);
534 } 536 }
535 } 537 }
536 } 538 }
537 539
538 #define JOY_AXIS_THRESHOLD 2000
539
540 void handle_joy_axis(int joystick, int axis, int16_t value) 540 void handle_joy_axis(int joystick, int axis, int16_t value)
541 { 541 {
542 if (joystick >= MAX_JOYSTICKS || axis >= joysticks[joystick].num_axes) { 542 if (joystick >= MAX_JOYSTICKS || axis >= joysticks[joystick].num_axes) {
543 return; 543 return;
544 } 544 }
545 joyaxis *jaxis = joysticks[joystick].axes + axis; 545 joyaxis *jaxis = joysticks[joystick].axes + axis;
546 int old_active = abs(jaxis->value) > JOY_AXIS_THRESHOLD; 546 int old_active = abs(jaxis->value) > jaxis->deadzone;
547 int new_active = abs(value) > JOY_AXIS_THRESHOLD; 547 int new_active = abs(value) > jaxis->deadzone;
548 int old_pos = jaxis->value > 0; 548 int old_pos = jaxis->value > 0;
549 int new_pos = value > 0; 549 int new_pos = value > 0;
550 jaxis->value = value; 550 jaxis->value = value;
551 if (old_active && (!new_active || old_pos != new_pos)) { 551 if (old_active && (!new_active || old_pos != new_pos)) {
552 //previously activated direction is no longer active 552 //previously activated direction is no longer active
871 871
872 typedef struct { 872 typedef struct {
873 int padnum; 873 int padnum;
874 tern_node *padbuttons; 874 tern_node *padbuttons;
875 tern_node *mousebuttons; 875 tern_node *mousebuttons;
876 int stick_deadzone;
877 int trigger_deadzone;
876 } pad_button_state; 878 } pad_button_state;
877 879
878 880
879 static long map_warning_pad = -1; 881 static long map_warning_pad = -1;
880 void process_pad_button(char *key, tern_val val, uint8_t valtype, void *data) 882 void process_pad_button(char *key, tern_val val, uint8_t valtype, void *data)
903 } 905 }
904 if (hostbutton & RENDER_DPAD_BIT) { 906 if (hostbutton & RENDER_DPAD_BIT) {
905 bind_dpad(hostpadnum, render_dpad_part(hostbutton), render_direction_part(hostbutton), bindtype, subtype_a, subtype_b); 907 bind_dpad(hostpadnum, render_dpad_part(hostbutton), render_direction_part(hostbutton), bindtype, subtype_a, subtype_b);
906 return; 908 return;
907 } else if (hostbutton & RENDER_AXIS_BIT) { 909 } else if (hostbutton & RENDER_AXIS_BIT) {
908 bind_axis(hostpadnum, render_axis_part(hostbutton), hostbutton & RENDER_AXIS_POS, bindtype, subtype_a, subtype_b); 910 bind_axis(hostpadnum, render_axis_part(hostbutton), hostbutton & RENDER_AXIS_POS, state->trigger_deadzone, bindtype, subtype_a, subtype_b);
909 return; 911 return;
910 } 912 }
911 } 913 }
912 bind_button(hostpadnum, hostbutton, bindtype, subtype_a, subtype_b); 914 bind_button(hostpadnum, hostbutton, bindtype, subtype_a, subtype_b);
913 } 915 }
934 warning("Invalid axis modifier %s for axis %s on pad %d\n", modifier, key, hostpadnum); 936 warning("Invalid axis modifier %s for axis %s on pad %d\n", modifier, key, hostpadnum);
935 } 937 }
936 } 938 }
937 char *end; 939 char *end;
938 long axis = strtol(key, &end, 10); 940 long axis = strtol(key, &end, 10);
941 int deadzone = state->stick_deadzone;
939 if (*end) { 942 if (*end) {
940 //key is not a valid base 10 integer 943 //key is not a valid base 10 integer
941 axis = render_translate_input_name(hostpadnum, key, 1); 944 axis = render_translate_input_name(hostpadnum, key, 1);
942 if (axis < 0) { 945 if (axis < 0) {
943 if (axis == RENDER_INVALID_NAME) { 946 if (axis == RENDER_INVALID_NAME) {
946 debug_message("No SDL 2 mapping exists for input %s on gamepad %d\n", key, hostpadnum); 949 debug_message("No SDL 2 mapping exists for input %s on gamepad %d\n", key, hostpadnum);
947 map_warning_pad = hostpadnum; 950 map_warning_pad = hostpadnum;
948 } 951 }
949 goto done; 952 goto done;
950 } 953 }
954 if (!strcmp("lefttrigger", key) || !strcmp("righttrigger", key) || !strcmp("l2", key) || !strcmp("r2", key)) {
955 deadzone = state->trigger_deadzone;
956 }
951 if (axis & RENDER_DPAD_BIT) { 957 if (axis & RENDER_DPAD_BIT) {
952 bind_dpad(hostpadnum, render_dpad_part(axis), render_direction_part(axis), bindtype, subtype_a, subtype_b); 958 bind_dpad(hostpadnum, render_dpad_part(axis), render_direction_part(axis), bindtype, subtype_a, subtype_b);
953 goto done; 959 goto done;
954 } else if (axis & RENDER_AXIS_BIT) { 960 } else if (axis & RENDER_AXIS_BIT) {
955 axis = render_axis_part(axis); 961 axis = render_axis_part(axis);
956 } else { 962 } else {
957 bind_button(hostpadnum, axis, bindtype, subtype_a, subtype_b); 963 bind_button(hostpadnum, axis, bindtype, subtype_a, subtype_b);
958 goto done; 964 goto done;
959 } 965 }
960 } 966 }
961 bind_axis(hostpadnum, axis, positive, bindtype, subtype_a, subtype_b); 967 bind_axis(hostpadnum, axis, positive, deadzone, bindtype, subtype_a, subtype_b);
962 done: 968 done:
963 free(key); 969 free(key);
964 return; 970 return;
965 } 971 }
966 972
1018 handle_binding_down(&bind); 1024 handle_binding_down(&bind);
1019 return 1; 1025 return 1;
1020 } 1026 }
1021 1027
1022 1028
1023 tern_node *get_binding_node_for_pad(int padnum) 1029 tern_node *get_binding_node_for_pad(int padnum, controller_info *info)
1024 { 1030 {
1025 if (padnum > MAX_JOYSTICKS) { 1031 if (padnum > MAX_JOYSTICKS) {
1026 return NULL; 1032 return NULL;
1027 } 1033 }
1028 tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval; 1034 tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval;
1036 char *type_id = render_joystick_type_id(padnum); 1042 char *type_id = render_joystick_type_id(padnum);
1037 pad = tern_find_node(pads, type_id); 1043 pad = tern_find_node(pads, type_id);
1038 free(type_id); 1044 free(type_id);
1039 } 1045 }
1040 if (!pad) { 1046 if (!pad) {
1041 controller_info info = get_controller_info(padnum); 1047 char *key = make_controller_type_key(info);
1042 char *key = make_controller_type_key(&info);
1043 pad = tern_find_node(pads, key); 1048 pad = tern_find_node(pads, key);
1044 free(key); 1049 free(key);
1045 } 1050 }
1046 if (!pad) { 1051 if (!pad) {
1047 pad = tern_find_node(pads, "default"); 1052 pad = tern_find_node(pads, "default");
1049 return pad; 1054 return pad;
1050 } 1055 }
1051 1056
1052 void handle_joy_added(int joystick) 1057 void handle_joy_added(int joystick)
1053 { 1058 {
1054 tern_node *pad = get_binding_node_for_pad(joystick); 1059 controller_info info = get_controller_info(joystick);
1060 tern_node *pad = get_binding_node_for_pad(joystick, &info);
1055 if (!pad) { 1061 if (!pad) {
1056 return; 1062 return;
1057 } 1063 }
1058 tern_node * dpad_node = tern_find_node(pad, "dpads"); 1064 tern_node * dpad_node = tern_find_node(pad, "dpads");
1059 if (dpad_node) { 1065 if (dpad_node) {
1076 } else if (hostbutton & RENDER_DPAD_BIT) { 1082 } else if (hostbutton & RENDER_DPAD_BIT) {
1077 bind_dpad(joystick, render_dpad_part(hostbutton), render_direction_part(hostbutton), bindtype, subtype_a, subtype_b); 1083 bind_dpad(joystick, render_dpad_part(hostbutton), render_direction_part(hostbutton), bindtype, subtype_a, subtype_b);
1078 } else if (hostbutton & RENDER_AXIS_BIT) { 1084 } else if (hostbutton & RENDER_AXIS_BIT) {
1079 //SDL2 knows internally whether this should be a positive or negative binding, but doesn't expose that externally 1085 //SDL2 knows internally whether this should be a positive or negative binding, but doesn't expose that externally
1080 //for now I'll just assume that any controller with axes for a d-pad has these mapped the "sane" way 1086 //for now I'll just assume that any controller with axes for a d-pad has these mapped the "sane" way
1081 bind_axis(joystick, render_axis_part(hostbutton), dir == 1 || dir == 3 ? 1 : 0, bindtype, subtype_a, subtype_b); 1087 bind_axis(joystick, render_axis_part(hostbutton), dir == 1 || dir == 3 ? 1 : 0, info.stick_deadzone, bindtype, subtype_a, subtype_b);
1082 } else { 1088 } else {
1083 bind_button(joystick, hostbutton, bindtype, subtype_a, subtype_b); 1089 bind_button(joystick, hostbutton, bindtype, subtype_a, subtype_b);
1084 } 1090 }
1085 } 1091 }
1086 } 1092 }
1087 } 1093 }
1088 } 1094 }
1095 pad_button_state state = {
1096 .padnum = joystick,
1097 .padbuttons = get_pad_buttons(),
1098 .mousebuttons = get_mouse_buttons(),
1099 .stick_deadzone = info.stick_deadzone,
1100 .trigger_deadzone = info.trigger_deadzone
1101 };
1089 tern_node *button_node = tern_find_node(pad, "buttons"); 1102 tern_node *button_node = tern_find_node(pad, "buttons");
1090 if (button_node) { 1103 if (button_node) {
1091 pad_button_state state = {
1092 .padnum = joystick,
1093 .padbuttons = get_pad_buttons(),
1094 .mousebuttons = get_mouse_buttons()
1095 };
1096 tern_foreach(button_node, process_pad_button, &state); 1104 tern_foreach(button_node, process_pad_button, &state);
1097 } 1105 }
1098 tern_node *axes_node = tern_find_node(pad, "axes"); 1106 tern_node *axes_node = tern_find_node(pad, "axes");
1099 if (axes_node) { 1107 if (axes_node) {
1100 pad_button_state state = {
1101 .padnum = joystick,
1102 .padbuttons = get_pad_buttons(),
1103 .mousebuttons = get_mouse_buttons()
1104 };
1105 tern_foreach(axes_node, process_pad_axis, &state); 1108 tern_foreach(axes_node, process_pad_axis, &state);
1106 } 1109 }
1107 } 1110 }
1108 1111
1109 //only handles keyboards and mice as gamepads are handled on hotplug events 1112 //only handles keyboards and mice as gamepads are handled on hotplug events