diff options
Diffstat (limited to 'linden/indra/llcharacter/llmotioncontroller.cpp')
-rw-r--r-- | linden/indra/llcharacter/llmotioncontroller.cpp | 157 |
1 files changed, 106 insertions, 51 deletions
diff --git a/linden/indra/llcharacter/llmotioncontroller.cpp b/linden/indra/llcharacter/llmotioncontroller.cpp index 2427fd8..aebfaf6 100644 --- a/linden/indra/llcharacter/llmotioncontroller.cpp +++ b/linden/indra/llcharacter/llmotioncontroller.cpp | |||
@@ -194,34 +194,44 @@ void LLMotionController::deleteAllMotions() | |||
194 | //----------------------------------------------------------------------------- | 194 | //----------------------------------------------------------------------------- |
195 | void LLMotionController::addLoadedMotion(LLMotion* motionp) | 195 | void LLMotionController::addLoadedMotion(LLMotion* motionp) |
196 | { | 196 | { |
197 | std::set<LLUUID> motions_to_kill; | ||
198 | |||
199 | // gather all inactive, loaded motions | ||
197 | if (mLoadedMotions.size() > MAX_MOTION_INSTANCES) | 200 | if (mLoadedMotions.size() > MAX_MOTION_INSTANCES) |
198 | { | 201 | { |
199 | // too many motions active this frame, kill all blenders | 202 | // too many motions active this frame, kill all blenders |
200 | mPoseBlender.clearBlenders(); | 203 | mPoseBlender.clearBlenders(); |
201 | 204 | ||
202 | for (U32 i = 0; i < mLoadedMotions.size(); i++) | 205 | for (motion_list_t::iterator loaded_motion_it = mLoadedMotions.begin(); |
206 | loaded_motion_it != mLoadedMotions.end(); | ||
207 | ++loaded_motion_it) | ||
203 | { | 208 | { |
204 | LLMotion* cur_motionp = mLoadedMotions.front(); | 209 | LLMotion* cur_motionp = *loaded_motion_it; |
205 | mLoadedMotions.pop_front(); | ||
206 | 210 | ||
207 | // motion isn't playing, delete it | 211 | // motion isn't playing, delete it |
208 | if (!isMotionActive(cur_motionp)) | 212 | if (!isMotionActive(cur_motionp)) |
209 | { | 213 | { |
210 | mCharacter->requestStopMotion(cur_motionp); | 214 | motions_to_kill.insert(cur_motionp->getID()); |
211 | mAllMotions.erase(cur_motionp->getID()); | ||
212 | delete cur_motionp; | ||
213 | if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES) | ||
214 | { | ||
215 | break; | ||
216 | } | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | // put active motion on back | ||
221 | mLoadedMotions.push_back(cur_motionp); | ||
222 | } | 215 | } |
223 | } | 216 | } |
224 | } | 217 | } |
218 | |||
219 | // clean up all inactive, loaded motions | ||
220 | for (std::set<LLUUID>::iterator motion_it = motions_to_kill.begin(); | ||
221 | motion_it != motions_to_kill.end(); | ||
222 | ++motion_it) | ||
223 | { | ||
224 | // look up the motion again by ID to get canonical instance | ||
225 | // and kill it only if that one is inactive | ||
226 | LLUUID motion_id = *motion_it; | ||
227 | LLMotion* motionp = findMotion(motion_id); | ||
228 | if (motionp && !isMotionActive(motionp)) | ||
229 | { | ||
230 | removeMotion(motion_id); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | // add new motion to loaded list | ||
225 | mLoadedMotions.push_back(motionp); | 235 | mLoadedMotions.push_back(motionp); |
226 | } | 236 | } |
227 | 237 | ||
@@ -280,14 +290,24 @@ BOOL LLMotionController::addMotion( const LLUUID& id, LLMotionConstructor constr | |||
280 | void LLMotionController::removeMotion( const LLUUID& id) | 290 | void LLMotionController::removeMotion( const LLUUID& id) |
281 | { | 291 | { |
282 | LLMotion* motionp = findMotion(id); | 292 | LLMotion* motionp = findMotion(id); |
293 | |||
294 | removeMotionInstance(motionp); | ||
295 | |||
296 | mAllMotions.erase(id); | ||
297 | } | ||
298 | |||
299 | // removes instance of a motion from all runtime structures, but does | ||
300 | // not erase entry by ID, as this could be a duplicate instance | ||
301 | // use removeMotion(id) to remove all references to a given motion by id. | ||
302 | void LLMotionController::removeMotionInstance(LLMotion* motionp) | ||
303 | { | ||
283 | if (motionp) | 304 | if (motionp) |
284 | { | 305 | { |
285 | stopMotionLocally(id, TRUE); | 306 | stopMotionInstance(motionp, TRUE); |
286 | 307 | ||
287 | mLoadingMotions.erase(motionp); | 308 | mLoadingMotions.erase(motionp); |
288 | mLoadedMotions.remove(motionp); | 309 | mLoadedMotions.remove(motionp); |
289 | mActiveMotions.remove(motionp); | 310 | mActiveMotions.remove(motionp); |
290 | mAllMotions.erase(id); | ||
291 | delete motionp; | 311 | delete motionp; |
292 | } | 312 | } |
293 | } | 313 | } |
@@ -348,28 +368,39 @@ LLMotion* LLMotionController::createMotion( const LLUUID &id ) | |||
348 | //----------------------------------------------------------------------------- | 368 | //----------------------------------------------------------------------------- |
349 | BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset) | 369 | BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset) |
350 | { | 370 | { |
351 | // look for motion in our list of created motions | 371 | // do we have an instance of this motion for this character? |
352 | LLMotion *motion = createMotion(id); | 372 | LLMotion *motion = findMotion(id); |
373 | |||
374 | // motion that is stopping will be allowed to stop but | ||
375 | // replaced by a new instance of that motion | ||
376 | if (motion | ||
377 | && motion->canDeprecate() | ||
378 | && motion->getFadeWeight() > 0.01f // not LOD-ed out | ||
379 | && (motion->isBlending() || motion->getStopTime() != 0.f)) | ||
380 | { | ||
381 | deprecateMotionInstance(motion); | ||
382 | // force creation of new instance | ||
383 | motion = NULL; | ||
384 | } | ||
385 | |||
386 | // create new motion instance | ||
387 | if (!motion) | ||
388 | { | ||
389 | motion = createMotion(id); | ||
390 | } | ||
353 | 391 | ||
354 | if (!motion) | 392 | if (!motion) |
355 | { | 393 | { |
356 | return FALSE; | 394 | return FALSE; |
357 | } | 395 | } |
358 | //if the motion is already active, then we're done | 396 | //if the motion is already active and allows deprecation, then let it keep playing |
359 | else if (isMotionActive(motion)) // motion is playing and... | 397 | else if (motion->canDeprecate() && isMotionActive(motion)) |
360 | { | 398 | { |
361 | if (motion->isStopped()) // motion has been stopped | 399 | return TRUE; |
362 | { | ||
363 | deactivateMotion(motion, false); | ||
364 | } | ||
365 | else if (mTime < motion->mSendStopTimestamp) // motion is still active | ||
366 | { | ||
367 | return TRUE; | ||
368 | } | ||
369 | } | 400 | } |
370 | 401 | ||
371 | // llinfos << "Starting motion " << name << llendl; | 402 | // llinfos << "Starting motion " << name << llendl; |
372 | return activateMotion(motion, mTime - start_offset); | 403 | return activateMotionInstance(motion, mTime - start_offset); |
373 | } | 404 | } |
374 | 405 | ||
375 | 406 | ||
@@ -380,6 +411,12 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate | |||
380 | { | 411 | { |
381 | // if already inactive, return false | 412 | // if already inactive, return false |
382 | LLMotion *motion = findMotion(id); | 413 | LLMotion *motion = findMotion(id); |
414 | |||
415 | return stopMotionInstance(motion, stop_immediate); | ||
416 | } | ||
417 | |||
418 | BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate) | ||
419 | { | ||
383 | if (!motion) | 420 | if (!motion) |
384 | { | 421 | { |
385 | return FALSE; | 422 | return FALSE; |
@@ -396,7 +433,7 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate | |||
396 | 433 | ||
397 | if (stop_immediate) | 434 | if (stop_immediate) |
398 | { | 435 | { |
399 | deactivateMotion(motion, false); | 436 | deactivateMotionInstance(motion); |
400 | } | 437 | } |
401 | return TRUE; | 438 | return TRUE; |
402 | } | 439 | } |
@@ -492,7 +529,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
492 | { | 529 | { |
493 | if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) | 530 | if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) |
494 | { | 531 | { |
495 | deactivateMotion(motionp, false); | 532 | deactivateMotionInstance(motionp); |
496 | } | 533 | } |
497 | else if (motionp->isStopped() && mTime > motionp->getStopTime()) | 534 | else if (motionp->isStopped() && mTime > motionp->getStopTime()) |
498 | { | 535 | { |
@@ -510,7 +547,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
510 | if (mLastTime <= motionp->mSendStopTimestamp) | 547 | if (mLastTime <= motionp->mSendStopTimestamp) |
511 | { | 548 | { |
512 | mCharacter->requestStopMotion( motionp ); | 549 | mCharacter->requestStopMotion( motionp ); |
513 | stopMotionLocally(motionp->getID(), FALSE); | 550 | stopMotionInstance(motionp, FALSE); |
514 | } | 551 | } |
515 | } | 552 | } |
516 | else if (mTime >= motionp->mActivationTimestamp) | 553 | else if (mTime >= motionp->mActivationTimestamp) |
@@ -538,7 +575,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
538 | if (mLastTime <= motionp->mSendStopTimestamp) | 575 | if (mLastTime <= motionp->mSendStopTimestamp) |
539 | { | 576 | { |
540 | mCharacter->requestStopMotion( motionp ); | 577 | mCharacter->requestStopMotion( motionp ); |
541 | stopMotionLocally(motionp->getID(), FALSE); | 578 | stopMotionInstance(motionp, FALSE); |
542 | } | 579 | } |
543 | } | 580 | } |
544 | 581 | ||
@@ -546,7 +583,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
546 | { | 583 | { |
547 | if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) | 584 | if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration()) |
548 | { | 585 | { |
549 | deactivateMotion(motionp, true); | 586 | posep->setWeight(0.f); |
587 | deactivateMotionInstance(motionp); | ||
550 | } | 588 | } |
551 | continue; | 589 | continue; |
552 | } | 590 | } |
@@ -572,7 +610,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
572 | } | 610 | } |
573 | else | 611 | else |
574 | { | 612 | { |
575 | deactivateMotion(motionp, true); | 613 | posep->setWeight(0.f); |
614 | deactivateMotionInstance(motionp); | ||
576 | continue; | 615 | continue; |
577 | } | 616 | } |
578 | } | 617 | } |
@@ -617,7 +656,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
617 | if (mLastTime <= motionp->mSendStopTimestamp) | 656 | if (mLastTime <= motionp->mSendStopTimestamp) |
618 | { | 657 | { |
619 | mCharacter->requestStopMotion( motionp ); | 658 | mCharacter->requestStopMotion( motionp ); |
620 | stopMotionLocally(motionp->getID(), FALSE); | 659 | stopMotionInstance(motionp, FALSE); |
621 | } | 660 | } |
622 | } | 661 | } |
623 | 662 | ||
@@ -661,7 +700,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty | |||
661 | // propagate this to the network | 700 | // propagate this to the network |
662 | // as not all viewers are guaranteed to have access to the same logic | 701 | // as not all viewers are guaranteed to have access to the same logic |
663 | mCharacter->requestStopMotion( motionp ); | 702 | mCharacter->requestStopMotion( motionp ); |
664 | stopMotionLocally(motionp->getID(), FALSE); | 703 | stopMotionInstance(motionp, FALSE); |
665 | } | 704 | } |
666 | 705 | ||
667 | } | 706 | } |
@@ -733,7 +772,7 @@ void LLMotionController::updateMotion() | |||
733 | // this motion should be playing | 772 | // this motion should be playing |
734 | if (!motionp->isStopped()) | 773 | if (!motionp->isStopped()) |
735 | { | 774 | { |
736 | activateMotion(motionp, mTime); | 775 | activateMotionInstance(motionp, mTime); |
737 | } | 776 | } |
738 | } | 777 | } |
739 | else if (status == LLMotion::STATUS_FAILURE) | 778 | else if (status == LLMotion::STATUS_FAILURE) |
@@ -741,6 +780,7 @@ void LLMotionController::updateMotion() | |||
741 | llinfos << "Motion " << motionp->getID() << " init failed." << llendl; | 780 | llinfos << "Motion " << motionp->getID() << " init failed." << llendl; |
742 | sRegistry.markBad(motionp->getID()); | 781 | sRegistry.markBad(motionp->getID()); |
743 | mLoadingMotions.erase(curiter); | 782 | mLoadingMotions.erase(curiter); |
783 | |||
744 | mAllMotions.erase(motionp->getID()); | 784 | mAllMotions.erase(motionp->getID()); |
745 | delete motionp; | 785 | delete motionp; |
746 | } | 786 | } |
@@ -773,9 +813,9 @@ void LLMotionController::updateMotion() | |||
773 | 813 | ||
774 | 814 | ||
775 | //----------------------------------------------------------------------------- | 815 | //----------------------------------------------------------------------------- |
776 | // activateMotion() | 816 | // activateMotionInstance() |
777 | //----------------------------------------------------------------------------- | 817 | //----------------------------------------------------------------------------- |
778 | BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time) | 818 | BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time) |
779 | { | 819 | { |
780 | if (mLoadingMotions.find(motion) != mLoadingMotions.end()) | 820 | if (mLoadingMotions.find(motion) != mLoadingMotions.end()) |
781 | { | 821 | { |
@@ -818,23 +858,38 @@ BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time) | |||
818 | } | 858 | } |
819 | 859 | ||
820 | //----------------------------------------------------------------------------- | 860 | //----------------------------------------------------------------------------- |
821 | // deactivateMotion() | 861 | // deactivateMotionInstance() |
822 | //----------------------------------------------------------------------------- | 862 | //----------------------------------------------------------------------------- |
823 | BOOL LLMotionController::deactivateMotion(LLMotion *motion, bool remove_weight) | 863 | BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion) |
824 | { | 864 | { |
825 | if( remove_weight ) | 865 | motion->deactivate(); |
866 | |||
867 | motion_set_t::iterator found_it = mDeprecatedMotions.find(motion); | ||
868 | if (found_it != mDeprecatedMotions.end()) | ||
826 | { | 869 | { |
827 | // immediately remove pose weighting instead of letting it time out | 870 | // deprecated motions need to be completely excised |
828 | LLPose *posep = motion->getPose(); | 871 | removeMotionInstance(motion); |
829 | posep->setWeight(0.f); | 872 | mDeprecatedMotions.erase(found_it); |
873 | } | ||
874 | else | ||
875 | { | ||
876 | // for motions that we are keeping, simply remove from active queue | ||
877 | mActiveMotions.remove(motion); | ||
830 | } | 878 | } |
831 | |||
832 | motion->deactivate(); | ||
833 | mActiveMotions.remove(motion); | ||
834 | 879 | ||
835 | return TRUE; | 880 | return TRUE; |
836 | } | 881 | } |
837 | 882 | ||
883 | void LLMotionController::deprecateMotionInstance(LLMotion* motion) | ||
884 | { | ||
885 | mDeprecatedMotions.insert(motion); | ||
886 | |||
887 | //fade out deprecated motion | ||
888 | stopMotionInstance(motion, FALSE); | ||
889 | //no longer canonical | ||
890 | mAllMotions.erase(motion->getID()); | ||
891 | } | ||
892 | |||
838 | //----------------------------------------------------------------------------- | 893 | //----------------------------------------------------------------------------- |
839 | // isMotionActive() | 894 | // isMotionActive() |
840 | //----------------------------------------------------------------------------- | 895 | //----------------------------------------------------------------------------- |
@@ -857,7 +912,7 @@ bool LLMotionController::isMotionLoading(LLMotion* motion) | |||
857 | //----------------------------------------------------------------------------- | 912 | //----------------------------------------------------------------------------- |
858 | LLMotion *LLMotionController::findMotion(const LLUUID& id) | 913 | LLMotion *LLMotionController::findMotion(const LLUUID& id) |
859 | { | 914 | { |
860 | return mAllMotions[id]; | 915 | return get_if_there<LLUUID, LLMotion*>(mAllMotions, id, NULL); |
861 | } | 916 | } |
862 | 917 | ||
863 | //----------------------------------------------------------------------------- | 918 | //----------------------------------------------------------------------------- |