//-----------------------------------------------------------------------------
// Purpose: Iterates through an object, and all it's children, looking for an
//			entity with a matching key and value
// Input  : key - 
//			value - 
// Output : CMapEntity - the entity found
//-----------------------------------------------------------------------------
CMapEntity *CMapClass::FindChildByKeyValue( LPCSTR key, LPCSTR value )
{
	if ( !key || !value )
		return NULL;

	POSITION p = Children.GetHeadPosition();
	while( p )
	{
		CMapClass *pChild = Children.GetNext( p );
		CMapEntity *e = pChild->FindChildByKeyValue( key, value );
		if ( e )
			return e;
	}

	return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Rebuilds the line path between keyframe entities
//			samples the interpolator function to get an approximation of the curve
//-----------------------------------------------------------------------------
void CMapAnimator::RebuildPath( void )
{
	CMapClass *pWorld = GetWorldObject( this );
	if ( !pWorld )
	{
		// Sometimes the object isn't linked back into the world yet when RebuildPath() 
		// is called... we will be get called again when needed, but may cause an incorrect
		// (linear-only) path to get drawn temporarily.
		return;
	}

	//
	// Build the path forward from the head. Keep a list of nodes we've visited to
	// use in detecting circularities.
	//
	CMapObjectList VisitedList;
	CMapKeyFrame *pCurKey = this;
	while ( pCurKey != NULL )
	{
		VisitedList.AddTail( pCurKey );

		//
		// Attach ourselves as this keyframe's animator.
		//
		pCurKey->SetAnimator( this );

		//
		// Get the entity parent of this keyframe so we can query keyvalues.
		//
		CMapEntity *pCurEnt = dynamic_cast<CMapEntity *>( pCurKey->GetParent() );
		if ( !pCurEnt )
		{
			return;
		}

		//
		// Find the next keyframe in the path.
		//
		CMapEntity *pNextEnt = pWorld->FindChildByKeyValue( "targetname", pCurEnt->GetKeyValue( "NextKey" ) );
		CMapKeyFrame *pNextKey = NULL;

		if ( pNextEnt )
		{
			pNextKey = pNextEnt->GetChildOfType( ( CMapKeyFrame * )NULL );
			pCurKey->SetNextKeyFrame(pNextKey);
		}
		else
		{
			pCurKey->SetNextKeyFrame( NULL );
		}

		pCurKey = pNextKey;

		//
		// If we detect a circularity, stop.
		//
		if ( VisitedList.Find( pCurKey ) )
		{
			break;
		}
	}

	//
	// Now traverse the path again building the spline points, once again checking
	// the visited list for circularities.
	//
	VisitedList.RemoveAll();
	pCurKey = this;
	CMapKeyFrame *pPrevKey = this;
	while ( pCurKey != NULL )
	{
		VisitedList.AddTail( pCurKey );

		pCurKey->BuildPathSegment(pPrevKey);

		pPrevKey = pCurKey;
		pCurKey = pCurKey->m_pNextKeyFrame;

		//
		// If we detect a circularity, stop.
		//
		if ( VisitedList.Find( pCurKey ) )
		{
			break;
		}
	}
}