//**************************************************************************** //* MODULE: Gfx //* FILENAME: SubAnimController.cpp //* OWNER: Gary Jesdanun //* CREATION DATE: 2/06/2003 //**************************************************************************** #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Gfx { /******************************************************************/ /* */ /* */ /******************************************************************/ CBonedAnimController::CBonedAnimController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { mp_quickAnim = Nx::CEngine::sInitQuickAnim(); mp_quickAnim->Enable( false ); Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); m_animScriptName = pAnimationComponent->GetAnimScriptName(); } /******************************************************************/ /* */ /* */ /******************************************************************/ CBonedAnimController::~CBonedAnimController() { if ( mp_quickAnim ) { Nx::CEngine::sUninitQuickAnim( mp_quickAnim ); mp_quickAnim = NULL; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CBonedAnimController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CBonedAnimController::GetPose( Gfx::CPose* pResultPose ) { Dbg_MsgAssert( pResultPose, ( "No return data" ) ); // int skipList[vMAX_BONES]; // GetSkeleton()->GetSkipList( &skipList[0] ); uint32* p_skip_list = GetSkeleton()->GetBoneSkipList(); uint32 skip_index = GetSkeleton()->GetBoneSkipIndex(); Dbg_Assert( mp_quickAnim ); // mp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, &skipList[0], mp_blendChannel->GetCurrentAnimTime() ); mp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, p_skip_list, skip_index, mp_blendChannel->GetCurrentAnimTime() ); mp_quickAnim->Enable( true ); return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CBonedAnimController::Update() { Dbg_MsgAssert( mp_blendChannel->m_loopingType != Gfx::LOOPING_WOBBLE, ( "Not supposed to be wobble type" ) ); float oldTime = mp_blendChannel->m_currentTime; mp_blendChannel->m_currentTime = mp_blendChannel->get_new_anim_time(); mp_blendChannel->ProcessCustomKeys( oldTime, mp_blendChannel->m_currentTime ); if ( mp_blendChannel->m_currentTime < oldTime ) { mp_quickAnim->Enable( false ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ EAnimFunctionResult CBonedAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript ) { switch ( Checksum ) { case 0x5f495ae0: // invalidateCache { mp_quickAnim->Enable( false ); // want the other controllers to be invalidated too return AF_NOT_EXECUTED; } break; case 0xaf2fae19: // playsequence { uint32 anim_name; float start_time; float end_time; int loop_type; float blend_period; float speed; pParams->GetChecksum( CRCD(0x6c2bfb7f,"animname"), &anim_name, Script::ASSERT ); pParams->GetFloat( CRCD(0xd16b61e6,"starttime"), &start_time, Script::ASSERT ); pParams->GetFloat( CRCD(0xab81bb3d,"endtime"), &end_time, Script::ASSERT ); pParams->GetInteger( CRCD(0xcd8d7c1b,"looptype"), &loop_type, Script::ASSERT ); pParams->GetFloat( CRCD(0x8f0d24ed,"blendperiod"), &blend_period, Script::ASSERT ); pParams->GetFloat( CRCD(0xf0d90109,"speed"), &speed, Script::ASSERT ); mp_blendChannel->CAnimChannel::PlaySequence( anim_name, start_time, end_time, (Gfx::EAnimLoopingType)loop_type, blend_period, speed); Dbg_Assert( mp_quickAnim ); mp_quickAnim->SetAnimAssetName( m_animScriptName + anim_name ); } break; default: return AF_NOT_EXECUTED; } return AF_TRUE; } /******************************************************************/ /* */ /* */ /******************************************************************/ CWobbleController::CWobbleController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { m_wobbleTargetTime = 0.0f; m_wobbleDetails.wobbleAmpA = 0.0f; m_wobbleDetails.wobbleAmpB = 0.0f; m_wobbleDetails.wobbleK1 = 0.0f; m_wobbleDetails.wobbleK2 = 0.0f; m_wobbleDetails.spazFactor = 0.0f; mp_quickAnim = Nx::CEngine::sInitQuickAnim(); mp_quickAnim->Enable( false ); Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); m_animScriptName = pAnimationComponent->GetAnimScriptName(); /* float startTime; float endTime; if ( pParams->GetFloat( "startTime", &startTime, Script::NO_ASSERT ); && pParams->GetFloat( "endTime", &endTime, Script::NO_ASSERT ) ) { m_wobbleTargetTime = ( startTime + endTime ) / 2; } */ } /******************************************************************/ /* */ /* */ /******************************************************************/ CWobbleController::~CWobbleController() { if ( mp_quickAnim ) { Nx::CEngine::sUninitQuickAnim( mp_quickAnim ); mp_quickAnim = NULL; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CWobbleController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CWobbleController::GetPose( Gfx::CPose* pResultPose ) { Dbg_MsgAssert( pResultPose, ( "No return data" ) ); // int skipList[vMAX_BONES]; // GetSkeleton()->GetSkipList( &skipList[0] ); uint32* p_skip_list = GetSkeleton()->GetBoneSkipList(); uint32 skip_index = GetSkeleton()->GetBoneSkipIndex(); Dbg_Assert( mp_quickAnim ); // mp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, &skipList[0], mp_blendChannel->GetCurrentAnimTime() ); mp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, p_skip_list, skip_index, mp_blendChannel->GetCurrentAnimTime() ); mp_quickAnim->Enable( true ); return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ float CWobbleController::get_new_wobble_time() { float AmpA = m_wobbleDetails.wobbleAmpA; float AmpB = m_wobbleDetails.wobbleAmpB; float k1 = m_wobbleDetails.wobbleK1; float k2 = m_wobbleDetails.wobbleK2; float SpazFactor = m_wobbleDetails.spazFactor; float new_time = m_wobbleTargetTime; Dbg_MsgAssert( mp_blendChannel->m_startTime < mp_blendChannel->m_endTime, ("start time must be smaller than end time for LOOPING_WOBBLE")); float l = ( mp_blendChannel->m_endTime - mp_blendChannel->m_startTime ) / 2; float mid = ( mp_blendChannel->m_endTime + mp_blendChannel->m_startTime ) / 2; float d = Mth::Abs( new_time - mid ); SpazFactor = 1 + ( SpazFactor - 1 ) * d / l; AmpA *= SpazFactor; AmpB *= SpazFactor; if ( new_time - AmpA - AmpB < mp_blendChannel->m_startTime ) { new_time = mp_blendChannel->m_startTime + AmpA + AmpB; } if ( new_time + AmpA + AmpB > mp_blendChannel->m_endTime ) { new_time = mp_blendChannel->m_endTime - AmpA - AmpB; } float t = (int)Tmr::ElapsedTime( 0 ) * k1; t -= 16.0f * ( ((int)t) / 16.0f ); float amp = AmpA + AmpB * sinf( t * 2.0f * Mth::PI ); t = (int)Tmr::ElapsedTime( 0 ) * k2; t -= 16.0f * ( ((int)t) / 16.0f ); new_time += amp * sinf( t * 2.0f * Mth::PI ); // These should never be true, but just in case. if (new_time < mp_blendChannel->m_startTime) { new_time = mp_blendChannel->m_startTime; } if (new_time > mp_blendChannel->m_endTime) { new_time = mp_blendChannel->m_endTime; } return new_time; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CWobbleController::Update() { // the looping check below is only needed until // we stop automatically adding the wobble // controller to all channels Dbg_MsgAssert ( mp_blendChannel->m_loopingType == Gfx::LOOPING_WOBBLE, ( "Was supposed to be wobble type %d", mp_blendChannel->m_loopingType ) ); // remember old time, so that we know whether to use the quick anim float oldTime = mp_blendChannel->m_currentTime; mp_blendChannel->m_currentTime = get_new_wobble_time(); // remember to use the quick anim if ( mp_blendChannel->m_currentTime < oldTime ) { mp_quickAnim->Enable( false ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CWobbleController::GetDebugInfo( Script::CStruct* p_info ) { #ifdef __DEBUG_CODE__ p_info->AddFloat( CRCD(0x359ac119,"m_wobbleTargetTime"), m_wobbleTargetTime ); p_info->AddFloat( CRCD(0xfd266a26,"wobbleAmpA"), m_wobbleDetails.wobbleAmpA ); p_info->AddFloat( CRCD(0x642f3b9c,"wobbleAmpB"), m_wobbleDetails.wobbleAmpB ); p_info->AddFloat( CRCD(0x0f43fd49,"wobbleK1"), m_wobbleDetails.wobbleK1 ); p_info->AddFloat( CRCD(0x964aacf3,"wobbleK2"), m_wobbleDetails.wobbleK2 ); p_info->AddFloat( CRCD(0xf90b0824,"spazFactor"), m_wobbleDetails.spazFactor ); #endif } /******************************************************************/ /* */ /* */ /******************************************************************/ EAnimFunctionResult CWobbleController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript ) { switch ( Checksum ) { case 0x5f495ae0: // invalidateCache { mp_quickAnim->Enable( false ); // want the other controllers to be invalidated too return AF_NOT_EXECUTED; } break; case 0xaf2fae19: // playsequence { uint32 anim_name; float start_time; float end_time; int loop_type; float blend_period; float speed; pParams->GetChecksum( CRCD(0x6c2bfb7f,"animname"), &anim_name, Script::ASSERT ); pParams->GetFloat( CRCD(0xd16b61e6,"starttime"), &start_time, Script::ASSERT ); pParams->GetFloat( CRCD(0xab81bb3d,"endtime"), &end_time, Script::ASSERT ); pParams->GetInteger( CRCD(0xcd8d7c1b,"looptype"), &loop_type, Script::ASSERT ); pParams->GetFloat( CRCD(0x8f0d24ed,"blendperiod"), &blend_period, Script::ASSERT ); pParams->GetFloat( CRCD(0xf0d90109,"speed"), &speed, Script::ASSERT ); mp_blendChannel->CAnimChannel::PlaySequence( anim_name, start_time, end_time, (Gfx::EAnimLoopingType)loop_type, blend_period, speed); Dbg_Assert( mp_quickAnim ); mp_quickAnim->SetAnimAssetName( m_animScriptName + anim_name ); } break; case 0xd0209498: // setwobbletarget { float wobbleTargetAlpha; if ( pParams->GetFloat( CRCD(0x4d747fa0,"wobbletargetalpha"), &wobbleTargetAlpha, Script::NO_ASSERT ) ) { // check bounds if ( wobbleTargetAlpha < 0.0f ) { wobbleTargetAlpha = 0.0f; } if ( wobbleTargetAlpha > 1.0f ) { wobbleTargetAlpha = 1.0f; } m_wobbleTargetTime = mp_blendChannel->m_startTime + ( mp_blendChannel->m_endTime - mp_blendChannel->m_startTime ) * wobbleTargetAlpha; } } break; case 0xea6d0efd: // setwobbledetails { float wobbleAmpA; float wobbleAmpB; float wobbleK1; float wobbleK2; float spazFactor; if ( pParams->GetFloat( CRCD(0xfd266a26,"wobbleAmpA"), &wobbleAmpA, Script::NO_ASSERT ) && pParams->GetFloat( CRCD(0x642f3b9c,"wobbleAmpB"), &wobbleAmpB, Script::NO_ASSERT ) && pParams->GetFloat( CRCD(0x0f43fd49,"wobbleK1"), &wobbleK1, Script::NO_ASSERT ) && pParams->GetFloat( CRCD(0x964aacf3,"wobbleK2"), &wobbleK2, Script::NO_ASSERT ) && pParams->GetFloat( CRCD(0xf90b0824,"spazFactor"), &spazFactor, Script::NO_ASSERT ) ) { m_wobbleDetails.wobbleAmpA = wobbleAmpA; m_wobbleDetails.wobbleAmpB = wobbleAmpB; m_wobbleDetails.wobbleK1 = wobbleK1; m_wobbleDetails.wobbleK2 = wobbleK2; m_wobbleDetails.spazFactor = spazFactor; } } break; default: return AF_NOT_EXECUTED; } return AF_TRUE; } /******************************************************************/ /* */ /* */ /******************************************************************/ CFlipRotateController::CFlipRotateController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { m_flipped = false; m_rotated = false; } /******************************************************************/ /* */ /* */ /******************************************************************/ CFlipRotateController::~CFlipRotateController() { } /******************************************************************/ /* */ /* */ /******************************************************************/ void CFlipRotateController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); int flipped; if ( pParams->GetInteger( CRCD(0x0c7a712c,"flipped"), &flipped, Script::NO_ASSERT ) ) { m_flipped = flipped; } int rotated; if ( pParams->GetInteger( CRCD(0x6ea3704a,"rotated"), &rotated, Script::NO_ASSERT ) ) { m_rotated = rotated; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CFlipRotateController::Update() { } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CFlipRotateController::GetPose( Gfx::CPose* pResultPose ) { // rather than using the m_flipped and m_rotated flags, // we should use the one stored in the CAnimationComponent // temporarily... this is because right now we don't want // to blend across the flip (but eventually we will want to) CSkeleton* pSkeleton = GetSkeleton(); Dbg_MsgAssert( pSkeleton, ( "No skeleton?" ) ); #ifdef __NOPT_ASSERT__ { // remove this scope if you actually want to use pAnimationComponent // in something other than the assertion Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); } #endif Obj::CSkaterFlipAndRotateComponent* pSkaterFlipAndRotateComponent = GetSkaterFlipAndRotateComponentFromObject( GetObject() ); if ( pSkaterFlipAndRotateComponent && pSkaterFlipAndRotateComponent->IsBoardRotated() ) // if ( m_rotated ) { int idx; // name of skateboard bone in new skeleton idx = pSkeleton->GetBoneIndexById( CRCD(0x98971faf, "bone_board_root") ); if ( idx != -1 ) { Mth::Quat* pQuat = (pResultPose->m_rotations + idx); *pQuat = Mth::Quat(0.0f,0.0f,1.0f,0.0f) * *pQuat; pQuat->Normalize(); } } // GJ: this remembers the flip state when the animation was // first launched, so that we can blend across the flip... // it produces some weird effects currently in the THPS5, // (such as the pelvis rotating 180 degrees), but this may // be due to the way the scripts were originally written... // i'll take a look at it later, but hopefully this will // give Left Field some of the functionality they've been // looking for... if ( m_flipped ) // if ( pAnimationComponent->IsFlipped() ) { int i; Gfx::CPose oldPose; int numBones = pSkeleton->GetNumBones(); // oldPose = *pResultPose; for ( i = 0; i < numBones; i++ ) { oldPose.m_rotations[i] = pResultPose->m_rotations[i]; } for ( i = 0; i < numBones; i++ ) { oldPose.m_translations[i] = pResultPose->m_translations[i]; } Mth::Quat* pQuat = (pResultPose->m_rotations); Mth::Vector* pTrans = (pResultPose->m_translations); for ( i = 0; i < numBones; i++ ) { int flipIndex = pSkeleton->GetFlipIndex(i); if ( flipIndex != -1 ) { *pQuat = *(oldPose.m_rotations+flipIndex); *pTrans = *(oldPose.m_translations+flipIndex); } else { *pQuat = *(oldPose.m_rotations+i); *pTrans = *(oldPose.m_translations+i); } // flip all rotations and translations on Y. (*pQuat)[X] = -(*pQuat)[X]; (*pQuat)[W] = -(*pQuat)[W]; (*pTrans)[X] = -(*pTrans)[X]; pQuat++; pTrans++; } } return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ CIKController::CIKController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ CIKController::~CIKController() { } /******************************************************************/ /* */ /* */ /******************************************************************/ void CIKController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CIKController::Update() { // here we'd do things like grab the position of the bike pedals // from the CBikeComponent, and override the leg bones, or whatever // if data needs be shared among different // blend channels, then we might want to consider // storing it in a CIKComponent... then, the // Update() function can grab it like so: // Obj::CIKComponent* pIKComponent = GetIKComponentFromObject( GetObject() ); // if ( pIKComponent ) // { // Mth::Vector steering_column_pos = pIKComponent->GetBonePosition( "steering_column" ); // Mth::Vector left_handle_bar_pos = pIKComponent->GetBonePosition( "left_handle_bar" ); // } // if each blend channel needs its own set of IK data // then we can just do it like so: // Mth::Vector steering_column_pos = m_steering_column_pos; // Mth::Vector left_handle_bar_pos = m_left_handle_bar_pos; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CIKController::GetDebugInfo( Script::CStruct* p_info ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ EAnimFunctionResult CIKController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript ) { switch ( Checksum ) { default: return AF_NOT_EXECUTED; } return AF_TRUE; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CIKController::GetPose( Gfx::CPose* pResultPose ) { return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ CProceduralAnimController::CProceduralAnimController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ CProceduralAnimController::~CProceduralAnimController() { } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::Update() { } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CProceduralAnimController::GetPose( Gfx::CPose* pResultPose ) { // To be consistent with THPS4, we should actually do this // AFTER building the object-space transform of each bone // (but i'll wait until someone actually asks for this feature) // I didn't fully re-implement this functionality from THPS4, // since we're going to do our procedural cloth animations // in a different way for THPS5. I've left this partial // implementation in as an example for other developers // to write their own controllers. // THPS4 had ping-ponging animations (so that we can animate // the shirt rising and falling)... we can re-implement // this later if we end up deciding to use this controller... CSkeleton* pSkeleton = GetSkeleton(); Dbg_MsgAssert( pSkeleton, ( "No skeleton?" ) ); Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); int numProceduralBones = pAnimationComponent->GetNumProceduralBones(); CProceduralBone* p_current_procedural_bone = pAnimationComponent->GetProceduralBones(); for ( int i = 0; i < numProceduralBones; i++ ) { int idx = pSkeleton->GetBoneIndexById( p_current_procedural_bone->m_name ); if ( idx != -1 ) { Mth::Quat* pQuat = pResultPose->m_rotations + idx; if ( p_current_procedural_bone->rotEnabled ) { Mth::Vector theRotVector = p_current_procedural_bone->currentRot; theRotVector.Scale( Mth::PI * 2.0f / 4096.0f ); Mth::Quat theRotQuat = Mth::EulerToQuat( theRotVector ); // TODO: should I be post-rotating this? *pQuat = theRotQuat * *pQuat; pQuat->Normalize(); } } p_current_procedural_bone++; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneTransMin( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->trans0 = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneTransMax( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->trans1 = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneTransSpeed( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->deltaTrans = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneTransActive( uint32 boneName, bool enabled ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->transEnabled = enabled; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneTransCurrent( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->currentTrans = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneRotMin( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->rot0[X] = vec[X] * 2.0f * Mth::PI / 4096.0f; pProceduralBone->rot0[Y] = vec[Y] * 2.0f * Mth::PI / 4096.0f; pProceduralBone->rot0[Z] = vec[Z] * 2.0f * Mth::PI / 4096.0f; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneRotMax( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->rot1[X] = vec[X] * 2.0f * Mth::PI / 4096.0f; pProceduralBone->rot1[Y] = vec[Y] * 2.0f * Mth::PI / 4096.0f; pProceduralBone->rot1[Z] = vec[Z] * 2.0f * Mth::PI / 4096.0f; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneRotSpeed( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->deltaRot = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneRotCurrent( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->currentRot = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneRotActive( uint32 boneName, bool enabled ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->rotEnabled = enabled; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneScaleMin( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->scale0 = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneScaleMax( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->scale1 = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneScaleSpeed( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->deltaScale = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneScaleCurrent( uint32 boneName, const Mth::Vector& vec ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->currentScale = vec; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CProceduralAnimController::SetProceduralBoneScaleActive( uint32 boneName, bool enabled ) { Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); Dbg_MsgAssert( pAnimationComponent, ( "No animation component?" ) ); CProceduralBone* pProceduralBone = pAnimationComponent->GetProceduralBoneByName( boneName ); if ( pProceduralBone ) { pProceduralBone->scaleEnabled = enabled; } } /******************************************************************/ /* */ /* */ /******************************************************************/ // TODO: It's kind of backwards for the CAnimationComponent to be calling // member functions in the CProceduralAnimController that set values // back inside the CAnimationComponent... This is because I haven't // really decided whether each blend channel should have its own // proc anim data, or whether the blend channels should share a single // set of proc anim data. Right now, the blend channels all share // a single set of proc anim data (stored in the CAnimationComponent). EAnimFunctionResult CProceduralAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript ) { switch ( Checksum ) { // @script | SetBoneTransMin | Sets the minimum translation extent for procedurally animated bone (in world units) // @parmopt float | x | 0 | minimum extent x // @parmopt float | y | 0 | minimum extent y // @parmopt float | z | 0 | minimum extent z // @parm name | bone | name of procedural bone case 0x02565bd1: // SetBoneTransMin { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneTransMin( boneName, vec ); } break; // @script | SetBoneTransMax | Sets the maximum translation extent for procedurally animated bone (in world units) // @parmopt float | x | 0 | maximum extent x // @parmopt float | y | 0 | maximum extent y // @parmopt float | z | 0 | maximum extent z // @parm name | bone | name of procedural bone case 0x3e5b6488: // SetBoneTransMax { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneTransMax( boneName, vec ); } break; // @script | SetBoneTransSpeed | Sets the speed at which the bone's translation will procedurally animate (in 4096 notation) // @parmopt int | x | 0 | speed x (2048 immediately goes from T0 to T1) // @parmopt int | y | 0 | speed y (2048 immediately goes from T0 to T1) // @parmopt int | z | 0 | speed z (2048 immediately goes from T0 to T1) // @parm name | bone | name of procedural bone case 0xc85b9ac0: // SetBoneTransSpeed { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); Dbg_Assert( mp_blendChannel ); this->SetProceduralBoneTransSpeed( boneName, vec ); } break; // @script | SetBoneTransCurrent | Immediately sets the procedurally animated bone to a specific translation (in 4096 notation) // @parmopt int | x | 0 | current x (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parmopt int | y | 0 | current y (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parmopt int | z | 0 | current z (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parm name | bone | name of procedural bone case 0x5ee9d5bd: // SetBoneTransCurrent { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneTransCurrent( boneName, vec ); } break; // @script | SetBoneTransActive | Sets whether the bone should procedurally animate its translation // @uparm int | active (either 0 or 1) // @parm name | bone | name of procedural bone case 0x5661fb72: // SetBoneTransActive { uint32 boneName; int enabled; pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); pParams->GetInteger( NONAME, &enabled, true ); Dbg_Assert( mp_blendChannel ); this->SetProceduralBoneTransActive( boneName, enabled ); } break; // @script | SetBoneRotMin | Sets the minimum rotation extent for procedurally animated bone (in 4096 notation) // @parmopt int | x | 0 | minimum extent x (in 4096 notation) // @parmopt int | y | 0 | minimum extent y (in 4096 notation) // @parmopt int | z | 0 | minimum extent z (in 4096 notation) // @parm name | bone | name of procedural bone case 0xa47767f2: // SetBoneRotMin { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneRotMin( boneName, vec ); } break; // @script | SetBoneRotMax | Sets the maximum rotation extent for procedurally animated bone (in 4096 notation) // @parmopt int | x | 0 | maximum extent x (in 4096 notation) // @parmopt int | y | 0 | maximum extent y (in 4096 notation) // @parmopt int | z | 0 | maximum extent z (in 4096 notation) case 0x987a58ab: // SetBoneRotMax { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneRotMax( boneName, vec ); } break; // @script | SetBoneRotSpeed | Sets the speed at which the bone's rotation will procedurally animate (in 4096 notation) // @parmopt int | x | 0 | speed x (2048 immediately goes from T0 to T1) // @parmopt int | y | 0 | speed y (2048 immediately goes from T0 to T1) // @parmopt int | z | 0 | speed z (2048 immediately goes from T0 to T1) // @parm name | bone | name of procedural bone case 0x599d3707: // SetBoneRotSpeed { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneRotSpeed( boneName, vec ); } break; // @script | SetBoneRotCurrent | Immediately sets the procedurally animated bone to a specific rotation (in 4096 notation) // @parmopt int | x | 0 | current x (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parmopt int | y | 0 | current y (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parmopt int | z | 0 | current z (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parm name | bone | name of procedural bone case 0x7235daa7: // SetBoneRotCurrent { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneRotCurrent( boneName, vec ); } break; // @script | SetBoneRotActive | Sets whether the bone should procedurally animate its rotation // @uparm int | active (either 0 or 1) // @parm name | bone | name of procedural bone case 0x53f06acc: // SetBoneRotActive { uint32 boneName; int enabled; pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); pParams->GetInteger( NONAME, &enabled, true ); this->SetProceduralBoneRotActive( boneName, enabled ); } break; // @script | SetBoneScaleMin | Sets the minimum translation extent for procedurally animated bone (in world units) // @parmopt float | x | 0 | minimum extent x // @parmopt float | y | 0 | minimum extent y // @parmopt float | z | 0 | minimum extent z // @parm name | bone | name of procedural bone case 0xc6889e91: // SetBoneScaleMin { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneScaleMin( boneName, vec ); } break; // @script | SetBoneScaleMax | Sets the maximum translation extent for procedurally animated bone (in world units) // @parmopt float | x | 0 | maximum extent x // @parmopt float | y | 0 | maximum extent y // @parmopt float | z | 0 | maximum extent z // @parm name | bone | name of procedural bone case 0xfa85a1c8: // SetBoneScaleMax { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneScaleMax( boneName, vec ); } break; // @script | SetBoneScaleSpeed | Sets the speed at which the bone's translation will procedurally animate (in 4096 notation) // @parmopt int | x | 0 | speed x (2048 immediately goes from T0 to T1) // @parmopt int | y | 0 | speed y (2048 immediately goes from T0 to T1) // @parmopt int | z | 0 | speed z (2048 immediately goes from T0 to T1) // @parm name | bone | name of procedural bone case 0xd32c2724: // SetBoneScaleSpeed { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneScaleSpeed( boneName, vec ); } break; // @script | SetBoneScaleCurrent | Immediately sets the procedurally animated bone to a specific translation (in 4096 notation) // @parmopt int | x | 0 | current x (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parmopt int | y | 0 | current y (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parmopt int | z | 0 | current z (0 = T0, 1024 = halfway between T0 and T1, 2048 = T1, 3072 = halfway between T1 and T0, 4096 = T0) // @parm name | bone | name of procedural bone case 0xd12b3713: // SetBoneScaleCurrent { Mth::Vector vec(0.0f,0.0f,0.0f); uint32 boneName; pParams->GetFloat( CRCD(0x7323e97c,"x"), &vec[X], false ); pParams->GetFloat( CRCD(0x0424d9ea,"y"), &vec[Y], false ); pParams->GetFloat( CRCD(0x9d2d8850,"z"), &vec[Z], false ); pParams->GetChecksum( CRCD(0xcab94088,"bone"), &boneName, true ); this->SetProceduralBoneScaleCurrent( boneName, vec ); } break; // @script | SetBoneScaleActive | Sets whether the bone should procedurally animate its translation // @uparm int | active (either 0 or 1) // @parm name | bone | name of procedural bone case 0xf11daaae: // SetBoneScaleActive { uint32 boneName; int enabled; pParams->GetChecksum( "bone", &boneName, true ); pParams->GetInteger( NONAME, &enabled, true ); this->SetProceduralBoneScaleActive( boneName, enabled ); } break; default: return AF_NOT_EXECUTED; } return AF_TRUE; } /******************************************************************/ /* */ /* */ /******************************************************************/ CPoseController::CPoseController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ CPoseController::~CPoseController() { } /******************************************************************/ /* */ /* */ /******************************************************************/ void CPoseController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CPoseController::Update() { } /******************************************************************/ /* */ /* */ /******************************************************************/ void CPoseController::SetPose( Gfx::CPose* pPose ) { memcpy( &m_pose, pPose, sizeof(Gfx::CPose) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CPoseController::GetPose( Gfx::CPose* pResultPose ) { // this nukes the existing pose, meaning that // this should be the only controller in the list... memcpy( pResultPose, &m_pose, sizeof(Gfx::CPose) ); return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ CLookAtController::CLookAtController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ CLookAtController::~CLookAtController() { } /******************************************************************/ /* */ /* */ /******************************************************************/ void CLookAtController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CLookAtController::Update() { Dbg_MsgAssert( 0, ( "Unimplemented function" ) ); // GJ: This is just a sample controller... I was thinking // that this could be used for orienting the head towards // an object in the scene, given some constraints } /******************************************************************/ /* */ /* */ /******************************************************************/ CPartialAnimController::CPartialAnimController( CBlendChannel* pBlendChannel ) : CBaseAnimController( pBlendChannel ) { mp_quickAnim = Nx::CEngine::sInitQuickAnim(); mp_quickAnim->Enable( false ); Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); m_animScriptName = pAnimationComponent->GetAnimScriptName(); mp_animChannel = new Gfx::CAnimChannel; } /******************************************************************/ /* */ /* */ /******************************************************************/ CPartialAnimController::~CPartialAnimController() { if ( mp_quickAnim ) { Nx::CEngine::sUninitQuickAnim( mp_quickAnim ); mp_quickAnim = NULL; } if ( mp_animChannel ) { delete mp_animChannel; mp_animChannel = NULL; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CPartialAnimController::InitFromStructure( Script::CStruct* pParams ) { CBaseAnimController::InitFromStructure( pParams ); uint32 anim_name; pParams->GetChecksum( CRCD(0x6c2bfb7f,"animName"), &anim_name, Script::ASSERT ); float From = 0.0f; float To = 0.0f; float Current = 0.0f; Obj::CAnimationComponent* pAnimationComponent = GetAnimationComponentFromObject( GetObject() ); float Duration = pAnimationComponent->AnimDuration( anim_name ); Gfx::GetTimeFromParams( &From, &To, Current, Duration, pParams, NULL ); Gfx::EAnimLoopingType loopingType; Gfx::GetLoopingTypeFromParams( &loopingType, pParams ); float speed = 1.0f; pParams->GetFloat( CRCD(0xf0d90109,"speed"), &speed, Script::NO_ASSERT ); pParams->GetFloat(CRCD(0x230ccbf4, "Current"), &Current); float blend_period = 0.0f; mp_animChannel->PlaySequence( anim_name, From, To, loopingType, blend_period, speed); if (Current != 0.0f) { mp_animChannel->AddTime(Current); } Dbg_Assert( mp_quickAnim ); mp_quickAnim->SetAnimAssetName( m_animScriptName + anim_name ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CPartialAnimController::GetPose( Gfx::CPose* pResultPose ) { #ifdef __NOPT_ASSERT__ { CSkeleton* pSkeleton = GetSkeleton(); Dbg_MsgAssert( pSkeleton, ( "No skeleton?" ) ); Dbg_MsgAssert( pResultPose, ( "No return data" ) ); } #endif // int skipList[vMAX_BONES]; // GetSkeleton()->GetSkipList( &skipList[0] ); uint32* p_skip_list = GetSkeleton()->GetBoneSkipList(); uint32 skip_index = GetSkeleton()->GetBoneSkipIndex(); #if 1 Dbg_Assert( mp_quickAnim ); mp_quickAnim->GetInterpolatedFrames( pResultPose->m_rotations, pResultPose->m_translations, p_skip_list, skip_index, mp_animChannel->GetCurrentAnimTime() ); mp_quickAnim->Enable( true ); #else Mth::Quat theRot[128]; Mth::Vector theTrans[128]; Dbg_Assert( mp_quickAnim ); mp_quickAnim->GetInterpolatedFrames( theRot, theTrans, p_skip_list, skip_index, mp_animChannel->GetCurrentAnimTime() ); mp_quickAnim->Enable( true ); Script::CArray* pArray = Script::GetArray( m_boneListName, Script::ASSERT ); for ( uint32 i = 0; i < pArray->GetSize(); i++ ) { int idx = pSkeleton->GetBoneIndexById( pArray->GetChecksum(i) ); if ( idx != -1 ) { *(pResultPose->m_rotations+idx)=theRot[idx]; *(pResultPose->m_translations+idx)=theTrans[idx]; } } #endif return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CPartialAnimController::Update() { // This class is used for either appending, // or overwriting a subset of the bones in the RT array, // given a CBonedAnimFrameData... Dbg_MsgAssert( mp_animChannel->m_loopingType != Gfx::LOOPING_WOBBLE, ( "Not supposed to be wobble type" ) ); float oldTime = mp_animChannel->m_currentTime; mp_animChannel->m_currentTime = mp_animChannel->get_new_anim_time(); // mp_animChannel->ProcessCustomKeys( oldTime, mp_animChannel->m_currentTime ); if ( mp_animChannel->m_currentTime < oldTime ) { mp_quickAnim->Enable( false ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ EAnimFunctionResult CPartialAnimController::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript ) { switch ( Checksum ) { case 0x5f495ae0: // InvalidateCache { mp_quickAnim->Enable( false ); // want the other controllers to be invalidated too return AF_NOT_EXECUTED; } break; case 0xd63a1b81: // GetPartialAnimParams { Dbg_Assert( pScript ); pScript->GetParams()->AddFloat( CRCD(0xaaecb346,"partialAnimTime"), mp_animChannel->GetCurrentAnimTime() ); pScript->GetParams()->AddChecksum( CRCD(0x659bf355,"partialAnim"), mp_animChannel->GetCurrentAnim() ); pScript->GetParams()->AddInteger( CRCD(0x4966cc11,"partialAnimComplete"), mp_animChannel->IsAnimComplete() ); return AF_TRUE; } break; case 0xbd4edd44: // SetPartialAnimSpeed { float speed; pParams->GetFloat( CRCD(0xf0d90109,"speed"), &speed, Script::ASSERT ); mp_animChannel->SetAnimSpeed( speed ); return AF_TRUE; } break; case 0x6aaeb76f: // IncrementPartialAnimTime { float incVal; pParams->GetFloat( CRCD(0x06c9f278,"incVal"), &incVal, Script::ASSERT ); // GJ: a way to fool the animation controller // into incrementing its time (frame rate // independent) for the viewer object float oldAnimSpeed = mp_animChannel->GetAnimSpeed(); mp_animChannel->SetAnimSpeed( 0.0f ); mp_animChannel->m_currentTime += incVal; mp_animChannel->Update(); mp_animChannel->SetAnimSpeed( oldAnimSpeed ); return AF_TRUE; } break; case 0xf5e2b871: // ReversePartialAnimDirection { mp_animChannel->ReverseDirection(); return AF_TRUE; } break; default: return AF_NOT_EXECUTED; } return AF_TRUE; } /******************************************************************/ /* */ /* */ /******************************************************************/ }