//----------------------------------------------------------------------------- // LLKeyframeMotionParam::onInitialize(LLCharacter *character) //----------------------------------------------------------------------------- LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character) { mCharacter = character; if (!loadMotions()) { return STATUS_FAILURE; } for (motion_map_t::iterator iter = mParameterizedMotions.begin(); iter != mParameterizedMotions.end(); ++iter) { motion_list_t& motionList = iter->second; for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2) { const ParameterizedMotion& paramMotion = *iter2; LLMotion* motion = paramMotion.mMotion; motion->onInitialize(character); // <FS> Fix copy paste error //if (motion->getDuration() > mEaseInDuration) if (motion->getEaseInDuration() > mEaseInDuration) // </FS> { mEaseInDuration = motion->getEaseInDuration(); } if (motion->getEaseOutDuration() > mEaseOutDuration) { mEaseOutDuration = motion->getEaseOutDuration(); } if (motion->getDuration() > mDuration) { mDuration = motion->getDuration(); } if (motion->getPriority() > mPriority) { mPriority = motion->getPriority(); } LLPose *pose = motion->getPose(); mPoseBlender.addMotion(motion); for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState()) { LLPose *blendedPose = mPoseBlender.getBlendedPose(); blendedPose->addJointState(jsp); } } } return STATUS_SUCCESS; }
void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type) { BOOL update_result = TRUE; U8 last_joint_signature[LL_CHARACTER_MAX_JOINTS]; memset(&last_joint_signature, 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); // iterate through active motions in chronological order for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ) { motion_list_t::iterator curiter = iter++; LLMotion* motionp = *curiter; if (motionp->getBlendType() != anim_type) { continue; } BOOL update_motion = FALSE; if (motionp->getPose()->getWeight() < 1.f) { update_motion = TRUE; } else { // NUM_JOINT_SIGNATURE_STRIDES should be multiple of 4 for (S32 i = 0; i < NUM_JOINT_SIGNATURE_STRIDES; i++) { U32 *current_signature = (U32*)&(mJointSignature[0][i * 4]); U32 test_signature = *(U32*)&(motionp->mJointSignature[0][i * 4]); if ((*current_signature | test_signature) > (*current_signature)) { *current_signature |= test_signature; update_motion = TRUE; } *((U32*)&last_joint_signature[i * 4]) = *(U32*)&(mJointSignature[1][i * 4]); current_signature = (U32*)&(mJointSignature[1][i * 4]); test_signature = *(U32*)&(motionp->mJointSignature[1][i * 4]); if ((*current_signature | test_signature) > (*current_signature)) { *current_signature |= test_signature; update_motion = TRUE; } } } if (!update_motion) { updateIdleMotion(motionp); continue; } LLPose *posep = motionp->getPose(); // only filter by LOD after running every animation at least once (to prime the avatar state) if (mHasRunOnce && motionp->getMinPixelArea() > mCharacter->getPixelArea()) { motionp->fadeOut(); //should we notify the simulator that this motion should be stopped (check even if skipped by LOD logic) if (mAnimTime > motionp->mSendStopTimestamp) { // notify character of timed stop event on first iteration past sendstoptimestamp // this will only be called when an animation stops itself (runs out of time) if (mLastTime <= motionp->mSendStopTimestamp) { mCharacter->requestStopMotion( motionp ); stopMotionInstance(motionp, FALSE); } } if (motionp->getFadeWeight() < 0.01f) { if (motionp->isStopped() && mAnimTime > motionp->getStopTime() + motionp->getEaseOutDuration()) { posep->setWeight(0.f); deactivateMotionInstance(motionp); } continue; } } else { motionp->fadeIn(); } //********************** // MOTION INACTIVE //********************** if (motionp->isStopped() && mAnimTime > motionp->getStopTime() + motionp->getEaseOutDuration()) { // this motion has gone on too long, deactivate it // did we have a chance to stop it? if (mLastTime <= motionp->getStopTime()) { // if not, let's stop it this time through and deactivate it the next posep->setWeight(motionp->getFadeWeight()); motionp->onUpdate(motionp->getStopTime() - motionp->mActivationTimestamp, last_joint_signature); } else { posep->setWeight(0.f); deactivateMotionInstance(motionp); continue; } } //********************** // MOTION EASE OUT //********************** else if (motionp->isStopped() && mAnimTime > motionp->getStopTime()) { // is this the first iteration in the ease out phase? if (mLastTime <= motionp->getStopTime()) { // store residual weight for this motion motionp->mResidualWeight = motionp->getPose()->getWeight(); } if (motionp->getEaseOutDuration() == 0.f) { posep->setWeight(0.f); } else { posep->setWeight(motionp->getFadeWeight() * motionp->mResidualWeight * cubic_step(1.f - ((mAnimTime - motionp->getStopTime()) / motionp->getEaseOutDuration()))); } // perform motion update update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); } //********************** // MOTION ACTIVE //********************** else if (mAnimTime > motionp->mActivationTimestamp + motionp->getEaseInDuration()) { posep->setWeight(motionp->getFadeWeight()); //should we notify the simulator that this motion should be stopped? if (mAnimTime > motionp->mSendStopTimestamp) { // notify character of timed stop event on first iteration past sendstoptimestamp // this will only be called when an animation stops itself (runs out of time) if (mLastTime <= motionp->mSendStopTimestamp) { mCharacter->requestStopMotion( motionp ); stopMotionInstance(motionp, FALSE); } } // perform motion update { LLFastTimer t(FTM_MOTION_ON_UPDATE); update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); } } //********************** // MOTION EASE IN //********************** else if (mAnimTime >= motionp->mActivationTimestamp) { if (mLastTime < motionp->mActivationTimestamp) { motionp->mResidualWeight = motionp->getPose()->getWeight(); } if (motionp->getEaseInDuration() == 0.f) { posep->setWeight(motionp->getFadeWeight()); } else { // perform motion update posep->setWeight(motionp->getFadeWeight() * motionp->mResidualWeight + (1.f - motionp->mResidualWeight) * cubic_step((mAnimTime - motionp->mActivationTimestamp) / motionp->getEaseInDuration())); } // perform motion update update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); } else { posep->setWeight(0.f); update_result = motionp->onUpdate(0.f, last_joint_signature); } // allow motions to deactivate themselves if (!update_result) { if (!motionp->isStopped() || motionp->getStopTime() > mAnimTime) { // animation has stopped itself due to internal logic // propagate this to the network // as not all viewers are guaranteed to have access to the same logic mCharacter->requestStopMotion( motionp ); stopMotionInstance(motionp, FALSE); } } // even if onupdate returns FALSE, add this motion in to the blend one last time mPoseBlender.addMotion(motionp); } }