Fixed bug 3446 - The haptic API does not allow to select the direction axes
authorSam Lantinga <slouken@libsdl.org>
Mon, 16 Mar 2020 13:28:38 -0700
changeset 13635701fe6486077
parent 13634 9a8e6854f652
child 13636 40c8eec2d15c
Fixed bug 3446 - The haptic API does not allow to select the direction axes

Mathieu Laurendeau

Consider a device supporting effects on multiple axes.
There's currently no way to play effects against a single-axis direction.


A device supporting effects against X and Y may not allow to play effects with a two-axis direction coordinate, even if one of the coordinates is null.

My current (ugly) work around for this is to add a direction type SDL_HAPTIC_X_FORCE to play effects against a X-axis only direction (patch attached).

This issue impacted two GIMX users using the following wheels:
- Leo Bodnar SimSteering force feedback wheel
- Accuforce direct drive wheel

Playing constant/spring/damper effects against a X-axis direction worked well for the first wheel, but not for the second one.

A better strategy seems to play the effects against the first axis reported by the DirectInput enumeration.

This strategy also works with Logitech wheels (at least the DFGT).

It's been more than a year that I have the latest patch (playing effects against the first axis only) in the GIMX software. It's being used by thousands of people, mostly for adapting their FFB wheel to the PS4. I had no report that proves this strategy to be wrong.
include/SDL_haptic.h
src/haptic/darwin/SDL_syshaptic.c
src/haptic/windows/SDL_dinputhaptic.c
     1.1 --- a/include/SDL_haptic.h	Mon Mar 16 12:25:02 2020 -0700
     1.2 +++ b/include/SDL_haptic.h	Mon Mar 16 13:28:38 2020 -0700
     1.3 @@ -336,6 +336,13 @@
     1.4   */
     1.5  #define SDL_HAPTIC_SPHERICAL  2
     1.6  
     1.7 +/**
     1.8 + *  \brief Uses first axis only.
     1.9 + *
    1.10 + *  \sa SDL_HapticDirection
    1.11 + */
    1.12 +#define SDL_HAPTIC_FIRST_AXIS 3
    1.13 +
    1.14  /* @} *//* Direction encodings */
    1.15  
    1.16  /* @} *//* Haptic features */
     2.1 --- a/src/haptic/darwin/SDL_syshaptic.c	Mon Mar 16 12:25:02 2020 -0700
     2.2 +++ b/src/haptic/darwin/SDL_syshaptic.c	Mon Mar 16 13:28:38 2020 -0700
     2.3 @@ -765,6 +765,10 @@
     2.4              rglDir[2] = dir->dir[2];
     2.5          }
     2.6          return 0;
     2.7 +    case SDL_HAPTIC_FIRST_AXIS:
     2.8 +        effect->dwFlags |= FFEFF_CARTESIAN;
     2.9 +        rglDir[0] = 0;
    2.10 +        return 0;
    2.11  
    2.12      default:
    2.13          return SDL_SetError("Haptic: Unknown direction type.");
    2.14 @@ -813,7 +817,11 @@
    2.15      envelope->dwSize = sizeof(FFENVELOPE);      /* Always should be this. */
    2.16  
    2.17      /* Axes. */
    2.18 -    dest->cAxes = haptic->naxes;
    2.19 +    if (src->constant.direction.type == SDL_HAPTIC_FIRST_AXIS) {
    2.20 +        dest->cAxes = 1;
    2.21 +    } else {
    2.22 +        dest->cAxes = haptic->naxes;
    2.23 +    }
    2.24      if (dest->cAxes > 0) {
    2.25          axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
    2.26          if (axes == NULL) {
     3.1 --- a/src/haptic/windows/SDL_dinputhaptic.c	Mon Mar 16 12:25:02 2020 -0700
     3.2 +++ b/src/haptic/windows/SDL_dinputhaptic.c	Mon Mar 16 13:28:38 2020 -0700
     3.3 @@ -589,6 +589,10 @@
     3.4          if (naxes > 2)
     3.5              rglDir[2] = dir->dir[2];
     3.6          return 0;
     3.7 +    case SDL_HAPTIC_FIRST_AXIS:
     3.8 +        effect->dwFlags |= DIEFF_CARTESIAN;
     3.9 +        rglDir[0] = 0;
    3.10 +        return 0;
    3.11  
    3.12      default:
    3.13          return SDL_SetError("Haptic: Unknown direction type.");
    3.14 @@ -637,7 +641,11 @@
    3.15      envelope->dwSize = sizeof(DIENVELOPE);      /* Always should be this. */
    3.16  
    3.17      /* Axes. */
    3.18 -    dest->cAxes = haptic->naxes;
    3.19 +    if (src->constant.direction.type == SDL_HAPTIC_FIRST_AXIS) {
    3.20 +        dest->cAxes = 1;
    3.21 +    } else {
    3.22 +        dest->cAxes = haptic->naxes;
    3.23 +    }
    3.24      if (dest->cAxes > 0) {
    3.25          axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
    3.26          if (axes == NULL) {