From 66d385232d83995cf275d1193ff64fa244965c20 Mon Sep 17 00:00:00 2001 From: Kitty Barnett <none@none> Date: Tue, 31 Aug 2010 00:38:29 +0200 Subject: [PATCH] - internal : added support for "force wear add" vs "force wear replace" -> partial commit of support 'framework' *only* (completely untested so force wearing is probably very broken/non-functional right now) -> an (unintended) side-effect of the current implementation is that "nostrip" *wearables* won't get replaced on a force-replace wear, revisit later --HG-- branch : RLVa --- indra/newview/llappearancemgr.cpp | 10 +- indra/newview/llappearancemgr.h | 2 +- indra/newview/rlvdefines.h | 1 - indra/newview/rlvhandler.cpp | 89 +++++++++-------- indra/newview/rlvhandler.h | 3 +- indra/newview/rlvhelper.cpp | 159 +++++++++++++++++++++--------- indra/newview/rlvhelper.h | 40 ++++++-- 7 files changed, 193 insertions(+), 111 deletions(-) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index def02105d6..81b893ef9a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1490,15 +1490,14 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) getDescendentsOfAssetType(category, wear_items_new, LLAssetType::AT_CLOTHING, false); getDescendentsOfAssetType(category, obj_items_new, LLAssetType::AT_OBJECT, false); getDescendentsOfAssetType(category, gest_items_new, LLAssetType::AT_GESTURE, false); - updateCOF(body_items_new, wear_items_new, obj_items_new, gest_items_new, append, LLAgentWearables::MAX_CLOTHING_PER_TYPE, category); + updateCOF(body_items_new, wear_items_new, obj_items_new, gest_items_new, append, category); } 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*/, U32 cntMaxPerType /*=LLAgentWearables::MAX_CLOTHING_PER_TYPE*/, - const LLUUID& idOutfit /*=LLUUID::null*/) + bool append /*=false*/, const LLUUID& idOutfit /*=LLUUID::null*/) // [/RLVa:KB] { // LLViewerInventoryCategory *pcat = gInventory.getCategory(category); @@ -1569,10 +1568,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new, // [/RLVa:KB] // Reduce wearables to max of one per type. removeDuplicateItems(wear_items); -// filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); -// [RLVa:KB] - Checked: 2010-08-09 (RLVa-1.2.0i) | Added: RLVa-1.2.0i - filterWearableItems(wear_items, cntMaxPerType); -// [/RLVa:KB] + filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); // // - Attachments: include COF contents only if appending. diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 5e9d27a57b..bf95ec88a8 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -54,7 +54,7 @@ public: // [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, U32 cntMaxPerType = LLAgentWearables::MAX_CLOTHING_PER_TYPE, const LLUUID& idOutfit = LLUUID::null); + bool append = false, const LLUUID& idOutfit = LLUUID::null); // [/RLVa:KB] void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append); diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 5251252aa0..72a56a6f62 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -59,7 +59,6 @@ // Workarounds #define RLV_WORKAROUND_REZMULTIPLEATTACH // See http://jira.secondlife.com/browse/SVC-5383 ; disables "Shared Wear" -#define RLV_WORKAROUND_SHAREDINVREPLACE // Keeps shared inventory working the way it did before multi-wearables/multi-attachments // ============================================================================ // Defines diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index e220c5a610..eeece1a827 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -1277,10 +1277,14 @@ ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const ERlvCmdRet eRet = RLV_RET_SUCCESS; switch (rlvCmd.getBehaviourType()) { - case RLV_BHVR_DETACH: // @detach[:<option>]=force - Checked: 2009-12-21 (RLVa-1.1.0k) | Modified: RLVa-1.1.0j - eRet = onForceRemAttach(rlvCmd); - if (RLV_RET_SUCCESS != eRet) - eRet = onForceWear(rlvCmd.getOption(), false, false); + case RLV_BHVR_DETACH: // @detach[:<option>]=force - Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c + { + RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption()); + if (rlvCmdOption.isSharedFolder()) + eRet = onForceWear(rlvCmdOption.getSharedFolder(), rlvCmd.getBehaviourType()); + else + eRet = onForceRemAttach(rlvCmd); + } break; case RLV_BHVR_REMATTACH: // @remattach[:<option>]=force eRet = onForceRemAttach(rlvCmd); @@ -1325,27 +1329,13 @@ ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const break; case RLV_BHVR_ADDOUTFIT: // @addoutfit:<option>=force <- synonym of @attach:<option>=force case RLV_BHVR_ATTACH: // @attach:<option>=force - Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c - { - RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption()); - VERIFY_OPTION(rlvCmdOption.isSharedFolder()); - - eRet = onForceWear(rlvCmdOption.getSharedFolder(), true, false); // Force attach single folder - } - break; case RLV_BHVR_ATTACHALL: // @attachall:<option>=force - Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c - { - RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption()); - VERIFY_OPTION(rlvCmdOption.isSharedFolder()); - - eRet = onForceWear(rlvCmdOption.getSharedFolder(), true, true); // Force attach nested folders - } - break; case RLV_BHVR_DETACHALL: // @detachall:<option>=force - Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c { RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption()); VERIFY_OPTION(rlvCmdOption.isSharedFolder()); - eRet = onForceWear(rlvCmdOption.getSharedFolder(), false, true); // Force detach nested folders + eRet = onForceWear(rlvCmdOption.getSharedFolder(), rlvCmd.getBehaviourType()); } break; case RLV_BHVR_ATTACHTHIS: // @attachthis[:<option>]=force - Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c @@ -1359,13 +1349,8 @@ ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const LLInventoryModel::cat_array_t folders; if (RlvInventory::instance().getPath(rlvGetPathOption.getItemIDs(), folders)) { - ERlvBehaviour eBehaviour = rlvCmd.getBehaviourType(); for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++) - { - onForceWear(folders.get(idxFolder), - (RLV_BHVR_ATTACHTHIS == eBehaviour) || (RLV_BHVR_ATTACHALLTHIS == eBehaviour), - (RLV_BHVR_ATTACHALLTHIS == eBehaviour) || (RLV_BHVR_DETACHALLTHIS == eBehaviour)); - } + onForceWear(folders.get(idxFolder), rlvCmd.getBehaviourType()); } } break; @@ -1480,29 +1465,47 @@ ERlvCmdRet RlvHandler::onForceSit(const RlvCommand& rlvCmd) const return RLV_RET_SUCCESS; } -// Checked: 2009-12-18 (RLVa-1.1.0k) | Modified: RLVa-1.1.0i -ERlvCmdRet RlvHandler::onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const -{ - const LLViewerInventoryCategory* pRlvRoot = RlvInventory::instance().getSharedRoot(); - const LLViewerInventoryCategory* pFolder = (pRlvRoot) ? RlvInventory::instance().getSharedFolder(strPath) : NULL; - if ( (!pFolder) || (pFolder->getUUID() == pRlvRoot->getUUID()) ) - return (pRlvRoot != NULL) ? RLV_RET_FAILED_OPTION : RLV_RET_FAILED_NOSHAREDROOT; - - RlvForceWear::instance().forceFolder(pFolder, - (fAttach) ? RlvForceWear::ACTION_ATTACH : RlvForceWear::ACTION_DETACH, - (fMatchAll) ? (RlvForceWear::eWearFlags)(RlvForceWear::FLAG_DEFAULT | RlvForceWear::FLAG_MATCHALL) : (RlvForceWear::FLAG_DEFAULT)); - return RLV_RET_SUCCESS; -} - // Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c -ERlvCmdRet RlvHandler::onForceWear(const LLViewerInventoryCategory* pFolder, bool fAttach, bool fMatchAll) const +ERlvCmdRet RlvHandler::onForceWear(const LLViewerInventoryCategory* pFolder, ERlvBehaviour eBhvr) const { if ( (pFolder) && (!RlvInventory::instance().isSharedFolder(pFolder->getUUID())) ) return RLV_RET_FAILED_OPTION; - RlvForceWear::instance().forceFolder(pFolder, - (fAttach) ? RlvForceWear::ACTION_ATTACH : RlvForceWear::ACTION_DETACH, - (fMatchAll) ? (RlvForceWear::eWearFlags)(RlvForceWear::FLAG_DEFAULT | RlvForceWear::FLAG_MATCHALL) : (RlvForceWear::FLAG_DEFAULT)); + RlvForceWear::EWearAction eAction; + switch (eBhvr) + { + case RLV_BHVR_ATTACH: + case RLV_BHVR_ATTACHALL: + case RLV_BHVR_ATTACHTHIS: + case RLV_BHVR_ATTACHALLTHIS: + case RLV_BHVR_ADDOUTFIT: + eAction = RlvForceWear::ACTION_WEAR_REPLACE; + break; + case RLV_BHVR_DETACH: + case RLV_BHVR_DETACHALL: + case RLV_BHVR_DETACHTHIS: + case RLV_BHVR_DETACHALLTHIS: + eAction = RlvForceWear::ACTION_REMOVE; + break; + default: + RLV_ASSERT(false); + return RLV_RET_FAILED_UNKNOWN; + } + + RlvForceWear::EWearFlags eFlags = RlvForceWear::FLAG_DEFAULT; + switch (eBhvr) + { + case RLV_BHVR_ATTACHALL: + case RLV_BHVR_ATTACHALLTHIS: + case RLV_BHVR_DETACHALL: + case RLV_BHVR_DETACHALLTHIS: + eFlags = (RlvForceWear::EWearFlags)(eFlags | RlvForceWear::FLAG_MATCHALL); + break; + default: + break; + } + + RlvForceWear::instance().forceFolder(pFolder, eAction, eFlags); return RLV_RET_SUCCESS; } diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h index 4447219cb3..306c8ba39e 100644 --- a/indra/newview/rlvhandler.h +++ b/indra/newview/rlvhandler.h @@ -162,8 +162,7 @@ protected: ERlvCmdRet onForceRemAttach(const RlvCommand& rlvCmd) const; ERlvCmdRet onForceRemOutfit(const RlvCommand& rlvCmd) const; ERlvCmdRet onForceSit(const RlvCommand& rlvCmd) const; - ERlvCmdRet onForceWear(const std::string& strPath, bool fAttach, bool fMatchAll) const; - ERlvCmdRet onForceWear(const LLViewerInventoryCategory* pFolder, bool fAttach, bool fMatchAll) const; + ERlvCmdRet onForceWear(const LLViewerInventoryCategory* pFolder, ERlvBehaviour eBhvr) const; // Command handlers (RLV_TYPE_REPLY) ERlvCmdRet processReplyCommand(const RlvCommand& rlvCmd) const; ERlvCmdRet onFindFolder(const RlvCommand& rlvCmd, std::string& strReply) const; diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 6d1a003e19..35465f4cb4 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -317,7 +317,7 @@ bool RlvForceWear::isWearingItem(const LLInventoryItem* pItem) } // Checked: 2010-03-21 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a -void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAction eAction, eWearFlags eFlags) +void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, EWearAction eAction, EWearFlags eFlags) { // [See LLWearableBridge::wearOnAvatar(): don't wear anything until initial wearables are loaded, can destroy clothing items] if (!gAgentWearables.areWearablesLoaded()) @@ -330,7 +330,7 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAc // Grab a list of all the items we'll be wearing/attaching LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items; - RlvWearableItemCollector f(pFolder->getUUID(), (ACTION_ATTACH == eAction), (FLAG_MATCHALL & eFlags)); + RlvWearableItemCollector f(pFolder->getUUID(), isWearAction(eAction), (eFlags & FLAG_MATCHALL)); gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, f); for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++) @@ -347,13 +347,13 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAc switch (pItem->getType()) { case LLAssetType::AT_BODYPART: - RLV_ASSERT(ACTION_ATTACH == eAction); // RlvWearableItemCollector shouldn't be supplying us with body parts on detach + RLV_ASSERT(isWearAction(eAction)); // RlvWearableItemCollector shouldn't be supplying us with body parts on detach case LLAssetType::AT_CLOTHING: - if (ACTION_ATTACH == eAction) + if (isWearAction(eAction)) { // The check for whether we're replacing a currently worn composite item happens in onWearableArrived() if (!isAddWearable(pItem)) - addWearable(pRlvItem); + addWearable(pRlvItem, eAction); } else { @@ -364,7 +364,7 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAc break; case LLAssetType::AT_OBJECT: - if (ACTION_ATTACH == eAction) + if (isWearAction(eAction)) { if ( (gRlvAttachmentLocks.canAttach(pRlvItem)) || (RlvSettings::getEnableSharedWear()) ) { @@ -388,7 +388,7 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAc else #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS { - addAttachment(pRlvItem); + addAttachment(pRlvItem, eAction); } } } @@ -403,7 +403,7 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, eWearAc #ifdef RLV_EXTENSION_FORCEWEAR_GESTURES case LLAssetType::AT_GESTURE: - if (ACTION_ATTACH == eAction) + if (isWearAction(eAction)) { if (std::find_if(m_addGestures.begin(), m_addGestures.end(), RlvPredIsEqualOrLinkedItem(pRlvItem)) == m_addGestures.end()) m_addGestures.push_back(pRlvItem); @@ -600,28 +600,69 @@ bool RlvForceWear::isStrippable(const LLInventoryItem* pItem) } #endif // RLV_EXTENSION_FLAG_NOSTRIP -// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f -void RlvForceWear::addAttachment(const LLViewerInventoryItem* pItem) +// Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c +void RlvForceWear::addAttachment(const LLViewerInventoryItem* pItem, EWearAction eAction) { // Remove it from 'm_remAttachments' if it's queued for detaching const LLViewerObject* pAttachObj = (isAgentAvatarValid()) ? gAgentAvatarp->getWornAttachment(pItem->getLinkedUUID()) : NULL; if ( (pAttachObj) && (isRemAttachment(pAttachObj)) ) m_remAttachments.erase(std::remove(m_remAttachments.begin(), m_remAttachments.end(), pAttachObj), m_remAttachments.end()); - // Add it to 'm_addAttachments' if it's not already there - if (!isAddAttachment(pItem)) - m_addAttachments.push_back((LLViewerInventoryItem*)pItem); + S32 idxAttachPt = RlvAttachPtLookup::getAttachPointIndex(pItem, true); + if (ACTION_WEAR_ADD == eAction) + { + // Insert it at the back if it's not already there + idxAttachPt |= ATTACHMENT_ADD; + if (!isAddAttachment(pItem)) + { + addattachments_map_t::iterator itAddAttachments = m_addAttachments.find(idxAttachPt); + if (itAddAttachments == m_addAttachments.end()) + { + m_addAttachments.insert(addattachment_pair_t(idxAttachPt, LLInventoryModel::item_array_t())); + itAddAttachments = m_addAttachments.find(idxAttachPt); + } + itAddAttachments->second.push_back((LLViewerInventoryItem*)pItem); + } + } + else if (ACTION_WEAR_REPLACE == eAction) + { + // Replace all pending attachments on this attachment point with the specified item (don't clear if it's the default attach point) + addattachments_map_t::iterator itAddAttachments = m_addAttachments.find(idxAttachPt | ATTACHMENT_ADD); + if ( (0 != idxAttachPt) && (itAddAttachments != m_addAttachments.end()) ) + itAddAttachments->second.clear(); + + itAddAttachments = m_addAttachments.find(idxAttachPt); + if (itAddAttachments == m_addAttachments.end()) + { + m_addAttachments.insert(addattachment_pair_t(idxAttachPt, LLInventoryModel::item_array_t())); + itAddAttachments = m_addAttachments.find(idxAttachPt); + } + + if (0 != idxAttachPt) + itAddAttachments->second.clear(); + itAddAttachments->second.push_back((LLViewerInventoryItem*)pItem); + } } -// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f +// Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c void RlvForceWear::remAttachment(const LLViewerObject* pAttachObj) { // Remove it from 'm_addAttachments' if it's queued for attaching const LLViewerInventoryItem* pItem = (pAttachObj->isAttachment()) ? gInventory.getItem(pAttachObj->getAttachmentItemID()) : NULL; - if ( (pItem) && (isAddAttachment(pItem)) ) + if (pItem) { - m_addAttachments.erase( - std::remove_if(m_addAttachments.begin(), m_addAttachments.end(), RlvPredIsEqualOrLinkedItem(pItem)), m_addAttachments.end()); + addattachments_map_t::iterator itAddAttachments = m_addAttachments.begin(); + while (itAddAttachments != m_addAttachments.end()) + { + LLInventoryModel::item_array_t& wearItems = itAddAttachments->second; + if (std::find_if(wearItems.begin(), wearItems.end(), RlvPredIsEqualOrLinkedItem(pItem)) != wearItems.end()) + wearItems.erase(std::remove_if(wearItems.begin(), wearItems.end(), RlvPredIsEqualOrLinkedItem(pItem)), wearItems.end()); + + if (wearItems.empty()) + m_addAttachments.erase(itAddAttachments++); + else + ++itAddAttachments; + } } // Add it to 'm_remAttachments' if it's not already there @@ -629,28 +670,49 @@ void RlvForceWear::remAttachment(const LLViewerObject* pAttachObj) m_remAttachments.push_back(pAttachObj); } -// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f -void RlvForceWear::addWearable(const LLViewerInventoryItem* pItem) +// Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c +void RlvForceWear::addWearable(const LLViewerInventoryItem* pItem, EWearAction eAction) { - // Remove it from 'm_remWearables' if it's queued for removal + // When replacing remove all currently worn wearables of this type + if (ACTION_WEAR_REPLACE == eAction) + forceRemove(pItem->getWearableType()); + // Remove it from 'm_remWearables' if it's pending removal const LLWearable* pWearable = gAgentWearables.getWearableFromItemID(pItem->getLinkedUUID());; if ( (pWearable) && (isRemWearable(pWearable)) ) m_remWearables.erase(std::remove(m_remWearables.begin(), m_remWearables.end(), pWearable), m_remWearables.end()); - // Add it to 'm_addWearables' if it's not already there - if (!isAddWearable(pItem)) - m_addWearables.push_back((LLViewerInventoryItem*)pItem); + addwearables_map_t::iterator itAddWearables = m_addWearables.find(pItem->getWearableType()); + if (itAddWearables == m_addWearables.end()) + { + m_addWearables.insert(addwearable_pair_t(pItem->getWearableType(), LLInventoryModel::item_array_t())); + itAddWearables = m_addWearables.find(pItem->getWearableType()); + } + + if (ACTION_WEAR_ADD == eAction) // Add it at the back if it's not already there + { + if (!isAddWearable(pItem)) + itAddWearables->second.push_back((LLViewerInventoryItem*)pItem); + } + else if (ACTION_WEAR_REPLACE == eAction) // Replace all pending wearables of this type with the specified item + { + itAddWearables->second.clear(); + itAddWearables->second.push_back((LLViewerInventoryItem*)pItem); + } } -// Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f +// Checked: 2010-08-30 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c void RlvForceWear::remWearable(const LLWearable* pWearable) { // Remove it from 'm_addWearables' if it's queued for wearing const LLViewerInventoryItem* pItem = gInventory.getItem(pWearable->getItemID()); if ( (pItem) && (isAddWearable(pItem)) ) { - m_addWearables.erase( - std::remove_if(m_addWearables.begin(), m_addWearables.end(), RlvPredIsEqualOrLinkedItem(pItem)), m_addWearables.end()); + addwearables_map_t::iterator itAddWearables = m_addWearables.find(pItem->getWearableType()); + + LLInventoryModel::item_array_t& wearItems = itAddWearables->second; + wearItems.erase(std::remove_if(wearItems.begin(), wearItems.end(), RlvPredIsEqualOrLinkedItem(pItem)), wearItems.end()); + if (wearItems.empty()) + m_addWearables.erase(itAddWearables); } // Add it to 'm_remWearables' if it's not already there @@ -730,45 +792,46 @@ void RlvForceWear::done() // Wearables need to be split into AT_BODYPART and AT_CLOTHING for COF LLInventoryModel::item_array_t addBodyParts, addClothing; - for (S32 idxItem = 0, cntItem = m_addWearables.count(); idxItem < cntItem; idxItem++) + for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.begin(); itAddWearables != m_addWearables.end(); ++itAddWearables) { - LLViewerInventoryItem* pItem = m_addWearables.get(idxItem); - if (LLAssetType::AT_BODYPART == pItem->getType()) - addBodyParts.push_back(pItem); - else - addClothing.push_back(pItem); + const LLInventoryModel::item_array_t& wearItems = itAddWearables->second; + for (S32 idxItem = 0, cntItem = wearItems.count(); idxItem < cntItem; idxItem++) + { + LLViewerInventoryItem* pItem = wearItems.get(idxItem); + if (LLAssetType::AT_BODYPART == pItem->getType()) + addBodyParts.push_back(pItem); + else + addClothing.push_back(pItem); + } } -#ifdef RLV_WORKAROUND_REZMULTIPLEATTACH - // Until SVC-5383 gets fixed we need to handle adding attachments ourselves instead of relying on COF + // Until LL provides a way for updateCOF to selectively attach add/replace we have to deal with attachments ourselves if (m_addAttachments.size()) { - for (S32 idxItem = 0, cntItem = m_addAttachments.count(); idxItem < cntItem; idxItem++) + for (addattachments_map_t::const_iterator itAddAttachments = m_addAttachments.begin(); + itAddAttachments != m_addAttachments.end(); ++itAddAttachments) { - const LLViewerInventoryItem* pItem = m_addAttachments.get(idxItem); - - S32 idxAttachPt = RlvAttachPtLookup::getAttachPointIndex(pItem, true); - if (0 != idxAttachPt) + const LLInventoryModel::item_array_t& wearItems = itAddAttachments->second; + for (S32 idxItem = 0, cntItem = wearItems.count(); idxItem < cntItem; idxItem++) { + const LLUUID& idItem = wearItems.get(idxItem)->getLinkedUUID(); + if (gAgentAvatarp->attachmentWasRequested(idItem)) + continue; + gAgentAvatarp->addAttachmentRequest(idItem); + LLSD payload; - payload["item_id"] = pItem->getLinkedUUID(); - payload["attachment_point"] = idxAttachPt; + payload["item_id"] = idItem; + payload["attachment_point"] = itAddAttachments->first; LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); } } - m_addAttachments.clear(); } -#endif // RLV_WORKAROUND_REZMULTIPLEATTACH // If there are additions we need to call LLAppearanceManager::updateCOF(), otherwise LLAppearanceManager::updateAppearanceFromCOF() if ( (!m_addWearables.empty()) || (!m_addAttachments.empty()) || (!m_addGestures.empty()) ) { -#ifndef RLV_WORKAROUND_SHAREDINVREPLACE - pAppearanceMgr->updateCOF(addBodyParts, addClothing, m_addAttachments, m_addGestures, true); -#else - pAppearanceMgr->updateCOF(addBodyParts, addClothing, m_addAttachments, m_addGestures, true, 1); -#endif // RLV_WORKAROUND_SHAREDINVREPLACE + pAppearanceMgr->updateCOF(addBodyParts, addClothing, LLInventoryModel::item_array_t(), m_addGestures, true); m_addWearables.clear(); m_addAttachments.clear(); diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 0839dd2401..ade4b58b16 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -218,11 +218,12 @@ protected: public: // Folders - enum eWearAction { ACTION_ATTACH, ACTION_DETACH }; - enum eWearFlags { FLAG_NONE = 0x00, FLAG_MATCHALL = 0x01, FLAG_DEFAULT = FLAG_NONE }; - void forceFolder(const LLViewerInventoryCategory* pFolder, eWearAction eAction, eWearFlags eFlags); + enum EWearAction { ACTION_WEAR_REPLACE, ACTION_WEAR_ADD, ACTION_REMOVE }; + enum EWearFlags { FLAG_NONE = 0x00, FLAG_MATCHALL = 0x01, FLAG_DEFAULT = FLAG_NONE }; + void forceFolder(const LLViewerInventoryCategory* pFolder, EWearAction eAction, EWearFlags eFlags); // Generic + static bool isWearAction(EWearAction eAction) { return (ACTION_WEAR_REPLACE == eAction) || (ACTION_WEAR_ADD == eAction); } static bool isWearableItem(const LLInventoryItem* pItem); static bool isWearingItem(const LLInventoryItem* pItem); @@ -245,15 +246,22 @@ public: public: void done(); protected: - void addAttachment(const LLViewerInventoryItem* pItem); + void addAttachment(const LLViewerInventoryItem* pItem, EWearAction eAction); void remAttachment(const LLViewerObject* pAttachObj); - void addWearable(const LLViewerInventoryItem* pItem); + void addWearable(const LLViewerInventoryItem* pItem, EWearAction eAction); void remWearable(const LLWearable* pWearable); // Convenience (prevents long lines that run off the screen elsewhere) bool isAddAttachment(const LLViewerInventoryItem* pItem) const { - return std::find_if(m_addAttachments.begin(), m_addAttachments.end(), RlvPredIsEqualOrLinkedItem(pItem)) != m_addAttachments.end(); + bool fFound = false; + for (addattachments_map_t::const_iterator itAddAttachments = m_addAttachments.begin(); + (!fFound) && (itAddAttachments != m_addAttachments.end()); ++itAddAttachments) + { + const LLInventoryModel::item_array_t& wearItems = itAddAttachments->second; + fFound = (std::find_if(wearItems.begin(), wearItems.end(), RlvPredIsEqualOrLinkedItem(pItem)) != wearItems.end()); + } + return fFound; } bool isRemAttachment(const LLViewerObject* pAttachObj) const { @@ -261,7 +269,14 @@ protected: } bool isAddWearable(const LLViewerInventoryItem* pItem) const { - return std::find_if(m_addWearables.begin(), m_addWearables.end(), RlvPredIsEqualOrLinkedItem(pItem)) != m_addWearables.end(); + bool fFound = false; + for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.begin(); + (!fFound) && (itAddWearables != m_addWearables.end()); ++itAddWearables) + { + const LLInventoryModel::item_array_t& wearItems = itAddWearables->second; + fFound = (std::find_if(wearItems.begin(), wearItems.end(), RlvPredIsEqualOrLinkedItem(pItem)) != wearItems.end()); + } + return fFound; } bool isRemWearable(const LLWearable* pWearable) const { @@ -269,9 +284,16 @@ protected: } protected: - LLInventoryModel::item_array_t m_addAttachments, m_addWearables, m_addGestures, m_remGestures; + typedef std::pair<LLWearableType::EType, LLInventoryModel::item_array_t> addwearable_pair_t; + typedef std::map<LLWearableType::EType, LLInventoryModel::item_array_t> addwearables_map_t; + addwearables_map_t m_addWearables; + typedef std::pair<S32, LLInventoryModel::item_array_t> addattachment_pair_t; + typedef std::map<S32, LLInventoryModel::item_array_t> addattachments_map_t; + addattachments_map_t m_addAttachments; + LLInventoryModel::item_array_t m_addGestures; std::list<const LLViewerObject*> m_remAttachments; - std::list<const LLWearable*> m_remWearables; + std::list<const LLWearable*> m_remWearables; + LLInventoryModel::item_array_t m_remGestures; private: friend class LLSingleton<RlvForceWear>; -- GitLab