Example #1
0
//------------------------------------------------------------------
//
//   FUNCTION : HandleShutdownEffect()
//
//   PURPOSE  : Given an instance and an effect that has just finished shutting down,
//				it will take the appropriate course of action. Note that this will
//				invalidate the node that is passed into it
//
//------------------------------------------------------------------
void CClientFXMgr::HandleShutdownEffect(CLIENTFX_INSTANCE* pInst, CLinkListNode<FX_LINK>* pKeyNode)
{
	//sanity check
	assert(pInst && pKeyNode);

	CBaseFX	*pFX = pKeyNode->m_Data.m_pFX;

	//we are finished shutting down, if we aren't looping, we need to destroy
	//the effect, otherwise just disable it
	if(pInst->m_bLoop && !pInst->m_bShutdown)
	{
		pFX->SetVisible(false);
		pFX->ClearState(FS_ACTIVE | FS_SHUTTINGDOWN | FS_INITIALFRAME);
	}
	else
	{
		pInst->DeleteFX(pKeyNode);
	}
}
Example #2
0
bool CClientFXMgr::CreateFXKey(const CLIENTFX_CREATESTRUCT &fxInit, CClientFXInstance* pInst, const FX_KEY* pKey )
{
	if( !pKey ) 
		return false;
	//
	// We need to go ahead and create this effect
	//

	FX_BASEDATA	fxData;
	fxData.m_tTransform			= fxInit.m_tTransform;
	fxData.m_bUseTargetData		= fxInit.m_bUseTargetData;
	fxData.m_hTargetObject		= fxInit.m_hTargetObject;
	fxData.m_vTargetOffset		= fxInit.m_vTargetOffset;
	fxData.m_pFxMgr				= this;
	fxData.m_hParentObject		= fxInit.m_hParentObject;
	fxData.m_hParentRigidBody	= fxInit.m_hParentRigidBody;
	fxData.m_hNodeAttach		= fxInit.m_hNode;
	fxData.m_hSocketAttach		= fxInit.m_hSocket;
	fxData.m_dwFlags			= fxInit.m_dwFlags;

	// Create the FX
	CBaseFX *pNewFX = CreateFX(pKey->m_pFxRef->m_sName, &fxData, pKey->m_pProps);
	if( pNewFX )
	{
		pNewFX->SetVisible(false);
		pNewFX->ClearState(FS_INITIALFRAME | FS_ACTIVE | FS_SHUTTINGDOWN | FS_SUSPENDED);

		// Add it onto the list for link referencing
		pInst->m_ActiveFXList.AddTail(&pNewFX->m_FXListLink);
	}
	else
	{
		return false;
	}

	return true;
}
Example #3
0
//------------------------------------------------------------------
//
//   FUNCTION : UpdateInstanceInterval()
//
//   PURPOSE  : Given an instance and a time interval, this will appropriately update
//				all effects contained within that interval
//
//------------------------------------------------------------------
void CClientFXMgr::UpdateInstanceInterval(CLIENTFX_INSTANCE* pInst, float fStartInterval, float fEndInterval)
{
	//here are the possible scenarios:
	// Inactive
	// Inactive -> Active -> Shutting down
	// Inactive -> Active -> Shutting down -> Inactive
	// Inactive -> Active
	// Shutting Down
	// Shutting Down -> Inactive
	// Shutting Down -> Active -> Shutting Down
	// Shutting Down -> Active -> Shutting Down -> Inactive
	// Shutting Down -> Active
	// Active

	//A note about intervals: The interval used is inclusive of both start and ends. This does
	//mean that a boundary such as a key beginning or end can be hit twice, but because of the
	//way the state flow works, this will not cause any issues, since when it is inactive
	//it will look for active and vice a versa. Therefore since the beginning and end cannot
	//lie on the same position this should not introduce any issues, but ensures that the
	//full track length is handled when updating

	//alright, run through all active effects and determine what to do
	CLinkListNode<FX_LINK>				*pActiveNode;
	CLinkListNode<FX_LINK>				*pNextActiveNode;

	//determine if this is a looping instance
	bool bLoopInstance = pInst->m_bLoop;

	pActiveNode = pInst->m_collActiveFX.GetHead();
	while( pActiveNode )
	{
		//cache the next node in case we delete this key
		pNextActiveNode = pActiveNode->m_pNext;

		//alright, first off look at the state of the key and see what to do
		CBaseFX	*pFX		= pActiveNode->m_Data.m_pFX;
		const FX_KEY* pKey	= pActiveNode->m_Data.m_pRef;

		//this is our time slice beginning
		float fCurrStart = fStartInterval;

		//skip dead space on inactive effects
		if(!pFX->IsActive())
		{
			//sanity check, the shutting down flag should never be set without active
			assert(!pFX->IsShuttingDown());

			//This check is to verify that we aren't shutting down the instance and have inactive effects.
			//If we are shutting down, inactive effects are immediately pruned, and then active effects
			//should be removed as they are completed
			assert(!pInst->m_bShutdown);

			//figure out the start time of this effect
			float fKeyStart = pKey->m_tmStart;

			//this effect is not active. See if it should be (loop keys always should be)
			if(pKey->m_bContinualLoop || ((fKeyStart >= fCurrStart) && (fKeyStart <= fEndInterval)))
			{
				//our effect has just become active, we need to reset its elapsed time to 0,
				//and switch it over to an initial frame
				pFX->SetElapsed(0.0f);
				pFX->SetState(FS_ACTIVE | FS_INITIALFRAME);
				pFX->ClearState(FS_SHUTTINGDOWN);
				pFX->SetVisible(true);

				//handle applying a fake effect offset
				ApplyEffectStartingOffset(pFX, pKey);

				//move our timeslice forward to the beginning of the key
				fCurrStart = fKeyStart;
			}
		}

		if(pFX->IsActive())
		{
			//we are an active effect, which means we are either in the time block or are
			//shutting down. 

			//see if we are currently shutting down, and if we are going to transition into
			//becoming active
			if(pFX->IsShuttingDown())
			{
				float fKeyStart = pKey->m_tmStart;

				//however, we can only bring it into the active state from here if the instance
				//will allow us
				bool bCanActivate = pInst->m_bLoop && !pInst->m_bShutdown;

				//this effect is not active. See if it should be
				if(bCanActivate && (fKeyStart >= fCurrStart) && (fKeyStart <= fEndInterval))
				{
					//it will become active in this range, so move up to there and change state
					pFX->Update(fKeyStart - fCurrStart);

					pFX->SetElapsed(0.0f);
					pFX->SetState(FS_INITIALFRAME | FS_ACTIVE);
					pFX->ClearState(FS_SHUTTINGDOWN);

					//handle applying a fake effect offset
					ApplyEffectStartingOffset(pFX, pKey);

					//move our time position up to the key start
					fCurrStart = fKeyStart;
				}
			}

			//alright, we are now in a chunk of time where either the block is active
			//or shutting down. If it is active, we need to update until the end of the slice
			//or the end of the effect
			if(!pFX->IsShuttingDown())
			{
				//we aren't shutting down, so we can update like normal
				float fTimeBlockEnd = fEndInterval;
				bool bCompleteKey	= ((pKey->m_tmEnd <= fTimeBlockEnd) && (pKey->m_tmEnd >= fCurrStart));

				//see if we hit the end of the key
				if(bCompleteKey)
				{
					fTimeBlockEnd = pKey->m_tmEnd;
				}

				//update based upon the interval length
				pFX->Update(fTimeBlockEnd - fCurrStart);

				//the initial update state should be cleared now
				pFX->ClearState(FS_INITIALFRAME);

				//see if we completed the key
				if(bCompleteKey)
				{
					//we did, so now switch to a shutting down state if it isn't continually looping,
					//otherwise we need to reset the elapsed time to 0
					if(pKey->m_bContinualLoop && bLoopInstance)
					{
						//we have looped our key, so reset the elapsed amount. However, if we are a
						//continually looping effect that started with an offset, we don't want
						//to lose that offset and should threfore just wrap based upon the lifespan
						if(pKey->m_fMaxStartOffset >= 0.001f)
						{
							pFX->SetElapsed((float)fmod(pFX->GetElapsed(), pFX->GetLifespan()));
						}
						else
						{
							//no starting offset, so just to make sure that everything syncs
							//up correctly and no error gets introduced, reset it to 0
							pFX->SetElapsed(0.0f);
						}
					}
					else
					{
						//we're past our key, so start shutting down
						pFX->SetState(FS_SHUTTINGDOWN);
					}
				}

				//update our time start
				fCurrStart = fTimeBlockEnd;
			}

			//alright, now handle shutting down, in which case we just want to update however
			//much time we have left in this interval, and see if the effect is completed
			if(pFX->IsShuttingDown())
			{
				//allow it to update
				pFX->Update(fEndInterval - fCurrStart);

				//can this effect do a smooth shutdown?
				bool bSmoothShutdown = pKey->m_bSmoothShutdown && pInst->m_bSmoothShutdown;

				//see if this effect is done shutting down
				if(pFX->IsFinishedShuttingDown() || !bSmoothShutdown)
				{
					//notify of an effect that has finished shutting down
					HandleShutdownEffect(pInst, pActiveNode);

					//move onto the next node and keep processing
					pActiveNode = pNextActiveNode;
					continue;
				}
			}
		}
		
		//and onto the next node
		pActiveNode = pNextActiveNode;
	}
}
Example #4
0
bool CClientFXMgr::CreateFXKey( CLIENTFX_INSTANCE* pInst, FX_KEY* pKey )
{
	if( !pInst || !pKey ) 
		return false;
	//
	// We need to go ahead and create this effect
	//

	assert(m_hCamera);

	FX_BASEDATA	fxData;
	fxData.m_vPos				= pInst->m_vPos;
	fxData.m_rRot				= pInst->m_rRot;
	fxData.m_dwID				= pInst->m_dwID;
	fxData.m_hTarget			= pInst->m_hTarget;
	fxData.m_dwObjectFlags		= pInst->m_dwObjectFlags;
	fxData.m_dwObjectFlags2		= pInst->m_dwObjectFlags2;
	fxData.m_bUseTargetData		= pInst->m_bUseTargetData;
	fxData.m_vTargetPos			= pInst->m_vTargetPos;
	fxData.m_vTargetNorm		= pInst->m_vTargetNorm;
	fxData.m_hCamera			= m_hCamera;

	// Save the parent
	fxData.m_hParent = pInst->m_hParent;

	// Is this FX supposed to be motion linked to another FX?
	if (pKey->m_bLinked)
	{
		CLinkListNode<FX_LINK>	*pNode = pInst->m_collActiveFX.GetHead();

		while (pNode)
		{
			if (pNode->m_Data.m_dwID == pKey->m_dwLinkedID)
			{
				// This is the one !!!
				if (pInst->ExistFX(pNode->m_Data.m_pFX))
				{
					CBaseFX	 *pMotionLinkFX	= pNode->m_Data.m_pFX;
					fxData.m_hParent = pMotionLinkFX->GetFXObject();
				}

				// done
				break;
			}
			
			pNode = pNode->m_pNext;
		}
	}

	// Create the FX
	CBaseFX *pNewFX = CreateFX(pKey->m_pFxRef->m_sName, &fxData, pKey->m_pProps, pInst->m_hParent);

	if( pNewFX )
	{
		pNewFX->SetVisible(false);
		pNewFX->ClearState(FS_INITIALFRAME | FS_ACTIVE | FS_SHUTTINGDOWN | FS_SUSPENDED);

		// Add it onto the list for link referencing

		FX_LINK	fxLink;
		fxLink.m_dwID = pKey->m_dwID;
		fxLink.m_pFX  = pNewFX;
		fxLink.m_pRef = pKey;

		pInst->m_collActiveFX.AddHead(fxLink);
	}
	else
	{
		return false;
	}

	return true;
}