diff options
| author | andreykproductengine <akleshchev@productengine.com> | 2015-07-15 16:06:55 +0300 | 
|---|---|---|
| committer | andreykproductengine <akleshchev@productengine.com> | 2015-07-15 16:06:55 +0300 | 
| commit | d092e375fdc3d69028dd1ce246acd8e9541303b9 (patch) | |
| tree | d86168d47ea3baa5e98b9d7060837fb3c5005211 | |
| parent | 2684c536906388da121ce2712a34d55aa786fa3f (diff) | |
| parent | 02441157a0d22619ccf2a2ee735c8f5251b54fdb (diff) | |
Merge downstream code and become version 3.8.2
| -rwxr-xr-x | .hgtags | 1 | ||||
| -rwxr-xr-x | indra/llcommon/llerror.cpp | 16 | ||||
| -rw-r--r-- | indra/newview/VIEWER_VERSION.txt | 2 | ||||
| -rwxr-xr-x | indra/newview/llagentwearables.cpp | 57 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.cpp | 195 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.h | 14 | ||||
| -rwxr-xr-x | indra/newview/llattachmentsmgr.cpp | 442 | ||||
| -rwxr-xr-x | indra/newview/llattachmentsmgr.h | 105 | ||||
| -rwxr-xr-x | indra/newview/llgesturemgr.cpp | 32 | ||||
| -rwxr-xr-x | indra/newview/llinventorybridge.cpp | 32 | ||||
| -rwxr-xr-x | indra/newview/llinventorybridge.h | 6 | ||||
| -rwxr-xr-x | indra/newview/llinventoryfunctions.cpp | 35 | ||||
| -rwxr-xr-x | indra/newview/llselectmgr.cpp | 68 | ||||
| -rwxr-xr-x | indra/newview/llselectmgr.h | 4 | ||||
| -rwxr-xr-x | indra/newview/llviewerinventory.cpp | 2 | ||||
| -rwxr-xr-x | indra/newview/llviewermenu.cpp | 2 | ||||
| -rwxr-xr-x | indra/newview/llviewerobject.cpp | 5 | ||||
| -rwxr-xr-x | indra/newview/llviewerobjectlist.cpp | 12 | ||||
| -rwxr-xr-x | indra/newview/llvoavatar.cpp | 30 | ||||
| -rwxr-xr-x | indra/newview/llvoavatarself.cpp | 41 | ||||
| -rwxr-xr-x | indra/newview/llvoavatarself.h | 7 | ||||
| -rwxr-xr-x | indra/newview/llwearableitemslist.cpp | 2 | 
22 files changed, 812 insertions, 298 deletions
| @@ -504,3 +504,4 @@ afd8d4756e8eda3c8f760625d1c17a2ad40ad6c8 3.7.27-release  d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release  67edc442c80b8d2fadd2a6c4a7184b469906cdbf 3.7.30-release  797ed69e6134ef48bb922577ab2540fb2d964668 3.8.0-release +3f61ed662347dc7c6941b8266e72746a66d90e2a 3.8.1-release diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 2100989316..5ed348e13c 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -119,6 +119,7 @@ namespace {  				LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;  			}  			mWantsTime = true; +            mWantsTags = true;  		}  		~RecordToFile() @@ -558,7 +559,7 @@ namespace LLError  		mFunctionString += std::string(mFunction) + ":";  		for (size_t i = 0; i < mTagCount; i++)  		{ -			mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " "); +			mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : ",");  		}  	} @@ -931,14 +932,19 @@ namespace  			}  			if (show_level && r->wantsLevel()) -				{ -				message_stream << site.mLevelString << " "; -				} +            { +				message_stream << site.mLevelString; +            }  			if (show_tags && r->wantsTags())  			{ -				message_stream << site.mTagString << " "; +				message_stream << site.mTagString;  			} +			if ((show_level && r->wantsLevel())|| +                (show_tags && r->wantsTags())) +            { +                message_stream << " "; +            }  			if (show_function && r->wantsFunctionName())  			{ diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index f280719674..a08ffae0ca 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.8.1 +3.8.2 diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 13b16f5218..cce1eb5895 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -27,6 +27,7 @@  #include "llviewerprecompiledheaders.h"  #include "llagentwearables.h" +#include "llattachmentsmgr.h"  #include "llaccordionctrltab.h"  #include "llagent.h"  #include "llagentcamera.h" @@ -1370,6 +1371,7 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo  	if (objects_to_remove.empty())  		return; +	LL_DEBUGS("Avatar") << "ATT [ObjectDetach] removing " << objects_to_remove.size() << " objects" << LL_ENDL;  	gMessageSystem->newMessage("ObjectDetach");  	gMessageSystem->nextBlockFast(_PREHASH_AgentData);  	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -1383,6 +1385,10 @@ void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remo  		//gAgentAvatarp->resetJointPositionsOnDetach(objectp);  		gMessageSystem->nextBlockFast(_PREHASH_ObjectData);  		gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); +		const LLUUID& item_id = objectp->getAttachmentItemID(); +		LLViewerInventoryItem *item = gInventory.getItem(item_id); +		LL_DEBUGS("Avatar") << "ATT removing object, item is " << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; +        LLAttachmentsMgr::instance().onDetachRequested(item_id);  	}  	gMessageSystem->sendReliable(gAgent.getRegionHost());  } @@ -1391,51 +1397,18 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra  {  	// Build a compound message to send all the objects that need to be rezzed.  	S32 obj_count = obj_item_array.size(); - -	// Limit number of packets to send -	const S32 MAX_PACKETS_TO_SEND = 10; -	const S32 OBJECTS_PER_PACKET = 4; -	const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET; -	if( obj_count > MAX_OBJECTS_TO_SEND ) +	if (obj_count > 0)  	{ -		obj_count = MAX_OBJECTS_TO_SEND; +		LL_DEBUGS("Avatar") << "ATT attaching multiple, total obj_count " << obj_count << LL_ENDL;  	} -				 -	// Create an id to keep the parts of the compound message together -	LLUUID compound_msg_id; -	compound_msg_id.generate(); -	LLMessageSystem* msg = gMessageSystem; - -	for(S32 i = 0; i < obj_count; ++i) -	{ -		if( 0 == (i % OBJECTS_PER_PACKET) ) -		{ -			// Start a new message chunk -			msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv); -			msg->nextBlockFast(_PREHASH_AgentData); -			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -			msg->nextBlockFast(_PREHASH_HeaderData); -			msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); -			msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); -			msg->addBOOLFast(_PREHASH_FirstDetachAll, false ); -		} -		const LLInventoryItem* item = obj_item_array.at(i).get(); -		msg->nextBlockFast(_PREHASH_ObjectData ); -		msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); -		msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); -		msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD);	// Wear at the previous or default attachment point -		pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); -		msg->addStringFast(_PREHASH_Name, item->getName()); -		msg->addStringFast(_PREHASH_Description, item->getDescription()); - -		if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) ) -		{ -			// End of message chunk -			msg->sendReliable( gAgent.getRegion()->getHost() ); -		} -	} +    for(LLInventoryModel::item_array_t::const_iterator it = obj_item_array.begin(); +        it != obj_item_array.end(); +        ++it) +    { +		const LLInventoryItem* item = *it; +        LLAttachmentsMgr::instance().addAttachmentRequest(item->getLinkedUUID(), 0, TRUE); +    }  }  // Returns false if the given wearable is already topmost/bottommost diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8200f0ba07..35593dd4ff 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -525,6 +525,15 @@ LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnD  {  } +LLRequestServerAppearanceUpdateOnDestroy::~LLRequestServerAppearanceUpdateOnDestroy() +{ +	LL_DEBUGS("Avatar") << "ATT requesting server appearance update" << LL_ENDL; +    if (!LLApp::isExiting()) +    { +        LLAppearanceMgr::instance().requestServerAppearanceUpdate(); +    } +} +  void edit_wearable_and_customize_avatar(LLUUID item_id)  {  	// Start editing the item if previously requested. @@ -828,6 +837,12 @@ void LLWearableHoldingPattern::onAllComplete()  		// pre-attachment states.  		gAgentAvatarp->clearAttachmentPosOverrides(); +		if (objects_to_remove.size() || items_to_add.size()) +		{ +			LL_DEBUGS("Avatar") << "ATT will remove " << objects_to_remove.size() +								<< " and add " << items_to_add.size() << " items" << LL_ENDL; +		} +  		// Take off the attachments that will no longer be in the outfit.  		LLAgentWearables::userRemoveMultipleAttachments(objects_to_remove); @@ -1356,28 +1371,46 @@ void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,          const LLUUID& item_id_to_wear = *it; -        if (item_id_to_wear.isNull()) continue; +        if (item_id_to_wear.isNull()) +        { +            LL_DEBUGS("Avatar") << "null id " << item_id_to_wear << LL_ENDL; +            continue; +        }          LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); -        if (!item_to_wear) continue; +        if (!item_to_wear) +        { +            LL_DEBUGS("Avatar") << "inventory item not found for id " << item_id_to_wear << LL_ENDL; +            continue; +        }          if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))          { +            LL_DEBUGS("Avatar") << "inventory item in library, will copy and wear " +                                << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL;              LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace)); -            copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb); +            copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), +                                item_to_wear->getUUID(), LLUUID::null, std::string(), cb);              continue;          }           else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))          { -            continue; // not in library and not in agent's inventory +			// not in library and not in agent's inventory +            LL_DEBUGS("Avatar") << "inventory item not in user inventory or library, skipping " +                                << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL; +            continue;           }          else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))          {              LLNotificationsUtil::add("CannotWearTrash"); +            LL_DEBUGS("Avatar") << "inventory item is in trash, skipping " +                                << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL;              continue;          }          else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911          { +            LL_DEBUGS("Avatar") << "inventory item is already in COF, skipping " +                                << item_to_wear->getName() << " id " << item_id_to_wear << LL_ENDL;              continue;          } @@ -2717,28 +2750,23 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,  LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id)  { -  	LLInventoryModel::item_array_t result; -	const LLViewerInventoryItem *vitem = -		dynamic_cast<const LLViewerInventoryItem*>(gInventory.getItem(item_id)); -	if (vitem) -	{ -		LLInventoryModel::cat_array_t cat_array; -		LLInventoryModel::item_array_t item_array; -		gInventory.collectDescendents(LLAppearanceMgr::getCOF(), -									  cat_array, -									  item_array, -									  LLInventoryModel::EXCLUDE_TRASH); -		for (S32 i=0; i<item_array.size(); i++) -		{ -			const LLViewerInventoryItem* inv_item = item_array.at(i).get(); -			if (inv_item->getLinkedUUID() == vitem->getLinkedUUID()) -			{ -				result.push_back(item_array.at(i)); -			} -		} -	} +    LLUUID linked_id = gInventory.getLinkedItemID(item_id); +    LLInventoryModel::cat_array_t cat_array; +    LLInventoryModel::item_array_t item_array; +    gInventory.collectDescendents(LLAppearanceMgr::getCOF(), +                                  cat_array, +                                  item_array, +                                  LLInventoryModel::EXCLUDE_TRASH); +    for (S32 i=0; i<item_array.size(); i++) +    { +        const LLViewerInventoryItem* inv_item = item_array.at(i).get(); +        if (inv_item->getLinkedUUID() == linked_id) +        { +            result.push_back(item_array.at(i)); +        } +    }  	return result;  } @@ -3315,7 +3343,7 @@ void RequestAgentUpdateAppearanceResponder::onRequestRequested()  	}  	// Actually send the request. -	LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL; +	LL_DEBUGS("Avatar") << "ATT sending bake request for cof_version " << cof_version << LL_ENDL;  	mRetryPolicy->reset();  	sendRequest();  } @@ -3788,6 +3816,11 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)  	{  		const LLUUID& id_to_remove = *it;  		const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove); +		LLViewerInventoryItem *item = gInventory.getItem(linked_item_id); +		if (item && item->getType() == LLAssetType::AT_OBJECT) +		{ +			LL_DEBUGS("Avatar") << "ATT removing attachment " << item->getName() << " id " << item->getUUID() << LL_ENDL; +		}  		removeCOFItemLinks(linked_item_id, cb);  		addDoomedTempAttachment(linked_item_id);  	} @@ -3795,10 +3828,9 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)  void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)  { -	LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove); -	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy; -	removeCOFItemLinks(linked_item_id, cb); -	addDoomedTempAttachment(linked_item_id); +	uuid_vec_t ids_to_remove; +	ids_to_remove.push_back(id_to_remove); +	removeItemsFromAvatar(ids_to_remove);  } @@ -3983,37 +4015,32 @@ void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)  void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)  { -	   gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - -	   if (mAttachmentInvLinkEnabled) -	   { -		   // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. -		   // it will trigger gAgentWariables.notifyLoadingFinished() -		   // But it is not acceptable solution. See EXT-7777 -		   if (!isLinkedInCOF(item_id)) -		   { -			   LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(); -			   LLAppearanceMgr::addCOFItemLink(item_id, cb);  // Add COF link for item. -		   } -	   } -	   else -	   { -		   //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; -	   } +	LLViewerInventoryItem *item = gInventory.getItem(item_id); +	LL_DEBUGS("Avatar") << "ATT registering attachment " +						<< (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; +	gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + +	LLAttachmentsMgr::instance().onAttachmentArrived(item_id);  }  void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)  { -	   gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); +	LLViewerInventoryItem *item = gInventory.getItem(item_id); +	LL_DEBUGS("Avatar") << "ATT unregistering attachment " +						<< (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; +	gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); -	   if (mAttachmentInvLinkEnabled) -	   { -		   LLAppearanceMgr::removeCOFItemLinks(item_id); -	   } -	   else -	   { -		   //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; -	   } +    LLAttachmentsMgr::instance().onDetachCompleted(item_id); +	if (mAttachmentInvLinkEnabled && isLinkedInCOF(item_id)) +	{ +		LL_DEBUGS("Avatar") << "ATT removing COF link for attachment " +							<< (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; +		LLAppearanceMgr::removeCOFItemLinks(item_id); +	} +	else +	{ +		//LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; +	}  }  BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const @@ -4027,14 +4054,6 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const  	return FALSE;  } -// static -bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) -{ -	const LLUUID& target_id = gInventory.getLinkedItemID(obj_id); -	LLLinkedItemIDMatches find_links(target_id); -	return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links); -} -  BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const  {  	if (!getIsInCOF(obj_id)) return FALSE; @@ -4153,10 +4172,56 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb)  	}  } +void add_wearable_type_counts(const uuid_vec_t& ids, +                              S32& clothing_count, +                              S32& bodypart_count, +                              S32& object_count, +                              S32& other_count) +{ +    for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) +    { +        const LLUUID& item_id_to_wear = *it; +        LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); +        if (item_to_wear) +        { +            if (item_to_wear->getType() == LLAssetType::AT_CLOTHING) +            { +                clothing_count++; +            } +            else if (item_to_wear->getType() == LLAssetType::AT_BODYPART) +            { +                bodypart_count++; +            } +            else if (item_to_wear->getType() == LLAssetType::AT_OBJECT) +            { +                object_count++; +            } +            else +            { +                other_count++; +            } +        } +        else +        { +            other_count++; +        } +    } +} +  void wear_multiple(const uuid_vec_t& ids, bool replace)  { -	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy; -    LLAppearanceMgr::instance().wearItemsOnAvatar(ids, false, replace, cb); +    S32 clothing_count = 0; +    S32 bodypart_count = 0; +    S32 object_count = 0; +    S32 other_count = 0; +    add_wearable_type_counts(ids, clothing_count, bodypart_count, object_count, other_count); + +    LLPointer<LLInventoryCallback> cb = NULL; +    if (clothing_count > 0 || bodypart_count > 0) +    { +        cb = new LLUpdateAppearanceOnDestroy; +    } +	LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, replace, cb);  }  // SLapp for easy-wearing of a stock (library) avatar diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index ee9d3b7209..4ed8c1bfb9 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -284,11 +284,6 @@ public:  	BOOL getIsInCOF(const LLUUID& obj_id) const;  	// Is this in the COF and can the user delete it from the COF?  	BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; - -	/** -	 * Checks if COF contains link to specified object. -	 */ -	static bool isLinkInCOF(const LLUUID& obj_id);  };  class LLUpdateAppearanceOnDestroy: public LLInventoryCallback @@ -320,6 +315,15 @@ private:  	LLUUID mItemID;  }; +class LLRequestServerAppearanceUpdateOnDestroy: public LLInventoryCallback +{ +public: +	LLRequestServerAppearanceUpdateOnDestroy() {} +	~LLRequestServerAppearanceUpdateOnDestroy(); + +	/* virtual */ void fire(const LLUUID& item_id) {} +}; +  LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);  // Invoke a given callable after category contents are fully fetched. diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index 256980eb04..2a137cc39b 100755 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -27,15 +27,24 @@  #include "llviewerprecompiledheaders.h"  #include "llattachmentsmgr.h" +#include "llvoavatarself.h"  #include "llagent.h" +#include "llappearancemgr.h"  #include "llinventorymodel.h"  #include "lltooldraganddrop.h" // pack_permissions_slam  #include "llviewerinventory.h"  #include "llviewerregion.h"  #include "message.h" +const F32 COF_LINK_BATCH_TIME = 5.0F; +const F32 MAX_ATTACHMENT_REQUEST_LIFETIME = 30.0F; +const F32 MIN_RETRY_REQUEST_TIME = 5.0F; +const F32 MAX_BAD_COF_TIME = 30.0F; -LLAttachmentsMgr::LLAttachmentsMgr() +LLAttachmentsMgr::LLAttachmentsMgr(): +    mAttachmentRequests("attach",MIN_RETRY_REQUEST_TIME), +    mDetachRequests("detach",MIN_RETRY_REQUEST_TIME), +    mQuestionableCOFLinks("badcof",MAX_BAD_COF_TIME)  {  } @@ -43,15 +52,37 @@ LLAttachmentsMgr::~LLAttachmentsMgr()  {  } -void LLAttachmentsMgr::addAttachment(const LLUUID& item_id, -									 const U8 attachment_pt, -									 const BOOL add) +void LLAttachmentsMgr::addAttachmentRequest(const LLUUID& item_id, +                                            const U8 attachment_pt, +                                            const BOOL add)  { +	LLViewerInventoryItem *item = gInventory.getItem(item_id); + +    if (mAttachmentRequests.wasRequestedRecently(item_id)) +    { +        LL_DEBUGS("Avatar") << "ATT not adding attachment to mPendingAttachments, recent request is already pending: " +                            << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +        return; +    } + +	LL_DEBUGS("Avatar") << "ATT adding attachment to mPendingAttachments " +						<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +  	AttachmentsInfo attachment;  	attachment.mItemID = item_id;  	attachment.mAttachmentPt = attachment_pt;  	attachment.mAdd = add;  	mPendingAttachments.push_back(attachment); + +    mAttachmentRequests.addTime(item_id); +} + +void LLAttachmentsMgr::onAttachmentRequested(const LLUUID& item_id) +{ +	LLViewerInventoryItem *item = gInventory.getItem(item_id); +	LL_DEBUGS("Avatar") << "ATT attachment was requested " +						<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +    mAttachmentRequests.addTime(item_id);  }  // static @@ -68,31 +99,79 @@ void LLAttachmentsMgr::onIdle()  		return;  	} -	S32 obj_count = mPendingAttachments.size(); +    if (LLApp::isExiting()) +    { +        return; +    } + +	requestPendingAttachments(); + +    linkRecentlyArrivedAttachments(); + +    expireOldAttachmentRequests(); + +    expireOldDetachRequests(); + +    checkInvalidCOFLinks(); +     +    spamStatusInfo(); +} + +void LLAttachmentsMgr::requestPendingAttachments() +{ +	if (mPendingAttachments.size()) +	{ +		requestAttachments(mPendingAttachments); +	} +} + +// Send request(s) for a group of attachments. As coded, this can +// request at most 40 attachments and the rest will be +// ignored. Currently the max attachments per avatar is 38, so the 40 +// limit should not be hit in practice. +void LLAttachmentsMgr::requestAttachments(attachments_vec_t& attachment_requests) +{ +	// Make sure we got a region before trying anything else +	if( !gAgent.getRegion() ) +	{ +		return; +	} + +    // For unknown reasons, requesting many attachments at once causes +    // frequent server-side failures. Here we're limiting the number +    // of attachments requested per idle loop. +    const S32 max_objects_per_request = 5; +	S32 obj_count = llmin((S32)attachment_requests.size(),max_objects_per_request);  	if (obj_count == 0)  	{  		return;  	} -	 +  	// Limit number of packets to send  	const S32 MAX_PACKETS_TO_SEND = 10;  	const S32 OBJECTS_PER_PACKET = 4;  	const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;  	if( obj_count > MAX_OBJECTS_TO_SEND )  	{ +        LL_WARNS() << "ATT Too many attachments requested: " << obj_count +                   << " exceeds limit of " << MAX_OBJECTS_TO_SEND << LL_ENDL; +  		obj_count = MAX_OBJECTS_TO_SEND;  	} +	LL_DEBUGS("Avatar") << "ATT [RezMultipleAttachmentsFromInv] attaching multiple from attachment_requests," +		" total obj_count " << obj_count << LL_ENDL; +  	LLUUID compound_msg_id;  	compound_msg_id.generate();  	LLMessageSystem* msg = gMessageSystem; -	 -	S32 i = 0; -	for (attachments_vec_t::const_iterator iter = mPendingAttachments.begin(); -		 iter != mPendingAttachments.end(); -		 ++iter) -	{ +    // by construction above, obj_count <= attachment_requests.size(), so no +    // check against attachment_requests.empty() is needed. +    llassert(obj_count <= attachment_requests.size()); + +    for (S32 i=0; i<obj_count; i++) +    {  		if( 0 == (i % OBJECTS_PER_PACKET) )  		{  			// Start a new message chunk @@ -106,32 +185,337 @@ void LLAttachmentsMgr::onIdle()  			msg->addBOOLFast(_PREHASH_FirstDetachAll, false );  		} -		const AttachmentsInfo &attachment = (*iter); +		const AttachmentsInfo& attachment = attachment_requests.front();  		LLViewerInventoryItem* item = gInventory.getItem(attachment.mItemID); -		if (!item) +		if (item) +        { +            LL_DEBUGS("Avatar") << "ATT requesting from attachment_requests " << item->getName() +                                << " " << item->getLinkedUUID() << LL_ENDL; +            S32 attachment_pt = attachment.mAttachmentPt; +            if (attachment.mAdd)  +                attachment_pt |= ATTACHMENT_ADD; +             +            msg->nextBlockFast(_PREHASH_ObjectData ); +            msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); +            msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); +            msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); +            pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); +            msg->addStringFast(_PREHASH_Name, item->getName()); +            msg->addStringFast(_PREHASH_Description, item->getDescription()); +        } +        else  		{ -			LL_INFOS() << "Attempted to add non-existant item ID:" << attachment.mItemID << LL_ENDL; -			continue; +			LL_WARNS("Avatar") << "ATT Attempted to add non-existent item ID:" << attachment.mItemID << LL_ENDL;  		} -		S32 attachment_pt = attachment.mAttachmentPt; -		if (attachment.mAdd)  -			attachment_pt |= ATTACHMENT_ADD; - -		msg->nextBlockFast(_PREHASH_ObjectData ); -		msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); -		msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); -		msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); -		pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); -		msg->addStringFast(_PREHASH_Name, item->getName()); -		msg->addStringFast(_PREHASH_Description, item->getDescription());  		if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )  		{  			// End of message chunk  			msg->sendReliable( gAgent.getRegion()->getHost() );  		} -		i++; +        attachment_requests.pop_front();  	} +} + +void LLAttachmentsMgr::linkRecentlyArrivedAttachments() +{ +    if (mRecentlyArrivedAttachments.size()) +    { +        // One or more attachments have arrived but have not yet been +        // processed for COF links +        if (mAttachmentRequests.empty()) +        { +            // Not waiting for any more. +            LL_DEBUGS("Avatar") << "ATT all pending attachments have arrived after " +                                << mCOFLinkBatchTimer.getElapsedTimeF32() << " seconds" << LL_ENDL; +        } +        else if (mCOFLinkBatchTimer.getElapsedTimeF32() > COF_LINK_BATCH_TIME) +        { +            LL_DEBUGS("Avatar") << "ATT " << mAttachmentRequests.size() +                                << " pending attachments have not arrived, but wait time exceeded" << LL_ENDL; +        } +        else +        { +            return; +        } + +        LL_DEBUGS("Avatar") << "ATT checking COF linkability for " << mRecentlyArrivedAttachments.size() +                            << " recently arrived items" << LL_ENDL; + +        uuid_vec_t ids_to_link; +        for (std::set<LLUUID>::iterator it = mRecentlyArrivedAttachments.begin(); +             it != mRecentlyArrivedAttachments.end(); ++it) +        { +            if (isAgentAvatarValid() && +                gAgentAvatarp->isWearingAttachment(*it) && +                !LLAppearanceMgr::instance().isLinkedInCOF(*it)) +            { +                LLUUID item_id = *it; +                LLViewerInventoryItem *item = gInventory.getItem(item_id); +                LL_DEBUGS("Avatar") << "ATT adding COF link for attachment " +                                    << (item ? item->getName() : "UNKNOWN") << " " << item_id << LL_ENDL; +                ids_to_link.push_back(item_id); +            } +        } +        if (ids_to_link.size()) +        { +            LLPointer<LLInventoryCallback> cb = new LLRequestServerAppearanceUpdateOnDestroy(); +            for (uuid_vec_t::const_iterator uuid_it = ids_to_link.begin(); +                 uuid_it != ids_to_link.end(); ++uuid_it) +            { +                LLAppearanceMgr::instance().addCOFItemLink(*uuid_it, cb); +            } +        } +        mRecentlyArrivedAttachments.clear(); +    } +} + +LLAttachmentsMgr::LLItemRequestTimes::LLItemRequestTimes(const std::string& op_name, F32 timeout): +    mOpName(op_name), +    mTimeout(timeout) +{ +} + +void LLAttachmentsMgr::LLItemRequestTimes::addTime(const LLUUID& inv_item_id) +{ +    LLInventoryItem *item = gInventory.getItem(inv_item_id); +    LL_DEBUGS("Avatar") << "ATT " << mOpName << " adding request time " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; +	LLTimer current_time; +	(*this)[inv_item_id] = current_time; +} + +void LLAttachmentsMgr::LLItemRequestTimes::removeTime(const LLUUID& inv_item_id) +{ +    LLInventoryItem *item = gInventory.getItem(inv_item_id); +	S32 remove_count = (*this).erase(inv_item_id); +    if (remove_count) +    { +        LL_DEBUGS("Avatar") << "ATT " << mOpName << " removing request time " +                            << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; +    } +} + +BOOL LLAttachmentsMgr::LLItemRequestTimes::getTime(const LLUUID& inv_item_id, LLTimer& timer) const +{ +	std::map<LLUUID,LLTimer>::const_iterator it = (*this).find(inv_item_id); +	if (it != (*this).end()) +	{ +        timer = it->second; +        return TRUE; +    } +    return FALSE; +} + +BOOL LLAttachmentsMgr::LLItemRequestTimes::wasRequestedRecently(const LLUUID& inv_item_id) const +{ +    LLTimer request_time; +    if (getTime(inv_item_id, request_time)) +    { +		F32 request_time_elapsed = request_time.getElapsedTimeF32(); +        return request_time_elapsed < mTimeout; +    } +    else +    { +        return FALSE; +    } +} + +// If we've been waiting for an attachment a long time, we want to +// forget the request, because if the request is invalid (say the +// object does not exist), the existence of a request that never goes +// away will gum up the COF batch logic, causing it to always wait for +// the timeout. Expiring a request means if the item does show up +// late, the COF link request may not get properly batched up, but +// behavior will be no worse than before we had the batching mechanism +// in place; the COF link will still be created, but extra +// requestServerAppearanceUpdate() calls may occur. +void LLAttachmentsMgr::expireOldAttachmentRequests() +{ +	for (std::map<LLUUID,LLTimer>::iterator it = mAttachmentRequests.begin(); +         it != mAttachmentRequests.end(); ) +    { +        std::map<LLUUID,LLTimer>::iterator curr_it = it; +        ++it; +        if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME) +        { +            LLInventoryItem *item = gInventory.getItem(curr_it->first); +            LL_WARNS("Avatar") << "ATT expiring request for attachment " +                                << (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first +                                << " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL; +            mAttachmentRequests.erase(curr_it); +        } +    } +} + +void LLAttachmentsMgr::expireOldDetachRequests() +{ +	for (std::map<LLUUID,LLTimer>::iterator it = mDetachRequests.begin(); +         it != mDetachRequests.end(); ) +    { +        std::map<LLUUID,LLTimer>::iterator curr_it = it; +        ++it; +        if (curr_it->second.getElapsedTimeF32() > MAX_ATTACHMENT_REQUEST_LIFETIME) +        { +            LLInventoryItem *item = gInventory.getItem(curr_it->first); +            LL_WARNS("Avatar") << "ATT expiring request for detach " +                                << (item ? item->getName() : "UNKNOWN") << " item_id " << curr_it->first +                                << " after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds" << LL_ENDL; +            mDetachRequests.erase(curr_it); +        } +    } +} + +// When an attachment arrives, we want to stop waiting for it, and add +// it to the set of recently arrived items. +void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id) +{ +    LLTimer timer; +    bool expected = mAttachmentRequests.getTime(inv_item_id, timer); +    if (!expected) +    { +        LLInventoryItem *item = gInventory.getItem(inv_item_id); +        LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: " +                   << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; +    } +    mAttachmentRequests.removeTime(inv_item_id); +    if (expected && mAttachmentRequests.empty()) +    { +        // mAttachmentRequests just emptied out +        LL_DEBUGS("Avatar") << "ATT all active attachment requests have completed" << LL_ENDL; +    } +    if (mRecentlyArrivedAttachments.empty()) +    { +        // Start the timer for sending off a COF link batch. +        mCOFLinkBatchTimer.reset(); +    } +    mRecentlyArrivedAttachments.insert(inv_item_id); +} + +void LLAttachmentsMgr::onDetachRequested(const LLUUID& inv_item_id) +{ +    mDetachRequests.addTime(inv_item_id); +} + +void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id) +{ +    LLTimer timer; +    LLInventoryItem *item = gInventory.getItem(inv_item_id); +    if (mDetachRequests.getTime(inv_item_id, timer)) +    { +        LL_DEBUGS("Avatar") << "ATT detach completed after " << timer.getElapsedTimeF32() +                            << " seconds for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; +        mDetachRequests.removeTime(inv_item_id); +        if (mDetachRequests.empty()) +        { +            LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL; +        } +    } +    else +    { +        LL_WARNS() << "ATT unexpected detach for " +                   << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; +    } + +    LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking " +                        << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; +    mQuestionableCOFLinks.addTime(inv_item_id); +} + +// Check for attachments that are (a) linked in COF and (b) not +// attached to the avatar.  This is a rotten function to have to +// include, because it runs the risk of either repeatedly spamming out +// COF link removals if they're failing for some reason, or getting +// into a tug of war with some other sequence of events that's in the +// process of adding the attachment in question. However, it's needed +// because we have no definitive source of authority for what things +// are actually supposed to be attached. Scripts, run on the server +// side, can remove an attachment without our expecting it. If this +// happens to an attachment that's just been added, then the COF link +// creation may still be in flight, and we will have to delete the +// link after it shows up. +// +// Note that we only flag items for possible link removal if they have +// been previously detached. This means that an attachment failure +// will leave the link in the COF, where it will hopefully resolve +// correctly on relog. +// +// See related: MAINT-5070, MAINT-4409 +// +void LLAttachmentsMgr::checkInvalidCOFLinks() +{ +        LLInventoryModel::cat_array_t cat_array; +        LLInventoryModel::item_array_t item_array; +        gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), +                                      cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); +        for (S32 i=0; i<item_array.size(); i++) +        { +            const LLViewerInventoryItem* inv_item = item_array.at(i).get(); +            const LLUUID& item_id = inv_item->getLinkedUUID(); +            if (inv_item->getType() == LLAssetType::AT_OBJECT) +            { +                LLTimer timer; +                bool is_flagged_questionable = mQuestionableCOFLinks.getTime(item_id,timer); +                bool is_wearing_attachment = isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item_id); +                if (is_wearing_attachment && is_flagged_questionable) +                { +                    LL_DEBUGS("Avatar") << "ATT was flagged questionable but is now "  +                                        << (is_wearing_attachment ? "attached " : "")  +                                        <<"removing flag after " +                                        << timer.getElapsedTimeF32() << " item " +                                        << inv_item->getName() << " id " << item_id << LL_ENDL; +                    mQuestionableCOFLinks.removeTime(item_id); +                } +            } +        } + +        for(LLItemRequestTimes::iterator it = mQuestionableCOFLinks.begin(); +            it != mQuestionableCOFLinks.end(); ) +        { +            LLItemRequestTimes::iterator curr_it = it; +            ++it; +            const LLUUID& item_id = curr_it->first; +            LLViewerInventoryItem *inv_item = gInventory.getItem(item_id); +            if (curr_it->second.getElapsedTimeF32() > MAX_BAD_COF_TIME) +            { +                if (LLAppearanceMgr::instance().isLinkedInCOF(item_id)) +                { +                    LL_DEBUGS("Avatar") << "ATT Linked in COF but not attached or requested, deleting link after " +                                        << curr_it->second.getElapsedTimeF32() << " seconds for "  +                                        << (inv_item ? inv_item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +                    LLAppearanceMgr::instance().removeCOFItemLinks(item_id); +                } +				mQuestionableCOFLinks.erase(curr_it); +                continue; +            } +        } +} + +void LLAttachmentsMgr::spamStatusInfo() +{ +#if 0 +    static LLTimer spam_timer; +    const F32 spam_frequency = 100.0F; -	mPendingAttachments.clear(); +    if (spam_timer.getElapsedTimeF32() > spam_frequency) +    { +        spam_timer.reset(); +         +        LLInventoryModel::cat_array_t cat_array; +        LLInventoryModel::item_array_t item_array; +        gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(), +                                      cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH); +        for (S32 i=0; i<item_array.size(); i++) +        { +            const LLViewerInventoryItem* inv_item = item_array.at(i).get(); +            if (inv_item->getType() == LLAssetType::AT_OBJECT) +            { +                LL_DEBUGS("Avatar") << "item_id: " << inv_item->getUUID() +                                    << " linked_item_id: " << inv_item->getLinkedUUID() +                                    << " name: " << inv_item->getName() +                                    << " parent: " << inv_item->getParentUUID() +                                    << LL_ENDL; +            } +        } +    } +#endif  } diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index 1d8ab74dfd..d56d6eb27b 100755 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -32,42 +32,101 @@  class LLViewerInventoryItem; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//--------------------------------------------------------------------------------  // LLAttachmentsMgr  //  -// The sole purpose of this class is to take attachment -// requests, queue them up, and send them all at once. -// This handles situations where the viewer may request -// a bunch of attachments at once in a short period of -// time, where each of the requests would normally be -// sent as a separate message versus being batched into -// one single message. -//  -// The intent of this batching is to reduce viewer->server -// traffic. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This class manages batching up of requests at two stages of +// attachment rezzing. +// +// First, attachments requested to rez get saved in +// mPendingAttachments and sent as a single +// RezMultipleAttachmentsFromInv request. This batching is needed +// mainly because of weaknessing the UI element->inventory item +// handling, such that we don't always know when we are requesting +// multiple items. Now they just pile up and get swept into a single +// request during the idle loop. +// +// Second, after attachments arrive, we need to generate COF links for +// them. There are both efficiency and UI correctness reasons why it +// is better to request all the COF links at once and run a single +// callback after they all complete. Given the vagaries of the +// attachment system, there is no guarantee that we will get all the +// attachments we ask for, but we frequently do. So in the common case +// that all the desired attachments arrive fairly quickly, we generate +// a single batched request for COF links. If attachments arrive late +// or not at all, we will still issue COF link requests once a timeout +// value has been exceeded. +// +// To handle attachments that never arrive, we forget about requests +// that exceed a timeout value. +//--------------------------------------------------------------------------------  class LLAttachmentsMgr: public LLSingleton<LLAttachmentsMgr>  {  public: -	LLAttachmentsMgr(); -	virtual ~LLAttachmentsMgr(); - -	void addAttachment(const LLUUID& item_id, -					   const U8 attachment_pt, -					   const BOOL add); -	static void onIdle(void *); -protected: -	void onIdle(); -private: +    // Stores info for attachments that will be requested during idle.  	struct AttachmentsInfo  	{  		LLUUID mItemID;  		U8 mAttachmentPt;  		BOOL mAdd;  	}; +	typedef std::deque<AttachmentsInfo> attachments_vec_t; + +	LLAttachmentsMgr(); +	virtual ~LLAttachmentsMgr(); + +	void addAttachmentRequest(const LLUUID& item_id, +                              const U8 attachment_pt, +                              const BOOL add); +    void onAttachmentRequested(const LLUUID& item_id); +	void requestAttachments(attachments_vec_t& attachment_requests); +	static void onIdle(void *); -	typedef std::vector<AttachmentsInfo> attachments_vec_t; +    void onAttachmentArrived(const LLUUID& inv_item_id); + +    void onDetachRequested(const LLUUID& inv_item_id); +    void onDetachCompleted(const LLUUID& inv_item_id); + +private: + +    class LLItemRequestTimes: public std::map<LLUUID,LLTimer> +    { +    public: +        LLItemRequestTimes(const std::string& op_name, F32 timeout); +        void addTime(const LLUUID& inv_item_id); +        void removeTime(const LLUUID& inv_item_id); +        BOOL wasRequestedRecently(const LLUUID& item_id) const; +        BOOL getTime(const LLUUID& inv_item_id, LLTimer& timer) const; + +    private: +        F32 mTimeout; +        std::string mOpName; +    }; + +	void removeAttachmentRequestTime(const LLUUID& inv_item_id); +	void onIdle(); +	void requestPendingAttachments(); +	void linkRecentlyArrivedAttachments(); +    void expireOldAttachmentRequests(); +    void expireOldDetachRequests(); +    void checkInvalidCOFLinks(); +    void spamStatusInfo(); + +    // Attachments that we are planning to rez but haven't requested from the server yet.  	attachments_vec_t mPendingAttachments; + +	// Attachments that have been requested from server but have not arrived yet. +	LLItemRequestTimes mAttachmentRequests; + +    // Attachments that have been requested to detach but have not gone away yet. +	LLItemRequestTimes mDetachRequests; + +    // Attachments that have arrived but have not been linked in the COF yet. +    std::set<LLUUID> mRecentlyArrivedAttachments; +    LLTimer mCOFLinkBatchTimer; + +    // Attachments that are linked in the COF but may be invalid. +	LLItemRequestTimes mQuestionableCOFLinks;  };  #endif diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 119872ec29..950a6cfaef 100755 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -59,10 +59,6 @@  // Longest time, in seconds, to wait for all animations to stop playing  const F32 MAX_WAIT_ANIM_SECS = 30.f; -// If this gesture is a link, get the base gesture that this link points to, -// otherwise just return this id. -static const LLUUID& get_linked_uuid(const LLUUID& item_id); -  // Lightweight constructor.  // init() does the heavy lifting.  LLGestureMgr::LLGestureMgr() @@ -253,7 +249,7 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id,  												BOOL inform_server,  												BOOL deactivate_similar)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	if( !gAssetStorage )  	{ @@ -307,7 +303,7 @@ void notify_update_label(const LLUUID& base_item_id)  void LLGestureMgr::deactivateGesture(const LLUUID& item_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = mActive.find(base_item_id);  	if (it == mActive.end())  	{ @@ -353,7 +349,7 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id)  void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)  { -	const LLUUID& base_in_item_id = get_linked_uuid(in_item_id); +	const LLUUID& base_in_item_id = gInventory.getLinkedItemID(in_item_id);  	uuid_vec_t gest_item_ids;  	// Deactivate all gestures that match @@ -440,7 +436,7 @@ void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& i  BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = mActive.find(base_item_id);  	return (it != mActive.end());  } @@ -448,7 +444,7 @@ BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id)  BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = mActive.find(base_item_id);  	if (it == mActive.end()) return FALSE; @@ -471,7 +467,7 @@ BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture)  void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = mActive.find(base_item_id);  	if (it == mActive.end()) @@ -513,7 +509,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges  void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id);  	if (it == mActive.end()) @@ -608,7 +604,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture)  // Convenience function that looks up the item_id for you.  void LLGestureMgr::playGesture(const LLUUID& item_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = mActive.find(base_item_id);  	if (it == mActive.end()) return; @@ -1297,7 +1293,7 @@ void LLGestureMgr::stopGesture(LLMultiGesture* gesture)  void LLGestureMgr::stopGesture(const LLUUID& item_id)  { -	const LLUUID& base_item_id = get_linked_uuid(item_id); +	const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);  	item_map_t::iterator it = mActive.find(base_item_id);  	if (it == mActive.end()) return; @@ -1457,14 +1453,4 @@ void LLGestureMgr::done()  	}  } -// static -const LLUUID& get_linked_uuid(const LLUUID &item_id) -{ -	LLViewerInventoryItem* item = gInventory.getItem(item_id); -	if (item && item->getIsLinkType()) -	{ -		return item->getLinkedUUID(); -	} -	return item_id; -} diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a047ed6fee..84f88e38ba 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5434,13 +5434,11 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach  	// Check for duplicate request.  	if (isAgentAvatarValid() && -		(gAgentAvatarp->attachmentWasRequested(item_id) || -		 gAgentAvatarp->isWearingAttachment(item_id))) +		gAgentAvatarp->isWearingAttachment(item_id))  	{ -		LL_WARNS() << "duplicate attachment request, ignoring" << LL_ENDL; +		LL_WARNS() << "ATT duplicate attachment request, ignoring" << LL_ENDL;  		return;  	} -	gAgentAvatarp->addAttachmentRequest(item_id);  	S32 attach_pt = 0;  	if (isAgentAvatarValid() && attachment) @@ -5490,36 +5488,14 @@ bool confirm_attachment_rez(const LLSD& notification, const LLSD& response)  		if (itemp)  		{ -			/* -			{ -				U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); -				 -				LLMessageSystem* msg = gMessageSystem; -				msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); -				msg->nextBlockFast(_PREHASH_AgentData); -				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -				msg->nextBlockFast(_PREHASH_ObjectData); -				msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); -				msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); -				msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); -				pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); -				msg->addStringFast(_PREHASH_Name, itemp->getName()); -				msg->addStringFast(_PREHASH_Description, itemp->getDescription()); -				msg->sendReliable(gAgent.getRegion()->getHost()); -				return false; -			} -			*/ -  			// Queue up attachments to be sent in next idle tick, this way the  			// attachments are batched up all into one message versus each attachment  			// being sent in its own separate attachments message.  			U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();  			BOOL is_add = notification["payload"]["is_add"].asBoolean(); -			LLAttachmentsMgr::instance().addAttachment(item_id, -													   attachment_pt, -													   is_add); +			LL_DEBUGS("Avatar") << "ATT calling addAttachmentRequest " << (itemp ? itemp->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +			LLAttachmentsMgr::instance().addAttachmentRequest(item_id, attachment_pt, is_add);  		}  	}  	return false; diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 300cef7deb..da33e8e680 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -690,6 +690,12 @@ void hide_context_entries(LLMenuGL& menu,  						  const menuentry_vec_t &entries_to_show,   						  const menuentry_vec_t &disabled_entries); +// Helper functions to classify actions. +bool isAddAction(const std::string& action); +bool isRemoveAction(const std::string& action); +bool isMarketplaceCopyAction(const std::string& action); +bool isMarketplaceSendAction(const std::string& action); +  class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel  {  public: diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 4075c329b9..6f6861dc7b 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -231,7 +231,7 @@ BOOL get_is_item_worn(const LLUUID& id)  		return FALSE;  	// Consider the item as worn if it has links in COF. -	if (LLAppearanceMgr::instance().isLinkInCOF(id)) +	if (LLAppearanceMgr::instance().isLinkedInCOF(id))  	{  		return TRUE;  	} @@ -265,7 +265,7 @@ BOOL get_can_item_be_worn(const LLUUID& id)  	if (!item)  		return FALSE; -	if (LLAppearanceMgr::isLinkInCOF(item->getLinkedUUID())) +	if (LLAppearanceMgr::instance().isLinkedInCOF(item->getLinkedUUID()))  	{  		// an item having links in COF (i.e. a worn item)  		return FALSE; @@ -1061,6 +1061,34 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)  	}  } +// Succeeds iff all selected items are bridges to objects, in which +// case returns their corresponding uuids. +bool get_selection_object_uuids(LLFolderView *root, uuid_vec_t& ids) +{ +	uuid_vec_t results; +	S32 non_object = 0; +	LLFolderView::selected_items_t selectedItems = root->getSelectedItems(); +	for(LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) +	{ +		LLObjectBridge *view_model = dynamic_cast<LLObjectBridge *>((*it)->getViewModelItem()); + +		if(view_model && view_model->getUUID().notNull()) +		{ +			results.push_back(view_model->getUUID()); +		} +		else +		{ +			non_object++; +		} +	} +	if (non_object == 0) +	{ +		ids = results; +		return true; +	} +	return false; +} +  void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root, const std::string& action)  {  	if ("rename" == action) @@ -1115,7 +1143,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root  		LLFloater::setFloaterHost(multi_propertiesp);  	} -      	std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();      uuid_vec_t ids;      std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); @@ -1128,7 +1155,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root      {          wear_multiple(ids, false);      } -    else if (action == "take_off" || action == "detach") +    else if (isRemoveAction(action))      {          LLAppearanceMgr::instance().removeItemsFromAvatar(ids);      } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 47a9353ffa..4fafbf917b 100755 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -52,6 +52,7 @@  // viewer includes  #include "llagent.h"  #include "llagentcamera.h" +#include "llattachmentsmgr.h"  #include "llviewerwindow.h"  #include "lldrawable.h"  #include "llfloaterinspect.h" @@ -2366,6 +2367,7 @@ void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search)  		"ObjectIncludeInSearch",  		packAgentAndSessionID,  		packObjectIncludeInSearch,  +        logNoOp,  		&include_in_search,  		SEND_ONLY_ROOTS);  } @@ -2415,6 +2417,7 @@ void LLSelectMgr::selectionSetClickAction(U8 action)  	sendListToRegions("ObjectClickAction",  					  packAgentAndSessionID,  					  packObjectClickAction,  +                      logNoOp,  					  &action,  					  SEND_INDIVIDUALS);  } @@ -2450,7 +2453,7 @@ void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::stri  	}  	else  	{ -		sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, &data, SEND_ONLY_ROOTS); +		sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, logNoOp, &data, SEND_ONLY_ROOTS);  	}  } @@ -2479,6 +2482,23 @@ void LLSelectMgr::packGodlikeHead(void* user_data)  }  // static +void LLSelectMgr::logNoOp(LLSelectNode* node, void *) +{ +} + +// static +void LLSelectMgr::logAttachmentRequest(LLSelectNode* node, void *) +{ +    LLAttachmentsMgr::instance().onAttachmentRequested(node->mItemID); +} + +// static +void LLSelectMgr::logDetachRequest(LLSelectNode* node, void *) +{ +    LLAttachmentsMgr::instance().onDetachRequested(node->mItemID); +} + +// static  void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *)  {  	std::string buf = llformat("%u", node->getObject()->getLocalID()); @@ -3584,10 +3604,11 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response,  			// attempt to derez into the trash.  			LLDeRezInfo info(DRD_TRASH, trash_id);  			LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", -										  packDeRezHeader, -										  packObjectLocalID, -										  (void*) &info, -										  SEND_ONLY_ROOTS); +                                                          packDeRezHeader, +                                                          packObjectLocalID, +                                                          logNoOp, +                                                          (void*) &info, +                                                          SEND_ONLY_ROOTS);  			// VEFFECT: Delete Object - one effect for all deletes  			if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD)  			{ @@ -3619,6 +3640,7 @@ void LLSelectMgr::selectForceDelete()  		"ObjectDelete",  		packDeleteHeader,  		packObjectLocalID, +        logNoOp,  		(void*)TRUE,  		SEND_ONLY_ROOTS);  } @@ -3789,7 +3811,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)  	data.offset = offset;  	data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); -	sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); +	sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS);  	if (select_copy)  	{ @@ -3844,7 +3866,7 @@ void LLSelectMgr::repeatDuplicate()  	data.offset = LLVector3::zero;  	data.flags = 0x0; -	sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); +	sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS);  	// move current selection based on delta from duplication position and update duplication position  	for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); @@ -3923,7 +3945,7 @@ void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region,  	data.mFlags				= (select_copy ? FLAGS_CREATE_SELECTED : 0x0);  	sendListToRegions("ObjectDuplicateOnRay",  -		packDuplicateOnRayHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); +                      packDuplicateOnRayHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS);  	if (select_copy)  	{ @@ -3973,6 +3995,7 @@ void LLSelectMgr::sendMultipleUpdate(U32 type)  		"MultipleObjectUpdate",  		packAgentAndSessionID,  		packMultipleUpdate, +        logNoOp,  		&type,  		send_type);  } @@ -4036,7 +4059,7 @@ void LLSelectMgr::sendOwner(const LLUUID& owner_id,  	data.group_id = group_id;  	data.override = override; -	sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, &data, SEND_ONLY_ROOTS); +	sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS);  }  // static @@ -4060,7 +4083,7 @@ void LLSelectMgr::packOwnerHead(void *user_data)  void LLSelectMgr::sendGroup(const LLUUID& group_id)  {  	LLUUID local_group_id(group_id); -	sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, &local_group_id, SEND_ONLY_ROOTS); +	sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, logNoOp, &local_group_id, SEND_ONLY_ROOTS);  } @@ -4084,7 +4107,7 @@ void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, con  	LLBuyData buy;  	buy.mCategoryID = category_id;  	buy.mSaleInfo = sale_info; -	sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, &buy, SEND_ONLY_ROOTS); +	sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, logNoOp, &buy, SEND_ONLY_ROOTS);  }  // static @@ -4128,7 +4151,7 @@ void LLSelectMgr::selectionSetObjectPermissions(U8 field,  	data.mMask = mask;  	data.mOverride = override; -	sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, &data, SEND_ONLY_ROOTS); +	sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, logNoOp, &data, SEND_ONLY_ROOTS);  }  void LLSelectMgr::packPermissionsHead(void* user_data) @@ -4171,6 +4194,7 @@ void LLSelectMgr::deselectAll()  		"ObjectDeselect",  		packAgentAndSessionID,  		packObjectLocalID, +        logNoOp,  		NULL,  		SEND_INDIVIDUALS); @@ -4201,6 +4225,7 @@ void LLSelectMgr::deselectAllForStandingUp()  		"ObjectDeselect",  		packAgentAndSessionID,  		packObjectLocalID, +        logNoOp,  		NULL,  		SEND_INDIVIDUALS); @@ -4282,6 +4307,7 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name)  		sendListToRegions("ObjectName",  						  packAgentAndSessionID,  						  packObjectName, +                          logNoOp,  						  (void*)(&name_copy),  						  SEND_ONLY_ROOTS);  	} @@ -4290,6 +4316,7 @@ void LLSelectMgr::selectionSetObjectName(const std::string& name)  		sendListToRegions("ObjectName",  						  packAgentAndSessionID,  						  packObjectName, +                          logNoOp,  						  (void*)(&name_copy),  						  SEND_INDIVIDUALS);  	} @@ -4305,6 +4332,7 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc)  		sendListToRegions("ObjectDescription",  						  packAgentAndSessionID,  						  packObjectDescription, +                          logNoOp,  						  (void*)(&desc_copy),  						  SEND_ONLY_ROOTS);  	} @@ -4313,6 +4341,7 @@ void LLSelectMgr::selectionSetObjectDescription(const std::string& desc)  		sendListToRegions("ObjectDescription",  						  packAgentAndSessionID,  						  packObjectDescription, +                          logNoOp,  						  (void*)(&desc_copy),  						  SEND_INDIVIDUALS);  	} @@ -4326,6 +4355,7 @@ void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category)  	sendListToRegions("ObjectCategory",  					  packAgentAndSessionID,  					  packObjectCategory, +                      logNoOp,  					  (void*)(&category),  					  SEND_ONLY_ROOTS);  } @@ -4335,6 +4365,7 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)  	sendListToRegions("ObjectSaleInfo",  					  packAgentAndSessionID,  					  packObjectSaleInfo, +                      logNoOp,  					  (void*)(&sale_info),  					  SEND_ONLY_ROOTS);  } @@ -4368,6 +4399,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)  			"ObjectAttach",  			packAgentIDAndSessionAndAttachment,   			packObjectIDAndRotation,  +            logAttachmentRequest,  			&attachment_point,   			SEND_ONLY_ROOTS );  		if (!build_mode) @@ -4388,6 +4420,7 @@ void LLSelectMgr::sendDetach()  		"ObjectDetach",  		packAgentAndSessionID,  		packObjectLocalID, +        logDetachRequest,  		NULL,  		SEND_ONLY_ROOTS );  } @@ -4404,6 +4437,7 @@ void LLSelectMgr::sendDropAttachment()  		"ObjectDrop",  		packAgentAndSessionID,  		packObjectLocalID, +        logDetachRequest,  		NULL,  		SEND_ONLY_ROOTS);  } @@ -4423,6 +4457,7 @@ void LLSelectMgr::sendLink()  		"ObjectLink",  		packAgentAndSessionID,  		packObjectLocalID, +        logNoOp,  		NULL,  		SEND_ONLY_ROOTS);  } @@ -4460,6 +4495,7 @@ void LLSelectMgr::sendDelink()  		"ObjectDelink",  		packAgentAndSessionID,  		packObjectLocalID, +        logNoOp,  		NULL,  		SEND_INDIVIDUALS);  } @@ -4512,6 +4548,7 @@ void LLSelectMgr::sendSelect()  		"ObjectSelect",  		packAgentAndSessionID,  		packObjectLocalID, +        logNoOp,  		NULL,  		SEND_INDIVIDUALS);  } @@ -4908,6 +4945,7 @@ void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data)  void LLSelectMgr::sendListToRegions(const std::string& message_name,  									void (*pack_header)(void *user_data),   									void (*pack_body)(LLSelectNode* node, void *user_data),  +                                    void (*log_func)(LLSelectNode* node, void *user_data),   									void *user_data,  									ESendType send_type)  { @@ -5029,6 +5067,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,  		{  			// add another instance of the body of the data  			(*pack_body)(node, user_data); +            // do any related logging +            (*log_func)(node, user_data);  			++objects_sent;  			++objects_in_this_packet; @@ -6679,7 +6719,7 @@ void LLSelectMgr::undo()  {  	BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");  	LLUUID group_id(gAgent.getGroupID()); -	sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); +	sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST);  }  //----------------------------------------------------------------------------- @@ -6697,7 +6737,7 @@ void LLSelectMgr::redo()  {  	BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");  	LLUUID group_id(gAgent.getGroupID()); -	sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); +	sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST);  }  //----------------------------------------------------------------------------- diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 316e72b11c..87d25e3a8c 100755 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -761,6 +761,7 @@ private:  	void sendListToRegions(	const std::string& message_name,  							void (*pack_header)(void *user_data),   							void (*pack_body)(LLSelectNode* node, void *user_data),  +							void (*log_func)(LLSelectNode* node, void *user_data),   							void *user_data,  							ESendType send_type); @@ -796,6 +797,9 @@ private:  	static void packHingeHead(void *user_data);  	static void packPermissionsHead(void* user_data);  	static void packGodlikeHead(void* user_data); +    static void logNoOp(LLSelectNode* node, void *user_data); +    static void logAttachmentRequest(LLSelectNode* node, void *user_data); +    static void logDetachRequest(LLSelectNode* node, void *user_data);  	static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle);  	// Get the first ID that matches test and whether or not all ids are identical in selected objects. diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d112118082..a8634d1e93 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -2306,5 +2306,3 @@ BOOL LLViewerInventoryItem::regenerateLink()  	gInventory.notifyObservers();  	return TRUE;  } - - diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9d680e23d1..ab36312cee 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6633,7 +6633,7 @@ class LLAttachmentDetachFromPoint : public view_listener_t  				LLViewerObject *attached_object = (*iter);  				ids_to_remove.push_back(attached_object->getAttachmentItemID());  			} -			} +        }  		if (!ids_to_remove.empty())  		{  			LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a2c0a91ea6..ac3f07fcd8 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1958,6 +1958,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead())  				{ +                    if (((LLViewerObject*)sent_parentp)->isAvatar()) +                    { +                        //LL_DEBUGS("Avatar") << "ATT got object update for attachment " << LL_ENDL;  +                    } +                      					//  					// We have a viewer object for the parent, and it's not dead.  					// Do the actual reparenting here. diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 7c36b30dd1..75732a1e19 100755 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -474,13 +474,13 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			{  				U32 flags = 0;  				mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); -			 +                  				if(flags & FLAGS_TEMPORARY_ON_REZ)  				{ -				compressed_dp.unpackUUID(fullid, "ID"); -				compressed_dp.unpackU32(local_id, "LocalID"); -				compressed_dp.unpackU8(pcode, "PCode"); -			} +                    compressed_dp.unpackUUID(fullid, "ID"); +                    compressed_dp.unpackU32(local_id, "LocalID"); +                    compressed_dp.unpackU8(pcode, "PCode"); +                }  				else //send to object cache  				{  					regionp->cacheFullUpdate(compressed_dp, flags); @@ -497,7 +497,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  								 gMessageSystem->getSenderPort());  				if (fullid.isNull())  				{ -					// LL_WARNS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; +					LL_DEBUGS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL;  					mNumUnknownUpdates++;  				}  			} diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a573b16954..f753448770 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -722,7 +722,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job  	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); -	LL_DEBUGS("Avatar") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; +	LL_DEBUGS("Avatar","Message") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;  	mPelvisp = NULL; @@ -5734,12 +5734,20 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent)  void LLVOAvatar::addChild(LLViewerObject *childp)  {  	childp->extractAttachmentItemID(); // find the inventory item this object is associated with. +	if (isSelf()) +	{ +	    const LLUUID& item_id = childp->getAttachmentItemID(); +		LLViewerInventoryItem *item = gInventory.getItem(item_id); +		LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + +	} +  	LLViewerObject::addChild(childp);  	if (childp->mDrawable)  	{  		if (!attachObject(childp))  		{ -			LL_WARNS() << "addChild() failed for "  +			LL_WARNS() << "ATT addChild() failed for "   					<< childp->getID()  					<< " item " << childp->getAttachmentItemID()  					<< LL_ENDL; @@ -5809,10 +5817,21 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi  //-----------------------------------------------------------------------------  const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)  { +	if (isSelf()) +	{ +		const LLUUID& item_id = viewer_object->getAttachmentItemID(); +		LLViewerInventoryItem *item = gInventory.getItem(item_id); +		LL_DEBUGS("Avatar") << "ATT attaching object " +							<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;	 +	}  	LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);  	if (!attachment || !attachment->addObject(viewer_object))  	{ +		const LLUUID& item_id = viewer_object->getAttachmentItemID(); +		LLViewerInventoryItem *item = gInventory.getItem(item_id); +		LL_WARNS("Avatar") << "ATT attach failed " +						   << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;	  		return 0;  	} @@ -5872,6 +5891,13 @@ void LLVOAvatar::lazyAttach()  		LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i];  		if (cur_attachment->mDrawable)  		{ +			if (isSelf()) +			{ +				const LLUUID& item_id = cur_attachment->getAttachmentItemID(); +				LLViewerInventoryItem *item = gInventory.getItem(item_id); +				LL_DEBUGS("Avatar") << "ATT attaching object " +									<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; +			}  			if (!attachObject(cur_attachment))  			{	// Drop it  				LL_WARNS() << "attachObject() failed for "  diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 56997c928a..c1ca0aed69 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -38,6 +38,7 @@  #include "pipeline.h"  #include "llagent.h" //  Get state values from here +#include "llattachmentsmgr.h"  #include "llagentcamera.h"  #include "llagentwearables.h"  #include "llhudeffecttrail.h" @@ -1118,44 +1119,6 @@ BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const  }  //----------------------------------------------------------------------------- -BOOL LLVOAvatarSelf::attachmentWasRequested(const LLUUID& inv_item_id) const -{ -	const F32 REQUEST_EXPIRATION_SECONDS = 5.0;  // any request older than this is ignored/removed. -	std::map<LLUUID,LLTimer>::iterator it = mAttachmentRequests.find(inv_item_id); -	if (it != mAttachmentRequests.end()) -	{ -		const LLTimer& request_time = it->second; -		F32 request_time_elapsed = request_time.getElapsedTimeF32(); -		if (request_time_elapsed > REQUEST_EXPIRATION_SECONDS) -		{ -			mAttachmentRequests.erase(it); -			return FALSE; -		} -		else -		{ -			return TRUE; -		} -	} -	else -	{ -		return FALSE; -	} -} - -//----------------------------------------------------------------------------- -void LLVOAvatarSelf::addAttachmentRequest(const LLUUID& inv_item_id) -{ -	LLTimer current_time; -	mAttachmentRequests[inv_item_id] = current_time; -} - -//----------------------------------------------------------------------------- -void LLVOAvatarSelf::removeAttachmentRequest(const LLUUID& inv_item_id) -{ -	mAttachmentRequests.erase(inv_item_id); -} - -//-----------------------------------------------------------------------------  // getWornAttachment()  //-----------------------------------------------------------------------------  LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id) @@ -1221,8 +1184,6 @@ const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *view  	{  		const LLUUID& attachment_id = viewer_object->getAttachmentItemID();  		LLAppearanceMgr::instance().registerAttachment(attachment_id); -		// Clear any pending requests once the attachment arrives. -		removeAttachmentRequest(attachment_id);  		updateLODRiggedAttachments();		  	} diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index dc5e64d547..332a6353ad 100755 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -291,19 +291,12 @@ protected:  public:  	void 				updateAttachmentVisibility(U32 camera_mode);  	BOOL 				isWearingAttachment(const LLUUID& inv_item_id) const; -	BOOL				attachmentWasRequested(const LLUUID& inv_item_id) const; -	void				addAttachmentRequest(const LLUUID& inv_item_id); -	void				removeAttachmentRequest(const LLUUID& inv_item_id);  	LLViewerObject* 	getWornAttachment(const LLUUID& inv_item_id);  	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); -private: -	// Track attachments that have been requested but have not arrived yet. -	mutable std::map<LLUUID,LLTimer> mAttachmentRequests; -  	//--------------------------------------------------------------------  	// HUDs  	//-------------------------------------------------------------------- diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 888ead0613..1c3808ce68 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -124,7 +124,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,  	// We don't use get_is_item_worn() here because this update is triggered by  	// an inventory observer upon link in COF beind added or removed so actual  	// worn status of a linked item may still remain unchanged. -	if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkInCOF(mInventoryItemUUID)) +	if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID))  	{  		search_label += LLTrans::getString("worn");  		item_state = IS_WORN; | 
