Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Replaced SDL_HAPTIC_SQUARE with SDL_HAPTIC_LEFTRIGHT.
Browse files Browse the repository at this point in the history
We needed a bit, so we're hoping no one needs this effect, especially when
it's fairly close to SDL_HAPTIC_SINE, we hope.

SDL_HAPTIC_LEFTRIGHT maps to XInput's functionality, so this removes the SINE
code for the XInput driver to keep things clean.

This also makes the simplified Rumble API use SDL_HAPTIC_LEFTRIGHT if
SDL_HAPTIC_SINE isn't available, to keep XInput working.

When we break the ABI, and can extend the supported capabilities field from
a Uint16, we'll add SDL_HAPTIC_SQUARE back in.

This patch is based on work by Ethan Lee.
  • Loading branch information
icculus committed Aug 10, 2013
1 parent dc5d2b2 commit a34acd0
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 62 deletions.
42 changes: 36 additions & 6 deletions include/SDL_haptic.h
Expand Up @@ -166,13 +166,18 @@ typedef struct _SDL_Haptic SDL_Haptic;
#define SDL_HAPTIC_SINE (1<<1)

/**
* \brief Square wave effect supported.
* \brief Left/Right effect supported.
*
* Periodic haptic effect that simulates square waves.
* Haptic effect for direct control over high/low frequency motors.
*
* \sa SDL_HapticPeriodic
* \sa SDL_HapticLeftRight
* \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
* we ran out of bits, and this is important for XInput devices.
*/
#define SDL_HAPTIC_SQUARE (1<<2)
#define SDL_HAPTIC_LEFTRIGHT (1<<2)

/* !!! FIXME: put this back when we have more bits in 2.1 */
/*#define SDL_HAPTIC_SQUARE (1<<2)*/

/**
* \brief Triangle wave effect supported.
Expand Down Expand Up @@ -645,6 +650,31 @@ typedef struct SDL_HapticRamp
Uint16 fade_level; /**< Level at the end of the fade. */
} SDL_HapticRamp;

/**
* \brief A structure containing a template for a Left/Right effect.
*
* This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
*
* The Left/Right effect is used to explicitly control the large and small
* motors, commonly found in modern game controllers. One motor is high
* frequency, the other is low frequency.
*
* \sa SDL_HAPTIC_LEFTRIGHT
* \sa SDL_HapticEffect
*/
typedef struct SDL_HapticLeftRight
{
/* Header */
Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */

/* Replay */
Uint32 length; /**< Duration of the effect. */

/* Rumble */
Uint16 large_magnitude; /**< Control of the large controller motor. */
Uint16 small_magnitude; /**< Control of the small controller motor. */
} SDL_HapticLeftRight;

/**
* \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
*
Expand Down Expand Up @@ -751,6 +781,7 @@ typedef struct SDL_HapticCustom
* \sa SDL_HapticPeriodic
* \sa SDL_HapticCondition
* \sa SDL_HapticRamp
* \sa SDL_HapticLeftRight
* \sa SDL_HapticCustom
*/
typedef union SDL_HapticEffect
Expand All @@ -761,6 +792,7 @@ typedef union SDL_HapticEffect
SDL_HapticPeriodic periodic; /**< Periodic effect. */
SDL_HapticCondition condition; /**< Condition effect. */
SDL_HapticRamp ramp; /**< Ramp effect. */
SDL_HapticLeftRight leftright; /**< Left/Right effect. */
SDL_HapticCustom custom; /**< Custom effect. */
} SDL_HapticEffect;

Expand Down Expand Up @@ -1182,8 +1214,6 @@ extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float stre
*/
extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);



/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
Expand Down
64 changes: 37 additions & 27 deletions src/haptic/SDL_haptic.c
Expand Up @@ -23,7 +23,7 @@
#include "SDL_syshaptic.h"
#include "SDL_haptic_c.h"
#include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */

#include "SDL_assert.h"

Uint8 SDL_numhaptics = 0;
SDL_Haptic **SDL_haptics = NULL;
Expand Down Expand Up @@ -723,32 +723,18 @@ SDL_HapticStopAll(SDL_Haptic * haptic)
return SDL_SYS_HapticStopAll(haptic);
}

static void
SDL_HapticRumbleCreate(SDL_HapticEffect * efx)
{
SDL_memset(efx, 0, sizeof(SDL_HapticEffect));
efx->type = SDL_HAPTIC_SINE;
efx->periodic.period = 1000;
efx->periodic.magnitude = 0x4000;
efx->periodic.length = 5000;
efx->periodic.attack_length = 0;
efx->periodic.fade_length = 0;
}

