Пример #1
0
//-----------------------------------------------------------------------------
// 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;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : effectnum - 
//-----------------------------------------------------------------------------
void CInput::ForceFeedback_Stop( int effectnum )
{
	if ( !m_pFF || !m_pFF->m_bForceFeedbackAvailable )
		return;


	// look up the effect
	FORCEFEEDBACK_t effect = (FORCEFEEDBACK_t)effectnum;

	if ( effect < 0 || effect >= NUM_FORCE_FEEDBACK_PRESETS )
	{
		Assert( !"ForceFeedback_Stop with bogus effectnum" );
		return;
	}

	EffectMap_t *map = &g_EffectMap[ effectnum ];

	vecEffectPtr_t *effects = map->pVecEffectPtr;

	// Stop the effects on the device
	int c = effects->Count();
	for ( int i = 0; i < c; ++i )
	{
		LPDIRECTINPUTEFFECT pEffect = (*effects)[ i ];
		pEffect->Stop();
	}
}
//--------------------------------------------------------------//
Win32ForceFeedback::~Win32ForceFeedback()
{
	//Get the effect - if it exists
	for(EffectList::iterator i = mEffectList.begin(); i != mEffectList.end(); ++i )
	{
		LPDIRECTINPUTEFFECT dxEffect = i->second;
		if( dxEffect )
			dxEffect->Unload();
	}

	mEffectList.clear();
}
//--------------------------------------------------------------//
void Win32ForceFeedback::remove( const Effect* eff )
{
	//Get the effect - if it exists
	EffectList::iterator i = mEffectList.find(eff->_handle);
	if( i != mEffectList.end() )
	{
		LPDIRECTINPUTEFFECT dxEffect = i->second;
		if( dxEffect )
		{
			dxEffect->Stop();
			//We care about the return value - as the effect might not
			//have been unlaoded
			if( SUCCEEDED(dxEffect->Unload()) )
				mEffectList.erase(i);
		}
		else
			mEffectList.erase(i);
	}
}
Пример #5
0
// release a DirectInput effect.  We don't need it anymore.
void ReleaseEffect( LPDIRECTINPUTEFFECT &lpDirectEffect )
{
	if( lpDirectEffect != NULL)
	{
		// should unload the effect on release, I hope
		lpDirectEffect->Release();
		lpDirectEffect = NULL;
	}
	return;
}
Пример #6
0
    // Strength ranges from 0 to 1
    void setWheelRumbleStrength(double strength)
    {
        DIPERIODIC pf = { FFWRMAX * strength * 10000,0,0,0.06 * 1000000 };

        g_sWheelRumbleConfig.cbTypeSpecificParams = sizeof(DIPERIODIC);
        g_sWheelRumbleConfig.lpvTypeSpecificParams = &pf;

        if (g_pWheelRumbleHandle) {
            g_pWheelRumbleHandle->SetParameters(&g_sWheelRumbleConfig, DIEP_DIRECTION |
                DIEP_TYPESPECIFICPARAMS | DIEP_START);
        }
    }
Пример #7
0
    // Magnitude ranges from -1 to 1
    void setAutoCenterStrength(double magnitude)
    {
        DICONSTANTFORCE cf = { magnitude * 10000 };

        g_sAutoCenterConfig.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
        g_sAutoCenterConfig.lpvTypeSpecificParams = &cf;

        if (g_pAutoCenterHandle) {
            g_pAutoCenterHandle->SetParameters(&g_sAutoCenterConfig, DIEP_DIRECTION |
                DIEP_TYPESPECIFICPARAMS | DIEP_START);
        }

    }
//--------------------------------------------------------------//
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!");
	}
}
Пример #9
0
HRESULT SetDeviceForcesXY(float x,float y)
{
	// Modifying an effect is basically the same as creating a new one, except
	// you need only specify the parameters you are modifying
	LONG rglDirection[2] = { 0, 0 };

	DICONSTANTFORCE cf;

	if( g_dwNumForceFeedbackAxis == 1 )
	{
		// If only one force feedback axis, then apply only one direction and 
		// keep the direction at zero
		cf.lMagnitude = x;
		rglDirection[0] = 0;
	}
	else
	{
		// If two force feedback axis, then apply magnitude from both directions 
		rglDirection[0] = x;
		rglDirection[1] = y;
		cf.lMagnitude = ( DWORD )sqrt( x * x + y * y );

	}

	DIEFFECT eff;
	ZeroMemory( &eff, sizeof( eff ) );
	eff.dwSize = sizeof( DIEFFECT );
	eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
	eff.cAxes = g_dwNumForceFeedbackAxis;
	eff.rglDirection = rglDirection;
	eff.lpEnvelope = 0;
	eff.cbTypeSpecificParams = sizeof( DICONSTANTFORCE );
	eff.lpvTypeSpecificParams = &cf;
	eff.dwStartDelay = 0;

	// Now set the new parameters and start the effect immediately.
	HRESULT hr = S_OK;
	
	hr = g_pEffect->SetParameters( &eff, DIEP_DIRECTION |DIEP_TYPESPECIFICPARAMS |DIEP_START );
	HRESULT a1 = DIERR_INVALIDPARAM;
	


	return hr;
}
Пример #10
0
//-----------------------------------------------------------------------------
// 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 );
			}
		}
	}
}
Пример #11
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;
    }
