diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 7270cad0da0d2cb47602e1b60c1fb8cf3c479feb..22d8f88420036be96335cc8e8f83c7c7dc82d4df 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -367,8 +367,17 @@ void LLControlAvatar::updateAnimations()
             }
         }
     }
-    mSignaledAnimations = anims;
+    if (!mPlaying && anims.size()>0)
+    {
+        mPlaying = true;
+        if (!mRootVolp->isAnySelected())
+        {
+            updateVolumeGeom();
+            mRootVolp->recursiveMarkForUpdate(TRUE);
+        }
+    }
 
+    mSignaledAnimations = anims;
     processAnimationStateChanges();
 }
 
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 31eda8582801dba814ebe6fbb7d081da5af21cae..29fb5dcd53cdaa88155ef67036bd6ce750022008 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5116,42 +5116,6 @@ void process_object_animation(LLMessageSystem *mesgsys, void **user_data)
 	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList);
 	LL_DEBUGS("AnimatedObjects") << "processing object animation requests, num_blocks " << num_blocks << LL_ENDL;
 
-#if 1 
-    // Here we go into skinned mode once, the first time we get an
-    // animation request, and then stay there. This is probably the
-    // normally desired behavior.
-    if (!avatarp->mPlaying)
-    {
-        avatarp->mPlaying = true;
-        if (!avatarp->mRootVolp->isAnySelected())
-        {
-            avatarp->updateVolumeGeom();
-            avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
-        }
-    }
-#else// AXON REMOVE BEFORE RELEASE?
-    // In this block we switch back into static mode when no animations are
-    // playing. This is mostly useful for debugging.
-    if (num_blocks > 0 && !avatarp->mPlaying)
-    {
-        avatarp->mPlaying = true;
-        if (!avatarp->mRootVolp->isAnySelected())
-        {
-            avatarp->updateVolumeGeom();
-            avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
-        }
-    }
-    else if (num_blocks == 0 && avatarp->mPlaying)
-    {
-        avatarp->mPlaying = false;
-        if (!avatarp->mRootVolp->isAnySelected())
-        {
-            avatarp->updateVolumeGeom();
-            avatarp->mRootVolp->recursiveMarkForUpdate(TRUE);
-        }
-    }
-#endif
-
 	volp->mObjectSignaledAnimations.clear();
 	
     for( S32 i = 0; i < num_blocks; i++ )
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index ee67f5062e960cb9e575b127b13f0540a4ae5814..0d515b28d0673e3292b791e85f70f05f1b4f2603 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -879,9 +879,18 @@ void LLViewerObject::addChild(LLViewerObject *childp)
 	if(childp->setParent(this))
 	{
 		mChildList.push_back(childp);
+        childp->afterReparent();
 	}
 }
 
+void LLViewerObject::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent)
+{
+}
+
+void LLViewerObject::afterReparent()
+{
+}
+
 void LLViewerObject::removeChild(LLViewerObject *childp)
 {
 	for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
@@ -2990,6 +2999,7 @@ void LLViewerObject::linkControlAvatar()
     if (getControlAvatar())
     {
         getControlAvatar()->rebuildAttachmentOverrides();
+        getControlAvatar()->updateAnimations();
     }
     else
     {
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 237529f21307c101c178d70a6c46ebe72e259336..dc99978302d465252be5267493c9a56a515ef357 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -259,6 +259,8 @@ public:
 	*/
 
 	virtual BOOL setParent(LLViewerObject* parent);
+    virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent);
+    virtual void afterReparent();
 	virtual void addChild(LLViewerObject *childp);
 	virtual void removeChild(LLViewerObject *childp);
 	const_child_list_t& getChildren() const { 	return mChildList; }
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 0688a5743981a39378b8c9193a944e02da09ccd7..54a53898fb0ab7fccec764d20e111a9c4c15c4c0 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3400,180 +3400,218 @@ bool LLVOAvatar::isInMuteList()
 	return muted;
 }
 