/*
* Checks to see if rumble is supported.
*/
int
SDL_HapticRumbleSupported(SDL_Haptic * haptic)
{
SDL_HapticEffect efx;

if (!ValidHaptic(haptic)) {
return -1;
}

SDL_HapticRumbleCreate(&efx);
return SDL_HapticEffectSupported(haptic, &efx);
/* Most things can use SINE, but XInput only has LEFTRIGHT. */
return ((haptic->supported & (SDL_HAPTIC_SINE|SDL_HAPTIC_LEFTRIGHT)) != 0);
}

/*
Expand All @@ -757,6 +743,8 @@ SDL_HapticRumbleSupported(SDL_Haptic * haptic)
int
SDL_HapticRumbleInit(SDL_Haptic * haptic)
{
SDL_HapticEffect *efx = &haptic->rumble_effect;

if (!ValidHaptic(haptic)) {
return -1;
}
Expand All @@ -766,8 +754,23 @@ SDL_HapticRumbleInit(SDL_Haptic * haptic)
return 0;
}

/* Copy over. */
SDL_HapticRumbleCreate(&haptic->rumble_effect);
SDL_zerop(efx);
if (haptic->supported & SDL_HAPTIC_SINE) {
efx->type = SDL_HAPTIC_SINE;
efx->periodic.period = 1000;
efx->periodic.magnitude = 0x4000;
efx->periodic.length = 5000;
efx->periodic.attack_length = 0;
efx->periodic.fade_length = 0;
} else if (haptic->supported & SDL_HAPTIC_LEFTRIGHT) { /* XInput? */
efx->type = SDL_HAPTIC_LEFTRIGHT;
efx->leftright.length = 5000;
efx->leftright.large_magnitude = 0x4000;
efx->leftright.small_magnitude = 0x4000;
} else {
return SDL_SetError("Device doesn't support rumble");
}

haptic->rumble_id = SDL_HapticNewEffect(haptic, &haptic->rumble_effect);
if (haptic->rumble_id >= 0) {
return 0;
Expand All @@ -781,7 +784,8 @@ SDL_HapticRumbleInit(SDL_Haptic * haptic)
int
SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length)
{
SDL_HapticPeriodic *efx;
SDL_HapticEffect *efx;
Sint16 magnitude;

if (!ValidHaptic(haptic)) {
return -1;
Expand All @@ -794,15 +798,22 @@ SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length)
/* Clamp strength. */
if (strength > 1.0f) {
strength = 1.0f;
}
else if (strength < 0.0f) {
} else if (strength < 0.0f) {
strength = 0.0f;
}
magnitude = (Sint16)(32767.0f*strength);

efx = &haptic->rumble_effect;
if (efx->type == SDL_HAPTIC_SINE) {
efx->periodic.magnitude = magnitude;
efx->periodic.length = length;
} else if (efx->type == SDL_HAPTIC_LEFTRIGHT) {
efx->leftright.small_magnitude = efx->leftright.large_magnitude = magnitude;
efx->leftright.length = length;
} else {
SDL_assert(0 && "This should have been caught elsewhere");
}

/* New effect. */
efx = &haptic->rumble_effect.periodic;
efx->magnitude = (Sint16)(32767.0f*strength);
efx->length = length;
if (SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) {
return -1;
}
Expand All @@ -827,4 +838,3 @@ SDL_HapticRumbleStop(SDL_Haptic * haptic)
return SDL_HapticStopEffect(haptic, haptic->rumble_id);
}


11 changes: 7 additions & 4 deletions src/haptic/darwin/SDL_syshaptic.c
Expand Up @@ -342,7 +342,8 @@ GetSupportedFeatures(SDL_Haptic * haptic)
/* Test for effects. */
FF_TEST(FFCAP_ET_CONSTANTFORCE, SDL_HAPTIC_CONSTANT);
FF_TEST(FFCAP_ET_RAMPFORCE, SDL_HAPTIC_RAMP);
FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE);
/* !!! FIXME: put this back when we have more bits in 2.1 */
/*FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE);*/
FF_TEST(FFCAP_ET_SINE, SDL_HAPTIC_SINE);
FF_TEST(FFCAP_ET_TRIANGLE, SDL_HAPTIC_TRIANGLE);
FF_TEST(FFCAP_ET_SAWTOOTHUP, SDL_HAPTIC_SAWTOOTHUP);
Expand Down Expand Up @@ -750,7 +751,8 @@ SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest,
break;

