//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =====// // // Dme representation of QC: $sequence // //===========================================================================// // Valve includes #include "datamodel/dmelementfactoryhelper.h" #include "movieobjects/dmeattributereference.h" #include "movieobjects/dmeanimationlist.h" #include "movieobjects/dmechannel.h" #include "movieobjects/dmeconnectionoperator.h" #include "movieobjects/dmedag.h" #include "mdlobjects/dmeanimcmd.h" #include "mdlobjects/dmeik.h" #include "mdlobjects/dmemotioncontrol.h" #include "mdlobjects/dmesequence.h" #include "mdlobjects/dmebonemask.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // CDmeAnimationEvent //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeAnimationEvent, CDmeAnimationEvent ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeAnimationEvent::OnConstruction() { m_nFrame.Init( this, "frame" ); m_sDataString.Init( this, "dataString" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeAnimationEvent::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceActivity //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceActivity, CDmeSequenceActivity ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceActivity::OnConstruction() { m_nWeight.InitAndSet( this, "weight", 1.0 ); m_sModifierList.Init( this, "modifierList" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceActivity::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceBlendBase //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceBlendBase, CDmeSequenceBlendBase ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBlendBase::OnConstruction() { m_sPoseParameterName.Init( this, "poseParameterName" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBlendBase::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceBlend //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceBlend, CDmeSequenceBlend ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBlend::OnConstruction() { m_flParamStart.Init( this, "paramStart" ); m_flParamEnd.Init( this, "paramEnd" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBlend::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceCalcBlend //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceCalcBlend, CDmeSequenceCalcBlend ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceCalcBlend::OnConstruction() { m_sAttachmentName.Init( this, "attachmentName" ); m_eMotionControl.InitAndCreate( this, "motionControl" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceCalcBlend::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceLayerBase //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceLayerBase, CDmeSequenceLayerBase ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceLayerBase::OnConstruction() { m_eAnimation.Init( this, "animation" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceLayerBase::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceAddLayer //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceAddLayer, CDmeSequenceAddLayer ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceAddLayer::OnConstruction() { } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceAddLayer::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceBlendLayer //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceBlendLayer, CDmeSequenceBlendLayer ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBlendLayer::OnConstruction() { m_flStartFrame.Init( this, "startFrame" ); m_flPeakFrame.Init( this, "peakFrame" ); m_flTailFrame.Init( this, "tailFrame" ); m_flEndFrame.Init( this, "endFrame" ); m_bSpline.Init( this, "spline" ); m_bCrossfade.Init( this, "crossfade" ); m_bNoBlend.Init( this, "noBlend" ); m_bLocal.Init( this, "local" ); m_sPoseParameterName.Init( this, "poseParameterName" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBlendLayer::OnDestruction() { } //----------------------------------------------------------------------------- // CDmeSequenceBase //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequenceBase, CDmeSequenceBase ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBase::OnConstruction() { m_eActivity.InitAndCreate( this, "activity" ); m_bHidden.InitAndSet( this, "hidden", false ); m_bDelta.InitAndSet( this, "delta", false ); m_bWorldSpace.InitAndSet( this, "worldSpace", false ); m_bPreDelta.InitAndSet( this, "preDelta", false ); m_bAutoPlay.InitAndSet( this, "autoPlay", false ); m_bRealtime.InitAndSet( this, "realtime", false ); m_flFadeIn.InitAndSet( this, "fadein", 0.2f ); m_flFadeOut.InitAndSet( this, "fadeout", 0.2f ); m_sEntryNode.Init( this, "entryNode" ); m_sExitNode.Init( this, "exitNode" ); m_bReverseNodeTransition.Init( this, "reverseNodeTransition" ); m_bSnap.Init( this, "snap" ); m_bPost.Init( this, "post" ); m_bLoop.Init( this, "loop" ); m_eIkLockList.Init( this, "ikLockList", FATTRIB_NEVERCOPY ); m_eAnimationEventList.Init( this, "animationEventList" ); m_eLayerList.Init( this, "layerList" ); m_sKeyValues.Init( this, "keyValues" ); if ( m_eActivity.GetElement() ) { if ( !Q_strcmp( "unnamed", m_eActivity.GetElement()->GetName() ) ) { m_eActivity.GetElement()->SetName( "" ); } } } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequenceBase::OnDestruction() { } //----------------------------------------------------------------------------- // qsort function for sorting DmeBaseSequence elements based on type and // sequence references. // // * A DmeBaseSequence must be either a DmeSequence or a DmeMultiSequence // They are mutually exclusive, cannot be both // * DmeMultiSequence refer to DmeSequence's so should always go last // * DmeMultiSequence cannot refer to other DmeMultiSequence so they are // considered equal // * DmeSequence can refer to other DmeSequence elements via DmeAnimCmd's // but circular references are not allowed. If a DmeSequence refers // to another, the DmeSequence being referenced needs to be before the // DmeSequence doing the referring // * If no referrals between two DmeSequence's, sort based on DmeAnimCmd count // so DmeSequence's with fewer DmeAnimCmd's go first //----------------------------------------------------------------------------- int CDmeSequenceBase::QSortFunction( const void *pVoidSeq1, const void *pVoidSeq2 ) { const CDmeSequenceBase *pBaseSeq1 = *( const CDmeSequenceBase ** )pVoidSeq1; const CDmeSequenceBase *pBaseSeq2 = *( const CDmeSequenceBase ** )pVoidSeq2; if ( !pBaseSeq1 || !pBaseSeq2 ) return 0; const CDmeSequence* pSeq1 = CastElement< CDmeSequence >( pBaseSeq1 ); // NULL if MultiSequence const CDmeSequence* pSeq2 = CastElement< CDmeSequence >( pBaseSeq2 ); // NULL if MultiSequence if ( pSeq1 && !pSeq2 ) // 1 Seq, 2 Multi, 1 < 2 return -1; if ( !pSeq1 && pSeq2 ) // 1 Multi, 2 Seq, 1 > 2 return 1; if ( !pSeq1 && !pSeq2 ) // Both Multi, 1 == 2, Multi can't refer to other multi return 0; // Both Seq, check for references bool bRef[2] = { false, false }; const CDmeSequence *const pSeq[2] = { pSeq1, pSeq2 }; for ( int i = 0; i < 2; ++i ) { for ( int j = 0; j < pSeq[i]->m_eAnimationCommandList.Count(); ++j ) { const CDmeAnimCmd *pAnimCmd = pSeq[i]->m_eAnimationCommandList[j]; const CDmeAnimCmdSubtract *pAnimCmdSubtract = CastElement< CDmeAnimCmdSubtract >( pAnimCmd ); if ( pAnimCmdSubtract && pAnimCmdSubtract->m_eAnimation.GetHandle() == pSeq[ (i + 1) % 2 ]->GetHandle() ) { bRef[i] = true; break; } else { const CDmeAnimCmdAlign *pAnimCmdAlign = CastElement< CDmeAnimCmdAlign >( pAnimCmd ); if ( pAnimCmdAlign && pAnimCmdAlign->m_eAnimation.GetHandle() == pSeq[ ( i + 1 ) % 2 ]->GetHandle() ) { bRef[i] = true; break; } } } } if ( bRef[0] && !bRef[1] ) // 1 references 2, so 1 > 2 return 1; if ( !bRef[0] && bRef[1] ) // 1 references by 2, so 1 < 2 return -1; if ( bRef[0] && bRef[1] ) { Error( "Animation %s & %s reference each other, circular references are not allowed\n", pSeq1->GetName(), pSeq2->GetName() ); return 0; } if ( pSeq1->m_eAnimationCommandList.Count() < pSeq2->m_eAnimationCommandList.Count() ) { return -1; } else if ( pSeq1->m_eAnimationCommandList.Count() > pSeq2->m_eAnimationCommandList.Count() ) { return 1; } return 0; } //----------------------------------------------------------------------------- // CDmeSequence //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeSequence, CDmeSequence ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequence::OnConstruction() { m_eSkeleton.Init( this, "skeleton" ); m_eAnimationList.Init( this, "animationList" ); m_flFPS.InitAndSet( this, "fps", 30.0f ); m_vOrigin.InitAndSet( this, "origin", Vector( 0.0f, 0.0f, 0.0f ) ); m_flScale.InitAndSet( this, "scale", 1.0f ); m_nStartLoop.Init( this, "startLoop" ); m_bForceLoop.Init( this, "forceLoop" ); m_bAutoIk.Init( this, "autoIk" ); m_flMotionRollback.InitAndSet( this, "motionRollback", 0.3f ); m_bAnimBlocks.InitAndSet( this, "animBlocks", true ); m_bAnimBlockStall.InitAndSet( this, "animBlockStall", true ); m_eMotionControl.InitAndCreate( this, "motionControl" ); m_eAnimationCommandList.Init( this, "animationCommandList" ); m_eIkRuleList.Init( this, "ikRuleList", FATTRIB_NEVERCOPY ); m_eBoneMask.Init( this, "boneMask" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequence::OnDestruction() { } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- CDmeChannelsClip *CDmeSequence::GetDmeChannelsClip() const { CDmeAnimationList *pDmeAnimationList = m_eAnimationList.GetElement(); if ( !pDmeAnimationList ) return NULL; for ( int i = 0; i < pDmeAnimationList->GetAnimationCount(); ++i ) { CDmeChannelsClip *pDmeChannelsClip = pDmeAnimationList->GetAnimation( i ); if ( pDmeChannelsClip ) return pDmeChannelsClip; } return NULL; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- DmeFramerate_t CDmeSequence::GetFrameRate( DmeFramerate_t fallbackFrameRate /* = 30 */, bool bForceFallback /* = false */ ) const { CDmeChannelsClip *pDmeChannelsClip = GetDmeChannelsClip(); if ( !pDmeChannelsClip ) return fallbackFrameRate; DmeFramerate_t dmeFrameRate = fallbackFrameRate; if ( !bForceFallback && pDmeChannelsClip->HasAttribute( "frameRate" ) ) { const int nFrameRate = pDmeChannelsClip->GetValue< int >( "frameRate", 0 ); if ( nFrameRate >= 0 ) { dmeFrameRate = DmeFramerate_t( nFrameRate ); } } return dmeFrameRate; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- int CDmeSequence::GetFrameCount( DmeFramerate_t fallbackFrameRate /* = 30 */, bool bForceFallback /* = false */ ) const { CDmeChannelsClip *pDmeChannelsClip = GetDmeChannelsClip(); if ( !pDmeChannelsClip ) return 0; const DmeFramerate_t dmeFrameRate = GetFrameRate( fallbackFrameRate, bForceFallback ); const DmeTime_t nStartTime = pDmeChannelsClip->GetStartTime(); const int nStartFrame = FrameForTime( nStartTime, dmeFrameRate ); const DmeTime_t nEndTime = pDmeChannelsClip->GetEndTime(); const int nEndFrame = FrameForTime( nEndTime, dmeFrameRate ); return nEndFrame - nStartFrame + 1; } //----------------------------------------------------------------------------- // Does a search through connection operators for dependent DmeOperators //----------------------------------------------------------------------------- void CDmeSequence::GetDependentOperators( CUtlVector< IDmeOperator * > &operatorList, CDmeOperator *pDmeOperator ) const { if ( !pDmeOperator || !CastElement< CDmeOperator >( pDmeOperator ) ) return; // Abort if the specified operator is already in the operatorList for ( int i = 0; i < operatorList.Count(); ++i ) { CDmeOperator *pTmpDmeOperator = CastElement< CDmeOperator >( reinterpret_cast< CDmeOperator * >( operatorList[i] ) ); if ( pTmpDmeOperator && pTmpDmeOperator == pDmeOperator ) return; } operatorList.AddToTail( pDmeOperator ); CUtlVector< CDmAttribute * > outAttrList; pDmeOperator->GetOutputAttributes( outAttrList ); for ( int i = 0; i < outAttrList.Count(); ++i ) { CDmElement *pDmElement = outAttrList[i]->GetOwner(); if ( !pDmElement ) continue; if ( pDmElement != pDmeOperator ) { CUtlVector< CDmElement * > reList0; FindReferringElements( reList0, pDmElement, g_pDataModel->GetSymbol( "element" ), false ); for ( int j = 0; j < reList0.Count(); ++j ) { CDmeAttributeReference *pRe0 = CastElement< CDmeAttributeReference >( reList0[j] ); if ( !pRe0 || pRe0->GetReferencedAttribute() != outAttrList[i] ) continue; CUtlVector< CDmElement * > reList1; FindReferringElements( reList1, pRe0, g_pDataModel->GetSymbol( "input" ), false ); for ( int k = 0; k < reList1.Count(); ++k ) { CDmeConnectionOperator *pRe1 = CastElement< CDmeConnectionOperator >( reList1[k] ); if ( !pRe1 ) continue; GetDependentOperators( operatorList, pRe1 ); } } } GetDependentOperators( operatorList, CastElement< CDmeOperator >( pDmElement ) ); } } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSequence::PrepareChannels( CUtlVector< IDmeOperator * > &dmeOperatorList ) { dmeOperatorList.RemoveAll(); CDmeAnimationList *pDmeAnimationList = m_eAnimationList.GetElement(); if ( !pDmeAnimationList ) return; for ( int i = 0; i < pDmeAnimationList->GetAnimationCount(); ++i ) { CDmeChannelsClip *pDmeChannelsClip = pDmeAnimationList->GetAnimation( i ); if ( !pDmeChannelsClip ) continue; for ( int j = 0; j < pDmeChannelsClip->m_Channels.Count(); ++j ) { CDmeChannel *pDmeChannel = pDmeChannelsClip->m_Channels[j]; if ( !pDmeChannel ) continue; pDmeChannel->SetMode( CM_PLAY ); GetDependentOperators( dmeOperatorList, pDmeChannel ); } } } //----------------------------------------------------------------------------- // Update channels so they are in position for the next frame //----------------------------------------------------------------------------- void CDmeSequence::UpdateChannels( CUtlVector< IDmeOperator * > &dmeOperatorList, DmeTime_t nClipTime ) { CDmeAnimationList *pDmeAnimationList = m_eAnimationList.GetElement(); if ( !pDmeAnimationList ) return; for ( int i = 0; i < pDmeAnimationList->GetAnimationCount(); ++i ) { CDmeChannelsClip *pDmeChannelsClip = pDmeAnimationList->GetAnimation( i ); if ( !pDmeChannelsClip ) continue; const DmeTime_t channelTime = pDmeChannelsClip->ToChildMediaTime( nClipTime ); const int nChannelsCount = pDmeChannelsClip->m_Channels.Count(); for ( int j = 0; j < nChannelsCount; ++j ) { pDmeChannelsClip->m_Channels[j]->SetCurrentTime( channelTime ); } } // Recompute the position of the joints { CDisableUndoScopeGuard guard; g_pDmElementFramework->SetOperators( dmeOperatorList ); g_pDmElementFramework->Operate( true ); } g_pDmElementFramework->BeginEdit(); } //----------------------------------------------------------------------------- // CDmeMultiSequence //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Expose this class to the scene database //----------------------------------------------------------------------------- IMPLEMENT_ELEMENT_FACTORY( DmeMultiSequence, CDmeMultiSequence ); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeMultiSequence::OnConstruction() { m_nBlendWidth.InitAndSet( this, "blendWidth", 0 ); m_eBlendRef.Init( this, "blendRef", FATTRIB_NEVERCOPY ); m_eBlendComp.Init( this, "blendComp", FATTRIB_NEVERCOPY ); m_eBlendCenter.Init( this, "blendCenter", FATTRIB_NEVERCOPY ); m_eSequenceList.Init( this, "sequenceList", FATTRIB_NEVERCOPY ); m_eBlendList.Init( this, "blendList" ); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeMultiSequence::OnDestruction() { }