//----------------------------------------------------------------------------- // Name: OnPlayEffects() // Desc: Plays all of the effects enumerated in the file //----------------------------------------------------------------------------- HRESULT OnPlayEffects( HWND hDlg ) { EFFECTS_NODE* pEffectNode = g_EffectsList.pNext; LPDIRECTINPUTEFFECT pDIEffect = NULL; HRESULT hr; // Stop all previous forces if( FAILED( hr = g_pFFDevice->SendForceFeedbackCommand( DISFFC_STOPALL ) ) ) return hr; while ( pEffectNode != &g_EffectsList ) { // Play all of the effects enumerated in the file pDIEffect = pEffectNode->pDIEffect; if( NULL != pDIEffect ) { if( FAILED( hr = pDIEffect->Start( pEffectNode->dwPlayRepeatCount, 0 ) ) ) return hr; } pEffectNode = pEffectNode->pNext; } return S_OK; }
//--------------------------------------------------------------// void Win32ForceFeedback::_upload( GUID guid, DIEFFECT* diEffect, const Effect* effect) { LPDIRECTINPUTEFFECT dxEffect = 0; //Get the effect - if it exists EffectList::iterator i = mEffectList.find(effect->_handle); //It has been created already if( i != mEffectList.end() ) dxEffect = i->second; else //This effect has not yet been created - generate a handle effect->_handle = mHandles++; if( dxEffect == 0 ) { //This effect has not yet been created, so create it HRESULT hr = mJoyStick->CreateEffect(guid, diEffect, &dxEffect, NULL); if(SUCCEEDED(hr)) { mEffectList[effect->_handle] = dxEffect; dxEffect->Start(INFINITE,0); } else if( hr == DIERR_DEVICEFULL ) OIS_EXCEPT(E_DeviceFull, "Remove an effect before adding more!"); else OIS_EXCEPT(E_General, "Unknown error creating effect->.."); } else { //ToDo -- Update the Effect HRESULT hr = dxEffect->SetParameters( diEffect, DIEP_DIRECTION | DIEP_DURATION | DIEP_ENVELOPE | DIEP_STARTDELAY | DIEP_TRIGGERBUTTON | DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS | DIEP_START ); if(FAILED(hr)) OIS_EXCEPT(E_InvalidParam, "Error updating device!"); } }
//----------------------------------------------------------------------------- // Purpose: // Input : effectnum - // params - //----------------------------------------------------------------------------- void CInput::ForceFeedback_Start( int effectnum, const FFBaseParams_t& params ) { if ( !m_pFF || !m_pFF->m_bForceFeedbackAvailable ) return; // Unpause system... if ( m_pFF->m_bPaused ) { ForceFeedback_Resume(); } // look up the effect FORCEFEEDBACK_t effect = (FORCEFEEDBACK_t)effectnum; if ( effect < 0 || effect >= NUM_FORCE_FEEDBACK_PRESETS ) { Assert( !"ForceFeedback_Start with bogus effectnum" ); return; } EffectMap_t *map = &g_EffectMap[ effectnum ]; vecEffectPtr_t *effects = map->pVecEffectPtr; // Play the effects on the device int c = effects->Count(); for ( int i = 0; i < c; ++i ) { LPDIRECTINPUTEFFECT pEffect = (*effects)[ i ]; if ( !map->m_bDownloaded ) { pEffect->Download(); map->m_bDownloaded = true; } DWORD flags = DIEP_DIRECTION | DIEP_GAIN | DIEP_DURATION; LONG rglDirection[2] = { 0, 100 }; // Fill in parameters DIEFFECT effect; Q_memset( &effect, 0, sizeof( effect ) ); effect.dwSize = sizeof( effect ); effect.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; effect.rglDirection = rglDirection; effect.cAxes = 2; HRESULT hr = pEffect->GetParameters( &effect, flags ); if ( !FAILED( hr ) ) { // If params.m_flDuration == 0.0f then that means use the duration in the file if ( params.m_flDuration <= -0.999f ) { effect.dwDuration = INFINITE; } else if( params.m_flDuration >= 0.001f ) { // Convert to microsseconds effect.dwDuration = (DWORD)( params.m_flDuration * 1000000.0f ); } effect.dwGain = params.m_flGain * 10000.0f; effect.rglDirection[ 0 ] = 100.0f * params.m_flDirection; effect.rglDirection[ 1 ] = 0; hr = pEffect->SetParameters( &effect, flags ); if ( !FAILED( hr ) ) { pEffect->Start( 1, params.m_bSolo ? DIES_SOLO : 0 ); } } } }
HRESULT InitForceFeedback() { HRESULT hr; DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y }; LONG rglDirection[2] = { 0, 0 }; if (FAILED(hr = g_pJoystick->SetCooperativeLevel(GetActiveWindow(), DISCL_EXCLUSIVE | DISCL_BACKGROUND))) return hr; if (FAILED(hr = g_pJoystick->Acquire())) return hr; // Autocenter ZeroMemory(&g_sAutoCenterConfig, sizeof(g_sAutoCenterConfig)); g_sAutoCenterConfig.dwStartDelay = 0; g_sAutoCenterConfig.dwSize = sizeof(DIEFFECT); g_sAutoCenterConfig.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; g_sAutoCenterConfig.dwDuration = INFINITE; g_sAutoCenterConfig.dwSamplePeriod = 0; g_sAutoCenterConfig.dwGain = DI_FFNOMINALMAX; g_sAutoCenterConfig.dwTriggerButton = DIEB_NOTRIGGER; g_sAutoCenterConfig.dwTriggerRepeatInterval = 0; g_sAutoCenterConfig.cAxes = 1; g_sAutoCenterConfig.rgdwAxes = rgdwAxes; g_sAutoCenterConfig.rglDirection = rglDirection; g_sAutoCenterConfig.lpEnvelope = 0; g_sAutoCenterConfig.dwStartDelay = 0; DICONSTANTFORCE cf = { 0 }; g_sAutoCenterConfig.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); g_sAutoCenterConfig.lpvTypeSpecificParams = &cf; if (FAILED(hr = g_pJoystick->CreateEffect(GUID_ConstantForce, &g_sAutoCenterConfig, &g_pAutoCenterHandle, nullptr))) return hr; if (FAILED(hr = g_pAutoCenterHandle->Start(INFINITE, 0))) return hr; // Rumble ZeroMemory(&g_sWheelRumbleConfig, sizeof(g_sWheelRumbleConfig)); g_sWheelRumbleConfig.dwStartDelay = 0; g_sWheelRumbleConfig.dwSize = sizeof(DIEFFECT); g_sWheelRumbleConfig.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; g_sWheelRumbleConfig.dwDuration = INFINITE; g_sWheelRumbleConfig.dwSamplePeriod = 0; g_sWheelRumbleConfig.dwGain = DI_FFNOMINALMAX; g_sWheelRumbleConfig.dwTriggerButton = DIEB_NOTRIGGER; g_sWheelRumbleConfig.dwTriggerRepeatInterval = 0; g_sWheelRumbleConfig.cAxes = 1; g_sWheelRumbleConfig.rgdwAxes = rgdwAxes; g_sWheelRumbleConfig.rglDirection = rglDirection; g_sWheelRumbleConfig.lpEnvelope = 0; g_sWheelRumbleConfig.dwStartDelay = 0; DIPERIODIC pf = { 0,0,0,0.08 }; g_sWheelRumbleConfig.cbTypeSpecificParams = sizeof(DIPERIODIC); g_sWheelRumbleConfig.lpvTypeSpecificParams = &pf; if (FAILED(hr = g_pJoystick->CreateEffect(GUID_Sine, &g_sWheelRumbleConfig, &g_pWheelRumbleHandle, nullptr))) return hr; if (FAILED(hr = g_pWheelRumbleHandle->Start(INFINITE, 0))) return hr; return S_OK; }