// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b void RlvAttachmentManager::onAttach(LLViewerJointAttachment* pAttachPt) { S32 idxAttachPt = gRlvHandler.getAttachPointIndex(pAttachPt->getObject()); if (!idxAttachPt) return; // If the attachment point has a pending "reattach" then we don't want to do anything rlv_attach_map_t::iterator itAttach = m_PendingAttach.find(idxAttachPt); if (itAttach != m_PendingAttach.end()) { if (pAttachPt->getItemID() == itAttach->second.idItem) m_PendingAttach.erase(itAttach); return; } // Check if the attach is the result of a user action (="Wear") rlv_wear_map_t::iterator itWear = m_PendingWear.find(pAttachPt->getItemID()); if (itWear != m_PendingWear.end()) { // We need to return the attachment point to its previous state if it's non-attachable if (gRlvHandler.isLockedAttachment(idxAttachPt, RLV_LOCK_ADD)) { // Get the state of the attachment point at the time the user picked "Wear" (if we don't have one it wasn't "add locked" then) std::map<S32, LLUUID>::iterator itAttachPrev = itWear->second.attachPts.find(idxAttachPt); if ( (itAttachPrev != itWear->second.attachPts.end()) && (pAttachPt->getItemID() != itAttachPrev->second) ) { // If it was empty we need to force detach the new attachment; if it wasn't we need to reattach the old one if (itAttachPrev->second.isNull()) { forceDetach(pAttachPt); m_PendingDetach.insert(std::pair<S32, LLUUID>(idxAttachPt, pAttachPt->getItemID())); } else if (m_PendingAttach.find(idxAttachPt) == m_PendingAttach.end()) // (only if we're not reattaching something else there) { m_PendingAttach.insert(std::pair<S32, RlvReattachInfo>(idxAttachPt, RlvReattachInfo(itAttachPrev->second))); } } } m_PendingWear.erase(itWear); // No need to start the timer since it should be running already if '!m_PendingWear.empty()' } }
// Checked: 2009-10-12 (RLVa-1.0.5b) | Modified: RLVa-1.0.5b void RlvAttachmentManager::onDetach(LLViewerJointAttachment* pAttachPt) { S32 idxAttachPt = gRlvHandler.getAttachPointIndex(pAttachPt->getObject()); if (!idxAttachPt) return; // If this is an attachment that we force-detached then we don't want to do anything (even if it is "remove locked") rlv_detach_map_t::iterator itDetach = m_PendingDetach.find(idxAttachPt); if ( (itDetach != m_PendingDetach.end()) && (itDetach->second == pAttachPt->getItemID()) ) { m_PendingDetach.erase(itDetach); return; } // If the attachment is currently "remove locked" and we're not already trying to reattach something there we should reattach it if ( (m_PendingAttach.find(idxAttachPt) == m_PendingAttach.end()) && (gRlvHandler.isLockedAttachment(idxAttachPt, RLV_LOCK_REMOVE)) ) { m_PendingAttach.insert(std::pair<S32, RlvReattachInfo>(idxAttachPt, RlvReattachInfo(pAttachPt->getItemID()))); startTimer(); } }
// Checked: 2010-07-28 (RLVa-1.1.3a) | Modified: RLVa-1.2.0i void RlvAttachmentLockWatchdog::onDetach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt) { S32 idxAttachPt = RlvAttachPtLookup::getAttachPointIndex(pAttachPt); const LLUUID& idAttachItem = (pAttachObj) ? pAttachObj->getAttachmentItemID() : LLUUID::null; RLV_ASSERT( (!gAgent.getAvatarObject()) || ((idxAttachPt) && (idAttachItem.notNull())) ); if ( (!idxAttachPt) || (idAttachItem.isNull()) ) return; // If it's an attachment that's pending force-detach then we don't want to do anything (even if it's currently "remove locked") rlv_detach_map_t::iterator itDetach = std::find(m_PendingDetach.begin(), m_PendingDetach.end(), idAttachItem); if (itDetach != m_PendingDetach.end()) { m_PendingDetach.erase(itDetach); return; } // If the attachment is currently "remove locked" then we should reattach it (unless it's already pending reattach) if (gRlvAttachmentLocks.isLockedAttachment(pAttachObj)) { bool fPendingAttach = false; for (rlv_attach_map_t::const_iterator itReattach = m_PendingAttach.lower_bound(idxAttachPt), itReattachEnd = m_PendingAttach.upper_bound(idxAttachPt); itReattach != itReattachEnd; ++itReattach) { if (itReattach->second.idItem == idAttachItem) { fPendingAttach = true; break; } } // TODO-RLVa: [RLVa-1.2.1] we should re-add the item to COF as well to make sure it'll reattach when the user relogs // -> check the call order in LLVOAvatarSelf::detachObject() since COF removal happens *after* we're called if (!fPendingAttach) { m_PendingAttach.insert(std::pair<S32, RlvReattachInfo>(idxAttachPt, RlvReattachInfo(idAttachItem))); startTimer(); } } }
// Checked: 2010-09-23 (RLVa-1.1.3a) | Modified: RLVa-1.2.1d void RlvAttachmentLockWatchdog::onAttach(const LLViewerObject* pAttachObj, const LLViewerJointAttachment* pAttachPt) { S32 idxAttachPt = RlvAttachPtLookup::getAttachPointIndex(pAttachObj); const LLUUID& idAttachItem = (pAttachObj) ? pAttachObj->getAttachmentItemID() : LLUUID::null; RLV_ASSERT( (!gAgent.getAvatarObject()) || ((idxAttachPt) && (idAttachItem.notNull())) ); if ( (!idxAttachPt) || (idAttachItem.isNull()) ) return; // Check if the attachment point has a pending "reattach" rlv_attach_map_t::iterator itAttach = m_PendingAttach.lower_bound(idxAttachPt), itAttachEnd = m_PendingAttach.upper_bound(idxAttachPt); if (itAttach != itAttachEnd) { bool fPendingReattach = false; for (; itAttach != itAttachEnd; ++itAttach) { if (idAttachItem == itAttach->second.idItem) { fPendingReattach = true; m_PendingAttach.erase(itAttach); break; } } if (!fPendingReattach) detach(pAttachObj); return; } // Check if the attach was allowed at the time it was requested rlv_wear_map_t::iterator itWear = m_PendingWear.find(idAttachItem); if (itWear != m_PendingWear.end()) { // We'll need to return the attachment point to its previous state if it was non-attachable if (itWear->second.isAddLockedAttachPt(idxAttachPt)) { // Get the saved state of the attachment point (but do nothing if the item itself was already worn then) std::map<S32, uuid_vec_t>::iterator itAttachPrev = itWear->second.attachPts.find(idxAttachPt); RLV_ASSERT(itAttachPrev != itWear->second.attachPts.end()); if (std::find(itAttachPrev->second.begin(), itAttachPrev->second.end(), idAttachItem) == itAttachPrev->second.end()) { // If it was empty we need to detach everything on the attachment point; if it wasn't we need to restore it to what it was if (itAttachPrev->second.empty()) { detach(idxAttachPt); } else { // Iterate over all the current attachments and force detach any that shouldn't be there c_llvo_vec_t attachObjs; for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator itAttachObj = pAttachPt->mAttachedObjects.begin(); itAttachObj != pAttachPt->mAttachedObjects.end(); ++itAttachObj) { const LLViewerObject* pAttachObj = *itAttachObj; uuid_vec_t::iterator itAttach = std::find(itAttachPrev->second.begin(), itAttachPrev->second.end(), pAttachObj->getAttachmentItemID()); if (itAttach == itAttachPrev->second.end()) detach(pAttachObj); else itAttachPrev->second.erase(itAttach); } // Whatever is left is something that needs to be reattached for (uuid_vec_t::const_iterator itAttach = itAttachPrev->second.begin(); itAttach != itAttachPrev->second.end(); ++itAttach) { m_PendingAttach.insert(std::pair<S32, RlvReattachInfo>(idxAttachPt, RlvReattachInfo(*itAttach))); } } } } else if (RLV_WEAR_REPLACE == itWear->second.eWearAction) { // Now that we know where this attaches to check if we can actually perform a "replace" bool fCanReplace = true; for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator itAttachObj = pAttachPt->mAttachedObjects.begin(); ((itAttachObj != pAttachPt->mAttachedObjects.end()) && (fCanReplace)); ++itAttachObj) { if (pAttachObj != *itAttachObj) fCanReplace &= !gRlvAttachmentLocks.isLockedAttachment(*itAttachObj); } if (fCanReplace) detach(idxAttachPt, pAttachObj); // Replace == allowed: detach everything except the new attachment else detach(pAttachObj); // Replace != allowed: detach the new attachment } m_PendingWear.erase(itWear); // No need to start the timer since it should be running already if '!m_PendingWear.empty()' } }