diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index edd4632a5d037ebb6b30992244e344dbfb8318b5..b9995022d409805c84ed63cd56bca8e8973d04cb 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1927,7 +1927,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, LLInventoryModel::item_array_t& wear_items_new, LLInventoryModel::item_array_t& obj_items_new, LLInventoryModel::item_array_t& gest_items_new, - bool append /*=false*/, const LLUUID& idOutfit /*=LLUUID::null*/) + bool append /*=false*/, const LLUUID& idOutfit /*=LLUUID::null*/, LLPointer<LLInventoryCallback> link_waiter /*= NULL*/) // [/RLVa:KB] { // LLViewerInventoryCategory *pcat = gInventory.getCategory(category); @@ -2056,7 +2056,11 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, // Will link all the above items. // link_waiter enforce flags are false because we've already fixed everything up in updateCOF(). - LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false); +// LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false); +// [RLVa:KB] Checked: 2015-05-05 (RLVa-1.4.12) + if (!link_waiter) + link_waiter = new LLUpdateAppearanceOnDestroy(false, false); +// [/RLVa:KB] LLSD contents = LLSD::emptyArray(); for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin(); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f87ea549a75c14a05a132cfa76e55177fbc02d44..9c168c38eec08d6c11d1d5e66d699f2447ee418f 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -59,7 +59,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr> // [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) | Added: RLVa-1.2.0a void updateCOF(LLInventoryModel::item_array_t& body_items_new, LLInventoryModel::item_array_t& wear_items_new, LLInventoryModel::item_array_t& obj_items_new, LLInventoryModel::item_array_t& gest_items_new, - bool append = false, const LLUUID& idOutfit = LLUUID::null); + bool append = false, const LLUUID& idOutfit = LLUUID::null, LLPointer<LLInventoryCallback> link_waiter = NULL); // [/RLVa:KB] void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append); diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 92d363c49cc3ca2c1479ee990618c85644911f84..c36a5f0fc345433cfc8d22d12f6a1f956c180f9e 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -888,7 +888,35 @@ void RlvForceWear::remWearable(const LLViewerWearable* pWearable) m_remWearables.push_back(pWearable); } -// Checked: 2010-09-18 (RLVa-1.2.1) +// Checked: 2015-05-05 (RLVa-1.4.12) +void RlvForceWear::updatePendingAttachments() +{ + if (RlvForceWear::instanceExists()) + { + RlvForceWear* pThis = RlvForceWear::getInstance(); + for (const pendingattachments_map_t::value_type& itAttach : pThis->m_pendingAttachments) + LLAttachmentsMgr::instance().addAttachment(itAttach.first, itAttach.second & ~ATTACHMENT_ADD, itAttach.second & ATTACHMENT_ADD); + pThis->m_pendingAttachments.clear(); + } +} + +// Checked: 2015-05-05 (RLVa-1.4.12) +void RlvForceWear::addPendingAttachment(const LLUUID& idItem, U8 idxPoint) +{ + auto itAttach = m_pendingAttachments.find(idItem); + if (m_pendingAttachments.end() == itAttach) + m_pendingAttachments.insert(std::make_pair(idItem, idxPoint)); + else + itAttach->second = idxPoint; +} + +// Checked: 2015-05-05 (RLVa-1.4.12) +void RlvForceWear::remPendingAttachment(const LLUUID& idItem) +{ + m_pendingAttachments.erase(idItem); +} + +// Checked: 2015-05-05 (RLVa-1.4.12) void RlvForceWear::done() { // Sanity check - don't go through all the motions below only to find out there's nothing to actually do @@ -898,41 +926,35 @@ void RlvForceWear::done() return; } - LLAppearanceMgr* pAppearanceMgr = LLAppearanceMgr::getInstance(); - // // Process removals // + uuid_vec_t remItems; + // Wearables if (m_remWearables.size()) { - for (std::list<const LLViewerWearable*>::const_iterator itWearable = m_remWearables.begin(); itWearable != m_remWearables.end(); ++itWearable) - pAppearanceMgr->removeItemFromAvatar((*itWearable)->getItemID()); + for (const LLViewerWearable* pWearable : m_remWearables) + remItems.push_back(pWearable->getItemID()); m_remWearables.clear(); } // Gestures if (m_remGestures.size()) { - // NOTE: LLGestureMgr::deactivateGesture() will call LLAppearanceMgr::removeCOFItemLinks() for us - for (S32 idxItem = 0, cntItem = m_remGestures.size(); idxItem < cntItem; idxItem++) - LLGestureMgr::instance().deactivateGesture(m_remGestures.at(idxItem)->getUUID()); + // NOTE: LLGestureMgr::deactivateGesture() will call LLAppearanceMgr::removeCOFItemLinks() for us and supply its own callback + for (const LLViewerInventoryItem* pItem : m_remGestures) + LLGestureMgr::instance().deactivateGesture(pItem->getUUID()); m_remGestures.clear(); } // Attachments if (m_remAttachments.size()) { - // Don't bother with COF if all we're doing is detaching some attachments (keeps people from rebaking on every @remattach=force) LLAgentWearables::userRemoveMultipleAttachments(m_remAttachments); - - for (std::vector<LLViewerObject*>::const_iterator itAttachObj = m_remAttachments.begin(); - itAttachObj != m_remAttachments.end(); ++itAttachObj) - { - pAppearanceMgr->removeCOFItemLinks((*itAttachObj)->getAttachmentItemID()); - } - + for (const LLViewerObject* pAttachObj : m_remAttachments) + remItems.push_back(pAttachObj->getAttachmentItemID()); m_remAttachments.clear(); } @@ -942,50 +964,51 @@ void RlvForceWear::done() // Wearables need to be split into AT_BODYPART and AT_CLOTHING for COF LLInventoryModel::item_array_t addBodyParts, addClothing; - for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.begin(); itAddWearables != m_addWearables.end(); ++itAddWearables) + for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.cbegin(); itAddWearables != m_addWearables.cend(); ++itAddWearables) { - const LLInventoryModel::item_array_t& wearItems = itAddWearables->second; - for (S32 idxItem = 0, cntItem = wearItems.size(); idxItem < cntItem; idxItem++) + // NOTE: LLAppearanceMgr will filter our duplicates so no need for us to check here + for (LLViewerInventoryItem* pItem : itAddWearables->second) { - LLViewerInventoryItem* pItem = wearItems.at(idxItem); - if (!pAppearanceMgr->isLinkInCOF(pItem->getUUID())) // It's important to examine COF here and *not* gAgentWearables - { - if (LLAssetType::AT_BODYPART == pItem->getType()) - addBodyParts.push_back(pItem); - else - addClothing.push_back(pItem); - } + if (LLAssetType::AT_BODYPART == pItem->getType()) + addBodyParts.push_back(pItem); + else + addClothing.push_back(pItem); } } m_addWearables.clear(); // Until LL provides a way for updateCOF to selectively attach add/replace we have to deal with attachments ourselves - for (addattachments_map_t::const_iterator itAddAttachments = m_addAttachments.begin(); - itAddAttachments != m_addAttachments.end(); ++itAddAttachments) + for (addattachments_map_t::const_iterator itAddAttachments = m_addAttachments.cbegin(); itAddAttachments != m_addAttachments.cend(); ++itAddAttachments) { - const LLInventoryModel::item_array_t& wearItems = itAddAttachments->second; - for (S32 idxItem = 0, cntItem = wearItems.size(); idxItem < cntItem; idxItem++) - { - const LLUUID& idItem = wearItems.at(idxItem)->getLinkedUUID(); - if (gAgentAvatarp->attachmentWasRequested(idItem)) - continue; - gAgentAvatarp->addAttachmentRequest(idItem); - - LLAttachmentsMgr::instance().addAttachment(idItem, itAddAttachments->first & ~ATTACHMENT_ADD, itAddAttachments->first & ATTACHMENT_ADD); - } + for (const LLViewerInventoryItem* pItem : itAddAttachments->second) + addPendingAttachment(pItem->getLinkedUUID(), itAddAttachments->first); } m_addAttachments.clear(); - // If there are additions we need to call LLAppearanceManager::updateCOF(), otherwise LLAppearanceManager::updateAppearanceFromCOF() + // + // Tie it all together + // + + // | Wearables | Attachments | Gestures | + // |======================================================| + // Add : | LLAppearanceMgr | <custom> | LLAppearanceMgr | + // Remove : | LLAppearanceMgr | LLAppearanceMgr | LLGestureMgr | + LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(false, false, boost::bind(RlvForceWear::updatePendingAttachments)); + + if (!remItems.empty()) + { + LLAppearanceMgr::instance().removeItemsFromAvatar(remItems, cb, true); + } + if ( (!addBodyParts.empty()) || (!addClothing.empty()) || (!m_addGestures.empty()) ) { LLInventoryModel::item_array_t addAttachments; - pAppearanceMgr->updateCOF(addBodyParts, addClothing, addAttachments, m_addGestures, true); + LLAppearanceMgr::instance().updateCOF(addBodyParts, addClothing, addAttachments, m_addGestures, true, LLUUID::null, cb); m_addGestures.clear(); } - // Since RlvForceWear is a singleton now we want to be sure there aren't any leftovers + // Make sure there are no leftovers for the next cycle RLV_ASSERT( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) ); RLV_ASSERT( (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) ); } diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index b97e4a8cb671407b4d248e6844f81f035098de1d..2d935f80e84469b8bc4a1513d2191d802903322b 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -276,6 +276,15 @@ class RlvForceWear : public LLSingleton<RlvForceWear> return std::find(m_remWearables.begin(), m_remWearables.end(), pWearable) != m_remWearables.end(); } + /* + * Pending attachments + */ +public: + static void updatePendingAttachments(); +protected: + void addPendingAttachment(const LLUUID& idItem, U8 idxPoint); + void remPendingAttachment(const LLUUID& idItem); + protected: typedef std::pair<LLWearableType::EType, LLInventoryModel::item_array_t> addwearable_pair_t; typedef std::map<LLWearableType::EType, LLInventoryModel::item_array_t> addwearables_map_t; @@ -288,6 +297,9 @@ class RlvForceWear : public LLSingleton<RlvForceWear> std::list<const LLViewerWearable*> m_remWearables; LLInventoryModel::item_array_t m_remGestures; + typedef std::map<LLUUID, U8> pendingattachments_map_t; + pendingattachments_map_t m_pendingAttachments; + private: friend class LLSingleton<RlvForceWear>; };