summaryrefslogtreecommitdiff
path: root/indra/llcharacter
diff options
context:
space:
mode:
authorMonroe Williams <monroe@lindenlab.com>2007-08-02 01:18:34 +0000
committerMonroe Williams <monroe@lindenlab.com>2007-08-02 01:18:34 +0000
commit7138fb673ac3df46b9cb5f23d0d74e70fdd2b6b3 (patch)
tree3c34a3a180b5275bd4166b0056765c5868f56447 /indra/llcharacter
parentf6a10b3214d79df4e8f5768acaa68edbd2de5620 (diff)
Merge down from Branch_1-18-1:
svn merge --ignore-ancestry svn+ssh://svn.lindenlab.com/svn/linden/release@66449 svn+ssh://svn.lindenlab.com/svn/linden/branches/Branch_1-18-1@67131
Diffstat (limited to 'indra/llcharacter')
-rw-r--r--indra/llcharacter/llmotion.cpp11
-rw-r--r--indra/llcharacter/llmotion.h8
-rw-r--r--indra/llcharacter/llmotioncontroller.cpp157
-rw-r--r--indra/llcharacter/llmotioncontroller.h15
-rw-r--r--indra/llcharacter/llpose.cpp20
-rw-r--r--indra/llcharacter/llpose.h2
6 files changed, 144 insertions, 69 deletions
diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp
index a53956223c..73aefa6640 100644
--- a/indra/llcharacter/llmotion.cpp
+++ b/indra/llcharacter/llmotion.cpp
@@ -106,6 +106,11 @@ void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata )
mDeactivateCallbackUserData = userdata;
}
+BOOL LLMotion::isBlending()
+{
+ return mPose.getWeight() < 1.f;
+}
+
//-----------------------------------------------------------------------------
// activate()
//-----------------------------------------------------------------------------
@@ -122,10 +127,16 @@ void LLMotion::activate()
void LLMotion::deactivate()
{
mActive = FALSE;
+ mPose.setWeight(0.f);
if (mDeactivateCallback) (*mDeactivateCallback)(mDeactivateCallbackUserData);
onDeactivate();
}
+BOOL LLMotion::canDeprecate()
+{
+ return TRUE;
+}
+
// End
diff --git a/indra/llcharacter/llmotion.h b/indra/llcharacter/llmotion.h
index 66882a2c11..77edba667f 100644
--- a/indra/llcharacter/llmotion.h
+++ b/indra/llcharacter/llmotion.h
@@ -79,13 +79,14 @@ public:
void setStopped(BOOL stopped) { mStopped = stopped; }
+ BOOL isBlending();
+
void activate();
void deactivate();
BOOL isActive() { return mActive; }
-
public:
//-------------------------------------------------------------------------
// animation callbacks to be implemented by subclasses
@@ -125,6 +126,11 @@ public:
// called when a motion is deactivated
virtual void onDeactivate() = 0;
+ // can we crossfade this motion with a new instance when restarted?
+ // should ultimately always be TRUE, but lack of emote blending, etc
+ // requires this
+ virtual BOOL canDeprecate();
+
// optional callback routine called when animation deactivated.
void setDeactivateCallback( void (*cb)(void *), void* userdata );
diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp
index 592a6bae2c..bef5ea5dbb 100644
--- a/indra/llcharacter/llmotioncontroller.cpp
+++ b/indra/llcharacter/llmotioncontroller.cpp
@@ -174,34 +174,44 @@ void LLMotionController::deleteAllMotions()
//-----------------------------------------------------------------------------
void LLMotionController::addLoadedMotion(LLMotion* motionp)
{
+ std::set<LLUUID> motions_to_kill;
+
+ // gather all inactive, loaded motions
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
{
// too many motions active this frame, kill all blenders
mPoseBlender.clearBlenders();
- for (U32 i = 0; i < mLoadedMotions.size(); i++)
+ for (motion_list_t::iterator loaded_motion_it = mLoadedMotions.begin();
+ loaded_motion_it != mLoadedMotions.end();
+ ++loaded_motion_it)
{
- LLMotion* cur_motionp = mLoadedMotions.front();
- mLoadedMotions.pop_front();
+ LLMotion* cur_motionp = *loaded_motion_it;
// motion isn't playing, delete it
if (!isMotionActive(cur_motionp))
{
- mCharacter->requestStopMotion(cur_motionp);
- mAllMotions.erase(cur_motionp->getID());
- delete cur_motionp;
- if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES)
- {
- break;
- }
- }
- else
- {
- // put active motion on back
- mLoadedMotions.push_back(cur_motionp);
+ motions_to_kill.insert(cur_motionp->getID());
}
}
}
+
+ // clean up all inactive, loaded motions
+ for (std::set<LLUUID>::iterator motion_it = motions_to_kill.begin();
+ motion_it != motions_to_kill.end();
+ ++motion_it)
+ {
+ // look up the motion again by ID to get canonical instance
+ // and kill it only if that one is inactive
+ LLUUID motion_id = *motion_it;
+ LLMotion* motionp = findMotion(motion_id);
+ if (motionp && !isMotionActive(motionp))
+ {
+ removeMotion(motion_id);
+ }
+ }
+
+ // add new motion to loaded list
mLoadedMotions.push_back(motionp);
}
@@ -260,14 +270,24 @@ BOOL LLMotionController::addMotion( const LLUUID& id, LLMotionConstructor constr
void LLMotionController::removeMotion( const LLUUID& id)
{
LLMotion* motionp = findMotion(id);
+
+ removeMotionInstance(motionp);
+
+ mAllMotions.erase(id);
+}
+
+// removes instance of a motion from all runtime structures, but does
+// not erase entry by ID, as this could be a duplicate instance
+// use removeMotion(id) to remove all references to a given motion by id.
+void LLMotionController::removeMotionInstance(LLMotion* motionp)
+{
if (motionp)
{
- stopMotionLocally(id, TRUE);
+ stopMotionInstance(motionp, TRUE);
mLoadingMotions.erase(motionp);
mLoadedMotions.remove(motionp);
mActiveMotions.remove(motionp);
- mAllMotions.erase(id);
delete motionp;
}
}
@@ -328,28 +348,39 @@ LLMotion* LLMotionController::createMotion( const LLUUID &id )
//-----------------------------------------------------------------------------
BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
{
- // look for motion in our list of created motions
- LLMotion *motion = createMotion(id);
+ // do we have an instance of this motion for this character?
+ LLMotion *motion = findMotion(id);
+
+ // motion that is stopping will be allowed to stop but
+ // replaced by a new instance of that motion
+ if (motion
+ && motion->canDeprecate()
+ && motion->getFadeWeight() > 0.01f // not LOD-ed out
+ && (motion->isBlending() || motion->getStopTime() != 0.f))
+ {
+ deprecateMotionInstance(motion);
+ // force creation of new instance
+ motion = NULL;
+ }
+
+ // create new motion instance
+ if (!motion)
+ {
+ 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 the motion is already active and allows deprecation, then let it keep playing
+ else if (motion->canDeprecate() && isMotionActive(motion))
{
- if (motion->isStopped()) // motion has been stopped
- {
- deactivateMotion(motion, false);
- }
- else if (mTime < motion->mSendStopTimestamp) // motion is still active
- {
- return TRUE;
- }
+ return TRUE;
}
// llinfos << "Starting motion " << name << llendl;
- return activateMotion(motion, mTime - start_offset);
+ return activateMotionInstance(motion, mTime - start_offset);
}
@@ -360,6 +391,12 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate
{
// if already inactive, return false
LLMotion *motion = findMotion(id);
+
+ return stopMotionInstance(motion, stop_immediate);
+}
+
+BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate)
+{
if (!motion)
{
return FALSE;
@@ -376,7 +413,7 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate
if (stop_immediate)
{
- deactivateMotion(motion, false);
+ deactivateMotionInstance(motion);
}
return TRUE;
}
@@ -472,7 +509,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
{
if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{
- deactivateMotion(motionp, false);
+ deactivateMotionInstance(motionp);
}
else if (motionp->isStopped() && mTime > motionp->getStopTime())
{
@@ -490,7 +527,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
else if (mTime >= motionp->mActivationTimestamp)
@@ -518,7 +555,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -526,7 +563,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
{
if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{
- deactivateMotion(motionp, true);
+ posep->setWeight(0.f);
+ deactivateMotionInstance(motionp);
}
continue;
}
@@ -552,7 +590,8 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
}
else
{
- deactivateMotion(motionp, true);
+ posep->setWeight(0.f);
+ deactivateMotionInstance(motionp);
continue;
}
}
@@ -597,7 +636,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -641,7 +680,7 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
// propagate this to the network
// as not all viewers are guaranteed to have access to the same logic
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -713,7 +752,7 @@ void LLMotionController::updateMotion()
// this motion should be playing
if (!motionp->isStopped())
{
- activateMotion(motionp, mTime);
+ activateMotionInstance(motionp, mTime);
}
}
else if (status == LLMotion::STATUS_FAILURE)
@@ -721,6 +760,7 @@ void LLMotionController::updateMotion()
llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
sRegistry.markBad(motionp->getID());
mLoadingMotions.erase(curiter);
+
mAllMotions.erase(motionp->getID());
delete motionp;
}
@@ -753,9 +793,9 @@ void LLMotionController::updateMotion()
//-----------------------------------------------------------------------------
-// activateMotion()
+// activateMotionInstance()
//-----------------------------------------------------------------------------
-BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time)
+BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
{
if (mLoadingMotions.find(motion) != mLoadingMotions.end())
{
@@ -798,23 +838,38 @@ BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time)
}
//-----------------------------------------------------------------------------
-// deactivateMotion()
+// deactivateMotionInstance()
//-----------------------------------------------------------------------------
-BOOL LLMotionController::deactivateMotion(LLMotion *motion, bool remove_weight)
+BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion)
{
- if( remove_weight )
+ motion->deactivate();
+
+ motion_set_t::iterator found_it = mDeprecatedMotions.find(motion);
+ if (found_it != mDeprecatedMotions.end())
{
- // immediately remove pose weighting instead of letting it time out
- LLPose *posep = motion->getPose();
- posep->setWeight(0.f);
+ // deprecated motions need to be completely excised
+ removeMotionInstance(motion);
+ mDeprecatedMotions.erase(found_it);
+ }
+ else
+ {
+ // for motions that we are keeping, simply remove from active queue
+ mActiveMotions.remove(motion);
}
-
- motion->deactivate();
- mActiveMotions.remove(motion);
return TRUE;
}
+void LLMotionController::deprecateMotionInstance(LLMotion* motion)
+{
+ mDeprecatedMotions.insert(motion);
+
+ //fade out deprecated motion
+ stopMotionInstance(motion, FALSE);
+ //no longer canonical
+ mAllMotions.erase(motion->getID());
+}
+
//-----------------------------------------------------------------------------
// isMotionActive()
//-----------------------------------------------------------------------------
@@ -837,7 +892,7 @@ bool LLMotionController::isMotionLoading(LLMotion* motion)
//-----------------------------------------------------------------------------
LLMotion *LLMotionController::findMotion(const LLUUID& id)
{
- return mAllMotions[id];
+ return get_if_there<LLUUID, LLMotion*>(mAllMotions, id, NULL);
}
//-----------------------------------------------------------------------------
diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h
index 19bab09a11..d5ea568479 100644
--- a/indra/llcharacter/llmotioncontroller.h
+++ b/indra/llcharacter/llmotioncontroller.h
@@ -159,16 +159,21 @@ public:
LLMotion *findMotion( const LLUUID& id );
protected:
+ // internal operations act on motion instances directly
+ // as there can be duplicate motions per id during blending overlap
void deleteAllMotions();
void addLoadedMotion(LLMotion *motion);
- BOOL activateMotion(LLMotion *motion, F32 time);
- BOOL deactivateMotion(LLMotion *motion, bool remove_weight);
+ BOOL activateMotionInstance(LLMotion *motion, F32 time);
+ BOOL deactivateMotionInstance(LLMotion *motion);
+ void deprecateMotionInstance(LLMotion* motion);
+ BOOL stopMotionInstance(LLMotion *motion, BOOL stop_imemdiate);
+ void removeMotionInstance(LLMotion* motion);
void updateRegularMotions();
void updateAdditiveMotions();
void resetJointSignatures();
void updateMotionsByType(LLMotion::LLMotionBlendType motion_type);
-protected:
+protected:
F32 mTimeFactor;
static LLMotionRegistry sRegistry;
LLPoseBlender mPoseBlender;
@@ -183,11 +188,13 @@ protected:
// Once an animations is loaded, it will be initialized and put on the mLoadedMotions deque.
// Any animation that is currently playing also sits in the mActiveMotions list.
- std::map<LLUUID, LLMotion*> mAllMotions;
+ typedef std::map<LLUUID, LLMotion*> motion_map_t;
+ motion_map_t mAllMotions;
motion_set_t mLoadingMotions;
motion_list_t mLoadedMotions;
motion_list_t mActiveMotions;
+ motion_set_t mDeprecatedMotions;
LLFrameTimer mTimer;
F32 mTime;
diff --git a/indra/llcharacter/llpose.cpp b/indra/llcharacter/llpose.cpp
index e1b24d62cb..1f6d208b84 100644
--- a/indra/llcharacter/llpose.cpp
+++ b/indra/llcharacter/llpose.cpp
@@ -255,9 +255,9 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
joint_state_index < JSB_NUM_JOINT_STATES && mJointStates[joint_state_index] != NULL;
joint_state_index++)
{
- U32 current_usage = mJointStates[joint_state_index]->getUsage();
- F32 current_weight = mJointStates[joint_state_index]->getWeight();
LLJointState* jsp = mJointStates[joint_state_index];
+ U32 current_usage = jsp->getUsage();
+ F32 current_weight = jsp->getWeight();
if (current_weight == 0.f)
{
@@ -272,17 +272,14 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
// add in pos for this jointstate modulated by weight
added_pos += jsp->getPosition() * (new_weight_sum - sum_weights[POS_WEIGHT]);
- //sum_weights[POS_WEIGHT] = new_weight_sum;
}
- // now do scale
if(current_usage & LLJointState::SCALE)
{
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
// add in scale for this jointstate modulated by weight
added_scale += jsp->getScale() * (new_weight_sum - sum_weights[SCALE_WEIGHT]);
- //sum_weights[SCALE_WEIGHT] = new_weight_sum;
}
if (current_usage & LLJointState::ROT)
@@ -291,7 +288,6 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
// add in rotation for this jointstate modulated by weight
added_rot = nlerp((new_weight_sum - sum_weights[ROT_WEIGHT]), added_rot, jsp->getRotation()) * added_rot;
- //sum_weights[ROT_WEIGHT] = new_weight_sum;
}
}
else
@@ -306,13 +302,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);
// blend positions from both
- blended_pos = lerp(mJointStates[joint_state_index]->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
+ blended_pos = lerp(jsp->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
sum_weights[POS_WEIGHT] = new_weight_sum;
}
else
{
// copy position from current
- blended_pos = mJointStates[joint_state_index]->getPosition();
+ blended_pos = jsp->getPosition();
sum_weights[POS_WEIGHT] = current_weight;
}
}
@@ -325,13 +321,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
// blend scales from both
- blended_scale = lerp(mJointStates[joint_state_index]->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
+ blended_scale = lerp(jsp->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
sum_weights[SCALE_WEIGHT] = new_weight_sum;
}
else
{
// copy scale from current
- blended_scale = mJointStates[joint_state_index]->getScale();
+ blended_scale = jsp->getScale();
sum_weights[SCALE_WEIGHT] = current_weight;
}
}
@@ -344,13 +340,13 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now)
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]);
// blend rotations from both
- blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, mJointStates[joint_state_index]->getRotation(), blended_rot);
+ blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, jsp->getRotation(), blended_rot);
sum_weights[ROT_WEIGHT] = new_weight_sum;
}
else
{
// copy rotation from current
- blended_rot = mJointStates[joint_state_index]->getRotation();
+ blended_rot = jsp->getRotation();
sum_weights[ROT_WEIGHT] = current_weight;
}
}
diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h
index 5d17bd8458..b3cc994960 100644
--- a/indra/llcharacter/llpose.h
+++ b/indra/llcharacter/llpose.h
@@ -61,7 +61,7 @@ public:
S32 getNumJointStates() const;
};
-const S32 JSB_NUM_JOINT_STATES = 4;
+const S32 JSB_NUM_JOINT_STATES = 6;
class LLJointStateBlender
{