|
@@ -66,36 +66,59 @@ static EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamep
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
+ const int real_button_count = gamepadEvent->numButtons;
|
|
|
+ const int real_axis_count = gamepadEvent->numAxes;
|
|
|
+ int first_trigger_button = -1;
|
|
|
int first_hat_button = -1;
|
|
|
int num_buttons = gamepadEvent->numButtons;
|
|
|
- if ((SDL_strcmp(gamepadEvent->mapping, "standard") == 0) && (num_buttons >= 16)) { // maps to a game console gamepad layout, turn the d-pad into a hat.
|
|
|
- num_buttons -= 4;
|
|
|
+ int num_axes = gamepadEvent->numAxes;
|
|
|
+ bool triggers_are_buttons = false;
|
|
|
+ if ((SDL_strcmp(gamepadEvent->mapping, "standard") == 0) && (num_buttons >= 16)) { // maps to a game console gamepad layout, turn the d-pad into a hat, treat triggers as analog.
|
|
|
+ num_buttons -= 4; // 4 dpad buttons become a hat.
|
|
|
first_hat_button = 12;
|
|
|
+
|
|
|
+ if (num_axes == 4) { // Chrome gives the triggers analog button values, Firefox exposes them as extra axes. Both have the digital buttons.
|
|
|
+ num_axes += 2; // the two trigger "buttons"
|
|
|
+ triggers_are_buttons = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // dump the digital trigger buttons in any case.
|
|
|
+ first_trigger_button = 6;
|
|
|
+ num_buttons -= 2;
|
|
|
}
|
|
|
|
|
|
item->first_hat_button = first_hat_button;
|
|
|
+ item->first_trigger_button = first_trigger_button;
|
|
|
+ item->triggers_are_buttons = triggers_are_buttons;
|
|
|
item->nhats = (first_hat_button >= 0) ? 1 : 0;
|
|
|
- item->naxes = gamepadEvent->numAxes;
|
|
|
+ item->naxes = num_axes;
|
|
|
item->nbuttons = num_buttons;
|
|
|
item->device_instance = SDL_GetNextObjectID();
|
|
|
|
|
|
item->timestamp = gamepadEvent->timestamp;
|
|
|
|
|
|
- for (i = 0; i < item->naxes; i++) {
|
|
|
- item->axis[i] = gamepadEvent->axis[i];
|
|
|
- }
|
|
|
-
|
|
|
int buttonidx = 0;
|
|
|
- for (i = 0; i < item->nbuttons; i++, buttonidx++) {
|
|
|
+ for (i = 0; i < real_button_count; i++, buttonidx++) {
|
|
|
if (buttonidx == first_hat_button) {
|
|
|
- buttonidx += 3; // skip these buttons, we're treating them as hat input.
|
|
|
+ buttonidx += 4; // skip these buttons, we're treating them as hat input.
|
|
|
+ } else if (buttonidx == first_trigger_button) {
|
|
|
+ buttonidx += 2; // skip these buttons, we're treating them as axes.
|
|
|
}
|
|
|
item->analogButton[i] = gamepadEvent->analogButton[buttonidx];
|
|
|
item->digitalButton[i] = gamepadEvent->digitalButton[buttonidx];
|
|
|
}
|
|
|
|
|
|
+ for (i = 0; i < real_axis_count; i++) {
|
|
|
+ item->axis[i] = gamepadEvent->axis[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (item->triggers_are_buttons) {
|
|
|
+ item->axis[real_axis_count] = (gamepadEvent->analogButton[first_trigger_button] * 2.0f) - 1.0f;
|
|
|
+ item->axis[real_axis_count+1] = (gamepadEvent->analogButton[first_trigger_button+1] * 2.0f) - 1.0f;
|
|
|
+ }
|
|
|
+
|
|
|
SDL_assert(item->nhats <= 1); // there is (currently) only ever one of these, faked from the d-pad buttons.
|
|
|
- if (item->nhats) {
|
|
|
+ if (first_hat_button != -1) {
|
|
|
Uint8 value = SDL_HAT_CENTERED;
|
|
|
// this currently expects the first button to be up, then down, then left, then right.
|
|
|
if (gamepadEvent->digitalButton[first_hat_button + 0]) {
|
|
@@ -393,14 +416,19 @@ static void EMSCRIPTEN_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
if (result == EMSCRIPTEN_RESULT_SUCCESS) {
|
|
|
if (gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) {
|
|
|
const int first_hat_button = item->first_hat_button;
|
|
|
+ const int first_trigger_button = item->first_trigger_button;
|
|
|
+ const int real_button_count = gamepadState.numButtons;
|
|
|
+ const int real_axis_count = gamepadState.numAxes;
|
|
|
|
|
|
int buttonidx = 0;
|
|
|
- for (i = 0; i < item->nbuttons; i++, buttonidx++) {
|
|
|
+ for (i = 0; i < real_button_count; i++, buttonidx++) {
|
|
|
if (buttonidx == first_hat_button) {
|
|
|
buttonidx += 4; // skip these buttons, we're treating them as hat input.
|
|
|
+ } else if (buttonidx == first_trigger_button) {
|
|
|
+ buttonidx += 2; // skip these buttons, we're treating them as axes.
|
|
|
}
|
|
|
if (item->digitalButton[i] != gamepadState.digitalButton[buttonidx]) {
|
|
|
- bool down = (gamepadState.digitalButton[buttonidx] != 0);
|
|
|
+ const bool down = (gamepadState.digitalButton[buttonidx] != 0);
|
|
|
SDL_SendJoystickButton(timestamp, item->joystick, i, down);
|
|
|
}
|
|
|
|
|
@@ -409,15 +437,20 @@ static void EMSCRIPTEN_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
item->digitalButton[i] = gamepadState.digitalButton[buttonidx];
|
|
|
}
|
|
|
|
|
|
- for (i = 0; i < item->naxes; i++) {
|
|
|
+ for (i = 0; i < real_axis_count; i++) {
|
|
|
if (item->axis[i] != gamepadState.axis[i]) {
|
|
|
- // do we need to do conversion?
|
|
|
- SDL_SendJoystickAxis(timestamp, item->joystick, i,
|
|
|
- (Sint16)(32767. * gamepadState.axis[i]));
|
|
|
+ SDL_SendJoystickAxis(timestamp, item->joystick, i, (Sint16)(32767.0f * gamepadState.axis[i]));
|
|
|
+ item->axis[i] = gamepadState.axis[i];
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // store to compare in next update
|
|
|
- item->axis[i] = gamepadState.axis[i];
|
|
|
+ if (item->triggers_are_buttons) {
|
|
|
+ for (i = 0; i < 2; i++) {
|
|
|
+ if (item->axis[real_axis_count+i] != gamepadState.analogButton[first_trigger_button+i]) {
|
|
|
+ SDL_SendJoystickAxis(timestamp, item->joystick, real_axis_count+i, (Sint16)(32767.0f * ((gamepadState.analogButton[first_trigger_button+i] * 2.0f) - 1.0f)));
|
|
|
+ item->axis[real_axis_count+i] = gamepadState.analogButton[first_trigger_button+i];
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
SDL_assert(item->nhats <= 1); // there is (currently) only ever one of these, faked from the d-pad buttons.
|