diff options
Diffstat (limited to 'indra/newview')
| -rwxr-xr-x | indra/newview/llagentwearables.cpp | 26 | ||||
| -rwxr-xr-x | indra/newview/llagentwearables.h | 5 | ||||
| -rwxr-xr-x | indra/newview/llaisapi.cpp | 1 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.cpp | 52 | ||||
| -rwxr-xr-x | indra/newview/llfloatermodelpreview.cpp | 10 | ||||
| -rwxr-xr-x | indra/newview/llinventorybridge.cpp | 20 | ||||
| -rwxr-xr-x | indra/newview/llviewerinventory.cpp | 16 | ||||
| -rwxr-xr-x | indra/newview/llviewerinventory.h | 6 | ||||
| -rwxr-xr-x | indra/newview/llviewerobject.cpp | 23 | ||||
| -rwxr-xr-x | indra/newview/llviewerobject.h | 2 | ||||
| -rwxr-xr-x | indra/newview/llvoavatar.cpp | 259 | ||||
| -rwxr-xr-x | indra/newview/llvoavatar.h | 14 | ||||
| -rwxr-xr-x | indra/newview/llvoavatarself.cpp | 40 | ||||
| -rwxr-xr-x | indra/newview/llvoavatarself.h | 5 | ||||
| -rwxr-xr-x | indra/newview/llvovolume.cpp | 58 | ||||
| -rwxr-xr-x | indra/newview/llwearableitemslist.cpp | 10 | ||||
| -rwxr-xr-x | indra/newview/skins/default/xui/en/strings.xml | 8 | 
17 files changed, 373 insertions, 182 deletions
| diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 3928bbadc8..f06ffb4fb3 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1088,7 +1088,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it  	if (isAgentAvatarValid())  	{  		gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); -		gAgentAvatarp->updateVisualParams();  		// If we have not yet declouded, we may want to use  		// baked texture UUIDs sent from the first objectUpdate message @@ -1106,6 +1105,12 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it  	notifyLoadingFinished(); +	// Copy wearable params to avatar. +	gAgentAvatarp->writeWearablesToAvatar(); + +	// Then update the avatar based on the copied params. +	gAgentAvatarp->updateVisualParams(); +  	gAgentAvatarp->dumpAvatarTEs("setWearableOutfit");  	LL_DEBUGS("Avatar") << "setWearableOutfit() end" << LL_ENDL; @@ -1248,9 +1253,12 @@ void LLAgentWearables::userRemoveWearablesOfType(const LLWearableType::EType &ty  	}  } -// Combines userRemoveMulipleAttachments() and userAttachMultipleAttachments() logic to -// get attachments into desired state with minimal number of adds/removes. -void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array) +// Given a desired set of attachments, find what objects need to be +// removed, and what additional inventory items need to be added. +void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array, +													llvo_vec_t& objects_to_remove, +													llvo_vec_t& objects_to_retain, +													LLInventoryModel::item_array_t& items_to_add)  {  	// Possible cases:  	// already wearing but not in request set -> take off. @@ -1269,7 +1277,6 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj  	}  	// Build up list of objects to be removed and items currently attached. -	llvo_vec_t objects_to_remove;  	for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();   		 iter != gAgentAvatarp->mAttachmentPoints.end();)  	{ @@ -1304,12 +1311,12 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj  				{  					// LL_INFOS() << "found object to keep, id " << objectp->getID() << ", item " << objectp->getAttachmentItemID() << LL_ENDL;  					current_item_ids.insert(object_item_id); +					objects_to_retain.push_back(objectp);  				}  			}  		}  	} -	LLInventoryModel::item_array_t items_to_add;  	for (LLInventoryModel::item_array_t::iterator it = obj_item_array.begin();  		 it != obj_item_array.end();  		 ++it) @@ -1328,12 +1335,6 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj  	// S32 remove_count = objects_to_remove.size();  	// S32 add_count = items_to_add.size();  	// LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL; - -	// Remove everything in objects_to_remove -	userRemoveMultipleAttachments(objects_to_remove); - -	// Add everything in items_to_add -	userAttachMultipleAttachments(items_to_add);  }  void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove) @@ -1353,6 +1354,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo  		 ++it)  	{  		LLViewerObject *objectp = *it; +		//gAgentAvatarp->resetJointPositionsOnDetach(objectp);  		gMessageSystem->nextBlockFast(_PREHASH_ObjectData);  		gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());  	} diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index cdb1bdbe05..1004482020 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -178,7 +178,10 @@ public:  	typedef std::vector<LLViewerObject*> llvo_vec_t; -	static void 	userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array); +	static void     findAttachmentsAddRemoveInfo(LLInventoryModel::item_array_t& obj_item_array, +												 llvo_vec_t& objects_to_remove, +												 llvo_vec_t& objects_to_retain, +												 LLInventoryModel::item_array_t& items_to_add);  	static void		userRemoveMultipleAttachments(llvo_vec_t& llvo_array);  	static void		userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 96de15bf75..9d887a61f1 100755 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -34,6 +34,7 @@  #include "llsdutil.h"  #include "llviewerregion.h"  #include "llinventoryobserver.h" +#include "llviewercontrol.h"  ///----------------------------------------------------------------------------  /// Classes for AISv3 support. diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e35cf011c7..d7ef5fcba7 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -807,15 +807,48 @@ void LLWearableHoldingPattern::onAllComplete()  		}  	} -	// Update wearables. -	LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " << mResolved << " wearable items " << LL_ENDL; -	LLAppearanceMgr::instance().updateAgentWearables(this); -	 -	// Update attachments to match those requested.  	if (isAgentAvatarValid())  	{  		LL_DEBUGS("Avatar") << self_av_string() << "Updating " << mObjItems.size() << " attachments" << LL_ENDL; -		LLAgentWearables::userUpdateAttachments(mObjItems); +		LLAgentWearables::llvo_vec_t objects_to_remove; +		LLAgentWearables::llvo_vec_t objects_to_retain; +		LLInventoryModel::item_array_t items_to_add; + +		LLAgentWearables::findAttachmentsAddRemoveInfo(mObjItems, +													   objects_to_remove, +													   objects_to_retain, +													   items_to_add); + +		LL_DEBUGS("Avatar") << self_av_string() << "Removing " << objects_to_remove.size() +							<< " attachments" << LL_ENDL; + +		// Here we remove the attachment pos overrides for *all* +		// attachments, even those that are not being removed. This is +		// needed to get joint positions all slammed down to their +		// pre-attachment states. +		gAgentAvatarp->clearAttachmentPosOverrides(); + +		// Take off the attachments that will no longer be in the outfit. +		LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); +		 +		// Update wearables. +		LL_INFOS("Avatar") << self_av_string() << "HP " << index() << " updating agent wearables with " +						   << mResolved << " wearable items " << LL_ENDL; +		LLAppearanceMgr::instance().updateAgentWearables(this); +		 +		// Restore attachment pos overrides for the attachments that +		// are remaining in the outfit. +		for (LLAgentWearables::llvo_vec_t::iterator it = objects_to_retain.begin(); +			 it != objects_to_retain.end(); +			 ++it) +		{ +			LLViewerObject *objectp = *it; +			gAgentAvatarp->addAttachmentPosOverridesForObject(objectp); +		} +		 +		// Add new attachments to match those requested. +		LL_DEBUGS("Avatar") << self_av_string() << "Adding " << items_to_add.size() << " attachments" << LL_ENDL; +		LLAgentWearables::userAttachMultipleAttachments(items_to_add);  	}  	if (isFetchCompleted() && isMissingCompleted()) @@ -2699,7 +2732,12 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInve  		const LLInventoryItem* item = item_array.at(i).get();  		if (item->getIsLinkType() && item->getLinkedUUID() == item_id)  		{ -			remove_inventory_item(item->getUUID(), cb); +			bool immediate_delete = false; +			if (item->getType() == LLAssetType::AT_OBJECT) +			{ +				immediate_delete = true; +			} +			remove_inventory_item(item->getUUID(), cb, immediate_delete);  		}  	}  } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 195a7f5ffe..0c81ab7e79 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1935,7 +1935,9 @@ bool LLModelLoader::doLoadModel()  										LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint );  										if ( pJoint )  										{    -											pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), mFilename); +											LLUUID fake_mesh_id; +											fake_mesh_id.generate(); +											pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, gAgentAvatarp->avString());  										}  										else  										{ @@ -3242,7 +3244,11 @@ U32 LLModelPreview::calcResourceCost()  	if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() )  	{ -		getPreviewAvatar()->setPelvisOffset( mPelvisZOffset ); +		// FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail. +		// see also call to addAttachmentPosOverride. +		LLUUID fake_mesh_id; +		fake_mesh_id.generate(); +		getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id );  	}  	F32 streaming_cost = 0.f; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 085986dc68..1910656066 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5344,16 +5344,20 @@ std::string LLObjectBridge::getLabelSuffix() const  		{  			return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");  		} -		std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); -		if (attachment_point_name == LLStringUtil::null) // Error condition, invalid attach point +		std::string attachment_point_name; +		if (gAgentAvatarp->getAttachedPointName(mUUID, attachment_point_name))  		{ -			attachment_point_name = "Invalid Attachment"; -		} -		// e.g. "(worn on ...)" / "(attached to ...)" -		LLStringUtil::format_map_t args; -		args["[ATTACHMENT_POINT]"] =  LLTrans::getString(attachment_point_name); +			LLStringUtil::format_map_t args; +			args["[ATTACHMENT_POINT]"] =  LLTrans::getString(attachment_point_name); -		return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); +			return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); +		} +		else +		{ +			LLStringUtil::format_map_t args; +			args["[ATTACHMENT_ERROR]"] =  LLTrans::getString(attachment_point_name); +			return LLItemBridge::getLabelSuffix() + LLTrans::getString("AttachmentErrorMessage", args); +		}  	}  	return LLItemBridge::getLabelSuffix();  } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d364fce45a..d6c8ba10f6 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1456,7 +1456,8 @@ void update_inventory_category(  void remove_inventory_items(  	LLInventoryObject::object_list_t& items_to_kill, -	LLPointer<LLInventoryCallback> cb) +	LLPointer<LLInventoryCallback> cb +	)  {  	for (LLInventoryObject::object_list_t::iterator it = items_to_kill.begin();  		 it != items_to_kill.end(); @@ -1468,12 +1469,13 @@ void remove_inventory_items(  void remove_inventory_item(  	const LLUUID& item_id, -	LLPointer<LLInventoryCallback> cb) +	LLPointer<LLInventoryCallback> cb, +	bool immediate_delete)  {  	LLPointer<LLInventoryObject> obj = gInventory.getItem(item_id);  	if (obj)  	{ -		remove_inventory_item(obj, cb); +		remove_inventory_item(obj, cb, immediate_delete);  	}  	else  	{ @@ -1483,7 +1485,8 @@ void remove_inventory_item(  void remove_inventory_item(  	LLPointer<LLInventoryObject> obj, -	LLPointer<LLInventoryCallback> cb) +	LLPointer<LLInventoryCallback> cb, +	bool immediate_delete)  {  	if(obj)  	{ @@ -1493,6 +1496,11 @@ void remove_inventory_item(  		{  			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);  			cmd_ptr->run_command(); + +			if (immediate_delete) +			{ +				gInventory.onObjectDeletedFromServer(item_id); +			}  		}  		else // no cap  		{ diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index d345c49cfb..ca92565600 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -394,11 +394,13 @@ void remove_inventory_items(  void remove_inventory_item(  	LLPointer<LLInventoryObject> obj, -	LLPointer<LLInventoryCallback> cb); +	LLPointer<LLInventoryCallback> cb, +	bool immediate_delete = false);  void remove_inventory_item(  	const LLUUID& item_id, -	LLPointer<LLInventoryCallback> cb); +	LLPointer<LLInventoryCallback> cb, +	bool immediate_delete = false);  void remove_inventory_category(  	const LLUUID& cat_id, diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 33b442815d..820249e181 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -359,10 +359,17 @@ void LLViewerObject::markDead()  		//LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL;  		// Root object of this hierarchy unlinks itself. +		LLVOAvatar *av = getAvatarAncestor();  		if (getParent())  		{  			((LLViewerObject *)getParent())->removeChild(this);  		} +		LLUUID mesh_id; +		if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) +		{ +			// This case is needed for indirectly attached mesh objects. +			av->resetJointPositionsOnDetach(mesh_id); +		}  		// Mark itself as dead  		mDead = TRUE; @@ -5006,6 +5013,22 @@ LLVOAvatar* LLViewerObject::asAvatar()  	return NULL;  } +// If this object is directly or indirectly parented by an avatar, return it. +LLVOAvatar* LLViewerObject::getAvatarAncestor() +{ +	LLViewerObject *pobj = (LLViewerObject*) getParent(); +	while (pobj) +	{ +		LLVOAvatar *av = pobj->asAvatar(); +		if (av) +		{ +			return av; +		} +		pobj =  (LLViewerObject*) pobj->getParent(); +	} +	return NULL; +} +  BOOL LLViewerObject::isParticleSource() const  {  	return !mPartSourcep.isNull() && !mPartSourcep->isDead(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 22ac4ce0db..05c87c153b 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -135,6 +135,8 @@ public:  	virtual LLVOAvatar* asAvatar(); +	LLVOAvatar* getAvatarAncestor(); +  	static void initVOClasses();  	static void cleanupVOClasses(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 904d08ac73..51ef2e7564 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -708,7 +708,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mVisualComplexity(0),  	mVisualComplexityStale(TRUE),  	mLoadedCallbacksPaused(FALSE), -	mHasPelvisOffset( FALSE ),  	mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)),  	mLastRezzedStatus(-1),  	mIsEditingAppearance(FALSE), @@ -770,10 +769,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mRuthTimer.reset();  	mRuthDebugTimer.reset();  	mDebugExistenceTimer.reset(); -	mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); -	mLastPelvisToFoot = 0.0f; -	mPelvisFixup = 0.0f; -	mLastPelvisFixup = 0.0f;      if(LLSceneMonitor::getInstance()->isEnabled())  	{ @@ -1258,17 +1253,18 @@ const LLVector3 LLVOAvatar::getRenderPosition() const  	}  	else if (isRoot())  	{ -		if ( !mHasPelvisOffset ) -		{ -			return mDrawable->getPositionAgent(); -		} -		else +		F32 fixup; +		if ( hasPelvisFixup( fixup) )  		{  			//Apply a pelvis fixup (as defined by the avs skin)  			LLVector3 pos = mDrawable->getPositionAgent(); -			pos[VZ] += mPelvisFixup; +			pos[VZ] += fixup;  			return pos;  		} +		else +		{ +			return mDrawable->getPositionAgent(); +		}  	}  	else  	{ @@ -3212,6 +3208,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		{  			debug_line += llformat(" - cof rcv:%d", last_received_cof_version);  		} +		debug_line += llformat(" bsz-z: %f avofs-z: %f", mBodySize[2], mAvatarOffset[2]);  		addDebugText(debug_line);  	}  	if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) @@ -3723,21 +3720,6 @@ void LLVOAvatar::updateHeadOffset()  	}  }  //------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup )  -{ -	mHasPelvisOffset = hasOffset; -	if ( mHasPelvisOffset ) -	{	 -		//Store off last pelvis to foot value -		mLastPelvisToFoot = mPelvisToFoot;		 -		mPelvisOffset	  = offsetAmount; -		mLastPelvisFixup  = mPelvisFixup; -		mPelvisFixup	  = pelvisFixup; -	} -} -//------------------------------------------------------------------------  // postPelvisSetRecalc  //------------------------------------------------------------------------  void LLVOAvatar::postPelvisSetRecalc( void ) @@ -3747,15 +3729,6 @@ void LLVOAvatar::postPelvisSetRecalc( void )  	dirtyMesh(2);  }  //------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount ) -{		 -	mHasPelvisOffset  = true; -	mLastPelvisFixup  = mPelvisFixup;	 -	mPelvisFixup	  = pelvisFixupAmount;	 -} -//------------------------------------------------------------------------  // updateVisibility()  //------------------------------------------------------------------------  void LLVOAvatar::updateVisibility() @@ -5063,10 +5036,162 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )  	return jointp;  } + +//----------------------------------------------------------------------------- +// getRiggedMeshID +// +// If viewer object is a rigged mesh, set the mesh id and return true. +// Otherwise, null out the id and return false. +//----------------------------------------------------------------------------- +// static +bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id) +{ +	mesh_id.setNull(); +	 +	//If a VO has a skin that we'll reset the joint positions to their default +	if ( pVO && pVO->mDrawable ) +	{ +		LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); +		if ( pVObj ) +		{ +			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); +			if (pSkinData  +				&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG	// full rig +				&& pSkinData->mAlternateBindMatrix.size() > 0 ) +					{				 +						mesh_id = pSkinData->mMeshID; +						return true; +					} +		} +	} +	return false; +} + +void LLVOAvatar::clearAttachmentPosOverrides() +{ +	//Subsequent joints are relative to pelvis +	avatar_joint_list_t::iterator iter = mSkeleton.begin(); +	avatar_joint_list_t::iterator end  = mSkeleton.end(); + +	for (; iter != end; ++iter) +	{ +		LLJoint* pJoint = (*iter); +		pJoint->clearAttachmentPosOverrides(); +	} +} + +//----------------------------------------------------------------------------- +// addAttachmentPosOverridesForObject +//----------------------------------------------------------------------------- +void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo) +{ +	LLVOAvatar *av = vo->getAvatarAncestor(); +	if (!av || (av != this)) +	{ +		LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; +	} +		 +	// Process all children +	LLViewerObject::const_child_list_t& children = vo->getChildren(); +	for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); +		 it != children.end(); ++it) +	{ +		LLViewerObject *childp = *it; +		addAttachmentPosOverridesForObject(childp); +	} + +	LLVOVolume *vobj = dynamic_cast<LLVOVolume*>(vo); +	bool pelvisGotSet = false; + +	if (!vobj) +	{ +		return; +	} +	if (vobj->isMesh() && +		((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) +	{ +		return; +	} +	LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						 +	const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + +	if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData ) +	{ +		const int bindCnt = pSkinData->mAlternateBindMatrix.size();								 +		if ( bindCnt > 0 ) +		{					 +			const int jointCnt = pSkinData->mJointNames.size(); +			const F32 pelvisZOffset = pSkinData->mPelvisOffset; +			const LLUUID& mesh_id = pSkinData->mMeshID; +			bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								 +			if ( fullRig ) +			{								 +				for ( int i=0; i<jointCnt; ++i ) +				{ +					std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); +					LLJoint* pJoint = getJoint( lookingForJoint ); +					if ( pJoint && pJoint->getId() != currentId ) +					{   									 +						pJoint->setId( currentId ); +						const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									 +						//Set the joint position +						pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString() ); +									 +						//If joint is a pelvis then handle old/new pelvis to foot values +						if ( lookingForJoint == "mPelvis" ) +						{	 +							pelvisGotSet = true;											 +						}										 +					}										 +				}																 +				if (pelvisZOffset != 0.0F) +				{ +					addPelvisFixup( pelvisZOffset, mesh_id ); +					pelvisGotSet = true;											 +				} +			}							 +		} +	} +					 +	//Rebuild body data if we altered joints/pelvis +	if ( pelvisGotSet )  +	{ +		postPelvisSetRecalc(); +	}		 +} +  //-----------------------------------------------------------------------------  // resetJointPositionsOnDetach  //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointPositionsOnDetach(const std::string& attachment_name) +void LLVOAvatar::resetJointPositionsOnDetach(LLViewerObject *vo) +{ +	LLVOAvatar *av = vo->getAvatarAncestor(); +	if (!av || (av != this)) +	{ +		LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; +	} +		 +	// Process all children +	LLViewerObject::const_child_list_t& children = vo->getChildren(); +	for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); +		 it != children.end(); ++it) +	{ +		LLViewerObject *childp = *it; +		resetJointPositionsOnDetach(childp); +	} + +	// Process self. +	LLUUID mesh_id; +	if (getRiggedMeshID(vo,mesh_id)) +	{ +		resetJointPositionsOnDetach(mesh_id); +	} +} + +//----------------------------------------------------------------------------- +// resetJointPositionsOnDetach +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id)  {	  	//Subsequent joints are relative to pelvis  	avatar_joint_list_t::iterator iter = mSkeleton.begin(); @@ -5078,22 +5203,18 @@ void LLVOAvatar::resetJointPositionsOnDetach(const std::string& attachment_name)  	{  		LLJoint* pJoint = (*iter);  		//Reset joints except for pelvis -		if ( pJoint && pJoint != pJointPelvis) +		if ( pJoint )  		{			  			pJoint->setId( LLUUID::null ); -			pJoint->removeAttachmentPosOverride(attachment_name); +			pJoint->removeAttachmentPosOverride(mesh_id, avString());  		}		 -		else  		if ( pJoint && pJoint == pJointPelvis)  		{ -			pJoint->setId( LLUUID::null ); +			removePelvisFixup( mesh_id );  			pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );  		}		  	}	 -	//make sure we don't apply the joint offset -	mHasPelvisOffset = false; -	mPelvisFixup	 = mLastPelvisFixup;  	postPelvisSetRecalc();	  }  //----------------------------------------------------------------------------- @@ -5740,31 +5861,18 @@ void LLVOAvatar::rebuildRiggedAttachments( void )  //-----------------------------------------------------------------------------  void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  { -	//If a VO has a skin that we'll reset the joint positions to their default -	if ( pVO && pVO->mDrawable ) +	LLUUID mesh_id; +	if (getRiggedMeshID(pVO, mesh_id))  	{ -		LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); -		if ( pVObj ) +		resetJointPositionsOnDetach(mesh_id); +		if ( gAgentCamera.cameraCustomizeAvatar() )  		{ -			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); -			if (pSkinData  -				&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG	// full rig -				&& pSkinData->mAlternateBindMatrix.size() > 0 ) -					{				 -						const std::string& attachment_name = pVO->getAttachmentItemName(); -						LLVOAvatar::resetJointPositionsOnDetach(attachment_name);							 -						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing  -						//This handles the case where we detach a replacement rig. -						if ( gAgentCamera.cameraCustomizeAvatar() ) -						{ -							gAgent.unpauseAnimation(); -							//Still want to refocus on head bone -							gAgentCamera.changeCameraToCustomizeAvatar(); -						} -					} -				} -			}				 +			gAgent.unpauseAnimation(); +			//Still want to refocus on head bone +			gAgentCamera.changeCameraToCustomizeAvatar();  		} +	} +}  //-----------------------------------------------------------------------------  // detachObject() @@ -7693,6 +7801,27 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara  						 pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]);  	} +	for (iter = mSkeleton.begin(); iter != end; ++iter) +	{ +		LLJoint* pJoint = (*iter); +		 +		LLVector3 pos; +		LLUUID mesh_id; + +		if (pJoint->hasAttachmentPosOverride(pos,mesh_id)) +		{ +			apr_file_printf( file, "\t\t<joint_offset name=\"%s\" position=\"%f %f %f\" mesh_id=\"%s\"/>\n",  +							 pJoint->getName().c_str(), pos[0], pos[1], pos[2], mesh_id.asString().c_str()); +		} +	} +	F32 pelvis_fixup; +	LLUUID mesh_id; +	if (hasPelvisFixup(pelvis_fixup, mesh_id)) +	{ +		apr_file_printf( file, "\t\t<pelvis_fixup z=\"%f\" mesh_id=\"%s\"/>\n",  +						 pelvis_fixup, mesh_id.asString().c_str()); +	} +  	apr_file_printf( file, "\t</archetype>\n" );  	apr_file_printf( file, "\n</linden_genepool>\n" ); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 66a357ff62..9a2aaf8aa3 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -199,7 +199,10 @@ public:  	virtual LLJoint*		getJoint(const std::string &name); -	void					resetJointPositionsOnDetach(const std::string& attachment_name); +	void 					addAttachmentPosOverridesForObject(LLViewerObject *vo); +	void					resetJointPositionsOnDetach(const LLUUID& mesh_id); +	void					resetJointPositionsOnDetach(LLViewerObject *vo); +	void					clearAttachmentPosOverrides();  	/*virtual*/ const LLUUID&	getID() const;  	/*virtual*/ void			addDebugText(const std::string& text); @@ -356,19 +359,11 @@ protected:  	/*virtual*/ LLAvatarJointMesh*	createAvatarJointMesh(); // Returns LLViewerJointMesh  public:  	void				updateHeadOffset(); -	void				setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; -	bool				hasPelvisOffset( void ) { return mHasPelvisOffset; }  	void				postPelvisSetRecalc( void ); -	void				setPelvisOffset( F32 pelvixFixupAmount );  	/*virtual*/ BOOL	loadSkeletonNode();  	/*virtual*/ void	buildCharacter(); -	bool				mHasPelvisOffset; -	LLVector3			mPelvisOffset; -	F32					mLastPelvisToFoot; -	F32					mPelvisFixup; -	F32					mLastPelvisFixup;  	LLVector3			mCurRootToHeadOffset;  	LLVector3			mTargetRootToHeadOffset; @@ -719,6 +714,7 @@ public:  	void 				clampAttachmentPositions();  	virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);  	virtual BOOL 		detachObject(LLViewerObject *viewer_object); +	static bool		    getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id );  	void				cleanupAttachedMesh( LLViewerObject* pVO );  	static LLVOAvatar*  findAvatarFromAttachment(LLViewerObject* obj);  	/*virtual*/ BOOL	isWearingWearableType(LLWearableType::EType type ) const; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 42a7c2e576..0be8df349d 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -262,7 +262,7 @@ void LLVOAvatarSelf::markDead()  {  	BOOL success = LLVOAvatar::loadAvatar(); -	// set all parameters sotred directly in the avatar to have +	// set all parameters stored directly in the avatar to have  	// the isSelfParam to be TRUE - this is used to prevent  	// them from being animated or trigger accidental rebakes  	// when we copy params from the wearable to the base avatar. @@ -718,13 +718,8 @@ void LLVOAvatarSelf::updateVisualParams()  	LLVOAvatar::updateVisualParams();  } -/*virtual*/ -void LLVOAvatarSelf::idleUpdateAppearanceAnimation() +void LLVOAvatarSelf::writeWearablesToAvatar()  { -	// Animate all top-level wearable visual parameters -	gAgentWearables.animateAllWearableParams(calcMorphAmount()); - -	// apply wearable visual params to avatar  	for (U32 type = 0; type < LLWearableType::WT_COUNT; type++)  	{  		LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); @@ -734,6 +729,17 @@ void LLVOAvatarSelf::idleUpdateAppearanceAnimation()  		}  	} +} + +/*virtual*/ +void LLVOAvatarSelf::idleUpdateAppearanceAnimation() +{ +	// Animate all top-level wearable visual parameters +	gAgentWearables.animateAllWearableParams(calcMorphAmount()); + +	// Apply wearable visual params to avatar +	writeWearablesToAvatar(); +  	//allow avatar to process updates  	LLVOAvatar::idleUpdateAppearanceAnimation(); @@ -1093,9 +1099,19 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id)  	return NULL;  } -const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id) const +bool LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const  { +	if (!gInventory.getItem(inv_item_id)) +	{ +		name = "ATTACHMENT_MISSING_ITEM"; +		return false; +	}  	const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); +	if (!gInventory.getItem(base_inv_item_id)) +	{ +		name = "ATTACHMENT_MISSING_BASE_ITEM"; +		return false; +	}  	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();   		 iter != mAttachmentPoints.end();   		 ++iter) @@ -1103,11 +1119,13 @@ const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id  		const LLViewerJointAttachment* attachment = iter->second;  		if (attachment->getAttachedObject(base_inv_item_id))  		{ -			return attachment->getName(); +			name = attachment->getName(); +			return true;  		}  	} -	return LLStringUtil::null; +	name = "ATTACHMENT_NOT_ATTACHED"; +	return false;  }  //virtual @@ -1142,8 +1160,6 @@ BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)  	const LLUUID attachment_id = viewer_object->getAttachmentItemID();  	if ( LLVOAvatar::detachObject(viewer_object) )  	{ -		LLVOAvatar::cleanupAttachedMesh( viewer_object ); -		  		// the simulator should automatically handle permission revocation  		stopMotionFromSource(attachment_id); diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index e03de9fa0b..13ffc057b0 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -86,12 +86,11 @@ public:  	/*virtual*/ void 		requestStopMotion(LLMotion* motion);  	/*virtual*/ LLJoint*	getJoint(const std::string &name); -				void		resetJointPositions( void ); -	  	/*virtual*/ BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight);  	/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight);  	/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight);  	/*virtual*/ void updateVisualParams(); +	void writeWearablesToAvatar();  	/*virtual*/ void idleUpdateAppearanceAnimation();  private: @@ -293,7 +292,7 @@ public:  	void				addAttachmentRequest(const LLUUID& inv_item_id);  	void				removeAttachmentRequest(const LLUUID& inv_item_id);  	LLViewerObject* 	getWornAttachment(const LLUUID& inv_item_id); -	const std::string   getAttachedPointName(const LLUUID& inv_item_id) const; +	bool				getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const;  	/*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);  	/*virtual*/ BOOL 	detachObject(LLViewerObject *viewer_object);  	static BOOL			detachAttachmentIntoInventory(const LLUUID& item_id); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9d16ce5a7b..66ee386874 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4528,7 +4528,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	//Determine if we've received skininfo that contains an  	//alternate bind matrix - if it does then apply the translational component  	//to the joints of the avatar. +#if 0  	bool pelvisGotSet = false; +#endif  	{  		LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_FACE_LIST); @@ -4613,54 +4615,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					//get drawpool of avatar with rigged face  					LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);				 +					// FIXME should this be inside the face loop? +					// doesn't seem to depend on any per-face state.  					if ( pAvatarVO )  					{ -						LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						 -						const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); -						if ( pSkinData ) -						{ -							const int bindCnt = pSkinData->mAlternateBindMatrix.size();								 -							if ( bindCnt > 0 ) -							{					 -								const int jointCnt = pSkinData->mJointNames.size(); -								const F32 pelvisZOffset = pSkinData->mPelvisOffset; -								bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;								 -								if ( fullRig ) -								{								 -									for ( int i=0; i<jointCnt; ++i ) -									{ -										std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); -										LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); -										if ( pJoint && pJoint->getId() != currentId ) -										{   									 -											pJoint->setId( currentId ); -											const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();									 -											 -											//Set the joint position -											const std::string& attachment_name = drawablep->getVObj()->getAttachmentItemName();				 -											pJoint->addAttachmentPosOverride( jointPos, attachment_name ); -									 -											//If joint is a pelvis then handle old/new pelvis to foot values -											if ( lookingForJoint == "mPelvis" ) -											{	 -												if ( !pAvatarVO->hasPelvisOffset() ) -												{										 -													pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); -													pelvisGotSet = true;											 -												}										 -											}										 -										}										 -									}																 -								}							 -							} -						} +						pAvatarVO->addAttachmentPosOverridesForObject(vobj);  					} -					 -					//Rebuild body data if we altered joints/pelvis -					if ( pelvisGotSet && pAvatarVO )  -					{ -						pAvatarVO->postPelvisSetRecalc(); -					}		  					if (pool)  					{ @@ -5018,14 +4978,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  			}  		} - -		 -		 -			 -		 -					 - -		  	}  	group->mBufferUsage = useage; diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index ca60b79f9d..fac0fd63ee 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -364,8 +364,14 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name,  	LLViewerInventoryItem* inv_item = getItem();  	if (inv_item && isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(inv_item->getLinkedUUID()))  	{ -		std::string joint = LLTrans::getString(gAgentAvatarp->getAttachedPointName(inv_item->getLinkedUUID())); -		title_joint =  title_joint + " (" + joint + ")"; +		std::string found_name; +		bool found = gAgentAvatarp->getAttachedPointName(inv_item->getLinkedUUID(),found_name); +		std::string trans_name = LLTrans::getString(found_name); +		if (!found) +		{ +			LL_WARNS() << "invalid attachment joint, err " << found_name << LL_ENDL; +		} +		title_joint =  title_joint + " (" + trans_name + ")";  	}  	LLPanelInventoryListItemBase::updateItem(title_joint, item_state); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 5dcb8e2cdf..945a77c071 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2307,6 +2307,7 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors.  	<string name="LoadingContents">Loading contents...</string>  	<string name="NoContents">No contents</string>  	<string name="WornOnAttachmentPoint" value=" (worn on [ATTACHMENT_POINT])" /> +	<string name="AttachmentErrorMessage" value=" ([ATTACHMENT_ERROR])" />  	<string name="ActiveGesture" value="[GESLABEL] (active)"/>  	<!-- Inventory permissions -->  	<string name="PermYes">Yes</string> @@ -2433,9 +2434,12 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors.  	<string name="Stomach">Stomach</string>  	<string name="Left Pec">Left Pec</string>  	<string name="Right Pec">Right Pec</string> -    <string name="Neck">Neck</string> -    <string name="Avatar Center">Avatar Center</string> +        <string name="Neck">Neck</string> +        <string name="Avatar Center">Avatar Center</string>  	<string name="Invalid Attachment">Invalid Attachment Point</string> +	<string name="ATTACHMENT_MISSING_ITEM">Error: missing item</string> +	<string name="ATTACHMENT_MISSING_BASE_ITEM">Error: missing base item</string> +	<string name="ATTACHMENT_NOT_ATTACHED">Error: object is in current outfit but not attached</string>    <!-- Avatar age computation, see LLDateUtil::ageFromDate -->    <string name="YearsMonthsOld">[AGEYEARS] [AGEMONTHS] old</string> | 