case SDL_HAPTIC_SINE:
case SDL_HAPTIC_SQUARE:
/* !!! FIXME: put this back when we have more bits in 2.1 */
/*case SDL_HAPTIC_SQUARE:*/
case SDL_HAPTIC_TRIANGLE:
case SDL_HAPTIC_SAWTOOTHUP:
case SDL_HAPTIC_SAWTOOTHDOWN:
Expand Down Expand Up @@ -978,8 +980,9 @@ SDL_SYS_HapticEffectType(Uint16 type)
case SDL_HAPTIC_RAMP:
return kFFEffectType_RampForce_ID;

case SDL_HAPTIC_SQUARE:
return kFFEffectType_Square_ID;
/* !!! FIXME: put this back when we have more bits in 2.1 */
/*case SDL_HAPTIC_SQUARE:
return kFFEffectType_Square_ID;*/

case SDL_HAPTIC_SINE:
return kFFEffectType_Sine_ID;
Expand Down
34 changes: 30 additions & 4 deletions src/haptic/linux/SDL_syshaptic.c
Expand Up @@ -99,7 +99,8 @@ EV_IsHaptic(int fd)
/* Convert supported features to SDL_HAPTIC platform-neutral features. */
EV_TEST(FF_CONSTANT, SDL_HAPTIC_CONSTANT);
EV_TEST(FF_SINE, SDL_HAPTIC_SINE);
EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE);
/* !!! FIXME: put this back when we have more bits in 2.1 */
/*EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE);*/
EV_TEST(FF_TRIANGLE, SDL_HAPTIC_TRIANGLE);
EV_TEST(FF_SAW_UP, SDL_HAPTIC_SAWTOOTHUP);
EV_TEST(FF_SAW_DOWN, SDL_HAPTIC_SAWTOOTHDOWN);
Expand All @@ -111,6 +112,7 @@ EV_IsHaptic(int fd)
EV_TEST(FF_CUSTOM, SDL_HAPTIC_CUSTOM);
EV_TEST(FF_GAIN, SDL_HAPTIC_GAIN);
EV_TEST(FF_AUTOCENTER, SDL_HAPTIC_AUTOCENTER);
EV_TEST(FF_RUMBLE, SDL_HAPTIC_LEFTRIGHT);

/* Return what it supports. */
return ret;
Expand Down Expand Up @@ -559,6 +561,7 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
SDL_HapticPeriodic *periodic;
SDL_HapticCondition *condition;
SDL_HapticRamp *ramp;
SDL_HapticLeftRight *leftright;

/* Clear up */
SDL_memset(dest, 0, sizeof(struct ff_effect));
Expand Down Expand Up @@ -596,7 +599,8 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
break;

case SDL_HAPTIC_SINE:
case SDL_HAPTIC_SQUARE:
/* !!! FIXME: put this back when we have more bits in 2.1 */
/*case SDL_HAPTIC_SQUARE:*/
case SDL_HAPTIC_TRIANGLE:
case SDL_HAPTIC_SAWTOOTHUP:
case SDL_HAPTIC_SAWTOOTHDOWN:
Expand All @@ -620,8 +624,9 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)
/* Periodic */
if (periodic->type == SDL_HAPTIC_SINE)
dest->u.periodic.waveform = FF_SINE;
else if (periodic->type == SDL_HAPTIC_SQUARE)
dest->u.periodic.waveform = FF_SQUARE;
/* !!! FIXME: put this back when we have more bits in 2.1 */
/*else if (periodic->type == SDL_HAPTIC_SQUARE)
dest->u.periodic.waveform = FF_SQUARE;*/
else if (periodic->type == SDL_HAPTIC_TRIANGLE)
dest->u.periodic.waveform = FF_TRIANGLE;
else if (periodic->type == SDL_HAPTIC_SAWTOOTHUP)
Expand Down Expand Up @@ -725,6 +730,27 @@ SDL_SYS_ToFFEffect(struct ff_effect *dest, SDL_HapticEffect * src)

break;

case SDL_HAPTIC_LEFTRIGHT:
leftright = &src->leftright;

/* Header */
dest->type = FF_RUMBLE;
dest->direction = 0;

/* Replay */
dest->replay.length = (leftright->length == SDL_HAPTIC_INFINITY) ?
0 : CLAMP(leftright->length);

/* Trigger */
dest->trigger.button = 0;
dest->trigger.interval = 0;

/* Rumble */
dest->u.rumble.strong_magnitude = leftright->large_magnitude;
dest->u.rumble.weak_magnitude = leftright->small_magnitude;

break;


default:
return SDL_SetError("Haptic: Unknown effect type.");
Expand Down

0 comments on commit a34acd0

Please sign in to comment.