Пример #12
0
// Create a force feedback effect handle and downloads the effect.  Parameters are self-explanatory.
bool CreateEffectHandle( HWND hWnd, LPDIRECTINPUTDEVICE8 lpDirectInputDevice, LPDIRECTINPUTEFFECT &pDIEffect, BYTE bRumbleTyp, long lStrength )
{
	if( pDIEffect )
		ReleaseEffect( pDIEffect );

	if( !lpDirectInputDevice || bRumbleTyp == RUMBLE_DIRECT )
		return false;	

	DWORD nAxes = 0;
	DWORD rgdwAxes[] = { DIJOFS_X, DIJOFS_Y };

	HRESULT hResult;

	// count the FF - axes of the joystick
	lpDirectInputDevice->EnumObjects( EnumCountFFAxes, &nAxes, DIDFT_FFACTUATOR | DIDFT_AXIS );

	if( nAxes == 0 )
		return false;
	nAxes = min( nAxes, 2 );


	// Must be unaquired for setting stuff like Co-op Level
	hResult = lpDirectInputDevice->Unacquire();
	//FF Requires EXCLUSIVE LEVEL, took me hours to find the reason why it wasnt working
	hResult = lpDirectInputDevice->SetCooperativeLevel( hWnd, DIB_FF );

	// fail if we can't set coop level --rabid
	if (hResult != DI_OK)
	{
		DebugWriteA("CreateEffectHandle: couldn't set coop level: %08X\n", hResult);
		return false;
	}

    // Since we will be playing force feedback effects, we should disable the
    // auto-centering spring.
	DIPROPDWORD dipdw;
    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj        = 0;
    dipdw.diph.dwHow        = DIPH_DEVICE;
    dipdw.dwData            = FALSE;
	
	hResult = lpDirectInputDevice->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph );

	long rglDirection[] = { 1, 1 };
	LPGUID EffectGuid;
    DIEFFECT eff;
    ZeroMemory( &eff, sizeof(eff) );

	eff.dwSize                  = sizeof(DIEFFECT);
	eff.dwFlags                 = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
	eff.dwGain                  = lStrength * 100;
    eff.dwTriggerButton         = DIEB_NOTRIGGER;
    eff.dwTriggerRepeatInterval = 0;
    eff.cAxes                   = nAxes; //Number of Axes
    eff.rgdwAxes                = rgdwAxes;
    eff.rglDirection            = rglDirection;
    eff.lpEnvelope              = NULL;
	eff.dwStartDelay            = 0;

	DICONSTANTFORCE cf;
	DIRAMPFORCE rf;
	DIPERIODIC pf;

	switch( bRumbleTyp )
	{
	case RUMBLE_CONSTANT:
		EffectGuid = (GUID*)&GUID_ConstantForce;

		eff.dwDuration              = 150000; // microseconds
		eff.dwSamplePeriod          = 0;
		eff.cbTypeSpecificParams    = sizeof(DICONSTANTFORCE);
		eff.lpvTypeSpecificParams   = &cf;

		cf.lMagnitude = 10000;
		break;
	case RUMBLE_RAMP:
		EffectGuid = (GUID*)&GUID_RampForce;
		
		eff.dwDuration              = 300000; // microseconds
		eff.dwSamplePeriod          = 0;
		eff.cbTypeSpecificParams    = sizeof(DIRAMPFORCE);
		eff.lpvTypeSpecificParams   = &rf;

		rf.lStart = 10000;
		rf.lEnd = 2000;
		break;
	
	case RUMBLE_CONDITION:
	case RUMBLE_PERIODIC:
		EffectGuid = (GUID*)&GUID_Sine;

		eff.dwDuration              = 150000; // microseconds
		eff.dwSamplePeriod          = 0;
		eff.cbTypeSpecificParams    = sizeof(DIPERIODIC);
		eff.lpvTypeSpecificParams   = &pf;

		pf.dwMagnitude = 10000;
		pf.lOffset = 0;
		pf.dwPhase = 0;
		pf.dwPeriod = 2000;
		break;

	case RUMBLE_NONE:
	case RUMBLE_CUSTOM:
	default:
		return false;
	}

	hResult = lpDirectInputDevice->CreateEffect( *EffectGuid, &eff, &pDIEffect, NULL );

	if (hResult == DI_OK)
	{
		hResult = lpDirectInputDevice->Acquire();
		hResult = pDIEffect->Download();
	}
	else
	{
		DebugWriteA("CreateEffectHandle: didn't CreateEffect: %08X\n", hResult);
	}
	return SUCCEEDED( hResult );
}