-void LLVOAvatar::updateDebugText()
+void LLVOAvatar::updateAppearanceMessageDebugText()
 {
-    // Leave mDebugText uncleared here, in case a derived class has added some state first
-
-	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
-	{
-		S32 central_bake_version = -1;
-		if (getRegion())
-		{
-			central_bake_version = getRegion()->getCentralBakeVersion();
-		}
-		bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded();
-		bool all_local_downloaded = allLocalTexturesCompletelyDownloaded();
-		std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d",
-										  isSelf() ? (all_local_downloaded ? "L" : "l") : "-",
-										  all_baked_downloaded ? "B" : "b",
-										  mUseLocalAppearance, mIsEditingAppearance,
-										  1, central_bake_version);
-		std::string origin_string = bakedTextureOriginInfo();
-		debug_line += " [" + origin_string + "]";
-		S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion();
-		S32 last_request_cof_version = mLastUpdateRequestCOFVersion;
-		S32 last_received_cof_version = mLastUpdateReceivedCOFVersion;
-		if (isSelf())
-		{
-			debug_line += llformat(" - cof: %d req: %d rcv:%d",
-								   curr_cof_version, last_request_cof_version, last_received_cof_version);
-			if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
-			{
-				debug_line += " FORCING ERRS";
-			}
-		}
-		else
-		{
-			debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
-		}
-		debug_line += llformat(" bsz-z: %.3f", mBodySize[2]);
-        if (mAvatarOffset[2] != 0.0f)
+    S32 central_bake_version = -1;
+    if (getRegion())
+    {
+        central_bake_version = getRegion()->getCentralBakeVersion();
+    }
+    bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded();
+    bool all_local_downloaded = allLocalTexturesCompletelyDownloaded();
+    std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d",
+                                      isSelf() ? (all_local_downloaded ? "L" : "l") : "-",
+                                      all_baked_downloaded ? "B" : "b",
+                                      mUseLocalAppearance, mIsEditingAppearance,
+                                      1, central_bake_version);
+    std::string origin_string = bakedTextureOriginInfo();
+    debug_line += " [" + origin_string + "]";
+    S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion();
+    S32 last_request_cof_version = mLastUpdateRequestCOFVersion;
+    S32 last_received_cof_version = mLastUpdateReceivedCOFVersion;
+    if (isSelf())
+    {
+        debug_line += llformat(" - cof: %d req: %d rcv:%d",
+                               curr_cof_version, last_request_cof_version, last_received_cof_version);
+        if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
         {
-            debug_line += llformat("avofs-z: %.3f", mAvatarOffset[2]);
+            debug_line += " FORCING ERRS";
         }
-		bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled();
-		debug_line += hover_enabled ? " H" : " h";
-		const LLVector3& hover_offset = getHoverOffset();
-		if (hover_offset[2] != 0.0)
-		{
-			debug_line += llformat(" hov_z: %.3f", hover_offset[2]);
-			debug_line += llformat(" %s", (isSitting() ? "S" : "T"));
-			debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));
-		}
-        LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition();
-		LLVector3 normal;
-        LLVector3 ankle_right_ground_agent = ankle_right_pos_agent;
-        resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal);
-        F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]);
-        debug_line += llformat(" relev %.3f", rightElev);
+    }
+    else
+    {
+        debug_line += llformat(" - cof rcv:%d", last_received_cof_version);
+    }
+    debug_line += llformat(" bsz-z: %.3f", mBodySize[2]);
+    if (mAvatarOffset[2] != 0.0f)
+    {
+        debug_line += llformat("avofs-z: %.3f", mAvatarOffset[2]);
+    }
+    bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled();
+    debug_line += hover_enabled ? " H" : " h";
+    const LLVector3& hover_offset = getHoverOffset();
+    if (hover_offset[2] != 0.0)
+    {
+        debug_line += llformat(" hov_z: %.3f", hover_offset[2]);
+        debug_line += llformat(" %s", (isSitting() ? "S" : "T"));
+        debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));
+    }
+    LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition();
+    LLVector3 normal;
+    LLVector3 ankle_right_ground_agent = ankle_right_pos_agent;
+    resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal);
+    F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]);
+    debug_line += llformat(" relev %.3f", rightElev);
 
-        LLVector3 root_pos = mRoot->getPosition();
-        LLVector3 pelvis_pos = mPelvisp->getPosition();
-        debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]);
+    LLVector3 root_pos = mRoot->getPosition();
+    LLVector3 pelvis_pos = mPelvisp->getPosition();
+    debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]);
 
-        S32 is_visible = (S32) isVisible();
-        S32 is_m_visible = (S32) mVisible;
-        debug_line += llformat(" v %d/%d", is_visible, is_m_visible);
+    S32 is_visible = (S32) isVisible();
+    S32 is_m_visible = (S32) mVisible;
+    debug_line += llformat(" v %d/%d", is_visible, is_m_visible);
 
-		addDebugText(debug_line);
-	}
+    addDebugText(debug_line);
+}
 
