From e5beb88409325c2e8155c79187f45f40127ea223 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sun, 6 Nov 2016 16:55:30 +0100 Subject: [PATCH 1/6] [FIXED] CATZ-251: Build button doesn't actually bring up the build floater --HG-- branch : RLVa --- indra/newview/lltoolmgr.cpp | 82 ++++++++++++++++++++++++---------- indra/newview/lltoolmgr.h | 7 +-- indra/newview/lltoolselect.cpp | 30 ++++++++----- indra/newview/rlvactions.cpp | 19 ++++++++ indra/newview/rlvactions.h | 15 +++++++ indra/newview/rlvhandler.cpp | 5 +-- indra/newview/rlvui.cpp | 11 ----- indra/newview/rlvui.h | 2 - 8 files changed, 117 insertions(+), 54 deletions(-) diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 2dc4cc086f..22d1b63d5a 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -57,9 +57,9 @@ #include "llviewerjoystick.h" #include "llviewermenu.h" #include "llviewerparcelmgr.h" -// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) -#include "rlvhandler.h" -#include "rlvui.h" +// [RLVa:KB] - Checked: RLVa-2.1.0 +#include "llfloatertools.h" +#include "rlvactions.h" // [/RLVa:KB] // Used when app not active to avoid processing hover. @@ -85,14 +85,9 @@ LLToolMgr::LLToolMgr() { // Not a panel, register these callbacks globally. LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this)); -// LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); -// LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.EnabledOrActive", boost::bind(&LLToolMgr::buildEnabledOrActive, this)); -// LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2)); -// [RLVa:KB] - Checked: 2010-09-11 (RLVa-1.2.1d) | Added: RLVa-1.2.1d - LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&RlvUIEnabler::isBuildEnabled)); - LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.EnabledOrActive", boost::bind(&RlvUIEnabler::isBuildEnabledOrActive)); - LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this)); -// [/RLVa:KB] + LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); + LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.EnabledOrActive", boost::bind(&LLToolMgr::buildEnabledOrActive, this)); + LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Marketplace.Enabled", boost::bind(&LLToolMgr::canAccessMarketplace, this)); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Marketplace.Toggle", boost::bind(&LLToolMgr::toggleMarketplace, this, _2)); @@ -270,18 +265,18 @@ bool LLToolMgr::inEdit() bool LLToolMgr::canEdit() { - return LLViewerParcelMgr::getInstance()->allowAgentBuild(); +// [RLVa:KB] - Patch: RLVa-2.1.0 + return LLViewerParcelMgr::getInstance()->allowAgentBuild() && RlvActions::canBuild(); +// [/RLVa:KB] +// return LLViewerParcelMgr::getInstance()->allowAgentBuild(); } -//bool LLToolMgr::buildEnabledOrActive() -//{ -// return inEdit() || canEdit(); -//} +bool LLToolMgr::buildEnabledOrActive() +{ + return inEdit() || canEdit(); +} -//void LLToolMgr::toggleBuildMode(const LLSD& sdname) -// [RLVa:KB] - Checked: 2012-04-26 (RLVa-1.4.6) | Added: RLVa-1.4.6 -void LLToolMgr::toggleBuildMode() -// [/RLVa:KB] +void LLToolMgr::toggleBuildMode(const LLSD& sdname) { // const std::string& param = sdname.asString(); // @@ -290,10 +285,36 @@ void LLToolMgr::toggleBuildMode() // { // return; // } - - bool build_visible = LLFloaterReg::instanceVisible("build"); - if (build_visible) +// +// bool build_visible = LLFloaterReg::instanceVisible("build"); +// if (build_visible) +// { +// [RLVa:KB] - Checked: RLVa-2.1.0 + if (gFloaterTools) { + if (gFloaterTools->isShown()) + leaveBuildMode(); + else + enterBuildMode("build" == sdname.asString()); + } +} + +void LLToolMgr::enterBuildMode(bool verify_canedit /*=false*/) +{ + if (!gFloaterTools) + return; + if (!gFloaterTools->isShown()) + gFloaterTools->openFloater(); + if (!gFloaterTools->isFrontmost()) + gFloaterTools->setVisibleAndFrontmost(true); + + if (verify_canedit && !canEdit()) + { + return; + } + + { +// [/RLVa:KB] ECameraMode camMode = gAgentCamera.getCameraMode(); if (CAMERA_MODE_MOUSELOOK == camMode || CAMERA_MODE_CUSTOMIZE_AVATAR == camMode) { @@ -332,7 +353,20 @@ void LLToolMgr::toggleBuildMode() LLViewerJoystick::getInstance()->setNeedsReset(); } - else +// [RLVa:KB] - Checked: RLVa-2.1.0 +} +// [/RLVa:KB] +// else +// [RLVa:KB] - Checked: RLVa-2.1.0 +void LLToolMgr::leaveBuildMode() +{ + if ( (!gFloaterTools) || (!gFloaterTools->getVisible()) ) + { + return; + } + + gFloaterTools->closeFloater(); +// [/RLVa:KB] { if (gSavedSettings.getBOOL("EditCameraMovement")) { diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index 4944c6ed71..5a64723b33 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -56,10 +56,11 @@ public: bool canEdit(); bool buildEnabledOrActive(); bool canAccessMarketplace(); -// [RLVa:KB] - Checked: 2012-04-26 (RLVa-1.4.6) | Added: RLVa-1.4.6 - void toggleBuildMode(); + void toggleBuildMode(const LLSD& sdname); +// [RLVa:KB] - Checked: RLVa-2.1.0 + void enterBuildMode(bool verify_canedit = false); + void leaveBuildMode(); // [/RLVa:KB] -// void toggleBuildMode(const LLSD& sdname); void toggleMarketplace(const LLSD& sdname); /* Determines if we are in Build mode or not. */ diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 2cd221c351..92f8db9ddb 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -86,7 +86,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi object = object->getRootEdit(); } -// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c +// [RLVa:KB] - Checked: RLVa-2.1.0 if ( (object) && (RlvActions::isRlvEnabled()) ) { if (!RlvActions::canEdit(object)) @@ -94,23 +94,31 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi if (!temp_select) return LLSelectMgr::getInstance()->getSelection(); else if (LLToolMgr::instance().inBuildMode()) - LLToolMgr::instance().toggleBuildMode(); + LLToolMgr::instance().leaveBuildMode(); } - if ( (RlvActions::hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!object->isAttachment()) || (!object->permYouOwner())) ) + if ( (RlvActions::hasBehaviour(RLV_BHVR_FARTOUCH)) && ( (!object->isAttachment()) || (!object->permYouOwner())) ) { static RlvCachedBehaviourModifier s_nFartouchDist(RLV_MODIFIER_FARTOUCHDIST); float nFartouchDistSq = s_nFartouchDist * s_nFartouchDist; - // NOTE: recheck why we did it this way, might be able to simplify - if ( (dist_vec_squared(gAgent.getPositionAgent(), object->getPositionRegion()) > nFartouchDistSq) && - (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > nFartouchDistSq) ) + + // User is allowed to edit/select this object if it's within their current fartouch distance + if (dist_vec_squared(gAgent.getPositionAgent(), object->getPositionRegion()) > nFartouchDistSq) { - if ( (LLFloaterReg::instanceVisible("build")) && (pick.mKeyMask != MASK_SHIFT) && (pick.mKeyMask != MASK_CONTROL) ) - LLSelectMgr::getInstance()->deselectAll(); - return LLSelectMgr::getInstance()->getSelection(); + // The object is out of range but we'll still allow them a temporary select (e.g. context menu) if the surface point is within range + if (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > 1.5f * 1.5f) + { + // Even the surface point is out of range so deny them the hit + if ( (LLFloaterReg::instanceVisible("build")) && (pick.mKeyMask != MASK_SHIFT) && (pick.mKeyMask != MASK_CONTROL) ) + LLSelectMgr::getInstance()->deselectAll(); + return LLSelectMgr::getInstance()->getSelection(); + } + else if (LLToolMgr::instance().inBuildMode()) + { + // Allow the selection but keep it temporary by pulling them out of build mode when they click too far + LLToolMgr::instance().leaveBuildMode(); + } } - else if (LLToolMgr::instance().inBuildMode()) - LLToolMgr::instance().toggleBuildMode(); } } // [/RLVa:KB] diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp index 913ded899c..b41302b5bf 100644 --- a/indra/newview/rlvactions.cpp +++ b/indra/newview/rlvactions.cpp @@ -282,6 +282,21 @@ bool RlvActions::isLocalTp(const LLVector3d& posGlobal) // World interaction // +bool RlvActions::canBuild() +{ + // User can access the build floater if: + // - allowed to edit existing objects OR + // - allowed to rez/create objects + return + (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) || + (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ)); +} + +bool RlvActions::canEdit() +{ + return (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)); +} + bool RlvActions::canEdit(const LLViewerObject* pObj) { // User can edit the specified object if: @@ -293,6 +308,10 @@ bool RlvActions::canEdit(const LLViewerObject* pObj) ((!hasBehaviour(RLV_BHVR_EDITOBJ)) || (!gRlvHandler.isException(RLV_BHVR_EDITOBJ, pObj->getRootEdit()->getID()))); } +bool RlvActions::canRez() +{ + return (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ)); +} bool RlvActions::canSit(const LLViewerObject* pObj, const LLVector3& posOffset /*= LLVector3::zero*/) { diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h index c034e829a1..6b21087635 100644 --- a/indra/newview/rlvactions.h +++ b/indra/newview/rlvactions.h @@ -171,11 +171,26 @@ public: // World interaction // ================= public: + /* + * Returns true if the user can build (= access the build tools) + */ + static bool canBuild(); + + /* + * Returns true if the user can edit existing objects (generic check not based on specific object type) + */ + static bool canEdit(); + /* * Returns true if the user can edit the specified object */ static bool canEdit(const LLViewerObject* pObj); + /* + * Returns true if the user can rez new objects (from inventory or through the create tool) + */ + static bool canRez(); + /* * Returns true if the user can sit up on the specified object */ diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 3500252033..bb3bc4e34f 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -1623,9 +1623,8 @@ void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour eBh if (LLFloaterReg::instanceVisible("beacons")) LLFloaterReg::hideInstance("beacons"); - // Hide the build floater if it's currently visible - if (LLFloaterReg::instanceVisible("build")) - LLToolMgr::instance().toggleBuildMode(); + // Hide the build floater + LLToolMgr::instance().leaveBuildMode(); } // Start or stop filtering opening the beacons floater diff --git a/indra/newview/rlvui.cpp b/indra/newview/rlvui.cpp index 01d01a061d..5ed9d74dc2 100644 --- a/indra/newview/rlvui.cpp +++ b/indra/newview/rlvui.cpp @@ -427,15 +427,4 @@ bool RlvUIEnabler::hasOpenProfile(const LLUUID& idAgent) return LLAvatarActions::profileVisible(idAgent); } -// Checked: 2010-09-11 (RLVa-1.2.1d) | Added: RLVa-1.2.1d -bool RlvUIEnabler::isBuildEnabled() -{ - return (gAgent.canEditParcel()) && ((!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) || (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ))); -} - -bool RlvUIEnabler::isBuildEnabledOrActive() -{ - return LLToolMgr::instance().inEdit() || isBuildEnabled(); -} - // ============================================================================ diff --git a/indra/newview/rlvui.h b/indra/newview/rlvui.h index 841904a860..81926974ee 100644 --- a/indra/newview/rlvui.h +++ b/indra/newview/rlvui.h @@ -79,8 +79,6 @@ public: static bool canViewRegionProperties(); // showloc static bool hasOpenIM(const LLUUID& idAgent); // shownames static bool hasOpenProfile(const LLUUID& idAgent); // shownames - static bool isBuildEnabled(); // edit and rez - static bool isBuildEnabledOrActive(); // edit and rez /* * Member variables From 59500ff77f47fe3a7cf5caf56e0f1baf0d062aa1 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sat, 12 Nov 2016 00:28:09 +0100 Subject: [PATCH 2/6] [FIXED] Items can be pasted from locked folders into unlocked folders and vice versa -> rather than blocking the context menu item we'll show a blocked notification toast to help the user identify why their paste is failing --HG-- branch : RLVa --- indra/newview/llinventorybridge.cpp | 9 +++++++ indra/newview/rlvactions.cpp | 26 +++++++++++++++++++ indra/newview/rlvactions.h | 22 ++++++++++++++++ indra/newview/rlvdefines.h | 1 + .../skins/default/xui/en/rlva_strings.xml | 5 ++++ 5 files changed, 63 insertions(+) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b08c6fd21a..ce64ba2c9a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3540,6 +3540,15 @@ void LLFolderBridge::perform_pasteFromClipboard() LLNotificationsUtil::add("StockPasteFailed", subs); return; } + +// [RLVa:KB] - Checked: RLVa-2.1.0 + if ( ((item) && (!RlvActions::canPaste(item, dest_folder))) || ((cat) && (!RlvActions::canPaste(cat, dest_folder))) ) + { + RlvActions::notifyBlocked(RLV_STRING_BLOCKED_INVFOLDER); + return; + } +// [/RLVa:KB] + } } diff --git a/indra/newview/rlvactions.cpp b/indra/newview/rlvactions.cpp index b41302b5bf..b4fd076b06 100644 --- a/indra/newview/rlvactions.cpp +++ b/indra/newview/rlvactions.cpp @@ -23,6 +23,7 @@ #include "rlvactions.h" #include "rlvhelper.h" #include "rlvhandler.h" +#include "rlvinventory.h" // ============================================================================ // Camera @@ -216,6 +217,26 @@ bool RlvActions::canShowNearbyAgents() return !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNEARBY); } +// ============================================================================ +// Inventory +// + +bool RlvActions::canPaste(const LLInventoryCategory* pSourceCat, const LLInventoryCategory* pDestCat) +{ + // The user can paste the specified object into the destination if: + // - the source and destination are subject to the same lock type (or none at all) => NOTE: this happens to be the same logic we use for moving + return (isRlvEnabled()) && (pSourceCat) && (pDestCat) && + ((!RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) || (RlvFolderLocks::instance().canMoveFolder(pSourceCat->getUUID(), pDestCat->getUUID()))); +} + +bool RlvActions::canPaste(const LLInventoryItem* pSourceItem, const LLInventoryCategory* pDestCat) +{ + // The user can paste the specified object into the destination if: + // - the source and destination are subject to the same lock type (or none at all) => NOTE: this happens to be the same logic we use for moving + return (isRlvEnabled()) && (pSourceItem) && (pDestCat) && + ((!RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) || (RlvFolderLocks::instance().canMoveItem(pSourceItem->getUUID(), pDestCat->getUUID()))); +} + // ============================================================================ // Movement // @@ -386,4 +407,9 @@ bool RlvActions::isRlvEnabled() return RlvHandler::isEnabled(); } +void RlvActions::notifyBlocked(const std::string& strNotifcation, const LLSD& sdArgs) +{ + RlvUtil::notifyBlocked(strNotifcation, sdArgs); +} + // ============================================================================ diff --git a/indra/newview/rlvactions.h b/indra/newview/rlvactions.h index 6b21087635..51fa36b613 100644 --- a/indra/newview/rlvactions.h +++ b/indra/newview/rlvactions.h @@ -19,6 +19,13 @@ #include "rlvdefines.h" +// ============================================================================ +// Forward declarations +// + +class LLInventoryCategory; +class LLInventoryItem; + // ============================================================================ // RlvActions class declaration - developer-friendly non-RLVa code facing class, use in lieu of RlvHandler whenever possible // @@ -122,6 +129,16 @@ protected: // Backwards logic so that we can initialize to 0 and it won't block when we forget to/don't check if RLVa is disabled static bool s_BlockNamesContexts[SNC_COUNT]; + // ========= + // Inventory + // ========= +public: + /* + * Returns true if the user is allowed to paste the specified inventory object (item/folder) into the specified destination category (within user inventory) + */ + static bool canPaste(const LLInventoryCategory* pSourceCat, const LLInventoryCategory* pDestCat); + static bool canPaste(const LLInventoryItem* pSourceItem, const LLInventoryCategory* pDestCat); + // ======== // Movement // ======== @@ -232,6 +249,11 @@ public: * Convenience function to check if RLVa is enabled without having to include rlvhandler.h */ static bool isRlvEnabled(); + + /* + * Shows one of the blocked toast notifications (see rlva_strings.xml) + */ + static void notifyBlocked(const std::string& strNotifcation, const LLSD& sdArgs = LLSD()); }; // ============================================================================ diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 9c150b9136..fbb21ea77c 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -374,6 +374,7 @@ enum ERlvAttachGroupType #define RLV_STRING_BLOCKED_AUTOPILOT "blocked_autopilot" #define RLV_STRING_BLOCKED_GENERIC "blocked_generic" #define RLV_STRING_BLOCKED_GROUPCHANGE "blocked_groupchange" +#define RLV_STRING_BLOCKED_INVFOLDER "blocked_invfolder" #define RLV_STRING_BLOCKED_PERMATTACH "blocked_permattach" #define RLV_STRING_BLOCKED_PERMTELEPORT "blocked_permteleport" #define RLV_STRING_BLOCKED_RECVIM "blocked_recvim" diff --git a/indra/newview/skins/default/xui/en/rlva_strings.xml b/indra/newview/skins/default/xui/en/rlva_strings.xml index 922173282b..5f6a92c35f 100644 --- a/indra/newview/skins/default/xui/en/rlva_strings.xml +++ b/indra/newview/skins/default/xui/en/rlva_strings.xml @@ -61,6 +61,11 @@ value Unable to change your active group due to an RLV restriction; switching back to [GROUP_SLURL] + blocked_invfolder + + value + Unable to perform the requested inventory action due to an RLV locked folder. + blocked_nearby value From 7e82891bce0ae0dbd06f7a0baf20465198a00f12 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sat, 12 Nov 2016 02:22:14 +0100 Subject: [PATCH 3/6] [FIXED] Items can be moved out of locked folders by manipulating node vs subtree locks -> see https://jira.phoenixviewer.com/browse/FIRE-15499 --HG-- branch : RLVa --- indra/newview/rlvlocks.cpp | 17 +++++++++++++---- indra/newview/rlvlocks.h | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/indra/newview/rlvlocks.cpp b/indra/newview/rlvlocks.cpp index b7ac55da32..908fc9fd04 100644 --- a/indra/newview/rlvlocks.cpp +++ b/indra/newview/rlvlocks.cpp @@ -1138,7 +1138,7 @@ bool RlvFolderLocks::isLockedFolderEntry(const LLUUID& idFolder, int eSourceType } // Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g -bool RlvFolderLocks::isLockedFolder(LLUUID idFolder, ERlvLockMask eLockTypeMask, int eSourceTypeMask, folderlock_source_t* plockSource) const +bool RlvFolderLocks::isLockedFolder(LLUUID idFolder, ERlvLockMask eLockTypeMask, int eSourceTypeMask, std::list* pLockSourceList) const { // Sanity check - if there are no folder locks then we don't have to actually do anything if (!hasLockedFolder(eLockTypeMask)) @@ -1178,9 +1178,10 @@ bool RlvFolderLocks::isLockedFolder(LLUUID idFolder, ERlvLockMask eLockTypeMask, if (PERM_DENY == pLockDescr->eLockPermission) { - if (plockSource) - *plockSource = pLockDescr->lockSource; - return true; // Folder is explicitly denied, indicate locked folder to our caller + if (pLockSourceList) + pLockSourceList->push_back(pLockDescr->lockSource); + else + return true; // Folder is explicitly denied, indicate locked folder to our caller (unless it wants a list of all lock sources) } else if (PERM_ALLOW == pLockDescr->eLockPermission) { @@ -1192,6 +1193,14 @@ bool RlvFolderLocks::isLockedFolder(LLUUID idFolder, ERlvLockMask eLockTypeMask, const LLViewerInventoryCategory* pParent = gInventory.getCategory(idFolderCur); idFolderCur = (pParent) ? pParent->getParentUUID() : idFolderRoot; } + + if ( (pLockSourceList) && (!pLockSourceList->empty()) ) + { + // If we're asked to return a list, make sure it's sorted so we can compare them + pLockSourceList->sort([](const folderlock_source_t& lhs, const folderlock_source_t& rhs) { return lhs.first < rhs.first && lhs.second < rhs.second; }); + return true; + } + // If we didn't encounter an explicit deny lock with no exception then the folder is locked if the entire inventory is locked down return (m_RootLockType & eLockTypeMask) && (eSourceTypeMask & ST_ROOTFOLDER) && (idsRlvObjRem.empty()) && (idsRlvObjAdd.empty()); } diff --git a/indra/newview/rlvlocks.h b/indra/newview/rlvlocks.h index 61ab0acbb0..bdbfc35170 100644 --- a/indra/newview/rlvlocks.h +++ b/indra/newview/rlvlocks.h @@ -326,7 +326,7 @@ public: // Returns TRUE if the attachment (specified by item UUID) is non-detachable as a result of a RLV_LOCK_REMOVE folder PERM_DENY lock bool isLockedAttachment(const LLUUID& idItem) const; // Returns TRUE if the folder is locked as a result of a RLV_LOCK_REMOVE folder PERM_DENY lock - bool isLockedFolder(LLUUID idFolder, ERlvLockMask eLock, int eSourceTypeMask = ST_MASK_ANY, folderlock_source_t* plockSource = NULL) const; + bool isLockedFolder(LLUUID idFolder, ERlvLockMask eLock, int eSourceTypeMask = ST_MASK_ANY, std::list* pLockSourceList = nullptr) const; // Returns TRUE if the wearable (specified by item UUID) is non-removable as a result of a RLV_LOCK_REMOVE folder PERM_DENY lock bool isLockedWearable(const LLUUID& idItem) const; @@ -608,11 +608,11 @@ inline bool RlvFolderLocks::canMoveFolder(const LLUUID& idFolder, const LLUUID& // * folder locked + destination locked => allow move only if both are subject to the same folder lock // * folder unlocked + destination unlocked => allow move (special case of above since both locks are equal when there is none) // => so the above becomes (isLockedFolder(A) == isLockedFolder(B)) && (lockA == lockB) - folderlock_source_t lockSource(ST_NONE, 0), lockSourceDest(ST_NONE, 0); - return + std::list locksSource, locksSourceDest; + return (!hasLockedFolderDescendent(idFolder, ST_MASK_ANY, PERM_MASK_ANY, RLV_LOCK_ANY, true)) && - ( (isLockedFolder(idFolder, RLV_LOCK_ANY, ST_MASK_ANY, &lockSource) == isLockedFolder(idFolderDest, RLV_LOCK_ANY, ST_MASK_ANY, &lockSourceDest)) && - (lockSource == lockSourceDest) ); + ( (isLockedFolder(idFolder, RLV_LOCK_ANY, ST_MASK_ANY, &locksSource) == isLockedFolder(idFolderDest, RLV_LOCK_ANY, ST_MASK_ANY, &locksSourceDest)) && + (locksSource == locksSourceDest) ); } // Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g @@ -644,11 +644,11 @@ inline bool RlvFolderLocks::canMoveItem(const LLUUID& idItem, const LLUUID& idFo // Block moving the folder to destination if: // - folder and destination are subject to different locks [see canMoveFolder() for more details] const LLViewerInventoryItem* pItem = gInventory.getItem(idItem); const LLUUID& idFolder = (pItem) ? pItem->getParentUUID() : LLUUID::null; - int maskSource = ST_MASK_ANY & ~ST_ROOTFOLDER; folderlock_source_t lockSource(ST_NONE, 0), lockSourceDest(ST_NONE, 0); - return - (idFolder.notNull()) && - (isLockedFolder(idFolder, RLV_LOCK_ANY, maskSource, &lockSource) == isLockedFolder(idFolderDest, RLV_LOCK_ANY, maskSource, &lockSourceDest)) && - (lockSource == lockSourceDest); + int maskSource = ST_MASK_ANY & ~ST_ROOTFOLDER; std::list locksSource, locksSourceDest; + return + (idFolder.notNull()) && + (isLockedFolder(idFolder, RLV_LOCK_ANY, maskSource, &locksSource) == isLockedFolder(idFolderDest, RLV_LOCK_ANY, maskSource, &locksSourceDest)) && + (locksSource == locksSourceDest); } // Checked: 2011-03-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0g From a1808b0c5fbe855123d805753d058dd1912ca85a Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sat, 12 Nov 2016 11:39:09 +0100 Subject: [PATCH 4/6] [FIXED] Path separator ('/') cannot be used in shared folder names and shouldn't be returned by @getinv and @findfolder(s) --HG-- branch : RLVa --- indra/newview/rlvdefines.h | 3 ++- indra/newview/rlvhandler.cpp | 6 ++++-- indra/newview/rlvinventory.h | 5 +++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index fbb21ea77c..53d06d7bb6 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -83,7 +83,8 @@ const S32 RLVa_VERSION_PATCH = 3; #define RLV_FOLDER_FLAG_NOSTRIP "nostrip" #define RLV_FOLDER_PREFIX_HIDDEN '.' -#define RLV_FOLDER_PREFIX_PUTINV '~' +#define RLV_FOLDER_PREFIX_PUTINV '~' +#define RLV_FOLDER_INVALID_CHARS "/" // ============================================================================ // Enumeration declarations diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index bb3bc4e34f..2d4683cff7 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -2965,9 +2965,11 @@ ERlvCmdRet RlvHandler::onGetInv(const RlvCommand& rlvCmd, std::string& strReply) // - aren't hidden // - aren't a folded folder (only really matters when "Enable Legacy Naming" is enabled - see related blog post) // (we can skip checking for . folders since the ones we'll want to hide start with '.' anyway) + // - don't have any invalid characters const std::string& strFolder = pFolders->at(idxFolder)->getName(); - if ( (!strFolder.empty()) && (RLV_FOLDER_PREFIX_HIDDEN != strFolder[0]) && - (!RlvInventory::isFoldedFolder(pFolders->at(idxFolder).get(), false)) ) + if ( (!strFolder.empty()) && (RLV_FOLDER_PREFIX_HIDDEN != strFolder[0]) && + (!RlvInventory::isFoldedFolder(pFolders->at(idxFolder).get(), false)) && + (std::string::npos == strFolder.find_first_of(RLV_FOLDER_INVALID_CHARS)) ) { if (!strReply.empty()) strReply.push_back(','); diff --git a/indra/newview/rlvinventory.h b/indra/newview/rlvinventory.h index 1d1f2ca34e..349715034d 100644 --- a/indra/newview/rlvinventory.h +++ b/indra/newview/rlvinventory.h @@ -203,8 +203,9 @@ public: LLStringUtil::toLower(strFolderName); // NOTE: hidden or "give to #RLV" folders can never be a match - if ( (strFolderName.empty()) || - (RLV_FOLDER_PREFIX_HIDDEN == strFolderName[0]) || (RLV_FOLDER_PREFIX_PUTINV == strFolderName[0]) ) + if ( (strFolderName.empty()) || + (RLV_FOLDER_PREFIX_HIDDEN == strFolderName[0]) || (RLV_FOLDER_PREFIX_PUTINV == strFolderName[0]) || + (std::string::npos != strFolderName.find_first_of(RLV_FOLDER_INVALID_CHARS)) ) { return false; } From 51c503af99ffbc0991303d9963535c009364a2ce Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sat, 12 Nov 2016 12:18:06 +0100 Subject: [PATCH 5/6] [FIXED] Force wear commands don't work from the console -> force wear actions would execute but stay in the queue until a scripted RLV commands excuted (or as a result of change in the locks) --HG-- branch : RLVa --- indra/newview/rlvfloaters.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/newview/rlvfloaters.cpp b/indra/newview/rlvfloaters.cpp index 4b4303cf27..90aa3bbbe4 100644 --- a/indra/newview/rlvfloaters.cpp +++ b/indra/newview/rlvfloaters.cpp @@ -810,6 +810,9 @@ void RlvFloaterConsole::onInput(LLUICtrl* pCtrl, const LLSD& sdParam) m_pOutputText->appendText("ERR: @" + strFailed, true); if (!strRetained.empty()) m_pOutputText->appendText("RET: @" + strRetained, true); + + if (RlvForceWear::instanceExists()) + RlvForceWear::instance().done(); } m_pOutputText->appendText(s_strRlvConsolePrompt, true); From 5266981c86f3ec2a79f01efa7f4d75614fc5e633 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Sat, 12 Nov 2016 13:45:02 +0100 Subject: [PATCH 6/6] @setgroup:=force will now do a "starts with" rather than an exact match -> see FIRE-20266 - problem when group name contains a comma (or colon?) -> an exact match has precedence over a partial match; in case of multiple partial matches the last match wins (group ordering isn't guaranteed so essentially 'random') -> @setgroup:=force is still preferred --HG-- branch : RLVa --- indra/newview/rlvhandler.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 2d4683cff7..0360623900 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -2473,21 +2473,33 @@ template<> template<> ERlvCmdRet RlvForceHandler::onCommand(const RlvCommand& rlvCmd) { if (!RlvActions::canChangeActiveGroup(rlvCmd.getObjectID())) - { return RLV_RET_FAILED_LOCK; - } LLUUID idGroup; bool fValid = false; - if (idGroup.set(rlvCmd.getOption())) + if ("none" == rlvCmd.getOption()) + { + idGroup.setNull(); + fValid = true; + } + else if (idGroup.set(rlvCmd.getOption())) { fValid = (idGroup.isNull()) || (gAgent.isInGroup(idGroup, true)); } else { - for (S32 idxGroup = 0, cntGroup = gAgent.mGroups.size(); (idxGroup < cntGroup) && (idGroup.isNull()); idxGroup++) - if (boost::iequals(gAgent.mGroups.at(idxGroup).mName, rlvCmd.getOption())) - idGroup = gAgent.mGroups.at(idxGroup).mID; - fValid = (idGroup.notNull()) || ("none" == rlvCmd.getOption()); + bool fExactMatch = false; + for (const auto& groupData : gAgent.mGroups) + { + // NOTE: exact matches take precedence over partial matches; in case of partial matches the last match wins + if (boost::istarts_with(groupData.mName, rlvCmd.getOption())) + { + idGroup = groupData.mID; + fExactMatch = groupData.mName.length() == rlvCmd.getOption().length(); + if (fExactMatch) + break; + } + } + fValid = idGroup.notNull(); } if (fValid)