Exemplo n.º 1
0
//-----------------------------------------------------------------------------
// stopMotionLocally()
//-----------------------------------------------------------------------------
BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate)
{
	// if already inactive, return false
	LLMotion *motion = findMotion(id);
	if (!motion)
	{
		return FALSE;
	}

	// If on active list, stop it
	if (isMotionActive(motion) && !motion->isStopped())
	{
		// when using timesteps, set stop time to last frame's time, otherwise grab current timer value
		// *FIX: should investigate this inconsistency...hints of obscure bugs

		F32 stop_time = (mTimeStep != 0.f || mPaused) ? (mTime) : mTimeOffset + (mTimer.getElapsedTimeF32() * mTimeFactor);
		motion->setStopTime(stop_time);

		if (stop_immediate)
		{
			deactivateMotion(motion, false);
		}
		return TRUE;
	}
	else if (isMotionLoading(motion))
	{
		motion->setStopped(TRUE);
		return TRUE;
	}

	return FALSE;
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// startMotion()
//-----------------------------------------------------------------------------
BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
{
	// look for motion in our list of created motions
	LLMotion *motion = createMotion(id);

	if (!motion)
	{
		return FALSE;
	}
	//if the motion is already active, then we're done
	else if (isMotionActive(motion)) // motion is playing and...
	{	
		if (motion->isStopped()) // motion has been stopped
		{
			deactivateMotion(motion, false);
		}
		else if (mTime < motion->mSendStopTimestamp)	// motion is still active
		{
			return TRUE;
		}
	}

//	llinfos << "Starting motion " << name << llendl;
	return activateMotion(motion, mTime - start_offset);
}
//-----------------------------------------------------------------------------
// updateLoadingMotions()
//-----------------------------------------------------------------------------
void LLMotionController::updateLoadingMotions()
{
	// query pending motions for completion
	for (motion_set_t::iterator iter = mLoadingMotions.begin();
		 iter != mLoadingMotions.end(); )
	{
		motion_set_t::iterator curiter = iter++;
		LLMotion* motionp = *curiter;
		if( !motionp)
		{
			continue; // maybe shouldn't happen but i've seen it -MG
		}
		LLMotion::LLMotionInitStatus status = motionp->onInitialize(mCharacter);
		if (status == LLMotion::STATUS_SUCCESS)
		{
			mLoadingMotions.erase(curiter);
			// add motion to our loaded motion list
			mLoadedMotions.insert(motionp);
			// this motion should be playing
			if (!motionp->isStopped())
			{
				//<singu>
				F32 start_time = mAnimTime;
				if (!mDisableSyncing)
				{
				  motionp->aisync_loaded();
				  start_time = motionp->syncActivationTime(start_time);
				}
				++mDisableSyncing;
				//</singu>
				activateMotionInstance(motionp, start_time);
				//<singu>
				--mDisableSyncing;
				//</singu>
			}
		}
		else if (status == LLMotion::STATUS_FAILURE)
		{
			llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
			sRegistry.markBad(motionp->getID());
			mLoadingMotions.erase(curiter);
			// Singu note: a motion in mLoadingMotions will not be in mActiveMotions
			// and therefore not be in mDeprecatedMotions. So, we don't have to
			// check for it's existence there.
			llassert(mDeprecatedMotions.find(motionp) == mDeprecatedMotions.end());
			mAllMotions.erase(motionp->getID());
			//<singu>
			// Make sure we're not registered anymore.
			motionp->unregister_client();
			//</singu>
			delete motionp;
		}
	}
}
//-----------------------------------------------------------------------------
// deactivateStoppedMotions()
//-----------------------------------------------------------------------------
void LLMotionController::deactivateStoppedMotions()
{
	// Since we're hidden, deactivate any stopped motions.
	for (motion_list_t::iterator iter = mActiveMotions.begin();
		 iter != mActiveMotions.end(); )
	{
		motion_list_t::iterator curiter = iter++;
		LLMotion* motionp = *curiter;
		if (motionp->isStopped())
		{
			deactivateMotionInstance(motionp);
		}
	}
}
Exemplo n.º 5
0
//-----------------------------------------------------------------------------
// setTimeStep()
//-----------------------------------------------------------------------------
void LLMotionController::setTimeStep(F32 step)
{
	mTimeStep = step;

	if (step != 0.f)
	{
		// make sure timestamps conform to new quantum
		for (motion_list_t::iterator iter = mActiveMotions.begin();
			 iter != mActiveMotions.end(); ++iter)
		{
			LLMotion* motionp = *iter;
			motionp->mActivationTimestamp = (F32)llfloor(motionp->mActivationTimestamp / step) * step;
			BOOL stopped = motionp->isStopped();
			motionp->setStopTime((F32)llfloor(motionp->getStopTime() / step) * step);
			motionp->setStopped(stopped);
			motionp->mSendStopTimestamp = (F32)llfloor(motionp->mSendStopTimestamp / step) * step;
		}
	}
}
//-----------------------------------------------------------------------------
// updateLoadingMotions()
//-----------------------------------------------------------------------------
void LLMotionController::updateLoadingMotions()
{
	// query pending motions for completion
	for (motion_set_t::iterator iter = mLoadingMotions.begin();
		 iter != mLoadingMotions.end(); )
	{
		motion_set_t::iterator curiter = iter++;
		LLMotion* motionp = *curiter;
		if( !motionp)
		{
			continue; // maybe shouldn't happen but i've seen it -MG
		}
		LLMotion::LLMotionInitStatus status = motionp->onInitialize(mCharacter);
		if (status == LLMotion::STATUS_SUCCESS)
		{
			mLoadingMotions.erase(curiter);
			// add motion to our loaded motion list
			mLoadedMotions.insert(motionp);
			// this motion should be playing
			if (!motionp->isStopped())
			{
				activateMotionInstance(motionp, mAnimTime);
			}
		}
		else if (status == LLMotion::STATUS_FAILURE)
		{
			llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
			sRegistry.markBad(motionp->getID());
			mLoadingMotions.erase(curiter);
			motion_set_t::iterator found_it = mDeprecatedMotions.find(motionp);
			if (found_it != mDeprecatedMotions.end())
			{
				mDeprecatedMotions.erase(found_it);
			}
			mAllMotions.erase(motionp->getID());
			delete motionp;
		}
	}
}
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);
	}
}
// Run all steps until you're either done or hit a wait.
void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
{
	if (!gesture)
	{
		return;
	}
	if (!isAgentAvatarValid() || hasLoadingAssets(gesture)) return;

	// Of the ones that started playing, have any stopped?

	std::set<LLUUID>::iterator gest_it;
	for (gest_it = gesture->mPlayingAnimIDs.begin(); 
		 gest_it != gesture->mPlayingAnimIDs.end(); 
		 )
	{
		if (gesture->mLocal)
		{
			// Local, erase if no longer playing (or gone)
			LLMotion* motion = gAgentAvatarp->findMotion(*gest_it);
			if (!motion || motion->isStopped())
				gesture->mPlayingAnimIDs.erase(gest_it);
			++gest_it;
		}
		// look in signaled animations (simulator's view of what is
		// currently playing.
		else if (gAgentAvatarp->mSignaledAnimations.find(*gest_it) != gAgentAvatarp->mSignaledAnimations.end())
		{
			++gest_it;
		}
		else
		{
			// not found, so not currently playing or scheduled to play
			// delete from the triggered set
			gesture->mPlayingAnimIDs.erase(gest_it++);
		}
	}

	// Of all the animations that we asked the sim to start for us,
	// pick up the ones that have actually started.
	for (gest_it = gesture->mRequestedAnimIDs.begin();
		 gest_it != gesture->mRequestedAnimIDs.end();
		 )
	{
	 LLVOAvatar::AnimIterator play_it = gAgentAvatarp->mSignaledAnimations.find(*gest_it);
		if (play_it != gAgentAvatarp->mSignaledAnimations.end())
		{
			// Hooray, this animation has started playing!
			// Copy into playing.
			gesture->mPlayingAnimIDs.insert(*gest_it);
			gesture->mRequestedAnimIDs.erase(gest_it++);
		}
		else
		{
			// nope, not playing yet
			++gest_it;
		}
	}

	// Run the current steps
	BOOL waiting = FALSE;
	while (!waiting && gesture->mPlaying)
	{
		// Get the current step, if there is one.
		// Otherwise enter the waiting at end state.
		LLGestureStep* step = NULL;
		if (gesture->mCurrentStep < (S32)gesture->mSteps.size())
		{
			step = gesture->mSteps[gesture->mCurrentStep];
			llassert(step != NULL);
		}
		else
		{
			// step stays null, we're off the end
			gesture->mWaitingAtEnd = TRUE;
		}


		// If we're waiting at the end, wait for all gestures to stop
		// playing.
		// TODO: Wait for all sounds to complete as well.
		if (gesture->mWaitingAtEnd)
		{
			// Neither do we have any pending requests, nor are they
			// still playing.
			if ((gesture->mRequestedAnimIDs.empty()
				&& gesture->mPlayingAnimIDs.empty()))
			{
				// all animations are done playing
				gesture->mWaitingAtEnd = FALSE;
				gesture->mPlaying = FALSE;
			}
			else
			{
				waiting = TRUE;
			}
			continue;
		}

		// If we're waiting on our animations to stop, poll for
		// completion.
		if (gesture->mWaitingAnimations)
		{
			// Neither do we have any pending requests, nor are they
			// still playing.
			if ((gesture->mRequestedAnimIDs.empty()
				&& gesture->mPlayingAnimIDs.empty()))
			{
				// all animations are done playing
				gesture->mWaitingAnimations = FALSE;
				gesture->mCurrentStep++;
			}
			else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
			{
				// we've waited too long for an animation
				LL_INFOS() << "Waited too long for animations to stop, continuing gesture."
					<< LL_ENDL;
				gesture->mWaitingAnimations = FALSE;
				gesture->mCurrentStep++;
			}
			else
			{
				waiting = TRUE;
			}
			continue;
		}

		// If we're waiting a fixed amount of time, check for timer
		// expiration.
		if (gesture->mWaitingTimer)
		{
			// We're waiting for a certain amount of time to pass
			LLGestureStepWait* wait_step = (LLGestureStepWait*)step;

			F32 elapsed = gesture->mWaitTimer.getElapsedTimeF32();
			if (elapsed > wait_step->mWaitSeconds)
			{
				// wait is done, continue execution
				gesture->mWaitingTimer = FALSE;
				gesture->mCurrentStep++;
			}
			else
			{
				// we're waiting, so execution is done for now
				waiting = TRUE;
			}
			continue;
		}

		// Not waiting, do normal execution
		runStep(gesture, step);
	}
}
Exemplo n.º 9
0
//-----------------------------------------------------------------------------
// updateMotion()
//-----------------------------------------------------------------------------
void LLMotionController::updateMotion()
{
	BOOL use_quantum = (mTimeStep != 0.f);

	// Update timing info for this time step.
	if (!mPaused)
	{
		F32 update_time = mTimeOffset + (mTimer.getElapsedTimeF32() * mTimeFactor);
		if (use_quantum)
		{
			F32 time_interval = fmodf(update_time, mTimeStep);

			// always animate *ahead* of actual time
			S32 quantum_count = llmax(0, llfloor((update_time - time_interval) / mTimeStep)) + 1;
			if (quantum_count == mTimeStepCount)
			{
				// we're still in same time quantum as before, so just interpolate and exit
				if (!mPaused)
				{
					F32 interp = time_interval / mTimeStep;
					mPoseBlender.interpolate(interp - mLastInterp);
					mLastInterp = interp;
				}
				
				return;
			}
			
			// is calculating a new keyframe pose, make sure the last one gets applied
			mPoseBlender.interpolate(1.f);
			mPoseBlender.clearBlenders();

			mTimeStepCount = quantum_count;
			mLastTime = mTime;
			mTime = (F32)quantum_count * mTimeStep;
			mLastInterp = 0.f;
		}
		else
		{
			mLastTime = mTime;
			mTime = update_time;
		}
	}

	// query pending motions for completion
	for (motion_set_t::iterator iter = mLoadingMotions.begin();
		 iter != mLoadingMotions.end(); )
	{
		motion_set_t::iterator curiter = iter++;
		LLMotion* motionp = *curiter;
		if( !motionp)
		{
			continue; // maybe shouldn't happen but i've seen it -MG
		}
		LLMotion::LLMotionInitStatus status = motionp->onInitialize(mCharacter);
		if (status == LLMotion::STATUS_SUCCESS)
		{
			mLoadingMotions.erase(curiter);
			// add motion to our loaded motion list
			addLoadedMotion(motionp);
			// this motion should be playing
			if (!motionp->isStopped())
			{
				activateMotion(motionp, mTime);
			}
		}
		else if (status == LLMotion::STATUS_FAILURE)
		{
			llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
			sRegistry.markBad(motionp->getID());
			mLoadingMotions.erase(curiter);
			mAllMotions.erase(motionp->getID());
			delete motionp;
		}
	}

	resetJointSignatures();

	if (!mPaused)
	{
		// update additive motions
		updateAdditiveMotions();
		resetJointSignatures();

		// update all regular motions
		updateRegularMotions();

		if (use_quantum)
		{
			mPoseBlender.blendAndCache(TRUE);
		}
		else
		{
			mPoseBlender.blendAndApply();
		}
	}

	mHasRunOnce = TRUE;
//	llinfos << "Motion controller time " << motionTimer.getElapsedTimeF32() << llendl;
}