-	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
-	{
-		if (!mBakedTextureDebugText.empty())
-			addDebugText(mBakedTextureDebugText);
-	}
+LLViewerInventoryItem* getObjectInventoryItem(LLViewerObject *vobj, LLUUID asset_id)
+{
+    LLViewerInventoryItem *item = NULL;
 
-    // Develop -> Avatar -> Animation Info
-	if (LLVOAvatar::sShowAnimationDebug)
-	{
-		for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
-			 iter != mMotionController.getActiveMotions().end(); ++iter)
-		{
-			LLMotion* motionp = *iter;
-			if (motionp->getMinPixelArea() < getPixelArea())
-			{
-				std::string output;
-                std::string motion_name = motionp->getName();
-				if (motion_name.empty())
-				{
-                    if (isControlAvatar())
+    if (vobj)
+    {
+        if (vobj->getInventorySerial()<=0)
+        {
+            vobj->requestInventory(); 
+        }
+        item = vobj->getInventoryItemByAsset(asset_id);
+    }
+    return item;
+}
+
+LLViewerInventoryItem* recursiveGetObjectInventoryItem(LLViewerObject *vobj, LLUUID asset_id)
+{
+    LLViewerInventoryItem *item = getObjectInventoryItem(vobj, asset_id);
+    if (!item)
+    {
+        LLViewerObject::const_child_list_t& children = vobj->getChildren();
+        for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
+             it != children.end(); ++it)
+        {
+            LLViewerObject *childp = *it;
+            item = getObjectInventoryItem(childp, asset_id);
+            if (item)
+            {
+                break;
+            }
+        }
+    }
+    return item;
+}
+
+void LLVOAvatar::updateAnimationDebugText()
+{
+    for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
+         iter != mMotionController.getActiveMotions().end(); ++iter)
+    {
+        LLMotion* motionp = *iter;
+        if (motionp->getMinPixelArea() < getPixelArea())
+        {
+            std::string output;
+            std::string motion_name = motionp->getName();
+            if (motion_name.empty())
+            {
+                if (isControlAvatar())
+                {
+                    LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
+                    // Try to get name from inventory of associated object
+                    LLVOVolume *volp = control_av->mRootVolp;
+                    LLViewerInventoryItem *item = recursiveGetObjectInventoryItem(volp,motionp->getID());
+                    if (item)
+                    {
+                        motion_name = item->getName();
+                    }
+                }
+            }
+            if (motion_name.empty())
+            {
+                std::string name;
+                if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf())
+                {
+                    name = motionp->getID().asString();
+                    LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin();
+                    for (; anim_it != mAnimationSources.end(); ++anim_it)
                     {
-                        LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
-                        // Try to get name from inventory of associated object
-                        LLVOVolume *volp = control_av->mRootVolp;
-                        if (volp)
+                        if (anim_it->second == motionp->getID())
                         {
-                            if (volp->getInventorySerial()<=0)
+                            LLViewerObject* object = gObjectList.findObject(anim_it->first);
+                            if (!object)
+                            {
+                                break;
+                            }
+                            if (object->isAvatar())
                             {
-                                volp->requestInventory(); 
+                                if (mMotionController.mIsSelf)
+                                {
+                                    // Searching inventory by asset id is really long
+                                    // so just mark as inventory
+                                    // Also item is likely to be named by LLPreviewAnim
+                                    name += "(inventory)";
+                                }
                             }
-                            LLViewerInventoryItem* item = volp->getInventoryItemByAsset(motionp->getID());
-                            if (item)
+                            else
                             {
-                                motion_name = item->getName();
+                                LLViewerInventoryItem* item = NULL;
+                                if (!object->isInventoryDirty())
+                                {
+                                    item = object->getInventoryItemByAsset(motionp->getID());
+                                }
+                                if (item)
+                                {
+                                    name = item->getName();
+                                }
+                                else if (object->isAttachment())
+                                {
+                                    name += "(" + getAttachmentItemName() + ")";
+                                }
+                                else
+                                {
+                                    // in-world object, name or content unknown
+                                    name += "(in-world)";
+                                }
                             }
+                            break;
                         }
                     }
                 }
-                if (motion_name.empty())
+                else
                 {
-					std::string name;
-					if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf())
-					{
-						name = motionp->getID().asString();
-						LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin();
-						for (; anim_it != mAnimationSources.end(); ++anim_it)
-						{
-							if (anim_it->second == motionp->getID())
-							{
-								LLViewerObject* object = gObjectList.findObject(anim_it->first);
-								if (!object)
-								{
-									break;
-								}
-								if (object->isAvatar())
-								{
-									if (mMotionController.mIsSelf)
-									{
-										// Searching inventory by asset id is really long
-										// so just mark as inventory
-										// Also item is likely to be named by LLPreviewAnim
-										name += "(inventory)";
-									}
-								}
-								else
-								{
-									LLViewerInventoryItem* item = NULL;
-									if (!object->isInventoryDirty())
-									{
-										item = object->getInventoryItemByAsset(motionp->getID());
-									}
-									if (item)
-									{
-										name = item->getName();
-									}
-									else if (object->isAttachment())
-									{
-										name += "(" + getAttachmentItemName() + ")";
-									}
-									else
-									{
-										// in-world object, name or content unknown
-										name += "(in-world)";
-									}
-								}
-								break;
-							}
-						}
-					}
-					else
-					{
-						name = LLUUID::null.asString();
-					}
-					output = llformat("%s - %d",
-							  name.c_str(),
-							  (U32)motionp->getPriority());
-				}
-				else
-				{
-					output = llformat("%s - %d",
-                                      motion_name.c_str(),
-                                      (U32)motionp->getPriority());
-				}
-				addDebugText(output);
-			}
-		}
+                    name = LLUUID::null.asString();
+                }
+                output = llformat("%s - %d",
+                                  name.c_str(),
+                                  (U32)motionp->getPriority());
+            }
+            else
+            {
+                output = llformat("%s - %d",
+                                  motion_name.c_str(),
+                                  (U32)motionp->getPriority());
+            }
+            addDebugText(output);
+        }
+    }
+}
+
+void LLVOAvatar::updateDebugText()
+{
+    // Leave mDebugText uncleared here, in case a derived class has added some state first
+
+	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+	{
+        updateAppearanceMessageDebugText();
+	}
+
+	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked"))
+	{
+		if (!mBakedTextureDebugText.empty())
+			addDebugText(mBakedTextureDebugText);
+	}
+
+    // Develop -> Avatar -> Animation Info
+	if (LLVOAvatar::sShowAnimationDebug)
+	{
+        updateAnimationDebugText();
 	}
 
 	if (!mDebugText.size() && mText.notNull())
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index de8da4f7cacfe9f6eeb0e9417c295c61040b830d..e9eadb77e940c1de485479643b33a344f63946bc 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -246,6 +246,8 @@ private: //aligned members
 	// Updates
 	//--------------------------------------------------------------------
 public:
+    void			updateAppearanceMessageDebugText();
+	void 			updateAnimationDebugText();
 	virtual void	updateDebugText();
 	virtual BOOL 	updateCharacter(LLAgent &agent);
     void			updateFootstepSounds();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 7192b4a196eb7053f215147014c54f5c4185a0af..aa50122ff0183d6bf79af656b5ca8e4291b3120d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1445,7 +1445,7 @@ BOOL LLVOVolume::setParent(LLViewerObject* parent)
 			gPipeline.markMoved(mDrawable);
 			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 		}
