1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-09 12:50:35 +00:00

Provide support for buttons and D-pads mapped to half axes, and

fix axes mapped to buttons and D-pads.
This commit is contained in:
Marcel Admiraal
2020-10-14 17:07:50 +01:00
parent 078c632592
commit 954b14ecec
2 changed files with 106 additions and 78 deletions

View File

@@ -759,7 +759,7 @@ void InputDefault::joy_button(int p_device, int p_button, bool p_pressed) {
} }
if (map.type == TYPE_AXIS) { if (map.type == TYPE_AXIS) {
_axis_event(p_device, map.index, p_pressed ? 1.0 : 0.0); _axis_event(p_device, map.index, p_pressed ? map.value : 0.0);
} }
// no event? // no event?
} }
@@ -809,7 +809,7 @@ void InputDefault::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
return; return;
}; };
JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis, p_value); JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis, val);
if (map.type == TYPE_BUTTON) { if (map.type == TYPE_BUTTON) {
//send axis event for triggers //send axis event for triggers
@@ -819,49 +819,39 @@ void InputDefault::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
_axis_event(p_device, axis, value); _axis_event(p_device, axis, value);
} }
if (map.index == JOY_DPAD_UP || map.index == JOY_DPAD_DOWN) { bool pressed = map.value > 0.5;
bool pressed = p_value.value != 0.0f;
int button = p_value.value < 0 ? JOY_DPAD_UP : JOY_DPAD_DOWN;
if (!pressed) {
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_UP, p_device))) {
_button_event(p_device, JOY_DPAD_UP, false);
}
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_DOWN, p_device))) {
_button_event(p_device, JOY_DPAD_DOWN, false);
}
}
if (pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) {
return;
}
_button_event(p_device, button, true);
return;
}
if (map.index == JOY_DPAD_LEFT || map.index == JOY_DPAD_RIGHT) {
bool pressed = p_value.value != 0.0f;
int button = p_value.value < 0 ? JOY_DPAD_LEFT : JOY_DPAD_RIGHT;
if (!pressed) {
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_LEFT, p_device))) {
_button_event(p_device, JOY_DPAD_LEFT, false);
}
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_RIGHT, p_device))) {
_button_event(p_device, JOY_DPAD_RIGHT, false);
}
}
if (pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) {
return;
}
_button_event(p_device, button, true);
return;
}
float deadzone = p_value.min == 0 ? 0.5f : 0.0f;
bool pressed = p_value.value > deadzone;
if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) { if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) {
// button already pressed or released, this is an axis bounce value // Button already pressed or released; so ignore.
return; return;
} }
_button_event(p_device, map.index, pressed); _button_event(p_device, map.index, pressed);
// Ensure opposite D-Pad button is also released.
switch (map.index) {
case JOY_DPAD_UP:
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_DOWN, p_device))) {
_button_event(p_device, JOY_DPAD_DOWN, false);
}
break;
case JOY_DPAD_DOWN:
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_UP, p_device))) {
_button_event(p_device, JOY_DPAD_UP, false);
}
break;
case JOY_DPAD_LEFT:
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_RIGHT, p_device))) {
_button_event(p_device, JOY_DPAD_RIGHT, false);
}
break;
case JOY_DPAD_RIGHT:
if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_LEFT, p_device))) {
_button_event(p_device, JOY_DPAD_LEFT, false);
}
break;
default:
// Nothing to do.
break;
}
return; return;
} }
@@ -902,18 +892,15 @@ void InputDefault::joy_hat(int p_device, int p_val) {
int cur_val = joy_names[p_device].hat_current; int cur_val = joy_names[p_device].hat_current;
if ((p_val & HAT_MASK_UP) != (cur_val & HAT_MASK_UP)) { for (int hat_direction = 0, hat_mask = 1; hat_direction < HAT_MAX; hat_direction++, hat_mask <<= 1) {
_button_event(p_device, map[HAT_UP].index, p_val & HAT_MASK_UP); if ((p_val & hat_mask) != (cur_val & hat_mask)) {
if (map[hat_direction].type == TYPE_BUTTON) {
_button_event(p_device, map[hat_direction].index, p_val & hat_mask);
} }
if (map[hat_direction].type == TYPE_AXIS) {
if ((p_val & HAT_MASK_RIGHT) != (cur_val & HAT_MASK_RIGHT)) { _axis_event(p_device, map[hat_direction].index, (p_val & hat_mask) ? map[hat_direction].value : 0.0);
_button_event(p_device, map[HAT_RIGHT].index, p_val & HAT_MASK_RIGHT);
} }
if ((p_val & HAT_MASK_DOWN) != (cur_val & HAT_MASK_DOWN)) {
_button_event(p_device, map[HAT_DOWN].index, p_val & HAT_MASK_DOWN);
} }
if ((p_val & HAT_MASK_LEFT) != (cur_val & HAT_MASK_LEFT)) {
_button_event(p_device, map[HAT_LEFT].index, p_val & HAT_MASK_LEFT);
} }
joy_names[p_device].hat_current = p_val; joy_names[p_device].hat_current = p_val;
@@ -956,6 +943,19 @@ InputDefault::JoyEvent InputDefault::_get_mapped_button_event(const JoyDeviceMap
return event; return event;
case TYPE_AXIS: case TYPE_AXIS:
event.index = binding.output.axis.axis; event.index = binding.output.axis.axis;
switch (binding.output.axis.range) {
case POSITIVE_HALF_AXIS:
event.value = 1;
break;
case NEGATIVE_HALF_AXIS:
event.value = -1;
break;
case FULL_AXIS:
// It doesn't make sense for a button to map to a full axis,
// but keeping as a default for a trigger with a positive half-axis.
event.value = 1;
break;
}
return event; return event;
default: default:
ERR_PRINT_ONCE("Joypad button mapping error."); ERR_PRINT_ONCE("Joypad button mapping error.");
@@ -965,7 +965,7 @@ InputDefault::JoyEvent InputDefault::_get_mapped_button_event(const JoyDeviceMap
return event; return event;
} }
InputDefault::JoyEvent InputDefault::_get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, const JoyAxis &p_value) { InputDefault::JoyEvent InputDefault::_get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value) {
JoyEvent event; JoyEvent event;
event.type = TYPE_MAX; event.type = TYPE_MAX;
@@ -973,21 +973,13 @@ InputDefault::JoyEvent InputDefault::_get_mapped_axis_event(const JoyDeviceMappi
for (int i = 0; i < mapping.bindings.size(); i++) { for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i]; const JoyBinding binding = mapping.bindings[i];
if (binding.inputType == TYPE_AXIS && binding.input.axis.axis == p_axis) { if (binding.inputType == TYPE_AXIS && binding.input.axis.axis == p_axis) {
float value = p_value.value; float value = p_value;
if (binding.input.axis.invert) if (binding.input.axis.invert)
value = -value; value = -value;
if (binding.input.axis.range == FULL_AXIS || if (binding.input.axis.range == FULL_AXIS ||
(binding.input.axis.range == POSITIVE_HALF_AXIS && value > 0) || (binding.input.axis.range == POSITIVE_HALF_AXIS && value > 0) ||
(binding.input.axis.range == NEGATIVE_HALF_AXIS && value < 0)) { (binding.input.axis.range == NEGATIVE_HALF_AXIS && value < 0)) {
event.type = binding.outputType; event.type = binding.outputType;
switch (binding.outputType) {
case TYPE_BUTTON:
event.index = binding.output.button;
return event;
case TYPE_AXIS:
event.index = binding.output.axis.axis;
event.value = value;
if (binding.output.axis.range != binding.input.axis.range) {
float shifted_positive_value = 0; float shifted_positive_value = 0;
switch (binding.input.axis.range) { switch (binding.input.axis.range) {
case POSITIVE_HALF_AXIS: case POSITIVE_HALF_AXIS:
@@ -1000,6 +992,27 @@ InputDefault::JoyEvent InputDefault::_get_mapped_axis_event(const JoyDeviceMappi
shifted_positive_value = (value + 1) / 2; shifted_positive_value = (value + 1) / 2;
break; break;
} }
switch (binding.outputType) {
case TYPE_BUTTON:
event.index = binding.output.button;
switch (binding.input.axis.range) {
case POSITIVE_HALF_AXIS:
event.value = shifted_positive_value;
break;
case NEGATIVE_HALF_AXIS:
event.value = 1 - shifted_positive_value;
break;
case FULL_AXIS:
// It doesn't make sense for a full axis to map to a button,
// but keeping as a default for a trigger with a positive half-axis.
event.value = (shifted_positive_value * 2) - 1;
break;
}
return event;
case TYPE_AXIS:
event.index = binding.output.axis.axis;
event.value = value;
if (binding.output.axis.range != binding.input.axis.range) {
switch (binding.output.axis.range) { switch (binding.output.axis.range) {
case POSITIVE_HALF_AXIS: case POSITIVE_HALF_AXIS:
event.value = shifted_positive_value; event.value = shifted_positive_value;
@@ -1028,32 +1041,45 @@ void InputDefault::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p
const JoyBinding binding = mapping.bindings[i]; const JoyBinding binding = mapping.bindings[i];
if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) { if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) {
int index; int hat_direction;
switch (binding.input.hat.hat_mask) { switch (binding.input.hat.hat_mask) {
case HAT_MASK_UP: case HAT_MASK_UP:
index = 0; hat_direction = HAT_UP;
break; break;
case HAT_MASK_RIGHT: case HAT_MASK_RIGHT:
index = 1; hat_direction = HAT_RIGHT;
break; break;
case HAT_MASK_DOWN: case HAT_MASK_DOWN:
index = 2; hat_direction = HAT_DOWN;
break; break;
case HAT_MASK_LEFT: case HAT_MASK_LEFT:
index = 3; hat_direction = HAT_LEFT;
break; break;
default: default:
ERR_PRINT_ONCE("Joypad button mapping error."); ERR_PRINT_ONCE("Joypad button mapping error.");
continue; continue;
} }
r_events[index].type = binding.outputType; r_events[hat_direction].type = binding.outputType;
switch (binding.outputType) { switch (binding.outputType) {
case TYPE_BUTTON: case TYPE_BUTTON:
r_events[index].index = binding.output.button; r_events[hat_direction].index = binding.output.button;
break; break;
case TYPE_AXIS: case TYPE_AXIS:
r_events[index].index = binding.output.axis.axis; r_events[hat_direction].index = binding.output.axis.axis;
switch (binding.output.axis.range) {
case POSITIVE_HALF_AXIS:
r_events[hat_direction].value = 1;
break;
case NEGATIVE_HALF_AXIS:
r_events[hat_direction].value = -1;
break;
case FULL_AXIS:
// It doesn't make sense for a hat direction to map to a full axis,
// but keeping as a default for a trigger with a positive half-axis.
r_events[hat_direction].value = 1;
break;
}
break; break;
default: default:
ERR_PRINT_ONCE("Joypad button mapping error."); ERR_PRINT_ONCE("Joypad button mapping error.");
@@ -1117,11 +1143,11 @@ void InputDefault::parse_mapping(String p_mapping) {
JoyAxisRange output_range = FULL_AXIS; JoyAxisRange output_range = FULL_AXIS;
if (output[0] == '+' || output[0] == '-') { if (output[0] == '+' || output[0] == '-') {
ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx])); ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx]));
output = output.right(1);
if (output[0] == '+') if (output[0] == '+')
output_range = POSITIVE_HALF_AXIS; output_range = POSITIVE_HALF_AXIS;
else if (output[0] == '-') else if (output[0] == '-')
output_range = NEGATIVE_HALF_AXIS; output_range = NEGATIVE_HALF_AXIS;
output = output.right(1);
} }
JoyAxisRange input_range = FULL_AXIS; JoyAxisRange input_range = FULL_AXIS;
@@ -1133,8 +1159,10 @@ void InputDefault::parse_mapping(String p_mapping) {
input = input.right(1); input = input.right(1);
} }
bool invert_axis = false; bool invert_axis = false;
if (input[input.length() - 1] == '~') if (input[input.length() - 1] == '~') {
invert_axis = true; invert_axis = true;
input = input.left(input.length() - 1);
}
JoystickList output_button = _get_output_button(output); JoystickList output_button = _get_output_button(output);
JoystickList output_axis = _get_output_axis(output); JoystickList output_axis = _get_output_axis(output);

View File

@@ -199,7 +199,7 @@ private:
Vector<JoyDeviceMapping> map_db; Vector<JoyDeviceMapping> map_db;
JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button); JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button);
JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, const JoyAxis &p_value); JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value);
void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]); void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]);
JoystickList _get_output_button(String output); JoystickList _get_output_button(String output);
JoystickList _get_output_axis(String output); JoystickList _get_output_axis(String output);