Improved way constant force and vibrate effects are combined to control left and right vibration motors under XInput

This commit is contained in:
Nik Henson 2011-09-13 22:50:50 +00:00
parent f6af182467
commit d34223ebd2
2 changed files with 53 additions and 17 deletions

View file

@ -1616,25 +1616,39 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
{ {
case FFStop: case FFStop:
// Stop command halts all vibration // Stop command halts all vibration
vibration.wLeftMotorSpeed = 0; pInfo->xiConstForceLeft = 0;
vibration.wRightMotorSpeed = 0; pInfo->xiConstForceRight = 0;
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)); pInfo->xiVibrateBoth = 0;
break;
case FFConstantForce: case FFConstantForce:
// Constant force effect is mapped to either left or right vibration motor depending on its direction and providing it's magnitude // Check if constant force effect is disabled
// is above threshold setting
if (m_xiConstForceMax == 0) if (m_xiConstForceMax == 0)
return false; return false;
// Constant force effect is mapped to either left or right vibration motor depending on its direction
negForce = ffCmd.force < 0.0f; negForce = ffCmd.force < 0.0f;
absForce = (negForce ? -ffCmd.force : ffCmd.force); absForce = (negForce ? -ffCmd.force : ffCmd.force);
threshold = (float)m_xiConstForceThreshold / 100.0f; threshold = (float)m_xiConstForceThreshold / 100.0f;
if ((absForce < threshold) && (absForce > 0.001)) // if absForce == 0, must process command to stop controller vibrating // Check if constant force effect is being stopped or is below threshold
return false; if (absForce == 0.0f || absForce < threshold)
if (negForce) {
vibration.wLeftMotorSpeed = min<WORD>(ffCmd.force * (float)(m_xiConstForceMax * XI_VIBRATE_SCALE), XI_VIBRATE_MAX); // If so, stop vibration due to force effect
pInfo->xiConstForceLeft = 0;
pInfo->xiConstForceRight = 0;
}
else if (negForce)
{
// If force is negative (to left), set left motor vibrating
pInfo->xiConstForceLeft = (WORD)(absForce * (float)(m_xiConstForceMax * XI_VIBRATE_SCALE));
pInfo->xiConstForceRight = 0;
}
else else
vibration.wRightMotorSpeed = min<WORD>(ffCmd.force * (float)(m_xiConstForceMax * XI_VIBRATE_SCALE), XI_VIBRATE_MAX); {
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)); // If force positive (to right), set right motor vibrating
pInfo->xiConstForceLeft = 0;
pInfo->xiConstForceRight = (WORD)(absForce * (float)(m_xiConstForceMax * XI_VIBRATE_SCALE));
}
break;
case FFSelfCenter: case FFSelfCenter:
case FFFriction: case FFFriction:
@ -1642,17 +1656,31 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
return false; return false;
case FFVibrate: case FFVibrate:
// Vibration effect is mapped to both vibration motors // Check if vibration effect is disabled
if (m_xiVibrateMax == 0) if (m_xiVibrateMax == 0)
return false; return false;
vibration.wLeftMotorSpeed = min<WORD>(ffCmd.force * (float)(m_xiVibrateMax * XI_VIBRATE_SCALE), XI_VIBRATE_MAX); // Check if vibration effect is being stopped
vibration.wRightMotorSpeed = min<WORD>(ffCmd.force * (float)(m_xiVibrateMax * XI_VIBRATE_SCALE), XI_VIBRATE_MAX); if (ffCmd.force == 0.0f)
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)); {
// If so, stop vibration due to vibration effect
pInfo->xiVibrateBoth = 0;
}
else
{
// Otherwise, set both motors vibrating
pInfo->xiVibrateBoth = (WORD)(ffCmd.force * (float)(m_xiVibrateMax * XI_VIBRATE_SCALE));
}
break;
default: default:
// Unknown feedback command // Unknown feedback command
return false; return false;
} }
// Combine vibration speeds from both constant force effect and vibration effect and set motors in action
vibration.wLeftMotorSpeed = min<WORD>(pInfo->xiConstForceLeft + pInfo->xiVibrateBoth, XI_VIBRATE_MAX);
vibration.wRightMotorSpeed = min<WORD>(pInfo->xiConstForceRight + pInfo->xiVibrateBoth, XI_VIBRATE_MAX);
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration));
} }
else else
{ {

View file

@ -49,11 +49,19 @@ struct DIMseState
struct DIJoyInfo struct DIJoyInfo
{ {
// DirectInput details
GUID guid; GUID guid;
bool isXInput;
int dInputNum; int dInputNum;
LPDIRECTINPUTEFFECT dInputEffects[NUM_JOY_AXES][NUM_FF_EFFECTS]; LPDIRECTINPUTEFFECT dInputEffects[NUM_JOY_AXES][NUM_FF_EFFECTS];
int xInputNum;
// XInput details
bool isXInput; // True if joystick is XInput controller
int xInputNum; // XInput controller number
// XInput force feedback state
WORD xiConstForceLeft;
WORD xiConstForceRight;
WORD xiVibrateBoth;
}; };
struct DIEnumDevsContext struct DIEnumDevsContext