From 93c753853666e7e34f289f9dafcd56d721ea1beb Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Fri, 11 Sep 2009 19:17:24 -0700 Subject: Applied patch to wear multiple attachments at once (VWR-5063) --- linden/indra/newview/llinventoryactions.cpp | 9 ++ linden/indra/newview/llinventorybridge.cpp | 172 +++++++++++++++++++--------- 2 files changed, 130 insertions(+), 51 deletions(-) (limited to 'linden/indra') diff --git a/linden/indra/newview/llinventoryactions.cpp b/linden/indra/newview/llinventoryactions.cpp index 2ee7307..b598c83 100644 --- a/linden/indra/newview/llinventoryactions.cpp +++ b/linden/indra/newview/llinventoryactions.cpp @@ -85,6 +85,9 @@ #include "lluictrlfactory.h" #include "llselectmgr.h" +// Defined in llinventorybridge.cpp +void wear_attachments_on_avatar(const std::set& item_ids, BOOL remove); + const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) @@ -115,6 +118,12 @@ bool doToSelected(LLFolderView* folder, std::string action) std::set selected_items; folder->getSelectionList(selected_items); + if ( ("attach" == action) && (selected_items.size() > 1) ) + { + wear_attachments_on_avatar(selected_items, FALSE); + return true; + } + LLMultiPreview* multi_previewp = NULL; LLMultiProperties* multi_propertiesp = NULL; diff --git a/linden/indra/newview/llinventorybridge.cpp b/linden/indra/newview/llinventorybridge.cpp index 52b15cb..3505bd3 100644 --- a/linden/indra/newview/llinventorybridge.cpp +++ b/linden/indra/newview/llinventorybridge.cpp @@ -111,6 +111,8 @@ void remove_inventory_category_from_avatar(LLInventoryCategory* category); void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata); void move_task_inventory_callback(S32 option, void* user_data); void confirm_replace_attachment_rez(S32 option, void* user_data); +void wear_attachments_on_avatar(const std::set& item_ids, BOOL remove); +void wear_attachments_on_avatar(const LLInventoryModel::item_array_t& items, BOOL remove); std::string ICON_NAME[ICON_NAME_COUNT] = { @@ -3671,6 +3673,31 @@ private: bool mAppend; }; +class LLWearAttachmentsCallback : public LLInventoryCallback +{ +public: + LLWearAttachmentsCallback(bool append) : mAppend(append) {} + void fire(const LLUUID& item_id) + { + mItemIDs.insert(item_id); + } +protected: + ~LLWearAttachmentsCallback() + { + if( LLInventoryCallbackManager::is_instantiated() ) + { + wear_attachments_on_avatar(mItemIDs, mAppend); + } + else + { + llwarns << "Dropping unhandled LLWearAttachments" << llendl; + } + } +private: + std::set mItemIDs; + bool mAppend; +}; + void LLOutfitObserver::done() { // We now have an outfit ready to be copied to agent inventory. Do @@ -4026,57 +4053,7 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) if( obj_count > 0 ) { // We've found some attachements. Add these. - - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - // Build a compound message to send all the objects that need to be rezzed. - - // 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 ) - { - obj_count = MAX_OBJECTS_TO_SEND; - } - - // Create an id to keep the parts of the compound message together - LLUUID compound_msg_id; - compound_msg_id.generate(); - LLMessageSystem* msg = gMessageSystem; - - for(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, !wear_info->mAppend ); - } - - LLInventoryItem* item = obj_item_array.get(i); - msg->nextBlockFast(_PREHASH_ObjectData ); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); - msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); - msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // 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() ); - } - } - } + wear_attachments_on_avatar(obj_item_array, !wear_info->mAppend); } } delete wear_info; @@ -4160,6 +4137,99 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B dec_busy_count(); } +void wear_attachments_on_avatar(const std::set& item_ids, BOOL remove) +{ + // NOTE: the inventory items can reside in the user's inventory, the library, or any combination of the two + + LLInventoryModel::item_array_t items; + LLPointer cb; + + for (std::set::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if ( (item) && (LLAssetType::AT_OBJECT == item->getType()) ) + { + if ( (gInventory.isObjectDescendentOf(*it, gAgent.getInventoryRootID())) ) + { + items.put(item); + } + else if ( (item->isComplete()) ) + { + if (cb.isNull()) + cb = new LLWearAttachmentsCallback(remove); + copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(), LLUUID::null, std::string(), cb); + } + } + } + + wear_attachments_on_avatar(items, remove); +} + +void wear_attachments_on_avatar(const LLInventoryModel::item_array_t& items, BOOL remove) +{ + // NOTE: all inventory items must reside in the user's inventory + + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if(!avatarp) + { + llwarns << "No avatar found." << llendl; + return; + } + + // Build a compound message to send all the objects that need to be rezzed. + + // 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; + + S32 count = items.count(); + if ( !count ) + { + return; + } + else if ( count > MAX_OBJECTS_TO_SEND ) + { + count = MAX_OBJECTS_TO_SEND; + } + + // 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 < 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, count ); + msg->addBOOLFast(_PREHASH_FirstDetachAll, remove ); + } + + LLInventoryItem* item = items.get(i); + msg->nextBlockFast(_PREHASH_ObjectData ); + msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() ); + msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); + msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // 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 == count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) ) + { + // End of message chunk + msg->sendReliable( gAgent.getRegion()->getHost() ); + } + } +} + void remove_inventory_category_from_avatar( LLInventoryCategory* category ) { if(!category) return; -- cgit v1.1