-        updateAnimatedObjectStateOnReparent(old_parent, parent);
+        onReparent(old_parent, parent);
 	}
 
 	return ret ;
@@ -3427,8 +3427,10 @@ bool LLVOVolume::isAnimatedObject() const
 
 // Called any time parenting changes for a volume. Update flags and
 // control av accordingly.  This is called after parent has been
-// changed to new_parent.
-void LLVOVolume::updateAnimatedObjectStateOnReparent(LLViewerObject *old_parent, LLViewerObject *new_parent)
+// changed to new_parent, but before new_parent's mChildList has changed.
+
+// virtual
+void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent)
 {
     LLVOVolume *old_volp = dynamic_cast<LLVOVolume*>(old_parent);
 
@@ -3442,11 +3444,6 @@ void LLVOVolume::updateAnimatedObjectStateOnReparent(LLViewerObject *old_parent,
             mControlAvatar = NULL;
             av->markForDeath();
         }
-        // If this succeeds now, it's because the new_parent is an animated object
-        if (isAnimatedObject() && getControlAvatar())
-        {
-            getControlAvatar()->addAttachmentOverridesForObject(this);
-        }
     }
     if (old_volp && old_volp->isAnimatedObject())
     {
@@ -3454,10 +3451,25 @@ void LLVOVolume::updateAnimatedObjectStateOnReparent(LLViewerObject *old_parent,
         {
             // We have been removed from an animated object, need to do cleanup.
             old_volp->getControlAvatar()->rebuildAttachmentOverrides();
+            old_volp->getControlAvatar()->updateAnimations();
         }
     }
 }
 
+// This needs to be called after onReparent(), because mChildList is
+// not updated until the end of LLViewerObject::addChild()
+
+// virtual
+void LLVOVolume::afterReparent()
+{
+    // If this succeeds now, it's because the new parent is an animated object
+    if (isAnimatedObject() && getControlAvatar())
+    {
+        getControlAvatar()->addAttachmentOverridesForObject(this);
+        getControlAvatar()->updateAnimations();
+    }
+}
+
 //----------------------------------------------------------------------------
 
 void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point)
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index afd6c234eef15c5ab6468877a87676c023269263..a6ba8014e2c2f85032b2a2a05cca76c1e3d1f84c 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -278,7 +278,8 @@ public:
     void setExtendedMeshFlags(U32 flags);
     bool canBeAnimatedObject() const;
     bool isAnimatedObject() const;
-    void updateAnimatedObjectStateOnReparent(LLViewerObject *old_parent, LLViewerObject *new_parent);
+    virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent);
+    virtual void afterReparent();
 
 	std::map<LLUUID, S32> 					mObjectSignaledAnimations; // requested state of Animation name/value