Mercurial > repos > blastem
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 |