Implemented force feedback
parent
fd07589ebb
commit
6a6025f557
|
@ -91,6 +91,8 @@ struct ApplicationPrivate
|
||||||
SDL_Joystick *joystick;
|
SDL_Joystick *joystick;
|
||||||
//! Id of joystick timer
|
//! Id of joystick timer
|
||||||
SDL_TimerID joystickTimer;
|
SDL_TimerID joystickTimer;
|
||||||
|
//! Haptic subsystem for the joystick
|
||||||
|
SDL_Haptic *haptic;
|
||||||
|
|
||||||
ApplicationPrivate()
|
ApplicationPrivate()
|
||||||
{
|
{
|
||||||
|
@ -100,6 +102,7 @@ struct ApplicationPrivate
|
||||||
glcontext = nullptr;
|
glcontext = nullptr;
|
||||||
joystick = nullptr;
|
joystick = nullptr;
|
||||||
joystickTimer = 0;
|
joystickTimer = 0;
|
||||||
|
haptic = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -516,6 +519,10 @@ bool CApplication::Create()
|
||||||
{
|
{
|
||||||
GetLogger()->Warn("Joystick subsystem init failed\nJoystick(s) will not be available\n");
|
GetLogger()->Warn("Joystick subsystem init failed\nJoystick(s) will not be available\n");
|
||||||
}
|
}
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0)
|
||||||
|
{
|
||||||
|
GetLogger()->Warn("Joystick haptic subsystem init failed\nForce feedback will not be available\n");
|
||||||
|
}
|
||||||
|
|
||||||
if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
|
if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
|
||||||
{
|
{
|
||||||
|
@ -725,6 +732,20 @@ bool CApplication::OpenJoystick()
|
||||||
// Create a timer for polling joystick state
|
// Create a timer for polling joystick state
|
||||||
m_private->joystickTimer = SDL_AddTimer(JOYSTICK_TIMER_INTERVAL, JoystickTimerCallback, nullptr);
|
m_private->joystickTimer = SDL_AddTimer(JOYSTICK_TIMER_INTERVAL, JoystickTimerCallback, nullptr);
|
||||||
|
|
||||||
|
// Initialize haptic subsystem
|
||||||
|
m_private->haptic = SDL_HapticOpenFromJoystick(m_private->joystick);
|
||||||
|
if (m_private->haptic == nullptr)
|
||||||
|
{
|
||||||
|
GetLogger()->Warn("Haptic subsystem open failed\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_HapticRumbleInit(m_private->haptic) != 0)
|
||||||
|
{
|
||||||
|
GetLogger()->Warn("Haptic rumble effect init failed\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,6 +755,11 @@ void CApplication::CloseJoystick()
|
||||||
|
|
||||||
GetLogger()->Info("Closing joystick\n");
|
GetLogger()->Info("Closing joystick\n");
|
||||||
|
|
||||||
|
StopForceFeedbackEffect();
|
||||||
|
|
||||||
|
SDL_HapticClose(m_private->haptic);
|
||||||
|
m_private->haptic = nullptr;
|
||||||
|
|
||||||
SDL_JoystickClose(m_private->joystick);
|
SDL_JoystickClose(m_private->joystick);
|
||||||
m_private->joystick = nullptr;
|
m_private->joystick = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1784,3 +1810,20 @@ void CApplication::SetTextInput(bool textInputEnabled)
|
||||||
SDL_StopTextInput();
|
SDL_StopTextInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CApplication::PlayForceFeedbackEffect(float strength, int length)
|
||||||
|
{
|
||||||
|
if (m_private->haptic == nullptr) return;
|
||||||
|
|
||||||
|
GetLogger()->Trace("Force feedback! length = %d ms, strength = %.2f\n", length, strength);
|
||||||
|
if (SDL_HapticRumblePlay(m_private->haptic, strength, length) != 0)
|
||||||
|
{
|
||||||
|
GetLogger()->Debug("Failed to play haptic effect\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CApplication::StopForceFeedbackEffect()
|
||||||
|
{
|
||||||
|
if (m_private->haptic == nullptr) return;
|
||||||
|
SDL_HapticRumbleStop(m_private->haptic);
|
||||||
|
}
|
||||||
|
|
|
@ -314,6 +314,11 @@ public:
|
||||||
//! Renders the image in window if needed
|
//! Renders the image in window if needed
|
||||||
void RenderIfNeeded(int updateRate);
|
void RenderIfNeeded(int updateRate);
|
||||||
|
|
||||||
|
//! Starts a force feedback effect on the joystick
|
||||||
|
void PlayForceFeedbackEffect(float strength = 1.0f, int length = 999999);
|
||||||
|
//! Stops a force feedback effect on the joystick
|
||||||
|
void StopForceFeedbackEffect();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Creates the window's SDL_Surface
|
//! Creates the window's SDL_Surface
|
||||||
bool CreateVideoSurface();
|
bool CreateVideoSurface();
|
||||||
|
|
|
@ -570,6 +570,8 @@ void CCamera::FlushEffect()
|
||||||
m_effectForce = 0.0f;
|
m_effectForce = 0.0f;
|
||||||
m_effectProgress = 0.0f;
|
m_effectProgress = 0.0f;
|
||||||
m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
|
m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
CApplication::GetInstancePointer()->StopForceFeedbackEffect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
|
void CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
|
||||||
|
@ -655,6 +657,25 @@ void CCamera::EffectFrame(const Event &event)
|
||||||
force *= 1.0f-dist;
|
force *= 1.0f-dist;
|
||||||
m_effectOffset *= force;
|
m_effectOffset *= force;
|
||||||
|
|
||||||
|
float forceFeedback = force;
|
||||||
|
if (m_effectType == CAM_EFFECT_VIBRATION)
|
||||||
|
{
|
||||||
|
forceFeedback *= 0.5f;
|
||||||
|
}
|
||||||
|
if (m_effectType == CAM_EFFECT_PET)
|
||||||
|
{
|
||||||
|
forceFeedback *= 0.75f;
|
||||||
|
}
|
||||||
|
if (m_effectType == CAM_EFFECT_EXPLO)
|
||||||
|
{
|
||||||
|
forceFeedback *= 3.0f;
|
||||||
|
}
|
||||||
|
if (forceFeedback > 1.0f) forceFeedback = 1.0f;
|
||||||
|
if (forceFeedback >= 0.1f)
|
||||||
|
{
|
||||||
|
CApplication::GetInstancePointer()->PlayForceFeedbackEffect(forceFeedback);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_effectProgress >= 1.0f)
|
if (m_effectProgress >= 1.0f)
|
||||||
FlushEffect();
|
FlushEffect();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue