// Checked: 2010-03-18 (RLVa-1.2.0c) | Added: RLVa-1.2.0a void RlvWearableLocks::removeWearableTypeLock(EWearableType eType, const LLUUID& idRlvObj, ERlvLockMask eLock) { /* // Sanity check - make sure it's an object we know about if ( (m_Objects.find(idRlvObj) == m_Objects.end()) || (!idxAttachPt) ) return; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE) */ if (eLock & RLV_LOCK_REMOVE) { RLV_ASSERT( m_WearableTypeRem.lower_bound(eType) != m_WearableTypeRem.upper_bound(eType) ); // The lock should always exist for (rlv_wearabletypelock_map_t::iterator itWearableType = m_WearableTypeRem.lower_bound(eType), endWearableType = m_WearableTypeRem.upper_bound(eType); itWearableType != endWearableType; ++itWearableType) { if (idRlvObj == itWearableType->second) { m_WearableTypeRem.erase(itWearableType); break; } } } if (eLock & RLV_LOCK_ADD) { RLV_ASSERT( m_WearableTypeAdd.lower_bound(eType) != m_WearableTypeAdd.upper_bound(eType) ); // The lock should always exist for (rlv_wearabletypelock_map_t::iterator itWearableType = m_WearableTypeAdd.lower_bound(eType), endWearableType = m_WearableTypeAdd.upper_bound(eType); itWearableType != endWearableType; ++itWearableType) { if (idRlvObj == itWearableType->second) { m_WearableTypeAdd.erase(itWearableType); break; } } } }
// Checked: 2010-03-01 (RLVa-1.2.0c) | Added: RLVa-1.2.0a void RlvUIEnabler::onToggleUnsit() { bool fEnable = !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); LLPanelStandStopFlying* pPanelStand = LLPanelStandStopFlying::getInstance(); RLV_ASSERT(pPanelStand); if (pPanelStand) { LLButton* pBtnStand = pPanelStand->findChild<LLButton>("stand_btn"); RLV_ASSERT(pBtnStand); if (pBtnStand) pBtnStand->setEnabled(fEnable); } }
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a void RlvAttachmentLocks::removeAttachmentLock(const LLUUID& idAttachObj, const LLUUID& idRlvObj) { /* // Sanity check - make sure it's an object we know about if ( (m_Objects.find(idRlvObj) == m_Objects.end()) || (!idxAttachPt) ) return; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE) */ #ifndef RLV_RELEASE // NOTE: pObj *can* be NULL [see comments for @detach=n in RlvHandler::onAddRemDetach()] const LLViewerObject* pDbgObj = gObjectList.findObject(idAttachObj); // Assertion: if the object exists then it's an attachment and always specifies the root RLV_VERIFY( (!pDbgObj) || ((pDbgObj->isAttachment()) && (pDbgObj == pDbgObj->getRootEdit())) ); #endif // RLV_RELEASE // NOTE: try to remove the lock even if pObj isn't an attachment (ie in case the user was able to "Drop" it) RLV_ASSERT( m_AttachObjRem.lower_bound(idAttachObj) != m_AttachObjRem.upper_bound(idAttachObj) ); // The lock should always exist for (rlv_attachobjlock_map_t::iterator itAttachObj = m_AttachObjRem.lower_bound(idAttachObj), endAttachObj = m_AttachObjRem.upper_bound(idAttachObj); itAttachObj != endAttachObj; ++itAttachObj) { if (idRlvObj == itAttachObj->second) { m_AttachObjRem.erase(itAttachObj); updateLockedHUD(); break; } } }
// Checked: 2010-03-02 (RLVa-1.1.3a) | Modified: RLVa-0.2.0g std::string RlvInventory::getSharedPath(const LLViewerInventoryCategory* pFolder) const { // Sanity check - no shared root or no folder => no path const LLViewerInventoryCategory* pRlvRoot = getSharedRoot(); if ( (!pRlvRoot) || (!pFolder) || (pRlvRoot->getUUID() == pFolder->getUUID()) ) return std::string(); const LLUUID& idRLV = pRlvRoot->getUUID(); const LLUUID& idRoot = gInventory.getRootFolderID(); std::string strPath; // Walk up the tree until we reach the top RLV_ASSERT(gInventory.isObjectDescendentOf(pFolder->getUUID(), pRlvRoot->getUUID())); while (pFolder) { strPath = "/" + pFolder->getName() + strPath; const LLUUID& idParent = pFolder->getParentUUID(); if (idRLV == idParent) // Reached the shared root, we're done break; else if (idRoot == idParent) // We reached the agent's inventory root (indicative of a logic error elsewhere) return std::string(); pFolder = gInventory.getCategory(idParent); } return strPath.erase(0, 1); }
// Checked: 2010-07-28 (RLVa-1.1.3a) | Modified: RLVa-1.2.0i void RlvAttachmentLockWatchdog::onWearAttachment(const LLUUID& idItem, ERlvWearMask eWearAction) { // We only need to keep track of user wears if there's actually anything locked RLV_ASSERT(idItem.notNull()); LLVOAvatar* pAvatar = gAgent.getAvatarObject(); if ( (idItem.isNull()) || (!pAvatar) || (!gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) ) return; // If the attachment point this will end up being attached to is: // - unlocked : nothing should happen (from RLVa's point of view) // - RLV_LOCK_ADD: the new attachment should get detached and the current one(s) reattached (unless it's currently empty) // - RLV_LOCK_REM: // o eWearAction == RLV_WEAR_ADD : nothing should happen (from RLVa's point of view) // o eWearAction == RLV_WEAR_REPLACE : examine whether the new attachment can indeed replace/detach the old one RlvWearInfo infoWear(idItem, eWearAction); RLV_ASSERT( (RLV_WEAR_ADD == eWearAction) || (RLV_WEAR_REPLACE == eWearAction) ); // One of the two, but never both for (LLVOAvatar::attachment_map_t::const_iterator itAttachPt = pAvatar->mAttachmentPoints.begin(); itAttachPt != pAvatar->mAttachmentPoints.end(); ++itAttachPt) { const LLViewerJointAttachment* pAttachPt = itAttachPt->second; // We only need to know which attachments were present for RLV_LOCK_ADD locked attachment points (and not RLV_LOCK_REM locked ones) if (gRlvAttachmentLocks.isLockedAttachmentPoint(pAttachPt, RLV_LOCK_ADD)) { uuid_vec_t attachObjs; for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator itAttachObj = pAttachPt->mAttachedObjects.begin(); itAttachObj != pAttachPt->mAttachedObjects.end(); ++itAttachObj) { const LLViewerObject* pAttachObj = *itAttachObj; if (std::find(m_PendingDetach.begin(), m_PendingDetach.end(), pAttachObj->getAttachmentItemID()) != m_PendingDetach.end()) continue; // Exclude attachments that are pending a force-detach attachObjs.push_back(pAttachObj->getAttachmentItemID()); } infoWear.attachPts.insert(std::pair<S32, uuid_vec_t>(itAttachPt->first, attachObjs)); } } m_PendingWear.insert(std::pair<LLUUID, RlvWearInfo>(idItem, infoWear)); #ifdef RLV_DEBUG infoWear.dumpInstance(); #endif // RLV_RELEASE startTimer(); }
// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a F32 RlvWindLightControl::getColorComponent(EColorComponent eComponent, bool& fError) const { switch (eComponent) { case COMPONENT_R: return getColorVector(fError).mV[0]; case COMPONENT_G: return getColorVector(fError).mV[1]; case COMPONENT_B: return getColorVector(fError).mV[2]; case COMPONENT_I: return get_intensity_from_color(getColorVector(fError)); // SL-2.8: Always seems to be 1.0 so get it manually default : RLV_ASSERT(false); fError = true; return 0.0; } }
// Checked: 2010-08-22 (RLVa-1.2.1a) | Added: RLVa-1.2.1a void RlvUIEnabler::onToggleTp() { // Disable the navigation bar "Home" button if both @tplm=n *and* @tploc=n restricted // <FS:Zi> Make navigation bar part of the UI // LLButton* pNavBarHomeBtn = LLNavigationBar::getInstance()->findChild<LLButton>("home_btn"); LLButton* pNavBarHomeBtn = LLNavigationBar::instance().getView()->findChild<LLButton>("home_btn"); // </FS:Zi> RLV_ASSERT(pNavBarHomeBtn); if (pNavBarHomeBtn) pNavBarHomeBtn->setEnabled(!(gRlvHandler.hasBehaviour(RLV_BHVR_TPLM) && gRlvHandler.hasBehaviour(RLV_BHVR_TPLOC))); }
// Checked: 2010-02-28 (RLVa-1.4.0a) | Added: RLVa-1.2.0a void RlvUIEnabler::onToggleShowMinimap() { bool fEnable = !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWMINIMAP); // Start or stop filtering showing the mini-map floater if (!fEnable) addGenericFloaterFilter("mini_map"); else removeGenericFloaterFilter("mini_map"); // Hide the mini-map floater if it's currently visible (or restore it if it was previously visible) static bool fPrevVisibile = false; if ( (!fEnable) && ((fPrevVisibile = LLFloaterReg::instanceVisible("mini_map"))) ) LLFloaterReg::hideInstance("mini_map"); else if ( (fEnable) && (fPrevVisibile) ) LLFloaterReg::showInstance("mini_map"); // Break/reestablish the visibility connection for the nearby people panel embedded minimap instance LLPanel* pPeoplePanel = LLFloaterSidePanelContainer::getPanel("people", "panel_people"); LLPanel* pNetMapPanel = (pPeoplePanel) ? pPeoplePanel->getChild<LLPanel>("minimaplayout", TRUE) : NULL; //AO: firestorm specific RLV_ASSERT( (pPeoplePanel) && (pNetMapPanel) ); if (pNetMapPanel) { pNetMapPanel->setMakeVisibleControlVariable( (fEnable) ? gSavedSettings.getControl("ShowRadarMinimap").get() : NULL); // Reestablishing the visiblity connection will show the panel if needed so we only need to take care of hiding it when needed if ( (!fEnable) && (pNetMapPanel->getVisible()) ) pNetMapPanel->setVisible(false); } // Break/reestablish the visibility connection for the radar panel embedded minimap instance LLFloater* pRadarFloater = LLFloaterReg::getInstance("fs_radar"); LLPanel* pRadarNetMapPanel = (pRadarFloater) ? pRadarFloater->getChild<LLPanel>("minimaplayout", TRUE) : NULL; //AO: firestorm specific RLV_ASSERT( (pRadarFloater) && (pRadarNetMapPanel) ); if (pRadarNetMapPanel) { pRadarNetMapPanel->setMakeVisibleControlVariable( (fEnable) ? gSavedSettings.getControl("ShowRadarMinimap").get() : NULL); // Reestablishing the visiblity connection will show the panel if needed so we only need to take care of hiding it when needed if ( (!fEnable) && (pRadarNetMapPanel->getVisible()) ) pRadarNetMapPanel->setVisible(false); } }
// Checked: 2009-12-05 (RLVa-1.1.0h) | Added: RLVa-1.1.0h ERlvBehaviour RlvCommand::getBehaviourFromString(const std::string& strBhvr, bool* pfStrict /*=NULL*/) { std::string::size_type idxStrict = strBhvr.find("_sec"); bool fStrict = (std::string::npos != idxStrict) && (idxStrict + 4 == strBhvr.length()); if (pfStrict) *pfStrict = fStrict; RLV_ASSERT(m_BhvrMap.size() > 0); bhvr_map_t::const_iterator itBhvr = m_BhvrMap.find( (!fStrict) ? strBhvr : strBhvr.substr(0, idxStrict)); if ( (itBhvr != m_BhvrMap.end()) && ((!fStrict) || (hasStrictVariant(itBhvr->second))) ) return itBhvr->second; return RLV_BHVR_UNKNOWN; }
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a void RlvAttachmentLocks::removeAttachmentPointLock(S32 idxAttachPt, const LLUUID& idRlvObj, ERlvLockMask eLock) { /* // Sanity check - make sure it's an object we know about if ( (m_Objects.find(idRlvObj) == m_Objects.end()) || (!idxAttachPt) ) return; // If (idxAttachPt) == 0 then: (pObj == NULL) || (pObj->isAttachment() == FALSE) */ if (eLock & RLV_LOCK_REMOVE) { RLV_ASSERT( m_AttachPtRem.lower_bound(idxAttachPt) != m_AttachPtRem.upper_bound(idxAttachPt) ); // The lock should always exist for (rlv_attachptlock_map_t::iterator itAttachPt = m_AttachPtRem.lower_bound(idxAttachPt), endAttachPt = m_AttachPtRem.upper_bound(idxAttachPt); itAttachPt != endAttachPt; ++itAttachPt) { if (idRlvObj == itAttachPt->second) { m_AttachPtRem.erase(itAttachPt); updateLockedHUD(); break; } } } if (eLock & RLV_LOCK_ADD) { RLV_ASSERT( m_AttachPtAdd.lower_bound(idxAttachPt) != m_AttachPtAdd.upper_bound(idxAttachPt) ); // The lock should always exist for (rlv_attachptlock_map_t::iterator itAttachPt = m_AttachPtAdd.lower_bound(idxAttachPt), endAttachPt = m_AttachPtAdd.upper_bound(idxAttachPt); itAttachPt != endAttachPt; ++itAttachPt) { if (idRlvObj == itAttachPt->second) { m_AttachPtAdd.erase(itAttachPt); break; } } } }
// Checked: 2010-04-22 (RLVa-1.2.0f) | Modified: RLVa-1.2.0f bool RlvUtil::isNearbyAgent(const LLUUID& idAgent) { // Sanity check since we call this with notification payloads as well and those strings tend to change from one release to another RLV_ASSERT(idAgent.notNull()); if ( (idAgent.notNull()) && (gAgent.getID() != idAgent) ) { std::vector<LLUUID> idAgents; LLWorld::getInstance()->getAvatars(&idAgents, NULL); for (int idxAgent = 0, cntAgent = idAgents.size(); idxAgent < cntAgent; idxAgent++) if (idAgents[idxAgent] == idAgent) return true; } return false; }
bool RlvObject::removeCommand(const RlvCommand& rlvCmd) { RLV_ASSERT(RLV_TYPE_REMOVE == rlvCmd.getParamType()); for (rlv_command_list_t::iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd) { //if (*itCmd == rlvCmd) <- commands will never be equal since one is an add and the other is a remove *rolls eyes* if ( (itCmd->getBehaviour() == rlvCmd.getBehaviour()) && (itCmd->getOption() == rlvCmd.getOption()) && (itCmd->isStrict() == rlvCmd.isStrict() ) ) { m_Commands.erase(itCmd); return true; } } return false; // Command was never added so nothing to remove now }
// Checked: 2010-12-11 (RLVa-1.2.2c) | Added: RLVa-1.2.2c bool RlvCommand::getCommands(bhvr_map_t& cmdList, const std::string &strMatch) { if (strMatch.empty()) return false; cmdList.clear(); RLV_ASSERT(m_BhvrMap.size() > 0); for (bhvr_map_t::const_iterator itBhvr = m_BhvrMap.begin(); itBhvr != m_BhvrMap.end(); ++itBhvr) { std::string strCmd = itBhvr->first; ERlvBehaviour eBhvr = itBhvr->second; if (std::string::npos != strCmd.find(strMatch)) cmdList.insert(std::pair<std::string, ERlvBehaviour>(strCmd, eBhvr)); if ( (hasStrictVariant(eBhvr)) && (std::string::npos != strCmd.append("_sec").find(strMatch)) ) cmdList.insert(std::pair<std::string, ERlvBehaviour>(strCmd, eBhvr)); } return (0 != cmdList.size()); }
// Checked: 2010-03-19 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a bool RlvAttachmentLocks::isLockedAttachmentExcept(const LLViewerObject* pObj, const LLUUID& idRlvObj) const { if (idRlvObj.isNull()) return isLockedAttachment(pObj); // If pObj is valid then it should always specify a root since we store root UUIDs in m_AttachObjRem RLV_ASSERT( (!pObj) || (pObj == pObj->getRootEdit()) ); // Loop over every object that has the specified attachment locked (but ignore any locks owned by idRlvObj) for (rlv_attachobjlock_map_t::const_iterator itAttachObj = m_AttachObjRem.lower_bound(pObj->getID()), endAttachObj = m_AttachObjRem.upper_bound(pObj->getID()); itAttachObj != endAttachObj; ++itAttachObj) { if (itAttachObj->second != idRlvObj) return true; } return isLockedAttachmentPointExcept(RlvAttachPtLookup::getAttachPointIndex(pObj), RLV_LOCK_REMOVE, idRlvObj); }
// Checked: 2010-03-22 (RLVa-1.2.0c) | Added: RLVa-1.2.0a bool rlvPredCanRemoveItem(const LLViewerInventoryItem* pItem) { if ( (pItem) && (RlvForceWear::isWearableItem(pItem)) ) { switch (pItem->getType()) { case LLAssetType::AT_BODYPART: case LLAssetType::AT_CLOTHING: return gRlvWearableLocks.canRemove(pItem); case LLAssetType::AT_OBJECT: return gRlvAttachmentLocks.canDetach(pItem); case LLAssetType::AT_GESTURE: return true; default: RLV_ASSERT(false); } } return false; }
bool RlvObject::addCommand(const RlvCommand& rlvCmd) { RLV_ASSERT(RLV_TYPE_ADD == rlvCmd.getParamType()); // Don't add duplicate commands for this object (ie @detach=n followed by another @detach=n later on) for (rlv_command_list_t::iterator itCmd = m_Commands.begin(); itCmd != m_Commands.end(); ++itCmd) { if ( (itCmd->getBehaviour() == rlvCmd.getBehaviour()) && (itCmd->getOption() == rlvCmd.getOption()) && (itCmd->isStrict() == rlvCmd.isStrict() ) ) { return false; } } // Now that we know it's not a duplicate, add it to the end of the list m_Commands.push_back(rlvCmd); return true; }
void LLFloaterAvatarPicker::onList() { getChildView("ok_btn")->setEnabled(isSelectBtnEnabled()); // [RLVa:KB] - Checked: 2010-06-05 (RLVa-1.2.2a) | Modified: RLVa-1.2.0d if (rlv_handler_t::isEnabled()) { LLTabContainer* pTabs = getChild<LLTabContainer>("ResidentChooserTabs"); LLPanel* pNearMePanel = getChild<LLPanel>("NearMePanel"); RLV_ASSERT( (pTabs) && (pNearMePanel) ); if ( (pTabs) && (pNearMePanel) ) { bool fRlvEnable = !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); pTabs->enableTabButton(pTabs->getIndexForPanel(pNearMePanel), fRlvEnable); if ( (!fRlvEnable) && (pTabs->getCurrentPanel() == pNearMePanel) ) pTabs->selectTabByName("SearchPanel"); } } // [/RLVa:KB] }
// 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-12-08 (RLVa-1.4.0a) | Modified: RLVa-1.2.2c void RlvUIEnabler::onToggleShowNames(bool fQuitting) { if (fQuitting) return; // Nothing to do if the viewer is shutting down bool fEnable = !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); // Refresh the nearby people list // <FS:Ansariel> [Standalone radar] //LLPanelPeople* pPeoplePanel = LLFloaterSidePanelContainer::getPanel<LLPanelPeople>("people", "panel_people"); //RLV_ASSERT( (pPeoplePanel) && (pPeoplePanel->getNearbyList()) ); //if ( (pPeoplePanel) && (pPeoplePanel->getNearbyList()) ) // pPeoplePanel->getNearbyList()->updateAvatarNames(); FSRadar* pRadar = FSRadar::getInstance(); RLV_ASSERT( (pRadar) ); if ( (pRadar) ) pRadar->updateNames(); // </FS:Ansariel> [Standalone radar] // Refresh the speaker list // <FS:Ansariel> [FS communication UI] FSFloaterVoiceControls* pCallFloater = LLFloaterReg::findTypedInstance<FSFloaterVoiceControls>("fs_voice_controls"); if (pCallFloater) pCallFloater->getAvatarCallerList()->updateAvatarNames(); // </FS:Ansariel> [FS communication UI] // Force the use of the "display name" cache so we can filter both display and legacy names (or return back to the user's preference) if (!fEnable) { LLAvatarNameCache::setForceDisplayNames(true); } else { LLAvatarNameCache::setForceDisplayNames(false); LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); } LLVOAvatar::invalidateNameTags(); // See handleDisplayNamesOptionChanged() }
// Checked: 2009-11-25 (RLVa-1.1.0f) | Added: RLVa-1.1.0f const char* RlvStrings::getStringFromReturnCode(ERlvCmdRet eRet) { // TODO-RLVa: [2009-11-25] clean this up along with the calling code in process_chat_from_simulator() once we're happy with the output switch (eRet) { case RLV_RET_SUCCESS_UNSET: return "unset"; case RLV_RET_SUCCESS_DUPLICATE: return "duplicate"; case RLV_RET_SUCCESS_DELAYED: return "delayed"; case RLV_RET_FAILED_SYNTAX: return "thingy error"; case RLV_RET_FAILED_OPTION: return "invalid option"; case RLV_RET_FAILED_PARAM: return "invalid param"; case RLV_RET_FAILED_LOCK: return "locked command"; case RLV_RET_FAILED_DISABLED: return "disabled command"; case RLV_RET_FAILED_UNKNOWN: return "unknown command"; case RLV_RET_FAILED_NOSHAREDROOT: return "missing #RLV"; // The following are identified by the chat verb case RLV_RET_RETAINED: case RLV_RET_SUCCESS: case RLV_RET_FAILED: break; // The following shouldn't occur case RLV_RET_UNKNOWN: default: RLV_ASSERT(false); break; }; return NULL; }
// Checked: 2010-11-11 (RLVa-1.2.1g) | Modified: RLVa-1.2.1g bool rlvPredCanWearItem(const LLViewerInventoryItem* pItem, ERlvWearMask eWearMask) { if ( (pItem) && (RlvForceWear::isWearableItem(pItem)) ) { if (RlvForceWear::isWearingItem(pItem)) return true; // Special exception for currently worn items switch (pItem->getType()) { case LLAssetType::AT_BODYPART: // NOTE: only one body part of each type is allowed so the only way to wear one is if we can replace the current one return (RLV_WEAR_LOCKED != (gRlvWearableLocks.canWear(pItem) & RLV_WEAR_REPLACE & eWearMask)); case LLAssetType::AT_CLOTHING: return (RLV_WEAR_LOCKED != (gRlvWearableLocks.canWear(pItem) & eWearMask)); case LLAssetType::AT_OBJECT: return (RLV_WEAR_LOCKED != (gRlvAttachmentLocks.canAttach(pItem) & eWearMask)); case LLAssetType::AT_GESTURE: return true; default: RLV_ASSERT(false); } } return false; }
// 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 if ( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) && (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) ) { return; } // // Process removals // uuid_vec_t remItems; // Wearables if (m_remWearables.size()) { 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 and supply its own callback for (const LLViewerInventoryItem* pItem : m_remGestures) LLGestureMgr::instance().deactivateGesture(pItem->getUUID()); m_remGestures.clear(); } // Attachments if (m_remAttachments.size()) { LLAgentWearables::userRemoveMultipleAttachments(m_remAttachments); for (const LLViewerObject* pAttachObj : m_remAttachments) remItems.push_back(pAttachObj->getAttachmentItemID()); m_remAttachments.clear(); } // // Process additions // // 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.cbegin(); itAddWearables != m_addWearables.cend(); ++itAddWearables) { // NOTE: LLAppearanceMgr will filter our duplicates so no need for us to check here for (LLViewerInventoryItem* pItem : itAddWearables->second) { 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.cbegin(); itAddAttachments != m_addAttachments.cend(); ++itAddAttachments) { for (const LLViewerInventoryItem* pItem : itAddAttachments->second) addPendingAttachment(pItem->getLinkedUUID(), itAddAttachments->first); } m_addAttachments.clear(); // // 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()) ) { // Clothing items only uuid_vec_t idClothing; for (const LLViewerInventoryItem* pItem : addClothing) idClothing.push_back(pItem->getUUID()); LLAppearanceMgr::instance().wearItemsOnAvatar(idClothing, false, false, cb); } else if ( (!addBodyParts.empty()) || (!addClothing.empty()) || (!m_addGestures.empty()) ) { // Mixture of body parts, clothing and/or gestures LLInventoryModel::item_array_t addAttachments; LLAppearanceMgr::instance().updateCOF(addBodyParts, addClothing, addAttachments, m_addGestures, true, LLUUID::null, cb); m_addGestures.clear(); } // 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()) ); }
// Checked: 2010-09-18 (RLVa-1.2.1) void RlvForceWear::done() { // Sanity check - don't go through all the motions below only to find out there's nothing to actually do if ( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) && (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) ) { return; } LLAppearanceMgr* pAppearanceMgr = LLAppearanceMgr::getInstance(); // // Process removals // // 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()); m_remWearables.clear(); } // Gestures if (m_remGestures.size()) { // NOTE: LLGestureMgr::deactivateGesture() will call LLAppearanceMgr::removeCOFItemLinks() for us for (S32 idxItem = 0, cntItem = m_remGestures.count(); idxItem < cntItem; idxItem++) LLGestureMgr::instance().deactivateGesture(m_remGestures.get(idxItem)->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()); } m_remAttachments.clear(); } // // Process additions // // 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) { const LLInventoryModel::item_array_t& wearItems = itAddWearables->second; for (S32 idxItem = 0, cntItem = wearItems.count(); idxItem < cntItem; idxItem++) { LLViewerInventoryItem* pItem = wearItems.get(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); } } } 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) { 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); LLAttachmentsMgr::instance().addAttachment(idItem, itAddAttachments->first & ~ATTACHMENT_ADD, itAddAttachments->first & ATTACHMENT_ADD); } } m_addAttachments.clear(); // If there are additions we need to call LLAppearanceManager::updateCOF(), otherwise LLAppearanceManager::updateAppearanceFromCOF() if ( (!addBodyParts.empty()) || (!addClothing.empty()) || (!m_addGestures.empty()) ) { LLInventoryModel::item_array_t addAttachments; pAppearanceMgr->updateCOF(addBodyParts, addClothing, addAttachments, m_addGestures, true); m_addGestures.clear(); } // Since RlvForceWear is a singleton now we want to be sure there aren't any leftovers RLV_ASSERT( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) ); RLV_ASSERT( (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) ); }
// 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; } } }
// 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()' } }
// Checked: 2011-08-29 (RLVa-1.4.1a) | Added: RLVa-1.4.1a bool RlvWindLight::setValue(const std::string& strRlvName, const std::string& strValue) { F32 nValue = 0.0f; // Sanity check - make sure strValue specifies a number for all settings except "preset" and "daycycle" if ( (RlvSettings::getNoSetEnv()) || ( (!LLStringUtil::convertToF32(strValue, nValue)) && (("preset" != strRlvName) && ("daycycle" != strRlvName)) ) ) { return false; } LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); LLEnvManagerNew* pEnvMgr = LLEnvManagerNew::getInstance(); if ("daytime" == strRlvName) { if (0.0f <= nValue) { pWLParams->mAnimator.deactivate(); pWLParams->mAnimator.setDayTime(nValue); pWLParams->mAnimator.update(pWLParams->mCurParams); } else { pEnvMgr->useRegionSettings(); } return true; } else if ("preset" == strRlvName) { std::string strPresetName = pWLParams->findPreset(strValue, LLEnvKey::SCOPE_LOCAL); if (!strPresetName.empty()) pEnvMgr->useSkyPreset(strPresetName); return !strPresetName.empty(); } else if ("daycycle" == strRlvName) { std::string strPresetName = LLDayCycleManager::instance().findPreset(strValue); if (!strPresetName.empty()) pEnvMgr->useDayCycle(strValue, LLEnvKey::SCOPE_LOCAL); return !strPresetName.empty(); } bool fError = false; pWLParams->mAnimator.deactivate(); if (("sunglowfocus" == strRlvName) || ("sunglowsize" == strRlvName)) { pWLParams->mGlow = pWLParams->mCurParams.getVector(pWLParams->mGlow.mName, fError); RLV_ASSERT_DBG(!fError); if ("sunglowfocus" == strRlvName) pWLParams->mGlow.b = -nValue * 5; else pWLParams->mGlow.r = (2 - nValue) * 20; pWLParams->mGlow.update(pWLParams->mCurParams); pWLParams->propagateParameters(); return true; } else if ("starbrightness" == strRlvName) { pWLParams->mCurParams.setStarBrightness(nValue); return true; } else if (("eastangle" == strRlvName) || ("sunmoonposition" == strRlvName)) { if ("eastangle" == strRlvName) pWLParams->mCurParams.setEastAngle(F_TWO_PI * nValue); else pWLParams->mCurParams.setSunAngle(F_TWO_PI * nValue); // Set the sun vector pWLParams->mLightnorm.r = -sin(pWLParams->mCurParams.getEastAngle()) * cos(pWLParams->mCurParams.getSunAngle()); pWLParams->mLightnorm.g = sin(pWLParams->mCurParams.getSunAngle()); pWLParams->mLightnorm.b = cos(pWLParams->mCurParams.getEastAngle()) * cos(pWLParams->mCurParams.getSunAngle()); pWLParams->mLightnorm.i = 1.f; pWLParams->propagateParameters(); return true; } else if ("cloudscrollx" == strRlvName) { pWLParams->mCurParams.setCloudScrollX(nValue + 10.0f); return true; } else if ("cloudscrolly" == strRlvName) { pWLParams->mCurParams.setCloudScrollY(nValue + 10.0f); return true; } std::map<std::string, RlvWindLightControl>::iterator itControl = m_ControlLookupMap.find(strRlvName); if (m_ControlLookupMap.end() != itControl) { switch (itControl->second.getControlType()) { case RlvWindLightControl::TYPE_FLOAT: return itControl->second.setFloat(nValue); case RlvWindLightControl::TYPE_COLOR_R: return itControl->second.setColorComponent(RlvWindLightControl::COMPONENT_R, nValue); default: RLV_ASSERT(false); } } else { // Couldn't find the exact name, check for a color control name RlvWindLightControl::EColorComponent eComponent = RlvWindLightControl::getComponentFromCharacter(strRlvName[strRlvName.length() - 1]); if (RlvWindLightControl::COMPONENT_NONE != eComponent) itControl = m_ControlLookupMap.find(strRlvName.substr(0, strRlvName.length() - 1)); if ( (m_ControlLookupMap.end() != itControl) && (itControl->second.isColorType()) ) return itControl->second.setColorComponent(eComponent, nValue); } return false; }
// Checked: 2010-03-14 (RLVa-1.2.0a) | Added: RLVa-1.2.0a void RlvRenameOnWearObserver::doneIdle() { const LLViewerInventoryCategory* pRlvRoot = NULL; if ( (RlvSettings::getEnableSharedWear()) || (!RlvSettings::getSharedInvAutoRename()) || (LLStartUp::getStartupState() < STATE_STARTED) || (!isAgentAvatarValid()) || ((pRlvRoot = RlvInventory::instance().getSharedRoot()) == NULL) ) { delete this; return; } const LLViewerJointAttachment* pAttachPt = NULL; S32 idxAttachPt = 0; // Kitty says this check really doesn't do much of anything. -- TS // RLV_ASSERT(mComplete.size() > 0); // Catch instances where we forgot to call startFetch() for (uuid_vec_t::const_iterator itItem = mComplete.begin(); itItem != mComplete.end(); ++itItem) { const LLUUID& idAttachItem = *itItem; // If the item resides under #RLV we'll rename it directly; otherwise settle for "renaming" all of its links residing under #RLV LLInventoryModel::item_array_t items; if (gInventory.isObjectDescendentOf(idAttachItem, pRlvRoot->getUUID())) items.push_back(gInventory.getItem(idAttachItem)); else items = gInventory.collectLinkedItems(idAttachItem, pRlvRoot->getUUID()); if (items.empty()) continue; if ( ((pAttachPt = gAgentAvatarp->getWornAttachmentPoint(idAttachItem)) == NULL) || ((idxAttachPt = RlvAttachPtLookup::getAttachPointIndex(pAttachPt)) == 0) ) { RLV_ASSERT(false); continue; } for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++) { LLViewerInventoryItem* pItem = items.get(idxItem); if (!pItem) continue; S32 idxAttachPtItem = RlvAttachPtLookup::getAttachPointIndex(pItem); if ( (idxAttachPt == idxAttachPtItem) || (idxAttachPtItem) ) continue; std::string strAttachPt = pAttachPt->getName(); LLStringUtil::toLower(strAttachPt); // If we can modify the item then we rename it directly, otherwise we create a new folder and move it if (pItem->getPermissions().allowModifyBy(gAgent.getID())) { std::string strName = pItem->getName(); LLStringUtil::truncate(strName, DB_INV_ITEM_NAME_STR_LEN - strAttachPt.length() - 3); strName += " (" + strAttachPt + ")"; pItem->rename(strName); pItem->updateServer(FALSE); gInventory.addChangedMask(LLInventoryObserver::LABEL, pItem->getUUID()); } else { // Don't do anything if the item is a direct descendant of the shared root, or a folded folder LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID()); if ( (pFolder) && (pFolder->getUUID() != pRlvRoot->getUUID()) && (!RlvInventory::isFoldedFolder(pFolder, false)) ) { std::string strFolderName = ".(" + strAttachPt + ")"; // Rename the item's parent folder if it's called "New Folder", isn't directly under #RLV and contains exactly 1 object if ( (LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_NONE) == pFolder->getName()) && (pFolder->getParentUUID() != pRlvRoot->getUUID()) && (1 == RlvInventory::getDirectDescendentsItemCount(pFolder, LLAssetType::AT_OBJECT)) ) { pFolder->rename(strFolderName); pFolder->updateServer(FALSE); gInventory.addChangedMask(LLInventoryObserver::LABEL, pFolder->getUUID()); } else { // "No modify" item with a non-renameable parent: create a new folder named and move the item into it LLUUID idFolder = gInventory.createNewCategory(pFolder->getUUID(), LLFolderType::FT_NONE, strFolderName, &RlvRenameOnWearObserver::onCategoryCreate, new LLUUID(pItem->getUUID())); if (idFolder.notNull()) { // Not using the new 'CreateInventoryCategory' cap so manually invoke the callback RlvRenameOnWearObserver::onCategoryCreate(LLSD().with("folder_id", idFolder), new LLUUID(pItem->getUUID())); } } } } } } gInventory.notifyObservers(); delete this; }
void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LLStyle::Params& input_append_params) { bool use_plain_text_chat_history = args["use_plain_text_chat_history"].asBoolean(); llassert(mEditor); if (!mEditor) { return; } mEditor->setPlainText(use_plain_text_chat_history); if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) { mUnreadChatSources.insert(chat.mFromName); mMoreChatPanel->setVisible(TRUE); std::string chatters; for (unread_chat_source_t::iterator it = mUnreadChatSources.begin(); it != mUnreadChatSources.end();) { chatters += *it; if (++it != mUnreadChatSources.end()) { chatters += ", "; } } LLStringUtil::format_map_t args; args["SOURCES"] = chatters; if (mUnreadChatSources.size() == 1) { mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args)); } else { mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args)); } S32 height = mMoreChatText->getTextPixelHeight() + 5; mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height); } LLColor4 txt_color = LLUIColorTable::instance().getColor("White"); LLViewerChat::getChatColor(chat,txt_color); LLFontGL* fontp = LLViewerChat::getChatFont(); std::string font_name = LLFontGL::nameFromFont(fontp); std::string font_size = LLFontGL::sizeFromFont(fontp); LLStyle::Params style_params; style_params.color(txt_color); style_params.readonly_color(txt_color); style_params.font.name(font_name); style_params.font.size(font_size); style_params.font.style(input_append_params.font.style); std::string prefix = chat.mText.substr(0, 4); //IRC styled /me messages. bool irc_me = prefix == "/me " || prefix == "/me'"; // Delimiter after a name in header copy/past and in plain text mode std::string delimiter = ": "; std::string shout = LLTrans::getString("shout"); std::string whisper = LLTrans::getString("whisper"); if (chat.mChatType == CHAT_TYPE_SHOUT || chat.mChatType == CHAT_TYPE_WHISPER || chat.mText.compare(0, shout.length(), shout) == 0 || chat.mText.compare(0, whisper.length(), whisper) == 0) { delimiter = " "; } // Don't add any delimiter after name in irc styled messages if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC) { delimiter = LLStringUtil::null; style_params.font.style = "ITALIC"; } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; // We graying out chat history by graying out messages that contains full date in a time string if (message_from_log) { style_params.color(LLColor4::grey); style_params.readonly_color(LLColor4::grey); } if (use_plain_text_chat_history) { LLStyle::Params timestamp_style(style_params); if (!message_from_log) { LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); timestamp_style.color(timestamp_color); timestamp_style.readonly_color(timestamp_color); } mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); if (utf8str_trim(chat.mFromName).size() != 0) { // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text. if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) { // [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Added: RLVa-1.2.0f // NOTE-RLVa: we don't need to do any @shownames or @showloc filtering here because we'll already have an existing URL std::string url = chat.mURL; RLV_ASSERT( (url.empty()) || (std::string::npos != url.find("objectim")) ); if ( (url.empty()) || (std::string::npos == url.find("objectim")) ) { // [/RLVa:KB] // for object IMs, create a secondlife:///app/objectim SLapp /*std::string*/ url = LLViewerChat::getSenderSLURL(chat, args); // [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Added: RLVa-1.2.0f } // [/RLVa:KB] // set the link for the object name to be the objectim SLapp // (don't let object names with hyperlinks override our objectim Url) LLStyle::Params link_params(style_params); LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); link_params.color = link_color; link_params.readonly_color = link_color; link_params.is_link = true; link_params.link_href = url; mEditor->appendText(chat.mFromName + delimiter, false, link_params); } // else if (chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) // [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Added: RLVa-1.2.0f else if (chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log && !chat.mRlvNamesFiltered) // [/RLVa:KB] { LLStyle::Params link_params(style_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); // Add link to avatar's inspector and delimiter to message. mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); } else { mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params); } } } else { LLView* view = NULL; LLInlineViewSegment::Params p; p.force_newline = true; p.left_pad = mLeftWidgetPad; p.right_pad = mRightWidgetPad; LLDate new_message_time = LLDate::now(); if (mLastFromName == chat.mFromName && mLastFromID == chat.mFromID && mLastMessageTime.notNull() && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 && mIsLastMessageFromLog == message_from_log) //distinguish between current and previous chat session's histories { view = getSeparator(); p.top_pad = mTopSeparatorPad; p.bottom_pad = mBottomSeparatorPad; } else { view = getHeader(chat, style_params, args); if (mEditor->getText().size() == 0) p.top_pad = 0; else p.top_pad = mTopHeaderPad; p.bottom_pad = mBottomHeaderPad; } p.view = view; //Prepare the rect for the view LLRect target_rect = mEditor->getDocumentView()->getRect(); // squeeze down the widget by subtracting padding off left and right target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); target_rect.mRight -= mRightWidgetPad; view->reshape(target_rect.getWidth(), view->getRect().getHeight()); view->setOrigin(target_rect.mLeft, view->getRect().mBottom); std::string widget_associated_text = "\n[" + chat.mTimeStr + "] "; if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM) widget_associated_text += chat.mFromName + delimiter; mEditor->appendWidget(p, widget_associated_text, false); mLastFromName = chat.mFromName; mLastFromID = chat.mFromID; mLastMessageTime = new_message_time; mIsLastMessageFromLog = message_from_log; } if (chat.mNotifId.notNull()) { LLNotificationPtr notification = LLNotificationsUtil::find(chat.mNotifId); if (notification != NULL) { LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); //we can't set follows in xml since it broke toasts behavior notify_box->setFollowsLeft(); notify_box->setFollowsRight(); notify_box->setFollowsTop(); ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); S32 offset = 0; // Children were added by addChild() which uses push_front to insert them into list, // so to get buttons in correct order reverse iterator is used (EXT-5906) for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) { LLButton * button = dynamic_cast<LLButton*> (*it); if (button != NULL) { button->setOrigin( offset, button->getRect().mBottom); button->setLeftHPad(2 * HPAD); button->setRightHPad(2 * HPAD); // set zero width before perform autoResize() button->setRect(LLRect(button->getRect().mLeft, button->getRect().mTop, button->getRect().mLeft, button->getRect().mBottom)); button->setAutoResize(true); button->autoResize(); offset += HPAD + button->getRect().getWidth(); button->setFollowsNone(); } } //Prepare the rect for the view LLRect target_rect = mEditor->getDocumentView()->getRect(); // squeeze down the widget by subtracting padding off left and right target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad(); target_rect.mRight -= mRightWidgetPad; notify_box->reshape(target_rect.getWidth(), notify_box->getRect().getHeight()); notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom); LLInlineViewSegment::Params params; params.view = notify_box; params.left_pad = mLeftWidgetPad; params.right_pad = mRightWidgetPad; mEditor->appendWidget(params, "\n", false); } } else { std::string message = irc_me ? chat.mText.substr(3) : chat.mText; //MESSAGE TEXT PROCESSING //*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010) if (use_plain_text_chat_history && gAgentID != chat.mFromID && chat.mFromID.notNull()) { std::string slurl_about = SLURL_APP_AGENT + chat.mFromID.asString() + SLURL_ABOUT; if (message.length() > slurl_about.length() && message.compare(0, slurl_about.length(), slurl_about) == 0) { message = message.substr(slurl_about.length(), message.length()-1); } } if (irc_me && !use_plain_text_chat_history) { message = chat.mFromName + message; } mEditor->appendText(message, FALSE, style_params); } mEditor->blockUndo(); // automatically scroll to end when receiving chat from myself if (chat.mFromID == gAgentID) { mEditor->setCursorAndScrollToEnd(); } }
// Checked: 2010-09-18 (RLVa-1.2.1a) | Modified: RLVa-1.2.1a void RlvForceWear::done() { // Sanity check - don't go through all the motions below only to find out there's nothing to actually do if ( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) && (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) ) { return; } // // Process removals // // Wearables if (m_remWearables.size()) { for (std::list<const LLWearable*>::const_iterator itWearable = m_remWearables.begin(); itWearable != m_remWearables.end(); ++itWearable) gAgent.removeWearable((*itWearable)->getType()); m_remWearables.clear(); } // Gestures if (m_remGestures.size()) { for (S32 idxGesture = 0, cntGesture = m_remGestures.count(); idxGesture < cntGesture; idxGesture++) { LLViewerInventoryItem* pItem = m_remGestures.get(idxGesture); gGestureManager.deactivateGesture(pItem->getUUID()); gInventory.updateItem(pItem); gInventory.notifyObservers(); } 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) gMessageSystem->newMessage("ObjectDetach"); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); for (std::list<const LLViewerObject*>::const_iterator itAttachObj = m_remAttachments.begin(); itAttachObj != m_remAttachments.end(); ++itAttachObj) { gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, (*itAttachObj)->getLocalID()); } gMessageSystem->sendReliable(gAgent.getRegionHost()); m_remAttachments.clear(); } // // Process additions // // Process wearables if (m_addWearables.size()) { // [See wear_inventory_category_on_avatar_step2()] LLWearableHoldingPattern* pWearData = new LLWearableHoldingPattern(TRUE); // We need to populate 'pWearData->mFoundList' before doing anything else because (some of) the assets might already be available for (addwearables_map_t::const_iterator itAddWearables = m_addWearables.begin(); itAddWearables != m_addWearables.end(); ++itAddWearables) { const LLInventoryModel::item_array_t& wearItems = itAddWearables->second; RLV_VERIFY(1 == wearItems.count()); if (wearItems.count() > 0) { LLViewerInventoryItem* pItem = wearItems.get(0); if ( (pItem) && ((LLAssetType::AT_BODYPART == pItem->getType()) || (LLAssetType::AT_CLOTHING == pItem->getType())) ) { LLFoundData* pFound = new LLFoundData(pItem->getUUID(), pItem->getAssetUUID(), pItem->getName(), pItem->getType()); pWearData->mFoundList.push_front(pFound); } } } if (!pWearData->mFoundList.size()) { delete pWearData; return; } // If all the assets are available locally then "pWearData" will be freed *before* the last "gWearableList.getAsset()" call returns bool fContinue = true; LLWearableHoldingPattern::found_list_t::const_iterator itWearable = pWearData->mFoundList.begin(); while ( (fContinue) && (itWearable != pWearData->mFoundList.end()) ) { const LLFoundData* pFound = *itWearable; ++itWearable; fContinue = (itWearable != pWearData->mFoundList.end()); gWearableList.getAsset(pFound->mAssetID, pFound->mName, pFound->mAssetType, wear_inventory_category_on_avatar_loop, (void*)pWearData); } 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) { 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); LLAttachmentsMgr::instance().addAttachment(idItem, itAddAttachments->first & ~ATTACHMENT_ADD, itAddAttachments->first & ATTACHMENT_ADD); } } m_addAttachments.clear(); // Process gestures if (m_addGestures.size()) { gGestureManager.activateGestures(m_addGestures); for (S32 idxGesture = 0, cntGesture = m_addGestures.count(); idxGesture < cntGesture; idxGesture++) gInventory.updateItem(m_addGestures.get(idxGesture)); gInventory.notifyObservers(); m_addGestures.clear(); } // Since RlvForceWear is a singleton now we want to be sure there aren't any leftovers RLV_ASSERT( (m_remWearables.empty()) && (m_remAttachments.empty()) && (m_remGestures.empty()) ); RLV_ASSERT( (m_addWearables.empty()) && (m_addAttachments.empty()) && (m_addGestures.empty()) ); }
// Checked: 2010-04-22 (RLVa-1.2.0f) | Modified: RLVa-1.2.0f void RlvUIEnabler::onToggleShowLoc() { bool fEnable = !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC); if (LLNavigationBar::instanceExists()) LLNavigationBar::instance().refreshLocationCtrl(); if (LLPanelTopInfoBar::instanceExists()) LLPanelTopInfoBar::instance().update(); if (!fEnable) { // Hide the "About Land" floater if it's currently visible if (LLFloaterReg::instanceVisible("about_land")) LLFloaterReg::hideInstance("about_land"); // Hide the "Region / Estate" floater if it's currently visible if (LLFloaterReg::instanceVisible("region_info")) LLFloaterReg::hideInstance("region_info"); // Hide the "God Tools" floater if it's currently visible if (LLFloaterReg::instanceVisible("god_tools")) LLFloaterReg::hideInstance("god_tools"); // // Manipulate the teleport history // // If the last entry in the persistent teleport history matches the current teleport history entry then we should remove it LLTeleportHistory* pTpHistory = LLTeleportHistory::getInstance(); LLTeleportHistoryStorage* pTpHistoryStg = LLTeleportHistoryStorage::getInstance(); RLV_ASSERT( (pTpHistory) && (pTpHistoryStg) && (pTpHistory->getItems().size() > 0) && (pTpHistory->getCurrentItemIndex() >= 0) ); if ( (pTpHistory) && (pTpHistory->getItems().size() > 0) && (pTpHistory->getCurrentItemIndex() >= 0) && (pTpHistoryStg) && (pTpHistory->getItems().size() > 0) ) { const LLTeleportHistoryItem& tpItem = pTpHistory->getItems().back(); const LLTeleportHistoryPersistentItem& tpItemStg = pTpHistoryStg->getItems().back(); if (pTpHistoryStg->compareByTitleAndGlobalPos(tpItemStg, LLTeleportHistoryPersistentItem(tpItem.mTitle, tpItem.mGlobalPos))) { // TODO-RLVa: [RLVa-1.2.2] Is there a reason why LLTeleportHistoryStorage::removeItem() doesn't trigger history changed? pTpHistoryStg->removeItem(pTpHistoryStg->getItems().size() - 1); pTpHistoryStg->mHistoryChangedSignal(-1); } } // Clear the current location in the teleport history if (pTpHistory) pTpHistory->updateCurrentLocation(gAgent.getPositionGlobal()); } else { // Reset the current location in the teleport history (also takes care of adding it to the persistent teleport history) LLTeleportHistory* pTpHistory = LLTeleportHistory::getInstance(); if ( (pTpHistory) && (NULL != gAgent.getRegion()) ) pTpHistory->updateCurrentLocation(gAgent.getPositionGlobal()); } // Start or stop filtering the "About Land" and "Region / Estate" floaters if ( (!fEnable) && (!m_ConnFloaterShowLoc.connected()) ) { m_ConnFloaterShowLoc = LLFloaterReg::setValidateCallback(boost::bind(&RlvUIEnabler::filterFloaterShowLoc, this, _1, _2)); m_ConnPanelShowLoc = LLFloaterSidePanelContainer::setValidateCallback(boost::bind(&RlvUIEnabler::filterPanelShowLoc, this, _1, _2, _3)); } else if ( (fEnable) && (m_ConnFloaterShowLoc.connected()) ) { m_ConnFloaterShowLoc.disconnect(); m_ConnPanelShowLoc.disconnect(); } }