diff options
-rw-r--r-- | indra/newview/llagentwearables.cpp | 107 | ||||
-rw-r--r-- | indra/newview/llagentwearables.h | 6 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.cpp | 26 |
3 files changed, 115 insertions, 24 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 6eb248ef74..50d378335e 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1684,7 +1684,80 @@ void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed) } } -void LLAgentWearables::userRemoveAllAttachments() +// Combines userRemoveAllAttachments() 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) +{ + // Possible cases: + // already wearing but not in request set -> take off. + // already wearing and in request set -> leave alone. + // not wearing and in request set -> put on. + + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (!avatarp) + { + llwarns << "No avatar found." << llendl; + return; + } + + std::set<LLUUID> requested_item_ids; + std::set<LLUUID> current_item_ids; + for (S32 i=0; i<obj_item_array.count(); i++) + requested_item_ids.insert(obj_item_array[i].get()->getLinkedUUID()); + + // 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 = avatarp->mAttachmentPoints.begin(); + iter != avatarp->mAttachmentPoints.end();) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + LLViewerObject* objectp = attachment->getObject(); + if (objectp) + { + LLUUID object_item_id = attachment->getItemID(); + if (requested_item_ids.find(object_item_id) != requested_item_ids.end()) + { + // Object currently worn, was requested. + // Flag as currently worn so we won't have to add it again. + current_item_ids.insert(object_item_id); + } + else + { + // object currently worn, not requested. + objects_to_remove.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) + { + LLUUID linked_id = (*it).get()->getLinkedUUID(); + if (current_item_ids.find(linked_id) != current_item_ids.end()) + { + // Requested attachment is already worn. + } + else + { + // Requested attachment is not worn yet. + items_to_add.push_back(*it); + } + } + // S32 remove_count = objects_to_remove.size(); + // S32 add_count = items_to_add.size(); + // llinfos << "remove " << remove_count << " add " << add_count << llendl; + + // 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) { LLVOAvatar* avatarp = gAgent.getAvatarObject(); if (!avatarp) @@ -1693,11 +1766,36 @@ void LLAgentWearables::userRemoveAllAttachments() return; } + if (objects_to_remove.empty()) + return; + gMessageSystem->newMessage("ObjectDetach"); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + for (llvo_vec_t::iterator it = objects_to_remove.begin(); + it != objects_to_remove.end(); + ++it) + { + LLViewerObject *objectp = *it; + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); + } + gMessageSystem->sendReliable(gAgent.getRegionHost()); +} +void LLAgentWearables::userRemoveAllAttachments() +{ + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (!avatarp) + { + llwarns << "No avatar found." << llendl; + return; + } + + llvo_vec_t objects_to_remove; + for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); iter != avatarp->mAttachmentPoints.end();) { @@ -1705,12 +1803,9 @@ void LLAgentWearables::userRemoveAllAttachments() LLViewerJointAttachment* attachment = curiter->second; LLViewerObject* objectp = attachment->getObject(); if (objectp) - { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID()); - } + objects_to_remove.push_back(objectp); } - gMessageSystem->sendReliable(gAgent.getRegionHost()); + userRemoveMultipleAttachments(objects_to_remove); } void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array) diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index f34b23e220..701ce7f05a 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -44,6 +44,7 @@ class LLInventoryItem; class LLVOAvatarSelf; class LLWearable; class LLInitialWearablesFetch; +class LLViewerObject; class LLAgentWearables { @@ -181,6 +182,11 @@ public: // MULTI-WEARABLE: assuming one wearable per type. Need upstream changes. static void userRemoveWearable(void* userdata); // userdata is EWearableType static void userRemoveAllClothes(void* userdata); // userdata is NULL + + typedef std::vector<LLViewerObject*> llvo_vec_t; + + static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array); + static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userRemoveAllAttachments(); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index dfed1cb57a..3831846e2e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -416,11 +416,11 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory if (!append && total_links > 0) { - // Remove all current outfit folder links since we're now replacing the contents. for (S32 i = 0; i < cof_items.count(); ++i) { gInventory.purgeObject(cof_items.get(i)->getUUID()); } + gInventory.notifyObservers(); } LLPointer<LLUpdateAppearanceOnDestroy> link_waiter = new LLUpdateAppearanceOnDestroy; @@ -532,19 +532,19 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory const LLUUID ¤t_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); // Processes that take time should show the busy cursor //inc_busy_count(); - + LLInventoryModel::cat_array_t cof_cats; LLInventoryModel::item_array_t cof_items; gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items, LLInventoryModel::EXCLUDE_TRASH); - + if (items.count() > 0) { - // Remove all current outfit folder links since we're now replacing the contents. for (S32 i = 0; i < cof_items.count(); ++i) { gInventory.purgeObject(cof_items.get(i)->getUUID()); } + gInventory.notifyObservers(); } LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; @@ -696,21 +696,11 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, } } - - //If the folder doesn't contain only gestures, take off all attachments. - if (!(wear_items.count() == 0 && obj_items.count() == 0 && gest_items.count() > 0) ) + // Update attachments to match those requested. + LLVOAvatar* avatar = gAgent.getAvatarObject(); + if( avatar ) { - LLAgentWearables::userRemoveAllAttachments(); - } - - if( obj_items.count() > 0 ) - { - // We've found some attachments. Add these. - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - LLAgentWearables::userAttachMultipleAttachments(obj_items); - } + LLAgentWearables::userUpdateAttachments(obj_items); } } |