diff options
| author | skidau <skidau@gmail.com> | 2015-01-16 12:39:24 +1100 |
|---|---|---|
| committer | skidau <skidau@gmail.com> | 2015-01-16 12:39:24 +1100 |
| commit | c2bdcbe71c8e559a3bb91ff1da7844dd65406582 (patch) | |
| tree | d00365cb2ddcc7ce02cdff7b677e0069c938aa7c /Source/Core/InputCommon/ControllerInterface | |
| parent | 9d9ffa5b8321b371edd40547232852ff81d309bd (diff) | |
| parent | 3300c176e46fda826e528d1ac10ff514ef3d9ec2 (diff) | |
Merge pull request #1837 from adamdmoss/sdl-more-haptic
SDL Input: Support more types of force feedback for controllers through SDL
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface')
| -rw-r--r-- | Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp | 94 | ||||
| -rw-r--r-- | Source/Core/InputCommon/ControllerInterface/SDL/SDL.h | 36 |
2 files changed, 112 insertions, 18 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp index 4402b286c3..a1fd428a0d 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.cpp @@ -18,6 +18,11 @@ namespace ciface namespace SDL { +// 10ms = 100Hz which homebrew docs very roughly imply is within WiiMote normal +// range, used for periodic haptic effects though often ignored by devices +static const u16 RUMBLE_PERIOD = 10; +static const u16 RUMBLE_LENGTH_MAX = 500; // ms: enough to span multiple frames at low FPS, but still finite + static std::string GetJoystickName(int index) { #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -126,6 +131,18 @@ Joystick::Joystick(SDL_Joystick* const joystick, const int sdl_index, const unsi // ramp effect if (supported_effects & SDL_HAPTIC_RAMP) AddOutput(new RampEffect(m_haptic)); + + // sine effect + if (supported_effects & SDL_HAPTIC_SINE) + AddOutput(new SineEffect(m_haptic)); + + // triangle effect + if (supported_effects & SDL_HAPTIC_TRIANGLE) + AddOutput(new TriangleEffect(m_haptic)); + + // left-right effect + if (supported_effects & SDL_HAPTIC_LEFTRIGHT) + AddOutput(new LeftRightEffect(m_haptic)); } #endif @@ -178,36 +195,81 @@ std::string Joystick::RampEffect::GetName() const return "Ramp"; } -void Joystick::ConstantEffect::SetState(ControlState state) +std::string Joystick::SineEffect::GetName() const { - if (state) - { - m_effect.type = SDL_HAPTIC_CONSTANT; - m_effect.constant.length = SDL_HAPTIC_INFINITY; - } - else - { - m_effect.type = 0; - } + return "Sine"; +} - m_effect.constant.level = (Sint16)(state * 0x7FFF); - Update(); +std::string Joystick::TriangleEffect::GetName() const +{ + return "Triangle"; +} + +std::string Joystick::LeftRightEffect::GetName() const +{ + return "LeftRight"; } -void Joystick::RampEffect::SetState(ControlState state) +void Joystick::HapticEffect::SetState(ControlState state) { + memset(&m_effect, 0, sizeof(m_effect)); if (state) { - m_effect.type = SDL_HAPTIC_RAMP; - m_effect.ramp.length = SDL_HAPTIC_INFINITY; + SetSDLHapticEffect(state); } else { + // this module uses type==0 to indicate 'off' m_effect.type = 0; } + Update(); +} +void Joystick::ConstantEffect::SetSDLHapticEffect(ControlState state) +{ + m_effect.type = SDL_HAPTIC_CONSTANT; + m_effect.constant.length = RUMBLE_LENGTH_MAX; + m_effect.constant.level = (Sint16)(state * 0x7FFF); +} + +void Joystick::RampEffect::SetSDLHapticEffect(ControlState state) +{ + m_effect.type = SDL_HAPTIC_RAMP; + m_effect.ramp.length = RUMBLE_LENGTH_MAX; m_effect.ramp.start = (Sint16)(state * 0x7FFF); - Update(); +} + +void Joystick::SineEffect::SetSDLHapticEffect(ControlState state) +{ + m_effect.type = SDL_HAPTIC_SINE; + m_effect.periodic.period = RUMBLE_PERIOD; + m_effect.periodic.magnitude = (Sint16)(state * 0x7FFF); + m_effect.periodic.offset = 0; + m_effect.periodic.phase = 18000; + m_effect.periodic.length = RUMBLE_LENGTH_MAX; + m_effect.periodic.delay = 0; + m_effect.periodic.attack_length = 0; +} + +void Joystick::TriangleEffect::SetSDLHapticEffect(ControlState state) +{ + m_effect.type = SDL_HAPTIC_TRIANGLE; + m_effect.periodic.period = RUMBLE_PERIOD; + m_effect.periodic.magnitude = (Sint16)(state * 0x7FFF); + m_effect.periodic.offset = 0; + m_effect.periodic.phase = 18000; + m_effect.periodic.length = RUMBLE_LENGTH_MAX; + m_effect.periodic.delay = 0; + m_effect.periodic.attack_length = 0; +} + +void Joystick::LeftRightEffect::SetSDLHapticEffect(ControlState state) +{ + m_effect.type = SDL_HAPTIC_LEFTRIGHT; + m_effect.leftright.length = RUMBLE_LENGTH_MAX; + // max ranges tuned to 'feel' similar in magnitude to triangle/sine on xbox360 controller + m_effect.leftright.large_magnitude = (Uint16)(state * 0x4000); + m_effect.leftright.small_magnitude = (Uint16)(state * 0xFFFF); } #endif diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h index dc449e9ab5..2bf695c698 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDL.h @@ -77,10 +77,13 @@ private: protected: void Update(); + virtual void SetSDLHapticEffect(ControlState state) = 0; SDL_HapticEffect m_effect; SDL_Haptic* m_haptic; int m_id; + private: + virtual void SetState(ControlState state) override final; }; class ConstantEffect : public HapticEffect @@ -88,7 +91,8 @@ private: public: ConstantEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {} std::string GetName() const override; - void SetState(ControlState state) override; + private: + void SetSDLHapticEffect(ControlState state) override; }; class RampEffect : public HapticEffect @@ -96,7 +100,35 @@ private: public: RampEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {} std::string GetName() const override; - void SetState(ControlState state) override; + private: + void SetSDLHapticEffect(ControlState state) override; + }; + + class SineEffect : public HapticEffect + { + public: + SineEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {} + std::string GetName() const override; + private: + void SetSDLHapticEffect(ControlState state) override; + }; + + class TriangleEffect : public HapticEffect + { + public: + TriangleEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {} + std::string GetName() const override; + private: + void SetSDLHapticEffect(ControlState state) override; + }; + + class LeftRightEffect : public HapticEffect + { + public: + LeftRightEffect(SDL_Haptic* haptic) : HapticEffect(haptic) {} + std::string GetName() const override; + private: + void SetSDLHapticEffect(ControlState state) override; }; #endif |
