summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Admiraal <madmiraal@users.noreply.github.com>2020-04-23 10:16:09 +0100
committerMarcel Admiraal <madmiraal@users.noreply.github.com>2020-05-13 10:33:19 +0100
commit1176e078b965994964e7699efd41d9a8958db6da (patch)
treeec7745e5f51cd0c2a3a7157af7c0adfcaa02bd7a
parenta92f5f306166251ccb72666c516805d364ea4cdc (diff)
Parse SDL game controller half axis and inverted axis entries.
-rw-r--r--core/input/input.cpp317
-rw-r--r--core/input/input.h79
-rw-r--r--core/input/input_builders.py13
3 files changed, 288 insertions, 121 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 357e4c06c1..8d0686cce4 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -831,21 +831,9 @@ void Input::joy_button(int p_device, int p_button, bool p_pressed) {
return;
}
- const Map<int, JoyEvent>::Element *el = map_db[joy.mapping].buttons.find(p_button);
- if (!el) {
- //don't process un-mapped events for now, it could mess things up badly for devices with additional buttons/axis
- //return _button_event(p_last_id, p_device, p_button, p_pressed);
- return;
- }
+ JoyEvent map = _get_mapped_button_event(map_db[joy.mapping], p_button);
- JoyEvent map = el->get();
if (map.type == TYPE_BUTTON) {
- //fake additional axis event for triggers
- if (map.index == JOY_L2 || map.index == JOY_R2) {
- float value = p_pressed ? 1.0f : 0.0f;
- int axis = map.index == JOY_L2 ? JOY_ANALOG_L2 : JOY_ANALOG_R2;
- _axis_event(p_device, axis, value);
- }
_button_event(p_device, map.index, p_pressed);
return;
}
@@ -901,13 +889,7 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
return;
};
- const Map<int, JoyEvent>::Element *el = map_db[joy.mapping].axis.find(p_axis);
- if (!el) {
- //return _axis_event(p_last_id, p_device, p_axis, p_value);
- return;
- };
-
- JoyEvent map = el->get();
+ JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis);
if (map.type == TYPE_BUTTON) {
//send axis event for triggers
@@ -976,12 +958,26 @@ void Input::joy_hat(int p_device, int p_val) {
_THREAD_SAFE_METHOD_;
const Joypad &joy = joy_names[p_device];
- const JoyEvent *map;
+ JoyEvent map[HAT_MAX];
- if (joy.mapping == -1) {
- map = hat_map_default;
- } else {
- map = map_db[joy.mapping].hat;
+ map[HAT_UP].type = TYPE_BUTTON;
+ map[HAT_UP].index = SDL_BUTTON_DPAD_UP;
+ map[HAT_UP].value = 0;
+
+ map[HAT_RIGHT].type = TYPE_BUTTON;
+ map[HAT_RIGHT].index = SDL_BUTTON_DPAD_RIGHT;
+ map[HAT_RIGHT].value = 0;
+
+ map[HAT_DOWN].type = TYPE_BUTTON;
+ map[HAT_DOWN].index = SDL_BUTTON_DPAD_DOWN;
+ map[HAT_DOWN].value = 0;
+
+ map[HAT_LEFT].type = TYPE_BUTTON;
+ map[HAT_LEFT].index = SDL_BUTTON_DPAD_LEFT;
+ map[HAT_LEFT].value = 0;
+
+ if (joy.mapping != -1) {
+ _get_mapped_hat_events(map_db[joy.mapping], 0, map);
};
int cur_val = joy_names[p_device].hat_current;
@@ -1025,50 +1021,145 @@ void Input::_axis_event(int p_device, int p_axis, float p_value) {
parse_input_event(ievent);
};
-Input::JoyEvent Input::_find_to_event(String p_to) {
+Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button) {
- // string names of the SDL buttons in the same order as input_event.h godot buttons
- static const char *buttons[] = { "a", "b", "x", "y", "leftshoulder", "rightshoulder", "lefttrigger", "righttrigger", "leftstick", "rightstick", "back", "start", "dpup", "dpdown", "dpleft", "dpright", "guide", nullptr };
+ JoyEvent event;
+ event.type = TYPE_MAX;
- static const char *axis[] = { "leftx", "lefty", "rightx", "righty", nullptr };
+ for (int i = 0; i < mapping.bindings.size(); i++) {
+ const SDLExtendedJoyBind binding = mapping.bindings[i];
+ if (binding.inputType == TYPE_BUTTON && binding.input.button == p_button) {
+ event.type = binding.outputType;
+ switch (binding.outputType) {
+ case TYPE_BUTTON:
+ event.index = binding.output.button;
+ break;
+ case TYPE_AXIS:
+ event.index = binding.output.axis.axis;
+ break;
+ default:
+ ERR_PRINT_ONCE("Joypad button mapping error.");
+ }
+ }
+ }
+ return event;
+}
- JoyEvent ret;
- ret.type = -1;
- ret.index = 0;
+Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis) {
- int i = 0;
- while (buttons[i]) {
+ JoyEvent event;
+ event.type = TYPE_MAX;
- if (p_to == buttons[i]) {
- ret.type = TYPE_BUTTON;
- ret.index = i;
- ret.value = 0;
- return ret;
- };
- ++i;
- };
+ for (int i = 0; i < mapping.bindings.size(); i++) {
+ const SDLExtendedJoyBind binding = mapping.bindings[i];
+ if (binding.inputType == TYPE_AXIS && binding.input.axis.axis == p_axis) {
+ event.type = binding.outputType;
+ switch (binding.outputType) {
+ case TYPE_BUTTON:
+ event.index = binding.output.button;
+ break;
+ case TYPE_AXIS:
+ event.index = binding.output.axis.axis;
+ break;
+ default:
+ ERR_PRINT_ONCE("Joypad button mapping error.");
+ }
+ }
+ }
+ return event;
+}
- i = 0;
- while (axis[i]) {
+void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[]) {
- if (p_to == axis[i]) {
- ret.type = TYPE_AXIS;
- ret.index = i;
- ret.value = 0;
- return ret;
- };
- ++i;
- };
+ for (int i = 0; i < mapping.bindings.size(); i++) {
+ const SDLExtendedJoyBind binding = mapping.bindings[i];
+ if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) {
- return ret;
+ int index;
+ switch (binding.input.hat.hat_mask) {
+ case HAT_MASK_UP:
+ index = 0;
+ break;
+ case HAT_MASK_RIGHT:
+ index = 1;
+ break;
+ case HAT_MASK_DOWN:
+ index = 2;
+ break;
+ case HAT_MASK_LEFT:
+ index = 3;
+ break;
+ default:
+ ERR_PRINT_ONCE("Joypad button mapping error.");
+ continue;
+ }
+
+ r_events[index].type = binding.outputType;
+ switch (binding.outputType) {
+ case TYPE_BUTTON:
+ r_events[index].index = binding.output.button;
+ break;
+ case TYPE_AXIS:
+ r_events[index].index = binding.output.axis.axis;
+ break;
+ default:
+ ERR_PRINT_ONCE("Joypad button mapping error.");
+ }
+ }
+ }
+}
+
+static const char *sdl_buttons[] = {
+ "a",
+ "b",
+ "x",
+ "y",
+ "back",
+ "guide",
+ "start",
+ "leftstick",
+ "rightstick",
+ "leftshoulder",
+ "rightshoulder",
+ "dpup",
+ "dpdown",
+ "dpleft",
+ "dpright",
+ nullptr
+};
+
+Input::SDLJoyButton Input::_get_output_button(String output) {
+
+ for (int i = 0; sdl_buttons[i]; i++) {
+ if (output == sdl_buttons[i])
+ return SDLJoyButton(i);
+ }
+ return SDLJoyButton::SDL_INVALID_BUTTON;
+}
+
+static const char *sdl_axes[] = {
+ "leftx",
+ "lefty",
+ "rightx",
+ "righty",
+ "lefttrigger",
+ "righttrigger",
+ nullptr
};
+Input::SDLJoyAxis Input::_get_output_axis(String output) {
+
+ for (int i = 0; sdl_axes[i]; i++) {
+ if (output == sdl_axes[i])
+ return SDLJoyAxis(i);
+ }
+ return SDLJoyAxis::SDL_INVALID_AXIS;
+}
+
void Input::parse_mapping(String p_mapping) {
_THREAD_SAFE_METHOD_;
JoyDeviceMapping mapping;
- for (int i = 0; i < HAT_MAX; ++i)
- mapping.hat[i].index = 1024 + i;
Vector<String> entry = p_mapping.split(",");
if (entry.size() < 2) {
@@ -1087,45 +1178,83 @@ void Input::parse_mapping(String p_mapping) {
if (entry[idx] == "")
continue;
- String from = entry[idx].get_slice(":", 1).replace(" ", "");
- String to = entry[idx].get_slice(":", 0).replace(" ", "");
+ String output = entry[idx].get_slice(":", 0).replace(" ", "");
+ String input = entry[idx].get_slice(":", 1).replace(" ", "");
+ ERR_CONTINUE_MSG(output.length() < 1 || input.length() < 2,
+ String(entry[idx] + "\nInvalid device mapping entry: " + entry[idx]));
- JoyEvent to_event = _find_to_event(to);
- if (to_event.type == -1)
+ if (output == "platform")
continue;
- String etype = from.substr(0, 1);
- if (etype == "a") {
-
- int aid = from.substr(1, from.length() - 1).to_int();
- mapping.axis[aid] = to_event;
-
- } else if (etype == "b") {
+ JoyAxisRange output_range = FULL_AXIS;
+ if (output[0] == '+' || output[0] == '-') {
+ ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx]));
+ output = output.right(1);
+ if (output[0] == '+')
+ output_range = POSITIVE_HALF_AXIS;
+ else if (output[0] == '-')
+ output_range = NEGATIVE_HALF_AXIS;
+ }
- int bid = from.substr(1, from.length() - 1).to_int();
- mapping.buttons[bid] = to_event;
+ JoyAxisRange input_range = FULL_AXIS;
+ if (input[0] == '+') {
+ input_range = POSITIVE_HALF_AXIS;
+ input = input.right(1);
+ } else if (input[0] == '-') {
+ input_range = NEGATIVE_HALF_AXIS;
+ input = input.right(1);
+ }
+ bool invert_axis = false;
+ if (input[input.length() - 1] == '~')
+ invert_axis = true;
+
+ SDLJoyButton output_button = _get_output_button(output);
+ SDLJoyAxis output_axis = _get_output_axis(output);
+ ERR_CONTINUE_MSG(output_button == SDL_INVALID_BUTTON && output_axis == SDL_INVALID_AXIS,
+ String(entry[idx] + "\nUnrecognised output string: " + output));
+ ERR_CONTINUE_MSG(output_button != SDL_INVALID_BUTTON && output_axis != SDL_INVALID_AXIS,
+ String("BUG: Output string matched both button and axis: " + output));
+
+ SDLExtendedJoyBind binding;
+ if (output_button != SDL_INVALID_BUTTON) {
+ binding.outputType = TYPE_BUTTON;
+ binding.output.button = output_button;
+ } else if (output_axis != SDL_INVALID_AXIS) {
+ binding.outputType = TYPE_AXIS;
+ binding.output.axis.axis = output_axis;
+ binding.output.axis.range = output_range;
+ }
- } else if (etype == "h") {
+ switch (input[0]) {
+ case 'b':
+ binding.inputType = TYPE_BUTTON;
+ binding.input.button = input.right(1).to_int();
+ break;
+ case 'a':
+ binding.inputType = TYPE_AXIS;
+ binding.input.axis.axis = input.right(1).to_int();
+ binding.input.axis.range = input_range;
+ if (invert_axis) {
+ int int_range = static_cast<int>(input_range);
+ int_range = -int_range;
+ binding.input.axis.range = static_cast<JoyAxisRange>(int_range);
+ }
+ break;
+ case 'h':
+ ERR_CONTINUE_MSG(input.length() != 4 || input[2] != '.',
+ String(entry[idx] + "\nInvalid hat input: " + input));
+ binding.inputType = TYPE_HAT;
+ binding.input.hat.hat = input.substr(1, 1).to_int();
+ binding.input.hat.hat_mask = static_cast<HatMask>(input.right(3).to_int());
+ break;
+ default:
+ ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input));
+ }
- int hat_value = from.get_slice(".", 1).to_int();
- switch (hat_value) {
- case 1:
- mapping.hat[HAT_UP] = to_event;
- break;
- case 2:
- mapping.hat[HAT_RIGHT] = to_event;
- break;
- case 4:
- mapping.hat[HAT_DOWN] = to_event;
- break;
- case 8:
- mapping.hat[HAT_LEFT] = to_event;
- break;
- };
- };
+ mapping.bindings.push_back(binding);
};
+
map_db.push_back(mapping);
- //printf("added mapping with uuid %ls\n", mapping.uid.c_str());
};
void Input::add_joy_mapping(String p_mapping, bool p_update_existing) {
@@ -1268,22 +1397,6 @@ Input::Input() {
event_dispatch_function = nullptr;
default_shape = CURSOR_ARROW;
- hat_map_default[HAT_UP].type = TYPE_BUTTON;
- hat_map_default[HAT_UP].index = JOY_DPAD_UP;
- hat_map_default[HAT_UP].value = 0;
-
- hat_map_default[HAT_RIGHT].type = TYPE_BUTTON;
- hat_map_default[HAT_RIGHT].index = JOY_DPAD_RIGHT;
- hat_map_default[HAT_RIGHT].value = 0;
-
- hat_map_default[HAT_DOWN].type = TYPE_BUTTON;
- hat_map_default[HAT_DOWN].index = JOY_DPAD_DOWN;
- hat_map_default[HAT_DOWN].value = 0;
-
- hat_map_default[HAT_LEFT].type = TYPE_BUTTON;
- hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT;
- hat_map_default[HAT_LEFT].value = 0;
-
fallback_mapping = -1;
// Parse default mappings.
diff --git a/core/input/input.h b/core/input/input.h
index 2e136dbf02..f95dff47a9 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -183,26 +183,91 @@ private:
TYPE_MAX,
};
+ enum SDLJoyButton {
+ SDL_INVALID_BUTTON = -1,
+ SDL_BUTTON_A,
+ SDL_BUTTON_B,
+ SDL_BUTTON_X,
+ SDL_BUTTON_Y,
+ SDL_BUTTON_BACK,
+ SDL_BUTTON_GUIDE,
+ SDL_BUTTON_START,
+ SDL_BUTTON_LEFTSTICK,
+ SDL_BUTTON_RIGHTSTICK,
+ SDL_BUTTON_LEFTSHOULDER,
+ SDL_BUTTON_RIGHTSHOULDER,
+ SDL_BUTTON_DPAD_UP,
+ SDL_BUTTON_DPAD_DOWN,
+ SDL_BUTTON_DPAD_LEFT,
+ SDL_BUTTON_DPAD_RIGHT,
+ SDL_BUTTON_MAX
+ };
+
+ enum SDLJoyAxis {
+ SDL_INVALID_AXIS = -1,
+ SDL_AXIS_LEFTX,
+ SDL_AXIS_LEFTY,
+ SDL_AXIS_RIGHTX,
+ SDL_AXIS_RIGHTY,
+ SDL_AXIS_TRIGGERLEFT,
+ SDL_AXIS_TRIGGERRIGHT,
+ SDL_AXIS_MAX,
+ };
+
+ enum JoyAxisRange {
+ NEGATIVE_HALF_AXIS = -1,
+ FULL_AXIS = 0,
+ POSITIVE_HALF_AXIS = 1
+ };
+
struct JoyEvent {
int type;
int index;
int value;
};
- struct JoyDeviceMapping {
+ struct SDLExtendedJoyBind {
+ JoyType inputType;
+ union {
+ int button;
+
+ struct {
+ int axis;
+ JoyAxisRange range;
+ } axis;
+ struct {
+ int hat;
+ HatMask hat_mask;
+ } hat;
+
+ } input;
+
+ JoyType outputType;
+ union {
+ SDLJoyButton button;
+
+ struct {
+ SDLJoyAxis axis;
+ JoyAxisRange range;
+ } axis;
+
+ } output;
+ };
+
+ struct JoyDeviceMapping {
String uid;
String name;
- Map<int, JoyEvent> buttons;
- Map<int, JoyEvent> axis;
- JoyEvent hat[HAT_MAX];
+ Vector<SDLExtendedJoyBind> bindings;
};
- JoyEvent hat_map_default[HAT_MAX];
-
Vector<JoyDeviceMapping> map_db;
- JoyEvent _find_to_event(String p_to);
+ JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button);
+ JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis);
+ void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]);
+ SDLJoyButton _get_output_button(String output);
+ SDLJoyAxis _get_output_axis(String output);
void _button_event(int p_device, int p_index, bool p_pressed);
void _axis_event(int p_device, int p_axis, float p_value);
float _handle_deadzone(int p_device, int p_axis, float p_value);
diff --git a/core/input/input_builders.py b/core/input/input_builders.py
index 53b90f2073..748ec06133 100644
--- a/core/input/input_builders.py
+++ b/core/input/input_builders.py
@@ -42,18 +42,7 @@ def make_default_controller_mappings(target, source, env):
src_path, current_platform, platform_mappings[current_platform][guid]
)
)
- valid_mapping = True
- for input_map in line_parts[2:]:
- if "+" in input_map or "-" in input_map or "~" in input_map:
- g.write(
- "// WARNING - DISCARDED UNSUPPORTED MAPPING TYPE FROM DATABASE {}: {} {}\n".format(
- src_path, current_platform, line
- )
- )
- valid_mapping = False
- break
- if valid_mapping:
- platform_mappings[current_platform][guid] = line
+ platform_mappings[current_platform][guid] = line
platform_variables = {
"Linux": "#if X11_ENABLED",