// Checked: 2010-08-30 (RLVa-1.1.3b) | 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 = (gAgent.getAvatarObject()) ? gAgent.getAvatarObject()->getWornAttachment(pItem->getLinkedUUID()) : NULL; if ( (pAttachObj) && (isRemAttachment(pAttachObj)) ) m_remAttachments.erase(std::remove(m_remAttachments.begin(), m_remAttachments.end(), pAttachObj), m_remAttachments.end()); 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-03-21 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a 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()) { LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return; } if (!isAgentAvatarValid()) return; // 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, eAction, eFlags); gInventory.collectDescendentsIf(pFolder->getUUID(), folders, items, FALSE, f, TRUE); // TRUE if we've already encountered this LLWearableType::EType (used only on wear actions and only for AT_CLOTHING) bool fSeenWType[LLWearableType::WT_COUNT] = { false }; EWearAction eCurAction = eAction; for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++) { LLViewerInventoryItem* pRlvItem = items.get(idxItem); LLViewerInventoryItem* pItem = (LLAssetType::AT_LINK == pRlvItem->getActualType()) ? pRlvItem->getLinkedItem() : pRlvItem; // If it's wearable it should be worn on detach // if ( (ACTION_DETACH == eAction) && (isWearableItem(pItem)) && (!isWearingItem(pItem)) ) // continue; // Each folder can specify its own EWearAction override if (isWearAction(eAction)) eCurAction = f.getWearAction(pRlvItem->getParentUUID()); else eCurAction = eAction; // NOTES: * if there are composite items then RlvWearableItemCollector made sure they can be worn (or taken off depending) // * some scripts issue @remattach=force,attach:worn-items=force so we need to attach items even if they're currently worn switch (pItem->getType()) { case LLAssetType::AT_BODYPART: RLV_ASSERT(isWearAction(eAction)); // RlvWearableItemCollector shouldn't be supplying us with body parts on detach case LLAssetType::AT_CLOTHING: if (isWearAction(eAction)) { // The first time we encounter any given clothing type we use 'eCurAction' (replace or add) // The second time we encounter a given clothing type we'll always add (rather than replace the previous iteration) eCurAction = (!fSeenWType[pItem->getWearableType()]) ? eCurAction : ACTION_WEAR_ADD; ERlvWearMask eWearMask = gRlvWearableLocks.canWear(pRlvItem); if ( ((ACTION_WEAR_REPLACE == eCurAction) && (eWearMask & RLV_WEAR_REPLACE)) || ((ACTION_WEAR_ADD == eCurAction) && (eWearMask & RLV_WEAR_ADD)) ) { // The check for whether we're replacing a currently worn composite item happens in onWearableArrived() if (!isAddWearable(pItem)) addWearable(pRlvItem, eCurAction); fSeenWType[pItem->getWearableType()] = true; } } else { const LLViewerWearable* pWearable = gAgentWearables.getWearableFromItemID(pItem->getUUID()); if ( (pWearable) && (isForceRemovable(pWearable, false)) ) remWearable(pWearable); } break; case LLAssetType::AT_OBJECT: if (isWearAction(eAction)) { ERlvWearMask eWearMask = gRlvAttachmentLocks.canAttach(pRlvItem); if ( ((ACTION_WEAR_REPLACE == eCurAction) && (eWearMask & RLV_WEAR_REPLACE)) || ((ACTION_WEAR_ADD == eCurAction) && (eWearMask & RLV_WEAR_ADD)) ) { if (!isAddAttachment(pRlvItem)) { #ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS // We still need to check whether we're about to replace a currently worn composite item // (which we're not if we're just reattaching an attachment we're already wearing) LLViewerInventoryCategory* pCompositeFolder = NULL; if ( (pAttachPt->getObject()) && (RlvSettings::getEnableComposites()) && (pAttachPt->getItemID() != pItem->getUUID()) && (gRlvHandler.getCompositeInfo(pAttachPt->getItemID(), NULL, &pCompositeFolder)) ) { // If we can't take off the composite folder this item would replace then don't allow it to get attached if (gRlvHandler.canTakeOffComposite(pCompositeFolder)) { forceFolder(pCompositeFolder, ACTION_DETACH, FLAG_DEFAULT); addAttachment(pRlvItem); } } else #endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS { addAttachment(pRlvItem, eCurAction); } } } } else { const LLViewerObject* pAttachObj = gAgentAvatarp->getWornAttachment(pItem->getUUID()); if ( (pAttachObj) && (isForceDetachable(pAttachObj, false)) ) remAttachment(pAttachObj); } break; #ifdef RLV_EXTENSION_FORCEWEAR_GESTURES case LLAssetType::AT_GESTURE: if (isWearAction(eAction)) { if (std::find_if(m_addGestures.begin(), m_addGestures.end(), RlvPredIsEqualOrLinkedItem(pRlvItem)) == m_addGestures.end()) m_addGestures.push_back(pRlvItem); } else { if (std::find_if(m_remGestures.begin(), m_remGestures.end(), RlvPredIsEqualOrLinkedItem(pRlvItem)) == m_remGestures.end()) m_remGestures.push_back(pRlvItem); } break; #endif // RLV_EXTENSION_FORCEWEAR_GESTURES default: break; } } }