Update RLVa to 1.4.0-compatible

This commit is contained in:
Siana Gearz
2012-01-25 21:11:33 +01:00
parent d385de9139
commit 7fec659979
31 changed files with 1637 additions and 322 deletions

View File

@@ -134,4 +134,7 @@ private:
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b);
#endif // LL_LLMD5_H

View File

@@ -1578,7 +1578,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
{
const LLUUID& old_item_id = getWearableItemID(type, 0);
if( (old_wearable->getAssetID() == new_wearable->getAssetID()) &&
(old_item_id == new_item->getUUID()) )
(old_item_id == new_item->getLinkedUUID()) )
{
lldebugs << "No change to wearable asset and item: " << LLWearableType::getTypeName( type ) << llendl;
continue;
@@ -1600,7 +1600,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
}
new_wearable->setName(new_item->getName());
new_wearable->setItemID(new_item->getUUID());
new_wearable->setItemID(new_item->getLinkedUUID());
if (LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART)
{
@@ -1675,9 +1675,9 @@ void LLAgentWearables::setWearableItem( LLInventoryItem* new_item, LLWearable* n
LLWearableType::EType type = new_wearable->getType();
// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d)
// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.1.4a)
// Block if: we can't wear on that layer; or we're already wearing something there we can't take off
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canWear(type)) )
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canWear(dynamic_cast<const LLViewerInventoryItem*>(new_item))) )
{
return;
}
@@ -1762,7 +1762,7 @@ void LLAgentWearables::setWearableFinal( LLInventoryItem* new_item, LLWearable*
{
old_item_id = old_wearable->getItemID();
}
new_wearable->setItemID(new_item->getUUID());
new_wearable->setItemID(new_item->getLinkedUUID());
setWearable(type,0,new_wearable);
if (old_item_id.notNull())

View File

@@ -76,8 +76,13 @@
// Returns true if you got at least one object
void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
{
// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l
if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT))) )
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
// Block rectangle selection if:
// - prevented from editing and no exceptions are set (see below for the case where exceptions are set)
// - prevented from interacting at all
if ( (rlv_handler_t::isEnabled()) &&
( ((gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasException(RLV_BHVR_EDIT))) ||
(gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT)) ) )
{
return;
}
@@ -242,6 +247,13 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
continue;
}
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canEdit(vobjp)) )
{
continue;
}
// [/RLVa:KB]
S32 result = LLViewerCamera::getInstance()->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius());
if (result)
{

View File

@@ -1167,6 +1167,9 @@ LLFloaterIMPanel::LLFloaterIMPanel(
void LLFloaterIMPanel::init(const std::string& session_label)
{
// set P2P type by default
mSessionType = P2P_SESSION;
mSessionLabel = session_label;
// [Ansariel: Display name support]
@@ -1219,6 +1222,15 @@ void LLFloaterIMPanel::init(const std::string& session_label)
break;
}
if ( (IM_NOTHING_SPECIAL != mDialog) && (IM_SESSION_P2P_INVITE != mDialog) )
{
// determine whether it is group or conference session
if (gAgent.isInGroup(mSessionUUID))
mSessionType = GROUP_SESSION;
else
mSessionType = ADHOC_SESSION;
}
mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
LLUICtrlFactory::getInstance()->buildFloater(this,
@@ -2192,40 +2204,48 @@ void LLFloaterIMPanel::sendMsg()
std::string prefix = utf8text.substr(0, 4);
if (prefix != "/me " && prefix != "/me'")
if (mRPMode) utf8text = "[[" + utf8text + "]]";
// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-1.0.0g
if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM))
// [RLVa:KB] - Checked: 2011-09-17 (RLVa-1.1.4b) | Modified: RLVa-1.1.4b
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIMTO)) )
{
if (IM_NOTHING_SPECIAL == mDialog) // One-on-one IM: allow if recipient is a sendim exception
bool fRlvFilter = false;
switch (mSessionType)
{
if (!gRlvHandler.isException(RLV_BHVR_SENDIM, mOtherParticipantUUID))
utf8text = RlvStrings::getString(RLV_STRING_BLOCKED_SENDIM);
}
else if (gAgent.isInGroup(mSessionUUID)) // Group chat: allow if recipient is a sendim exception
{
if (!gRlvHandler.isException(RLV_BHVR_SENDIM, mSessionUUID))
utf8text = RlvStrings::getString(RLV_STRING_BLOCKED_SENDIM);
}
else if (mSpeakers) // Conference chat: allow if all participants are sendim exceptions
{
LLSpeakerMgr::speaker_list_t speakers;
mSpeakers->getSpeakerList(&speakers, TRUE);
for (LLSpeakerMgr::speaker_list_t::const_iterator itSpeaker = speakers.begin();
itSpeaker != speakers.end(); ++itSpeaker)
{
LLSpeaker* pSpeaker = *itSpeaker;
if ( (gAgent.getID() != pSpeaker->mID) && (!gRlvHandler.isException(RLV_BHVR_SENDIM, pSpeaker->mID)) )
case P2P_SESSION: // One-on-one IM
fRlvFilter = !gRlvHandler.canSendIM(mOtherParticipantUUID);
break;
case GROUP_SESSION: // Group chat
fRlvFilter = !gRlvHandler.canSendIM(mSessionUUID);
break;
case ADHOC_SESSION: // Conference chat: allow if all participants can be sent an IM
{
utf8text = RlvStrings::getString(RLV_STRING_BLOCKED_SENDIM);
break;
if (!mSpeakers)
{
fRlvFilter = true;
break;
}
LLSpeakerMgr::speaker_list_t speakers;
mSpeakers->getSpeakerList(&speakers, TRUE);
for (LLSpeakerMgr::speaker_list_t::const_iterator itSpeaker = speakers.begin();
itSpeaker != speakers.end(); ++itSpeaker)
{
const LLSpeaker* pSpeaker = *itSpeaker;
if ( (gAgent.getID() != pSpeaker->mID) && (!gRlvHandler.canSendIM(pSpeaker->mID)) )
{
fRlvFilter = true;
break;
}
}
}
}
break;
default:
fRlvFilter = true;
break;
}
else // Catch all fall-through
{
if (fRlvFilter)
utf8text = RlvStrings::getString(RLV_STRING_BLOCKED_SENDIM);
}
}
// [/RLVa:KB]

View File

@@ -279,6 +279,17 @@ public:
static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
typedef enum e_session_type
{
P2P_SESSION,
GROUP_SESSION,
ADHOC_SESSION
} SType;
bool isP2PSessionType() const { return mSessionType == P2P_SESSION;}
bool isAdHocSessionType() const { return mSessionType == ADHOC_SESSION;}
bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;}
SType mSessionType;
private:
// called by constructors
void init(const std::string& session_label);

View File

@@ -1656,17 +1656,18 @@ public:
{
return;
}
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
// TODO-RLVa: duplicate from process_improved_im()?
if (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM))
// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIMFROM)) )
{
if (gAgent.isInGroup(session_id))
if (gAgent.isInGroup(session_id)) // Group chat: don't accept the invite if not an exception
{
if (!gRlvHandler.isException(RLV_BHVR_RECVIM, session_id))
if (!gRlvHandler.canReceiveIM(session_id))
return;
}
else if (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id))
message = message.substr(0, message_offset) + RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM);
else if (!gRlvHandler.canReceiveIM(from_id)) // Conference chat: don't block; censor if not an exception
{
message = RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM);
}
}
// [/RLVa:KB]

View File

@@ -1375,6 +1375,11 @@ BOOL LLItemBridge::isItemRenameable() const
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (!RlvFolderLocks::instance().canRenameItem(mUUID)) )
return FALSE;
// [/RLVa:KB]
return (item->getPermissions().allowModifyBy(gAgent.getID()));
}
return FALSE;
@@ -1545,6 +1550,13 @@ BOOL LLFolderBridge::isItemRemovable()
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( ((rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveFolder(mUUID))) )
{
return FALSE;
}
// [/RLVa:KB]
LLVOAvatar* avatar = gAgentAvatarp;
if( !avatar )
{
@@ -1728,6 +1740,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
//
//--------------------------------------------------------------------------------
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
if ( (is_movable) && (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) )
{
is_movable = RlvFolderLocks::instance().canMoveFolder(cat_id, mUUID);
}
// [/RLVa:KB]
accept = is_movable
&& (mUUID != cat_id) // Can't move a folder into itself
&& (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
@@ -2864,6 +2883,22 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID());
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (is_movable) )
{
if (move_is_into_current_outfit)
{
// RELEASE-RLVa: [RLVa-1.3.0] Keep sync'ed with code below => LLAppearanceMgr::wearItemOnAvatar() with "replace == true"
const LLViewerInventoryItem* pItem = dynamic_cast<const LLViewerInventoryItem*>(inv_item);
is_movable = rlvPredCanWearItem(pItem, RLV_WEAR_REPLACE);
}
if (is_movable)
{
is_movable = (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (RlvFolderLocks::instance().canMoveItem(inv_item->getUUID(), mUUID));
}
}
// [/RLVa:KB]
accept = is_movable && (mUUID != inv_item->getParentUUID());
if(accept && drop)
{
@@ -2894,7 +2929,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
wear_inventory_item_on_avatar(inv_item);
break;
case LLAssetType::AT_OBJECT:
rez_attachment((LLViewerInventoryItem*)inv_item, NULL, false);
rez_attachment((LLViewerInventoryItem*)inv_item, NULL, true);
break;
/*
case LLAssetType::AT_GESTURE:
@@ -3834,6 +3869,12 @@ BOOL LLObjectBridge::isItemRemovable()
{
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(mUUID)) )
{
return FALSE;
}
// [/RLVa:KB]
const LLInventoryObject *obj = model->getItem(mUUID);
if (obj && obj->getIsLinkType())
{
@@ -4888,8 +4929,8 @@ void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, B
// item->setAssetUUID(wearable->getID());
// item->updateAssetOnServer();
// }
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b
if (!gRlvWearableLocks.canWear(wearable->getType()))
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.4a
if (!gRlvWearableLocks.canWear(item))
{
continue;
}
@@ -5053,6 +5094,18 @@ BOOL LLWearableBridge::isItemRemovable()
{
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(mUUID)) )
{
return FALSE;
}
// [/RLVa:KB]
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(mUUID)) )
{
return FALSE;
}
// [/RLVa:KB]
const LLInventoryObject *obj = model->getItem(mUUID);
if (obj && obj->getIsLinkType())
{
@@ -5196,6 +5249,13 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Wearable Wear"));
items.push_back(std::string("Wearable Edit"));
// [RLVa:KB] - Checked: 2011-09-16 (RLVa-1.1.4a) | Added: RLVa-1.1.4a
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) )
{
disabled_items.push_back(std::string("Wearable Wear"));
disabled_items.push_back(std::string("Wearable Edit"));
}
// [/RLVa:KB]
if ((flags & FIRST_SELECTED_ITEM) == 0)
{
@@ -5215,20 +5275,24 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
switch (item->getType())
{
case LLAssetType::AT_CLOTHING:
items.push_back(std::string("Take Off"));
items.push_back(std::string("Take Off"));
// [RLVa:KB] - Checked: 2011-09-16 (RLVa-1.1.4a) | Added: RLVa-1.1.4a
if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) )
disabled_items.push_back(std::string("Take Off"));
// [/RLVa:KB]
// Fallthrough since clothing and bodypart share wear options
case LLAssetType::AT_BODYPART:
if (get_is_item_worn(item->getUUID()))
{
disabled_items.push_back(std::string("Wearable And Wear"));
disabled_items.push_back(std::string("Wearable Add"));
}
}
else
{
items.push_back(std::string("Wearable Wear"));
disabled_items.push_back(std::string("Take Off"));
disabled_items.push_back(std::string("Wearable Edit"));
}
}
/*if (LLWearableType::getAllowMultiwear(mWearableType))
{

View File

@@ -75,6 +75,11 @@
#include "llvoavatarself.h"
#include "llwearablelist.h"
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
#include "rlvhandler.h"
#include "rlvlocks.h"
// [/RLVa:KB]
#include "cofmgr.h"
BOOL LLInventoryState::sWearNewClothing = FALSE;
@@ -269,10 +274,10 @@ BOOL get_is_item_worn(const LLInventoryItem *item)
return FALSE;
// Consider the item as worn if it has links in COF.
if (LLCOFMgr::instance().isLinkInCOF(item->getUUID()))
{
/* if (LLCOFMgr::instance().isLinkInCOF(item->getUUID()))
{ REMOVED due to advice from Kitty Barnett, looks like it WILL cause trouble on some grids -SG
return TRUE;
}
} */
switch(item->getType())
{
@@ -390,6 +395,14 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
}
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) &&
(RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(id)) )
{
return FALSE;
}
// [/RLVa:KB]
const LLInventoryObject *obj = model->getItem(id);
if (obj && obj->getIsLinkType())
{
@@ -418,6 +431,14 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( ((rlv_handler_t::isEnabled()) &&
(RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveFolder(id))) )
{
return FALSE;
}
// [/RLVa:KB]
if (!isAgentAvatarValid()) return FALSE;
const LLInventoryCategory* category = model->getCategory(id);
@@ -453,6 +474,13 @@ BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
return FALSE;
}
// [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
if ( (rlv_handler_t::isEnabled()) && (model == &gInventory) && (!RlvFolderLocks::instance().canRenameFolder(id)) )
{
return FALSE;
}
// [/RLVa:KB]
LLViewerInventoryCategory* cat = model->getCategory(id);
if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) &&
@@ -627,6 +655,38 @@ bool LLFindWearables::operator()(LLInventoryCategory* cat,
return FALSE;
}
LLFindWearablesEx::LLFindWearablesEx(bool is_worn, bool include_body_parts)
: mIsWorn(is_worn)
, mIncludeBodyParts(include_body_parts)
{}
bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
if (!vitem) return false;
// Skip non-wearables.
if (!vitem->isWearableType() && vitem->getType() != LLAssetType::AT_OBJECT)
{
return false;
}
// Skip body parts if requested.
if (!mIncludeBodyParts && vitem->getType() == LLAssetType::AT_BODYPART)
{
return false;
}
// Skip broken links.
if (vitem->getIsBrokenLink())
{
return false;
}
return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
}
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------

View File

@@ -276,6 +276,22 @@ public:
LLInventoryItem* item);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFindWearables
//
// Collects wearables based on given criteria.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFindWearablesEx : public LLInventoryCollectFunctor
{
public:
LLFindWearablesEx(bool is_worn, bool include_body_parts = true);
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
private:
bool mIncludeBodyParts;
bool mIsWorn;
};
/** Inventory Collector Functions
** **
*******************************************************************************/

View File

@@ -3719,7 +3719,20 @@ void LLSelectMgr::deselectAllIfTooFar()
return;
}
// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
if ( (!mSelectedObjects->isEmpty()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_EDITOBJ))) )
{
struct NotTransientOrEditable : public LLSelectedNodeFunctor
{
bool apply(LLSelectNode* pNode)
{
const LLViewerObject* pObj = pNode->getObject();
return (!pNode->isTransient()) && (pObj) && (!gRlvHandler.canEdit(pObj));
}
} f;
if (mSelectedObjects->getFirstRootNode(&f, TRUE))
deselectAll();
}
#ifdef RLV_EXTENSION_CMD_INTERACT
// [Fall-back code] Don't allow an active selection (except for HUD attachments - see above) when @interact=n restricted
if (gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT))

View File

@@ -104,10 +104,10 @@ void LLToolFace::pickCallback(const LLPickInfo& pick_info)
return;
}
// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
if ( (rlv_handler_t::isEnabled()) &&
( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ||
((gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (!gRlvHandler.canTouch(hit_obj, pick_info.mObjectOffset))) ) )
( (!gRlvHandler.canEdit(hit_obj)) ||
((gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (!gRlvHandler.canTouch(hit_obj, pick_info.mObjectOffset))) ) )
{
return;
}

View File

@@ -87,10 +87,10 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
object = object->getRootEdit();
}
// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
if (rlv_handler_t::isEnabled())
{
if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
if (!gRlvHandler.canEdit(object))
{
if (!temp_select)
{

View File

@@ -1969,9 +1969,10 @@ class LLObjectOpen : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | OK
// [RLVa:KB] - Checked: 2011-09-16 (RLVa-1.1.4b) | Modified: RLVa-1.1.4b
// TODO-RLVa: shouldn't we be checking for fartouch here as well?
if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
const LLViewerObject* pObj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canEdit(pObj)) )
{
return true;
}
@@ -2059,9 +2060,13 @@ bool toggle_build_mode()
}
// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b)
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (LLSelectMgr::getInstance()) )
bool fRlvCanEdit = (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDITOBJ));
if (!fRlvCanEdit)
{
LLSelectMgr::getInstance()->deselectAll();
LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection();
RlvSelectIsEditable f;
if ((hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) != NULL))
LLSelectMgr::getInstance()->deselectAll();
}
// [/RLVa:KB]
@@ -2167,9 +2172,13 @@ class LLObjectEdit : public view_listener_t
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f
if (rlv_handler_t::isEnabled())
{
if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))
bool fRlvCanEdit = (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDITOBJ));
if (!fRlvCanEdit)
{
return true; // Can't edit any object under @edit=n
LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection();
RlvSelectIsEditable f;
if ((hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) != NULL))
return true; // Can't edit any object under @edit=n
}
else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) &&
(SELECT_TYPE_WORLD == LLSelectMgr::getInstance()->getSelection()->getSelectType()) &&

View File

@@ -2012,9 +2012,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
// [/RLVa:KB]
// else if (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM)
// [RLVa:KB] - Checked: 2010-03-23 (RLVa-1.2.0a) | Modified: RLVa-1.0.0g
else if ( (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) &&
( (!gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) || (gRlvHandler.isException(RLV_BHVR_RECVIM, from_id))) )
// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
else if ( (offline == IM_ONLINE && !is_linden && is_busy && name != SYSTEM_FROM) && (gRlvHandler.canReceiveIM(from_id)) )
// [/RLVa:KB]
{
// return a standard "busy" message, but only do it to online IM
@@ -2102,10 +2101,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
else
{
// standard message, not from system
// [RLVa:KB] - Checked: 2010-03-23 (RLVa-1.1.3a) | Modified: RLVa-1.2.0a
// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
// Don't block offline IMs, or IMs from Lindens
if ( (rlv_handler_t::isEnabled()) && (offline != IM_OFFLINE) && (!is_linden) &&
(gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) )
if ( (rlv_handler_t::isEnabled()) && (offline != IM_OFFLINE) && (!is_linden) && (!gRlvHandler.canReceiveIM(from_id)) )
{
if (!is_muted)
RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM_REMOTE), session_id);
@@ -2448,24 +2446,33 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Only show messages if we have a session open (which
// should happen after you get an "invitation"
if ( !gIMMgr->hasSession(session_id) )
// if ( !gIMMgr->hasSession(session_id) )
// {
// return;
// }
// [RLVa:KB] - Checked: 2011-09-17 (RLVa-1.1.4b) | Modified: RLVa-1.1.4b
LLFloaterIMPanel* pIMFloater = gIMMgr->findFloaterBySession(session_id);
if (!pIMFloater)
{
return;
}
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) )
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIMFROM)) )
{
if (gAgent.isInGroup(session_id))
switch (pIMFloater->mSessionType)
{
if (!gRlvHandler.isException(RLV_BHVR_RECVIM, session_id))
case LLFloaterIMPanel::GROUP_SESSION: // Group chat
if ( (from_id != gAgent.getID()) && (!gRlvHandler.canReceiveIM(session_id)) )
return;
break;
case LLFloaterIMPanel::ADHOC_SESSION: // Conference chat
if ( (from_id != gAgent.getID()) && (!gRlvHandler.canReceiveIM(from_id)) )
message = RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM);
break;
default:
RLV_ASSERT(false);
return;
}
else
{
if ( (from_id != gAgent.getID()) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) )
message = message.substr(0, message_offset) + RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM);
}
}
// [/RLVa:KB]
@@ -2616,7 +2623,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
else
{
// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3a) | Modified: RLVa-1.0.0d
// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
if (rlv_handler_t::isEnabled())
{
if (!gRlvHandler.canTeleportViaLure(from_id))
@@ -2627,9 +2634,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
return;
}
// Censor lure message if: 1) @revcim=n restricted (and sender isn't an exception), or 2) @showloc=n restricted
if ( ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVIM)) && (!gRlvHandler.isException(RLV_BHVR_RECVIM, from_id)) ) ||
(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
// Censor lure message if: 1) restricted from receiving IMs from the sender, or 2) @showloc=n restricted
if ( (!gRlvHandler.canReceiveIM(from_id)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
{
message = RlvStrings::getString(RLV_STRING_HIDDEN);
}
@@ -2646,11 +2652,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
payload["godlike"] = FALSE;
//LLNotificationsUtil::add("TeleportOffered", args, payload);
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b
if ( (rlv_handler_t::isEnabled()) &&
((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (gRlvHandler.isException(RLV_BHVR_ACCEPTTP, from_id))) )
// [RLVa:KB] - Checked: 2010-12-11 (RLVa-1.2.2c) | Modified: RLVa-1.2.2c
if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_ACCEPTTP)) || (fRlvSummon)) )
{
gRlvHandler.setCanCancelTp(false);
if (is_busy)
busy_message(msg,from_id);
LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
}
else
@@ -3297,10 +3304,14 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
{
if (!RlvUtil::isEmote(mesg))
{
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVCHAT)) && (!gRlvHandler.isException(RLV_BHVR_RECVCHAT, from_id)) )
if ( ((gRlvHandler.hasBehaviour(RLV_BHVR_RECVCHAT)) && (!gRlvHandler.isException(RLV_BHVR_RECVCHAT, from_id))) &&
((!gRlvHandler.hasBehaviour(RLV_BHVR_RECVCHATFROM)) || (gRlvHandler.isException(RLV_BHVR_RECVCHATFROM, from_id))) )
{
gRlvHandler.filterChat(mesg, false);
}
}
else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_RECVEMOTE)) && (!gRlvHandler.isException(RLV_BHVR_RECVEMOTE, from_id)) )
else if ( ((gRlvHandler.hasBehaviour(RLV_BHVR_RECVEMOTE)) && (!gRlvHandler.isException(RLV_BHVR_RECVEMOTE, from_id))) &&
((!gRlvHandler.hasBehaviour(RLV_BHVR_RECVEMOTEFROM)) || (gRlvHandler.isException(RLV_BHVR_RECVEMOTEFROM, from_id))) )
{
mesg = "/me ...";
}
@@ -6322,13 +6333,14 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
if(0 == option)
{
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0b
if (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM))
// [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
if ( (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIM)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SENDIMTO)) )
{
// Filter the lure message if one of the recipients of the lure can't be sent an IM to
for (LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray();
it != notification["payload"]["ids"].endArray(); ++it)
{
if (!gRlvHandler.isException(RLV_BHVR_SENDIM, it->asUUID()))
if (!gRlvHandler.canSendIM(it->asUUID()))
{
text = RlvStrings::getString(RLV_STRING_HIDDEN);
break;

View File

@@ -5244,8 +5244,8 @@ BOOL LLViewerObject::permTransfer() const
// given you modify rights to. JC
BOOL LLViewerObject::allowOpen() const
{
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b)
return !flagInventoryEmpty() && (permYouOwner() || permModify()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT));
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
return !flagInventoryEmpty() && (permYouOwner() || permModify()) && ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canEdit(this)));
// [/RLVa:KB]
// return !flagInventoryEmpty() && (permYouOwner() || permModify());
}

View File

@@ -2056,6 +2056,11 @@ void LLVOAvatar::buildCharacter()
return;
}
// [RLVa:KB] - Checked: 2010-12-12 (RLVa-1.2.2c) | Added: RLVa-1.2.2c
if (isSelf())
RlvAttachPtLookup::initLookupTable();
// [/RLVa:KB]
//-------------------------------------------------------------------------
// initialize "well known" joint pointers
//-------------------------------------------------------------------------

View File

@@ -2733,9 +2733,11 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
{
if (!mbCanSelect ||
// (gHideSelectedObjects && isSelected()) ||
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b
// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c
( (LLSelectMgr::getInstance()->mHideSelectedObjects && isSelected()) &&
((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(getRootEdit()))) ) ||
( (!rlv_handler_t::isEnabled()) ||
( ((!isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(getRootEdit()))) &&
(gRlvHandler.canEdit(this)) ) ) ) ||
// [/RLVa:KB]
mDrawable->isDead() ||
!gPipeline.hasRenderType(mDrawable->getRenderType()))

View File

@@ -2847,7 +2847,9 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f
const LLViewerObject* pObj = drawablep->getVObj();
if ( (pObj) && (pObj->isSelected()) &&
((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))) )
( (!rlv_handler_t::isEnabled()) ||
( ((!pObj->isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))) &&
(gRlvHandler.canEdit(pObj)) ) ) )
// [/RLVa:KB]
{
return;

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -500,6 +500,13 @@ bool RlvSelectHasLockedAttach::apply(LLSelectNode* pNode)
return (pNode->getObject()) ? gRlvAttachmentLocks.isLockedAttachment(pNode->getObject()->getRootEdit()) : false;
}
// Checked: 2010-11-29 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
bool RlvSelectIsEditable::apply(LLSelectNode* pNode)
{
const LLViewerObject* pObj = pNode->getObject();
return (pObj) && (!gRlvHandler.canEdit(pObj));
}
// Checked: 2009-07-05 (RLVa-1.0.0b) | Modified: RLVa-0.2.0f
bool RlvSelectIsOwnedByOrGroupOwned::apply(LLSelectNode* pNode)
{

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -208,6 +208,13 @@ struct RlvSelectHasLockedAttach : public LLSelectedNodeFunctor
virtual bool apply(LLSelectNode* pNode);
};
// Filters out selected objects that can't be editable (i.e. getFirstNode() will return NULL if the selection is fully editable)
struct RlvSelectIsEditable : public LLSelectedNodeFunctor
{
RlvSelectIsEditable() {}
/*virtual*/ bool apply(LLSelectNode* pNode);
};
struct RlvSelectIsOwnedByOrGroupOwned : public LLSelectedNodeFunctor
{
RlvSelectIsOwnedByOrGroupOwned(const LLUUID& uuid) : m_idAgent(uuid) {}
@@ -268,6 +275,12 @@ protected:
const LLViewerInventoryItem* m_pItem;
};
template<typename T> struct RlvPredValuesEqual
{
bool operator()(const T* pT2) const { return (pT1) && (pT2) && (*pT1 == *pT2); }
const T* pT1;
};
// ============================================================================
// Inlined class member functions
//

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -76,8 +76,8 @@ const S32 RLV_VERSION_BUILD = 1;
// Implementation version
const S32 RLVa_VERSION_MAJOR = 1;
const S32 RLVa_VERSION_MINOR = 1;
const S32 RLVa_VERSION_PATCH = 3;
const S32 RLVa_VERSION_BUILD = 2;
const S32 RLVa_VERSION_PATCH = 4;
const S32 RLVa_VERSION_BUILD = 0;
// Uncomment before a final release
#define RLV_RELEASE
@@ -135,10 +135,16 @@ enum ERlvBehaviour {
RLV_BHVR_REMATTACH, // "remattach"
RLV_BHVR_ADDOUTFIT, // "addoutfit"
RLV_BHVR_REMOUTFIT, // "remoutfit"
RLV_BHVR_SHAREDWEAR, // "sharedwear"
RLV_BHVR_SHAREDUNWEAR, // "sharedunwear"
RLV_BHVR_UNSHAREDWEAR, // "unsharedwear"
RLV_BHVR_UNSHAREDUNWEAR, // "unsharedunwear"
RLV_BHVR_EMOTE, // "emote"
RLV_BHVR_SENDCHAT, // "sendchat"
RLV_BHVR_RECVCHAT, // "recvchat"
RLV_BHVR_RECVCHATFROM, // "recvchatfrom"
RLV_BHVR_RECVEMOTE, // "recvemote"
RLV_BHVR_RECVEMOTEFROM, // "recvemotefrom"
RLV_BHVR_REDIRCHAT, // "redirchat"
RLV_BHVR_REDIREMOTE, // "rediremote"
RLV_BHVR_CHATWHISPER, // "chatwhisper"
@@ -146,7 +152,9 @@ enum ERlvBehaviour {
RLV_BHVR_CHATSHOUT, // "chatshout"
RLV_BHVR_SENDCHANNEL, // "sendchannel"
RLV_BHVR_SENDIM, // "sendim"
RLV_BHVR_SENDIMTO, // "sendimto"
RLV_BHVR_RECVIM, // "recvim"
RLV_BHVR_RECVIMFROM, // "recvimfrom"
RLV_BHVR_PERMISSIVE, // "permissive"
RLV_BHVR_NOTIFY, // "notify"
RLV_BHVR_SHOWINV, // "showinv"
@@ -168,13 +176,18 @@ enum ERlvBehaviour {
RLV_BHVR_ACCEPTTP, // "accepttp"
RLV_BHVR_ALLOWIDLE, // "allowidle"
RLV_BHVR_EDIT, // "edit"
RLV_BHVR_EDITOBJ, // "editobj"
RLV_BHVR_REZ, // "rez"
RLV_BHVR_FARTOUCH, // "fartouch"
RLV_BHVR_INTERACT, // "interact"
RLV_BHVR_TOUCH, // "touch"
RLV_BHVR_TOUCHTHIS, // "touchthis"
RLV_BHVR_TOUCHATTACH, // "touchattach"
RLV_BHVR_TOUCHATTACHSELF, // "touchattachself"
RLV_BHVR_TOUCHATTACHOTHER, // "touchattachother"
RLV_BHVR_TOUCHHUD, // "touchhud"
RLV_BHVR_TOUCHWORLD, // "touchworld"
RLV_BHVR_TOUCHALL, // "touchall"
RLV_BHVR_TOUCHME, // "touchme"
RLV_BHVR_FLY, // "fly"
RLV_BHVR_UNSIT, // "unsit"
RLV_BHVR_SIT, // "sit"
@@ -186,13 +199,18 @@ enum ERlvBehaviour {
RLV_BHVR_ATTACHOVER, // "attachover"
RLV_BHVR_ATTACHTHIS, // "attachthis"
RLV_BHVR_ATTACHTHISOVER, // "attachthisover"
RLV_BHVR_ATTACHTHISEXCEPT, // "attachthisexcept"
RLV_BHVR_DETACHTHIS, // "detachthis"
RLV_BHVR_DETACHTHISEXCEPT, // "detachthisexcept"
RLV_BHVR_ATTACHALL, // "attachall"
RLV_BHVR_ATTACHALLOVER, // "attachallover"
RLV_BHVR_DETACHALL, // "detachall"
RLV_BHVR_ATTACHALLTHIS, // "attachallthis"
RLV_BHVR_ATTACHALLTHISEXCEPT, // "attachallthisexcept"
RLV_BHVR_ATTACHALLTHISOVER, // "attachallthisover"
RLV_BHVR_DETACHALLTHIS, // "detachallthis"
RLV_BHVR_DETACHALLTHISEXCEPT, // "detachallthisexcept"
RLV_BHVR_ADJUSTHEIGHT, // "adjustheight"
RLV_BHVR_TPTO, // "tpto"
RLV_BHVR_VERSION, // "version"
RLV_BHVR_VERSIONNEW, // "versionnew"
@@ -303,6 +321,8 @@ enum ERlvAttachGroupType
#define RLV_SETTING_FIRSTUSE_PREFIX "FirstRLV"
#define RLV_SETTING_FIRSTUSE_GIVETORLV RLV_SETTING_FIRSTUSE_PREFIX"GiveToRLV"
#define RLV_SETTING_AVATAROFFSET_Z "AscentAvatarZModifier"
// ============================================================================
// Strings
//

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -97,10 +97,19 @@ RlvHandler::~RlvHandler()
// Behaviour related functions
//
bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const
bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBhvr, const std::string& strOption, const LLUUID& idObj) const
{
for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
if ( (idObj != itObj->second.m_UUID) && (itObj->second.hasBehaviour(eBehaviour, strOption, false)) )
if ( (idObj != itObj->second.getObjectID()) && (itObj->second.hasBehaviour(eBhvr, strOption, false)) )
return true;
return false;
}
// Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h
bool RlvHandler::hasBehaviourRoot(const LLUUID& idObjRoot, ERlvBehaviour eBhvr, const std::string& strOption) const
{
for (rlv_object_map_t::const_iterator itObj = m_Objects.begin(); itObj != m_Objects.end(); ++itObj)
if ( (idObjRoot == itObj->second.getRootID()) && (itObj->second.hasBehaviour(eBhvr, strOption, false)) )
return true;
return false;
}
@@ -112,7 +121,7 @@ bool RlvHandler::isException(ERlvBehaviour eBhvr, const RlvExceptionOption& varO
if (RLV_CHECK_DEFAULT == typeCheck)
typeCheck = ( (hasBehaviour(eBhvr)) && (!isPermissive(eBhvr)) ) ? RLV_CHECK_STRICT : RLV_CHECK_PERMISSIVE;
std::list<LLUUID> objList;
uuid_vec_t objList;
if (RLV_CHECK_STRICT == typeCheck)
{
// If we're "strict checking" then we need the UUID of every object that currently has 'eBhvr' restricted
@@ -131,7 +140,7 @@ bool RlvHandler::isException(ERlvBehaviour eBhvr, const RlvExceptionOption& varO
return true;
// For strict checks we don't return until the list is empty (every object with 'eBhvr' restricted also contains the exception)
std::list<LLUUID>::iterator itList = std::find(objList.begin(), objList.end(), itException->second.idObject);
uuid_vec_t::iterator itList = std::find(objList.begin(), objList.end(), itException->second.idObject);
if (itList != objList.end())
objList.erase(itList);
if (objList.empty())
@@ -226,7 +235,7 @@ ERlvCmdRet RlvHandler::processCommand(const RlvCommand& rlvCmd, bool fFromObj)
}
// Using a stack for executing commands solves a few problems:
// - if we passed RlvObject::m_UUID for idObj somewhere and process a @clear then idObj points to invalid/cleared memory at the end
// - if we passed RlvObject::m_idObj for idObj somewhere and process a @clear then idObj points to invalid/cleared memory at the end
// - if command X triggers command Y along the way then getCurrentCommand()/getCurrentObject() still return Y even when finished
m_CurCommandStack.push(&rlvCmd); m_CurObjectStack.push(rlvCmd.getObjectID());
const LLUUID& idCurObj = m_CurObjectStack.top();
@@ -393,7 +402,12 @@ void RlvHandler::onSitOrStand(bool fSitting)
if ( (hasBehaviour(RLV_BHVR_STANDTP)) && (!fSitting) && (!m_posSitSource.isExactlyZero()) )
{
RlvUtil::forceTp(m_posSitSource);
// NOTE: we need to do this due to the way @standtp triggers a forced teleport:
// - when standing we're called from LLVOAvatar::sitDown() which is called from LLVOAvatar::getOffObject()
// -> at the time sitDown() is called the avatar's parent is still the linkset it was sitting on so "isRoot()" on the avatar will
// return FALSE and we will crash in LLVOAvatar::getRenderPosition() when trying to teleport
// -> postponing the teleport until the next idle tick will ensure that everything has all been properly cleaned up
doOnIdleOneTime(boost::bind(RlvUtil::forceTp, m_posSitSource));
m_posSitSource.setZero();
}
}
@@ -424,7 +438,7 @@ void RlvHandler::onAttach(const LLViewerObject* pAttachObj, const LLViewerJointA
// We need to check this object for an active "@detach=n" and actually lock it down now that it's been attached somewhere
if (itObj->second.hasBehaviour(RLV_BHVR_DETACH, false))
gRlvAttachmentLocks.addAttachmentLock(pAttachObj->getID(), itObj->second.m_UUID);
gRlvAttachmentLocks.addAttachmentLock(pAttachObj->getID(), itObj->second.getObjectID());
}
}
}
@@ -464,7 +478,7 @@ void RlvHandler::onDetach(const LLViewerObject* pAttachObj, const LLViewerJointA
// If this object has an active "@detach=n" then we need to release the attachment lock since it's no longer attached
if (itObj->second.hasBehaviour(RLV_BHVR_DETACH, false))
gRlvAttachmentLocks.removeAttachmentLock(pAttachObj->getID(), itObj->second.m_UUID);
gRlvAttachmentLocks.removeAttachmentLock(pAttachObj->getID(), itObj->second.getObjectID());
}
}
}
@@ -484,7 +498,7 @@ void RlvHandler::onDetach(const LLViewerObject* pAttachObj, const LLViewerJointA
if (itCurObj->second.m_idRoot == pAttachObj->getID())
{
RLV_INFOS << "Clearing " << itCurObj->first.asString() << ":" << RLV_ENDL;
processCommand(itCurObj->second.m_UUID, "clear", true);
processCommand(itCurObj->second.getObjectID(), "clear", true);
RLV_INFOS << "\t-> done" << RLV_ENDL;
}
}
@@ -503,7 +517,7 @@ bool RlvHandler::onGC()
RLV_ASSERT(itObj);
#endif // RLV_DEBUG
const LLViewerObject* pObj = gObjectList.findObject(itCurObj->second.m_UUID);
const LLViewerObject* pObj = gObjectList.findObject(itCurObj->second.getObjectID());
if (!pObj)
{
// If the RlvObject once existed in gObjectList and now doesn't then expire it right away
@@ -532,7 +546,7 @@ bool RlvHandler::onGC()
// -> if it does run it likely means that there's a @detach=n in a *child* prim that we couldn't look up in onAttach()
// -> since RLV doesn't currently support @detach=n from child prims it's actually not such a big deal right now but still
if ( (pObj->isAttachment()) && (itCurObj->second.hasBehaviour(RLV_BHVR_DETACH, false)) )
gRlvAttachmentLocks.addAttachmentLock(pObj->getID(), itCurObj->second.m_UUID);
gRlvAttachmentLocks.addAttachmentLock(pObj->getID(), itCurObj->second.getObjectID());
}
}
}
@@ -568,8 +582,6 @@ void RlvHandler::onIdleStartup(void* pParam)
// Checked: 2010-03-09 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
void RlvHandler::onLoginComplete()
{
RlvAttachPtLookup::initLookupTable();
RlvInventory::instance().fetchWornItems();
RlvInventory::instance().fetchSharedInventory();
@@ -584,7 +596,44 @@ void RlvHandler::onLoginComplete()
// String/chat censoring functions
//
// LL must have included an strlen for UTF8 *somewhere* but I can't seem to find it so this one is home grown
// Checked: 2010-04-11 (RLVa-1.3.0h) | Modified: RLVa-1.3.0h
bool RlvHandler::canTouch(const LLViewerObject* pObj, const LLVector3& posOffset /*=LLVector3::zero*/) const
{
const LLUUID& idRoot = (pObj) ? pObj->getRootEdit()->getID() : LLUUID::null;
bool fCanTouch = (idRoot.notNull()) && ((!pObj->isHUDAttachment()) || (!hasBehaviour(RLV_BHVR_TOUCHALL))) &&
((!hasBehaviour(RLV_BHVR_TOUCHTHIS)) || (!isException(RLV_BHVR_TOUCHTHIS, idRoot, RLV_CHECK_PERMISSIVE)));
if (fCanTouch)
{
if ( (!pObj->isAttachment()) || (!pObj->permYouOwner()) )
{
// Rezzed prim or attachment worn by another avie
fCanTouch =
( (!hasBehaviour(RLV_BHVR_TOUCHWORLD)) || (isException(RLV_BHVR_TOUCHWORLD, idRoot, RLV_CHECK_PERMISSIVE)) ) &&
( (!pObj->isAttachment()) || (!hasBehaviour(RLV_BHVR_TOUCHATTACHOTHER)) ) &&
( (!hasBehaviour(RLV_BHVR_FARTOUCH)) ||
(dist_vec_squared(gAgent.getPositionGlobal(), pObj->getPositionGlobal() + LLVector3d(posOffset)) <= 1.5f * 1.5f) );
}
else if (!pObj->isHUDAttachment())
{
// Regular attachment worn by this avie
fCanTouch =
((!hasBehaviour(RLV_BHVR_TOUCHATTACH)) || (isException(RLV_BHVR_TOUCHATTACH, idRoot, RLV_CHECK_PERMISSIVE))) &&
((!hasBehaviour(RLV_BHVR_TOUCHATTACHSELF)) || (isException(RLV_BHVR_TOUCHATTACH, idRoot, RLV_CHECK_PERMISSIVE)));
}
#ifdef RLV_EXTENSION_CMD_TOUCHXXX
else
{
// HUD attachment
fCanTouch = (!hasBehaviour(RLV_BHVR_TOUCHHUD)) || (isException(RLV_BHVR_TOUCHHUD, idRoot, RLV_CHECK_PERMISSIVE));
}
#endif // RLV_EXTENSION_CMD_TOUCHXXX
}
if ( (!fCanTouch) && (hasBehaviour(RLV_BHVR_TOUCHME)) )
fCanTouch = hasBehaviourRoot(idRoot, RLV_BHVR_TOUCHME);
return fCanTouch;
}
size_t utf8str_strlen(const std::string& utf8)
{
const char* pUTF8 = utf8.c_str(); size_t length = 0;
@@ -943,6 +992,18 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
case RLV_BHVR_REMATTACH: // @addattach[:<option>]=n|y
eRet = onAddRemAttach(rlvCmd, fRefCount);
break;
case RLV_BHVR_ATTACHTHIS: // @attachthis[:<option>]=n|y
case RLV_BHVR_DETACHTHIS: // @detachthis[:<option>]=n|y
case RLV_BHVR_ATTACHALLTHIS: // @attachtallhis[:<option>]=n|y
case RLV_BHVR_DETACHALLTHIS: // @detachallthis[:<option>]=n|y
eRet = onAddRemFolderLock(rlvCmd, fRefCount);
break;
case RLV_BHVR_ATTACHTHISEXCEPT: // @attachthisexcept[:<option>]=n|y
case RLV_BHVR_DETACHTHISEXCEPT: // @detachthisexcept[:<option>]=n|y
case RLV_BHVR_ATTACHALLTHISEXCEPT: // @attachallthisexcept[:<option>]=n|y
case RLV_BHVR_DETACHALLTHISEXCEPT: // @detachallthisexcept[:<option>]=n|y
eRet = onAddRemFolderLockException(rlvCmd, fRefCount);
break;
case RLV_BHVR_SETENV: // @setenv=n|y
eRet = onAddRemSetEnv(rlvCmd, fRefCount);
break;
@@ -969,6 +1030,44 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
}
}
break;
case RLV_BHVR_SHAREDWEAR: // @sharedwear=n|y - Checked: 2011-03-28 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
case RLV_BHVR_SHAREDUNWEAR: // @sharedunwear=n|y - Checked: 2011-03-28 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
{
VERIFY_OPTION_REF(strOption.empty());
RlvFolderLocks::folderlock_source_t lockSource(RlvFolderLocks::ST_SHAREDPATH, LLStringUtil::null);
RlvFolderLocks::ELockScope eLockScope = RlvFolderLocks::SCOPE_SUBTREE;
ERlvLockMask eLockType = (RLV_BHVR_SHAREDUNWEAR == eBhvr) ? RLV_LOCK_REMOVE : RLV_LOCK_ADD;
if (RLV_TYPE_ADD == eType)
RlvFolderLocks::instance().addFolderLock(lockSource, RlvFolderLocks::PERM_DENY, eLockScope, rlvCmd.getObjectID(), eLockType);
else
RlvFolderLocks::instance().removeFolderLock(lockSource, RlvFolderLocks::PERM_DENY, eLockScope, rlvCmd.getObjectID(), eLockType);
}
break;
case RLV_BHVR_UNSHAREDWEAR: // @unsharedwear=n|y - Checked: 2011-03-28 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
case RLV_BHVR_UNSHAREDUNWEAR: // @unsharedunwear=n|y - Checked: 2011-03-28 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
{
VERIFY_OPTION_REF(strOption.empty());
// Lock down the inventory root
RlvFolderLocks::folderlock_source_t lockSource(RlvFolderLocks::ST_ROOTFOLDER, 0);
RlvFolderLocks::ELockScope eLockScope = RlvFolderLocks::SCOPE_SUBTREE;
ERlvLockMask eLockType = (RLV_BHVR_UNSHAREDUNWEAR == eBhvr) ? RLV_LOCK_REMOVE : RLV_LOCK_ADD;
if (RLV_TYPE_ADD == eType)
RlvFolderLocks::instance().addFolderLock(lockSource, RlvFolderLocks::PERM_DENY, eLockScope, rlvCmd.getObjectID(), eLockType);
else
RlvFolderLocks::instance().removeFolderLock(lockSource, RlvFolderLocks::PERM_DENY, eLockScope, rlvCmd.getObjectID(), eLockType);
// Add the #RLV shared folder as an exception
lockSource = RlvFolderLocks::folderlock_source_t(RlvFolderLocks::ST_SHAREDPATH, LLStringUtil::null);
if (RLV_TYPE_ADD == eType)
RlvFolderLocks::instance().addFolderLock(lockSource, RlvFolderLocks::PERM_ALLOW, eLockScope, rlvCmd.getObjectID(), eLockType);
else
RlvFolderLocks::instance().removeFolderLock(lockSource, RlvFolderLocks::PERM_ALLOW, eLockScope, rlvCmd.getObjectID(), eLockType);
}
break;
case RLV_BHVR_REDIRCHAT: // @redirchat:<channel>=n|y - Checked: 2010-03-26 (RLVa-1.2.0b) | Modified: RLVa-1.1.0h
case RLV_BHVR_REDIREMOTE: // @rediremote:<channel>=n|y - Checked: 2010-03-26 (RLVa-1.2.0b) | Modified: RLVa-1.1.0h
{
@@ -1140,8 +1239,17 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
pObj->mText->setString( (RLV_TYPE_ADD == eType) ? "" : pObj->mText->getPreFilteredText());
}
break;
case RLV_BHVR_EDIT: // @edit=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
case RLV_BHVR_EDIT: // @edit[:<uuid>=n|y - Checked: 2011-09-16 (RLVa-1.4.0b) | Modified: RLVa-1.4.0b
{
LLUUID idException(strOption);
if (idException.notNull()) // If there's an option then it should specify a valid UUID
{
if (RLV_TYPE_ADD == eType)
addException(rlvCmd.getObjectID(), eBhvr, idException);
else
removeException(rlvCmd.getObjectID(), eBhvr, idException);
break;
}
VERIFY_OPTION_REF(strOption.empty());
if (RLV_TYPE_ADD == eType)
@@ -1163,20 +1271,6 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
}
}
break;
#ifdef RLV_EXTENSION_CMD_TOUCHXXX
case RLV_BHVR_TOUCH: // @touch:<uuid>=n - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
{
// There should be an option and it should specify a valid UUID
LLUUID idException(strOption);
VERIFY_OPTION_REF(idException.notNull());
if (RLV_TYPE_ADD == eType)
addException(rlvCmd.getObjectID(), eBhvr, idException);
else
removeException(rlvCmd.getObjectID(), eBhvr, idException);
}
break;
#endif // RLV_EXTENSION_CMD_TOUCHXXX
case RLV_BHVR_FLY: // @fly=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
{
VERIFY_OPTION_REF(strOption.empty());
@@ -1207,6 +1301,10 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
#ifdef RLV_EXTENSION_CMD_INTERACT
case RLV_BHVR_INTERACT: // @interact=n|y - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
#endif // RLV_EXTENSION_CMD_INTERACT
case RLV_BHVR_TOUCHATTACHSELF: // @touchattachself=n|y - Checked: 2011-01-21 (RLVa-1.3.0e) | Added: RLVa-1.3.0e
case RLV_BHVR_TOUCHATTACHOTHER: // @touchattachother=n|y - Checked: 2011-01-21 (RLVa-1.3.0e) | Added: RLVa-1.3.0e
case RLV_BHVR_TOUCHALL: // @touchall=n|y - Checked: 2011-01-21 (RLVa-1.3.0e) | Added: RLVa-1.3.0e
case RLV_BHVR_TOUCHME: // @touchme=n|y - Checked: 2011-04-11 (RLVa-1.3.0h) | Added: RLVa-1.3.0h
case RLV_BHVR_UNSIT: // @unsit=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
case RLV_BHVR_SIT: // @sit=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
case RLV_BHVR_SITTP: // @sittp=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
@@ -1220,11 +1318,11 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
case RLV_BHVR_RECVIM: // @recvim[:<uuid>]=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
case RLV_BHVR_TPLURE: // @tplure[:<uuid>]=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
case RLV_BHVR_ACCEPTTP: // @accepttp[:<uuid>]=n|y - Checked: 2009-12-05 (RLVa-1.1.0h) | Modified: RLVa-1.1.0h
#ifdef RLV_EXTENSION_CMD_TOUCHXXX
case RLV_BHVR_TOUCHWORLD: // @touchworld[:<uuid>=n|y - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
case RLV_BHVR_TOUCHATTACH: // @touchattach[:<uuid>=n|y - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
#ifdef RLV_EXTENSION_CMD_TOUCHXXX
case RLV_BHVR_TOUCHHUD: // @touchhud[:<uuid>=n|y - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
#endif // RLV_EXTENSION_CMD_TOUCHXXX
case RLV_BHVR_TOUCHWORLD: // @touchworld[:<uuid>=n|y - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
{
LLUUID idException(strOption);
if (idException.notNull()) // If there's an option then it should specify a valid UUID
@@ -1238,6 +1336,29 @@ ERlvCmdRet RlvHandler::processAddRemCommand(const RlvCommand& rlvCmd)
VERIFY_OPTION_REF(strOption.empty());
}
break;
//
// The following block is only valid if there an option that specifies a valid UUID (reference-counted per option)
//
case RLV_BHVR_RECVCHATFROM: // @recvchatfrom:<uuid>=n|y - Checked: 2010-11-30 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
case RLV_BHVR_RECVEMOTEFROM: // @recvemotefrom:<uuid>=n|y - Checked: 2010-11-30 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
case RLV_BHVR_SENDIMTO: // @sendimto:<uuid>=n|y - Checked: 2010-11-30 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
case RLV_BHVR_RECVIMFROM: // @recvimfrom:<uuid>=n|y - Checked: 2010-11-30 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
case RLV_BHVR_EDITOBJ: // @editobj:<uuid>=n|y - Checked: 2010-11-29 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
case RLV_BHVR_TOUCHTHIS: // @touchthis:<uuid>=n|y - Checked: 2010-01-01 (RLVa-1.1.0l) | Added: RLVa-1.1.0l
{
// There should be an option and it should specify a valid UUID
LLUUID idException(strOption);
VERIFY_OPTION_REF(idException.notNull());
if (RLV_TYPE_ADD == eType)
addException(rlvCmd.getObjectID(), eBhvr, idException);
else
removeException(rlvCmd.getObjectID(), eBhvr, idException);
}
break;
//
// Unknown or invalid
//
case RLV_BHVR_UNKNOWN:
// Pass unknown commands on to registered command handlers
return (notifyCommandHandlers(&RlvCommandHandler::onAddRemCommand, rlvCmd, eRet, false)) ? eRet : RLV_RET_FAILED_UNKNOWN;
@@ -1359,6 +1480,82 @@ ERlvCmdRet RlvHandler::onAddRemDetach(const RlvCommand& rlvCmd, bool& fRefCount)
return RLV_RET_SUCCESS;
}
// Checked: 2010-11-30 (RLVa-1.3.0b) | Added: RLVa-1.3.0b
ERlvCmdRet RlvHandler::onAddRemFolderLock(const RlvCommand& rlvCmd, bool& fRefCount)
{
RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption());
RlvFolderLocks::folderlock_source_t lockSource;
if (rlvCmdOption.isEmpty())
{
lockSource = RlvFolderLocks::folderlock_source_t(RlvFolderLocks::ST_ATTACHMENT, rlvCmd.getObjectID());
}
else if (rlvCmdOption.isSharedFolder())
{
lockSource = RlvFolderLocks::folderlock_source_t(RlvFolderLocks::ST_SHAREDPATH, rlvCmd.getOption());
}
else if (rlvCmdOption.isAttachmentPoint())
{
lockSource = RlvFolderLocks::folderlock_source_t(RlvFolderLocks::ST_ATTACHMENTPOINT, RlvAttachPtLookup::getAttachPointIndex(rlvCmdOption.getAttachmentPoint()));
}
else if (rlvCmdOption.isWearableType())
{
lockSource = RlvFolderLocks::folderlock_source_t(RlvFolderLocks::ST_WEARABLETYPE, rlvCmdOption.getWearableType());
}
else
{
fRefCount = false; // Don't reference count failure
return RLV_RET_FAILED_OPTION;
}
ERlvBehaviour eBhvr = rlvCmd.getBehaviourType();
// Determine the lock type
ERlvLockMask eLockType = ((RLV_BHVR_ATTACHTHIS == eBhvr) || (RLV_BHVR_ATTACHALLTHIS == eBhvr)) ? RLV_LOCK_ADD : RLV_LOCK_REMOVE;
// Determine the folder lock options from the issued behaviour
RlvFolderLocks::ELockPermission eLockPermission = RlvFolderLocks::PERM_DENY;
RlvFolderLocks::ELockScope eLockScope =
((RLV_BHVR_ATTACHALLTHIS == eBhvr) || (RLV_BHVR_DETACHALLTHIS == eBhvr)) ? RlvFolderLocks::SCOPE_SUBTREE : RlvFolderLocks::SCOPE_NODE;
if (RLV_TYPE_ADD == rlvCmd.getParamType())
RlvFolderLocks::instance().addFolderLock(lockSource, eLockPermission, eLockScope, rlvCmd.getObjectID(), eLockType);
else
RlvFolderLocks::instance().removeFolderLock(lockSource, eLockPermission, eLockScope, rlvCmd.getObjectID(), eLockType);
fRefCount = true;
return RLV_RET_SUCCESS;
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
ERlvCmdRet RlvHandler::onAddRemFolderLockException(const RlvCommand& rlvCmd, bool& fRefCount)
{
// Sanity check - the option should specify a shared folder path
RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption());
if (!rlvCmdOption.isSharedFolder())
return RLV_RET_FAILED_OPTION;
ERlvBehaviour eBhvr = rlvCmd.getBehaviourType();
// Determine the lock type
ERlvLockMask eLockType =
((RLV_BHVR_ATTACHTHISEXCEPT == eBhvr) || (RLV_BHVR_ATTACHALLTHISEXCEPT == eBhvr)) ? RLV_LOCK_ADD : RLV_LOCK_REMOVE;
// Determine the folder lock options from the issued behaviour
RlvFolderLocks::ELockPermission eLockPermission = RlvFolderLocks::PERM_ALLOW;
RlvFolderLocks::ELockScope eLockScope =
((RLV_BHVR_ATTACHALLTHISEXCEPT == eBhvr) || (RLV_BHVR_DETACHALLTHISEXCEPT == eBhvr)) ? RlvFolderLocks::SCOPE_SUBTREE : RlvFolderLocks::SCOPE_NODE;
RlvFolderLocks::folderlock_source_t lockSource(RlvFolderLocks::ST_SHAREDPATH, rlvCmd.getOption());
if (RLV_TYPE_ADD == rlvCmd.getParamType())
RlvFolderLocks::instance().addFolderLock(lockSource, eLockPermission, eLockScope, rlvCmd.getObjectID(), eLockType);
else
RlvFolderLocks::instance().removeFolderLock(lockSource, eLockPermission, eLockScope, rlvCmd.getObjectID(), eLockType);
fRefCount = true;
return RLV_RET_SUCCESS;
}
// Checked: 2010-03-18 (RLVa-1.2.0e) | Modified: RLVa-1.2.0a
ERlvCmdRet RlvHandler::onAddRemSetEnv(const RlvCommand& rlvCmd, bool& fRefCount)
{
@@ -1443,28 +1640,27 @@ ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const
case RLV_BHVR_SIT: // @sit:<option>=force
eRet = onForceSit(rlvCmd);
break;
case RLV_BHVR_TPTO: // @tpto:<option>=force - Checked: 2010-04-07 (RLVa-1.2.0d) | Modified: RLVa-1.0.0h
case RLV_BHVR_ADJUSTHEIGHT: // @adjustheight:<options>=force - Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f
{
eRet = RLV_RET_FAILED_OPTION;
if ( (!rlvCmd.getOption().empty()) && (std::string::npos == rlvCmd.getOption().find_first_not_of("0123456789/.")) )
RlvCommandOptionAdjustHeight rlvCmdOption(rlvCmd);
VERIFY_OPTION(rlvCmdOption.isValid());
LLVOAvatar* pAvatar = gAgentAvatarp;
if (pAvatar)
{
LLVector3d posGlobal;
boost_tokenizer tokens(rlvCmd.getOption(), boost::char_separator<char>("/", "", boost::keep_empty_tokens)); int idx = 0;
for (boost_tokenizer::const_iterator itToken = tokens.begin(); itToken != tokens.end(); ++itToken)
{
if (idx < 3)
LLStringUtil::convertToF64(*itToken, posGlobal[idx++]);
}
if (idx == 3)
{
gAgent.teleportViaLocation(posGlobal);
eRet = RLV_RET_SUCCESS;
}
F32 nValue = (rlvCmdOption.m_nPelvisToFoot - pAvatar->getPelvisToFoot()) * rlvCmdOption.m_nPelvisToFootDeltaMult;
nValue += rlvCmdOption.m_nPelvisToFootOffset;
gSavedSettings.setF32(RLV_SETTING_AVATAROFFSET_Z, llclamp<F32>(nValue, -1.0f, 1.0f));
}
}
break;
case RLV_BHVR_TPTO: // @tpto:<option>=force - Checked: 2011-03-28 (RLVa-1.3.0f) | Modified: RLVa-1.3.0f
{
RlvCommandOptionTpTo rlvCmdOption(rlvCmd);
VERIFY_OPTION( (rlvCmdOption.isValid()) && (!rlvCmdOption.m_posGlobal.isNull()) );
gAgent.teleportViaLocation(rlvCmdOption.m_posGlobal);
}
break;
case RLV_BHVR_ATTACH:
case RLV_BHVR_ATTACHOVER:
case RLV_BHVR_ATTACHALL:

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -46,15 +46,19 @@ public:
// - to check exceptions -> isException()
public:
// Returns TRUE is at least one object contains the specified behaviour (and optional option)
bool hasBehaviour(ERlvBehaviour eBehaviour) const { return (eBehaviour < RLV_BHVR_COUNT) ? (0 != m_Behaviours[eBehaviour]) : false; }
bool hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const;
bool hasBehaviour(ERlvBehaviour eBhvr) const { return (eBhvr < RLV_BHVR_COUNT) ? (0 != m_Behaviours[eBhvr]) : false; }
bool hasBehaviour(ERlvBehaviour eBhvr, const std::string& strOption) const;
// Returns TRUE if at least one object (except the specified one) contains the specified behaviour (and optional option)
bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const;
bool hasBehaviourExcept(ERlvBehaviour eBehaviour, const std::string& strOption, const LLUUID& idObj) const;
bool hasBehaviourExcept(ERlvBehaviour eBhvr, const LLUUID& idObj) const;
bool hasBehaviourExcept(ERlvBehaviour eBhvr, const std::string& strOption, const LLUUID& idObj) const;
// Returns TRUE if at least one object in the linkset with specified root ID contains the specified behaviour (and optional option)
bool hasBehaviourRoot(const LLUUID& idObjRoot, ERlvBehaviour eBhvr, const std::string& strOption = LLStringUtil::null) const;
// Adds or removes an exception for the specified behaviour
void addException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption);
void removeException(const LLUUID& idObj, ERlvBehaviour eBhvr, const RlvExceptionOption& varOption);
// Returns TRUE if the specified behaviour has an added exception
bool hasException(ERlvBehaviour eBhvr) const;
// Returns TRUE if the specified option was added as an exception for the specified behaviour
bool isException(ERlvBehaviour eBhvr, const RlvExceptionOption& varOption, ERlvExceptionCheck typeCheck = RLV_CHECK_DEFAULT) const;
// Returns TRUE if the specified behaviour should behave "permissive" (rather than "strict"/"secure")
@@ -90,7 +94,10 @@ public:
void setSitSource(const LLVector3d& posSource) { m_posSitSource = posSource; } // @standtp
// Command specific helper functions
bool canShowHoverText(LLViewerObject* pObj) const; // @showhovertext* command family
bool canEdit(const LLViewerObject* pObj) const; // @edit and @editobj
bool canReceiveIM(const LLUUID& idSender) const; // @recvim and @recvimfrom
bool canShowHoverText(const LLViewerObject* pObj) const; // @showhovertext* command family
bool canSendIM(const LLUUID& idRecipient) const; // @sendim and @sendimto
bool canSit(LLViewerObject* pObj, const LLVector3& posOffset = LLVector3::zero) const;
bool canStand() const;
bool canTeleportViaLure(const LLUUID& idAgent) const;
@@ -149,6 +156,8 @@ protected:
ERlvCmdRet processAddRemCommand(const RlvCommand& rlvCmd);
ERlvCmdRet onAddRemAttach(const RlvCommand& rlvCmd, bool& fRefCount);
ERlvCmdRet onAddRemDetach(const RlvCommand& rlvCmd, bool& fRefCount);
ERlvCmdRet onAddRemFolderLock(const RlvCommand& rlvCmd, bool& fRefCount);
ERlvCmdRet onAddRemFolderLockException(const RlvCommand& rlvCmd, bool& fRefCount);
ERlvCmdRet onAddRemSetEnv(const RlvCommand& rlvCmd, bool& fRefCount);
// Command handlers (RLV_TYPE_FORCE)
ERlvCmdRet processForceCommand(const RlvCommand& rlvCmd) const;
@@ -221,8 +230,42 @@ inline void RlvHandler::addException(const LLUUID& idObj, ERlvBehaviour eBhvr, c
m_Exceptions.insert(std::pair<ERlvBehaviour, RlvException>(eBhvr, RlvException(idObj, eBhvr, varOption)));
}
// Checked: 2010-11-29 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
inline bool RlvHandler::canEdit(const LLViewerObject* pObj) const
{
// The specified object can be edited if:
// - not generally restricted from editing (or the object's root is an exception)
// - not specifically restricted from editing this object's root
return
(pObj) &&
((!hasBehaviour(RLV_BHVR_EDIT)) || (isException(RLV_BHVR_EDIT, pObj->getRootEdit()->getID()))) &&
((!hasBehaviour(RLV_BHVR_EDITOBJ)) || (!isException(RLV_BHVR_EDITOBJ, pObj->getRootEdit()->getID())));
}
// Checked: 2010-11-30 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
inline bool RlvHandler::canReceiveIM(const LLUUID& idSender) const
{
// User can receive an IM from "sender" (could be an agent or a group) if:
// - not generally restricted from receiving IMs (or the sender is an exception)
// - not specifically restricted from receiving an IM from the sender
return
( (!hasBehaviour(RLV_BHVR_RECVIM)) || (isException(RLV_BHVR_RECVIM, idSender)) ) &&
( (!hasBehaviour(RLV_BHVR_RECVIMFROM)) || (!isException(RLV_BHVR_RECVIMFROM, idSender)) );
}
// Checked: 2010-11-30 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
inline bool RlvHandler::canSendIM(const LLUUID& idRecipient) const
{
// User can send an IM to "recipient" (could be an agent or a group) if:
// - not generally restricted from sending IMs (or the recipient is an exception)
// - not specifically restricted from sending an IM to the recipient
return
( (!hasBehaviour(RLV_BHVR_SENDIM)) || (isException(RLV_BHVR_SENDIM, idRecipient)) ) &&
( (!hasBehaviour(RLV_BHVR_SENDIMTO)) || (!isException(RLV_BHVR_SENDIMTO, idRecipient)) );
}
// Checked: 2010-03-27 (RLVa-1.2.0b) | Modified: RLVa-1.0.0f
inline bool RlvHandler::canShowHoverText(LLViewerObject *pObj) const
inline bool RlvHandler::canShowHoverText(const LLViewerObject *pObj) const
{
return ( (!pObj) || (LL_PCODE_VOLUME != pObj->getPCode()) ||
!( (hasBehaviour(RLV_BHVR_SHOWHOVERTEXTALL)) ||
@@ -264,57 +307,20 @@ inline bool RlvHandler::canTeleportViaLure(const LLUUID& idAgent) const
return ((!hasBehaviour(RLV_BHVR_TPLURE)) || (isException(RLV_BHVR_TPLURE, idAgent))) && (canStand());
}
// Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l
inline bool RlvHandler::canTouch(const LLViewerObject* pObj, const LLVector3& posOffset /*=LLVector3::zero*/) const
inline bool RlvHandler::hasBehaviour(ERlvBehaviour eBhvr, const std::string& strOption) const
{
#ifdef RLV_EXTENSION_CMD_TOUCHXXX
bool fCanTouch = (pObj) &&
( (!hasBehaviour(RLV_BHVR_TOUCH)) || (!isException(RLV_BHVR_TOUCH, pObj->getRootEdit()->getID(), RLV_CHECK_PERMISSIVE)) );
if (fCanTouch)
{
if ( (!pObj->isAttachment()) || (!pObj->permYouOwner()) )
{
// Rezzed prim or attachment worn by another avie
fCanTouch =
( (!hasBehaviour(RLV_BHVR_TOUCHWORLD)) ||
(isException(RLV_BHVR_TOUCHWORLD, pObj->getRootEdit()->getID(), RLV_CHECK_PERMISSIVE)) ) &&
( (!hasBehaviour(RLV_BHVR_FARTOUCH)) ||
(dist_vec_squared(gAgent.getPositionGlobal(), pObj->getPositionGlobal() + LLVector3d(posOffset)) <= 1.5f * 1.5f) );
}
else if (pObj->isHUDAttachment())
{
// HUD attachment
fCanTouch = (!hasBehaviour(RLV_BHVR_TOUCHHUD)) ||
(isException(RLV_BHVR_TOUCHHUD, pObj->getRootEdit()->getID(), RLV_CHECK_PERMISSIVE));
}
else
{
// Regular attachment worn by this avie
fCanTouch =
( (!hasBehaviour(RLV_BHVR_TOUCHATTACH)) ||
(isException(RLV_BHVR_TOUCHATTACH, pObj->getRootEdit()->getID(), RLV_CHECK_PERMISSIVE)) );
}
}
return fCanTouch;
#else
return (pObj) &&
(
((pObj->isAttachment()) && (pObj->permYouOwner())) ||
( (!hasBehaviour(RLV_BHVR_FARTOUCH)) ||
(dist_vec_squared(gAgent.getPositionGlobal(), pObj->getPositionGlobal() + LLVector3d(posOffset)) <= 1.5f * 1.5f) )
);
#endif // RLV_EXTENSION_CMD_TOUCHXXX
return hasBehaviourExcept(eBhvr, strOption, LLUUID::null);
}
inline bool RlvHandler::hasBehaviour(ERlvBehaviour eBehaviour, const std::string& strOption) const
inline bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBhvr, const LLUUID& idObj) const
{
return hasBehaviourExcept(eBehaviour, strOption, LLUUID::null);
return hasBehaviourExcept(eBhvr, LLStringUtil::null, idObj);
}
inline bool RlvHandler::hasBehaviourExcept(ERlvBehaviour eBehaviour, const LLUUID& idObj) const
// Checked: 2010-11-29 (RLVa-1.3.0c) | Added: RLVa-1.3.0c
inline bool RlvHandler::hasException(ERlvBehaviour eBhvr) const
{
return hasBehaviourExcept(eBehaviour, std::string(), idObj);
return (m_Exceptions.find(eBhvr) != m_Exceptions.end());
}
inline bool RlvHandler::isPermissive(ERlvBehaviour eBhvr) const

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -35,6 +35,8 @@
#include "rlvinventory.h"
#include "rlvhandler.h"
#include <boost/algorithm/string.hpp>
// Defined in llinventorybridge.cpp
void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
@@ -74,6 +76,9 @@ RlvCommand::RlvCommand(const LLUUID& idObj, const std::string& strCommand)
return;
}
// HACK: all those @*overorreplace synonyms are rather tedious (and error-prone) to deal with so replace them their equivalent
if ( (RLV_TYPE_FORCE == m_eParamType) && (m_strBehaviour.length() - 13 == m_strBehaviour.rfind("overorreplace")) )
m_strBehaviour.erase(m_strBehaviour.length() - 13, 13);
// HACK: all those @addoutfit* synonyms are rather tedious (and error-prone) to deal with so replace them their @attach* equivalent
if ( (RLV_TYPE_FORCE == m_eParamType) && (0 == m_strBehaviour.find("addoutfit")) )
m_strBehaviour.replace(0, 9, "attach");
@@ -157,16 +162,19 @@ void RlvCommand::initLookupTable()
// NOTE: keep this matched with the enumeration at all times
std::string arBehaviours[RLV_BHVR_COUNT] =
{
"detach", "attach", "addattach", "remattach", "addoutfit", "remoutfit", "emote", "sendchat", "recvchat", "recvemote",
"redirchat", "rediremote", "chatwhisper", "chatnormal", "chatshout", "sendchannel", "sendim", "recvim", "permissive",
"detach", "attach", "addattach", "remattach", "addoutfit", "remoutfit", "sharedwear", "sharedunwear", "unsharedwear",
"unsharedunwear", "emote", "sendchat", "recvchat", "recvchatfrom", "recvemote", "recvemotefrom", "redirchat", "rediremote",
"chatwhisper", "chatnormal", "chatshout", "sendchannel", "sendim", "sendimto", "recvim", "recvimfrom", "permissive",
"notify", "showinv", "showminimap", "showworldmap", "showloc", "shownames", "showhovertext", "showhovertexthud",
"showhovertextworld", "showhovertextall", "tplm", "tploc", "tplure", "viewnote", "viewscript", "viewtexture",
"acceptpermission", "accepttp", "allowidle", "edit", "rez", "fartouch", "interact", "touch", "touchattach", "touchhud",
"touchworld", "fly", "unsit", "sit", "sittp", "standtp", "setdebug", "setenv", "detachme", "attachover", "attachthis",
"attachthisover", "detachthis", "attachall", "attachallover", "detachall", "attachallthis", "attachallthisover",
"detachallthis", "tpto", "version", "versionnew", "versionnum", "getattach", "getattachnames", "getaddattachnames",
"getremattachnames", "getoutfit", "getoutfitnames", "getaddoutfitnames", "getremoutfitnames", "findfolder", "findfolders",
"getpath", "getpathnew", "getinv", "getinvworn", "getsitid", "getcommand", "getstatus", "getstatusall"
"showhovertextworld", "showhovertextall", "tplm", "tploc", "tplure", "viewnote", "viewscript", "viewtexture",
"acceptpermission", "accepttp", "allowidle", "edit", "editobj", "rez", "fartouch", "interact",
"touchthis", "touchattach", "touchattachself", "touchattachother", "touchhud", "touchworld", "touchall", "touchme",
"fly", "unsit", "sit", "sittp", "standtp", "setdebug", "setenv", "detachme", "attachover", "attachthis", "attachthisover",
"attachthisexcept", "detachthis", "detachthisexcept", "attachall", "attachallover", "detachall", "attachallthis",
"attachallthisexcept", "attachallthisover", "detachallthis", "detachallthisexcept", "adjustheight", "tpto",
"version", "versionnew", "versionnum", "getattach", "getattachnames", "getaddattachnames", "getremattachnames",
"getoutfit", "getoutfitnames", "getaddoutfitnames", "getremoutfitnames", "findfolder", "findfolders", "getpath",
"getpathnew", "getinv", "getinvworn", "getsitid", "getcommand", "getstatus", "getstatusall"
};
for (int idxBvhr = 0; idxBvhr < RLV_BHVR_COUNT; idxBvhr++)
@@ -177,7 +185,7 @@ void RlvCommand::initLookupTable()
}
// ============================================================================
// RlvCommandOption
// RlvCommandOption structures
//
// Checked: 2010-09-28 (RLVa-1.1.3a) | Added: RLVa-1.2.1c
@@ -203,26 +211,21 @@ RlvCommandOptionGeneric::RlvCommandOptionGeneric(const std::string& strOption)
}
}
// Checked: 2010-09-28 (RLVa-1.1.3a) | Added: RLVa-1.2.1c
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.3.0b
RlvCommandOptionGetPath::RlvCommandOptionGetPath(const RlvCommand& rlvCmd)
: m_fValid(true) // Assume the option will be a valid one until we find out otherwise
{
m_fValid = true; // Assume the option will be a valid one until we find out otherwise
// @getpath[:<option>]=<channel> => <option> is transformed to a list of inventory item UUIDs to get the path of
RlvCommandOptionGeneric rlvCmdOption(rlvCmd.getOption());
if (rlvCmdOption.isWearableType()) // <option> can be a clothing layer
{
LLWearableType::EType wtType = rlvCmdOption.getWearableType();
m_idItems.push_back(gAgentWearables.getWearableItemID(wtType, 0)); // TODO: MULTI-WEARABLE
getItemIDs(rlvCmdOption.getWearableType(), m_idItems, false);
}
else if (rlvCmdOption.isAttachmentPoint()) // ... or it can specify an attachment point
{
const LLViewerJointAttachment* pAttachPt = rlvCmdOption.getAttachmentPoint();
for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator itAttachObj = pAttachPt->mAttachedObjects.begin();
itAttachObj != pAttachPt->mAttachedObjects.end(); ++itAttachObj)
{
m_idItems.push_back((*itAttachObj)->getAttachmentItemID());
}
getItemIDs(rlvCmdOption.getAttachmentPoint(), m_idItems, false);
}
else if (rlvCmdOption.isEmpty()) // ... or it can be empty (in which case we act on the object that issued the command)
{
@@ -236,12 +239,70 @@ RlvCommandOptionGetPath::RlvCommandOptionGetPath(const RlvCommand& rlvCmd)
}
}
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.3.0b
bool RlvCommandOptionGetPath::getItemIDs(const LLViewerJointAttachment* pAttachPt, uuid_vec_t& idItems, bool fClear)
{
if (fClear)
idItems.clear();
uuid_vec_t::size_type cntItemsPrev = idItems.size();
if (pAttachPt)
{
for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator itAttachObj = pAttachPt->mAttachedObjects.begin();
itAttachObj != pAttachPt->mAttachedObjects.end(); ++itAttachObj)
{
idItems.push_back((*itAttachObj)->getAttachmentItemID());
}
}
return (cntItemsPrev != idItems.size());
}
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.3.0b
bool RlvCommandOptionGetPath::getItemIDs(LLWearableType::EType wtType, uuid_vec_t& idItems, bool fClear)
{
if (fClear)
idItems.clear();
uuid_vec_t::size_type cntItemsPrev = idItems.size();
if (gAgentWearables.getWearable(wtType, 0))
idItems.push_back(gAgentWearables.getWearableItemID(wtType,0));
return (cntItemsPrev != idItems.size());
}
// Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f
RlvCommandOptionAdjustHeight::RlvCommandOptionAdjustHeight(const RlvCommand& rlvCmd)
: m_nPelvisToFoot(0.0f), m_nPelvisToFootDeltaMult(0.0f), m_nPelvisToFootOffset(0.0f)
{
std::vector<std::string> cmdTokens;
boost::split(cmdTokens, rlvCmd.getOption(), boost::is_any_of(";"));
if (1 == cmdTokens.size())
{
m_fValid = (LLStringUtil::convertToF32(cmdTokens[0], m_nPelvisToFootOffset));
m_nPelvisToFootOffset = llclamp<F32>(m_nPelvisToFootOffset / 100, -1.0f, 1.0f);
}
else if ( (2 <= cmdTokens.size()) && (cmdTokens.size() <= 3) )
{
m_fValid = (LLStringUtil::convertToF32(cmdTokens[0], m_nPelvisToFoot)) &&
(LLStringUtil::convertToF32(cmdTokens[1], m_nPelvisToFootDeltaMult)) &&
( (2 == cmdTokens.size()) || (LLStringUtil::convertToF32(cmdTokens[2], m_nPelvisToFootOffset)) );
}
}
// Checked: 2011-03-28 (RLVa-1.3.0f) | Added: RLVa-1.3.0f
RlvCommandOptionTpTo::RlvCommandOptionTpTo(const RlvCommand &rlvCmd)
{
std::vector<std::string> cmdTokens;
boost::split(cmdTokens, rlvCmd.getOption(), boost::is_any_of("/"));
m_fValid = (3 == cmdTokens.size());
for (int idxAxis = 0; (idxAxis < 3) && (m_fValid); idxAxis++)
m_fValid &= (bool)LLStringUtil::convertToF64(cmdTokens[idxAxis], m_posGlobal[idxAxis]);
}
// =========================================================================
// RlvObject
//
RlvObject::RlvObject(const LLUUID& idObj) : m_UUID(idObj), m_nLookupMisses(0)
{
RlvObject::RlvObject(const LLUUID& idObj) : m_idObj(idObj), m_nLookupMisses(0)
{
LLViewerObject* pObj = gObjectList.findObject(idObj);
m_fLookup = (NULL != pObj);
m_idxAttachPt = (pObj) ? ATTACHMENT_ID_FROM_STATE(pObj->getState()) : 0;

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -99,84 +99,81 @@ typedef std::list<RlvCommand> rlv_command_list_t;
// RlvCommandOption (and derived classed)
//
class RlvCommandOption
struct RlvCommandOption
{
protected:
RlvCommandOption() {}
RlvCommandOption() : m_fValid(false) {}
public:
virtual ~RlvCommandOption() {}
public:
virtual bool isAttachmentPoint() const { return false; }
virtual bool isAttachmentPointGroup() const { return false; }
virtual bool isEmpty() const = 0;
virtual bool isSharedFolder() const { return false; }
virtual bool isString() const { return false; }
virtual bool isUUID() const { return false; }
virtual bool isValid() const = 0;
virtual bool isWearableType() const { return false; }
virtual LLViewerJointAttachment* getAttachmentPoint() const { return NULL; }
virtual ERlvAttachGroupType getAttachmentPointGroup() const { return RLV_ATTACHGROUP_INVALID; }
virtual LLViewerInventoryCategory* getSharedFolder() const { return NULL; }
virtual const std::string& getString() const { return LLStringUtil::null; }
virtual const LLUUID& getUUID() const { return LLUUID::null; }
virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_INVALID; }
virtual bool isEmpty() const { return false; }
virtual bool isValid() const { return m_fValid; }
protected:
bool m_fValid;
};
class RlvCommandOptionGeneric : public RlvCommandOption
struct RlvCommandOptionGeneric : public RlvCommandOption
{
public:
explicit RlvCommandOptionGeneric(const std::string& strOption);
RlvCommandOptionGeneric(LLViewerJointAttachment* pAttachPt) : m_fEmpty(false) { m_varOption = pAttachPt; }
RlvCommandOptionGeneric(LLViewerInventoryCategory* pFolder) : m_fEmpty(false) { m_varOption = pFolder; }
RlvCommandOptionGeneric(const LLUUID& idOption) : m_fEmpty(false) { m_varOption = idOption; }
RlvCommandOptionGeneric(LLWearableType::EType wtType) : m_fEmpty(false) { m_varOption = wtType; }
/*virtual*/ ~RlvCommandOptionGeneric() {}
public:
/*virtual*/ bool isAttachmentPoint() const { return (!isEmpty()) && (typeid(LLViewerJointAttachment*) == m_varOption.type()); }
/*virtual*/ bool isAttachmentPointGroup() const { return (!isEmpty()) && (typeid(ERlvAttachGroupType) == m_varOption.type()); }
/*virtual*/ bool isEmpty() const { return m_fEmpty; }
/*virtual*/ bool isSharedFolder() const { return (!isEmpty()) && (typeid(LLViewerInventoryCategory*) == m_varOption.type()); }
/*virtual*/ bool isString() const { return (!isEmpty()) && (typeid(std::string) == m_varOption.type()); }
/*virtual*/ bool isUUID() const { return (!isEmpty()) && (typeid(LLUUID) == m_varOption.type()); }
/*virtual*/ bool isValid() const { return true; } // This doesn't really have any significance for the generic class
/*virtual*/ bool isWearableType() const { return (!isEmpty()) && (typeid(LLWearableType::EType) == m_varOption.type()); }
bool isAttachmentPoint() const { return (!isEmpty()) && (typeid(LLViewerJointAttachment*) == m_varOption.type()); }
bool isAttachmentPointGroup() const { return (!isEmpty()) && (typeid(ERlvAttachGroupType) == m_varOption.type()); }
bool isEmpty() const { return m_fEmpty; }
bool isSharedFolder() const { return (!isEmpty()) && (typeid(LLViewerInventoryCategory*) == m_varOption.type()); }
bool isString() const { return (!isEmpty()) && (typeid(std::string) == m_varOption.type()); }
bool isUUID() const { return (!isEmpty()) && (typeid(LLUUID) == m_varOption.type()); }
bool isWearableType() const { return (!isEmpty()) && (typeid(LLWearableType::EType) == m_varOption.type()); }
/*virtual*/ LLViewerJointAttachment* getAttachmentPoint() const
{ return (isAttachmentPoint()) ? boost::get<LLViewerJointAttachment*>(m_varOption) : RlvCommandOption::getAttachmentPoint(); }
/*virtual*/ ERlvAttachGroupType getAttachmentPointGroup() const
{ return (isAttachmentPointGroup()) ? boost::get<ERlvAttachGroupType>(m_varOption) : RlvCommandOption::getAttachmentPointGroup(); }
/*virtual*/ LLViewerInventoryCategory* getSharedFolder() const
{ return (isSharedFolder()) ? boost::get<LLViewerInventoryCategory*>(m_varOption) : RlvCommandOption::getSharedFolder(); }
/*virtual*/ const std::string& getString() const
{ return (isString()) ? boost::get<std::string>(m_varOption) : RlvCommandOption::getString(); }
/*virtual*/ const LLUUID& getUUID() const
{ return (isUUID()) ? boost::get<LLUUID>(m_varOption) : RlvCommandOption::getUUID(); }
/*virtual*/ LLWearableType::EType getWearableType() const
{ return (isWearableType()) ? boost::get<LLWearableType::EType>(m_varOption) : RlvCommandOption::getWearableType(); }
LLViewerJointAttachment* getAttachmentPoint() const
{ return (isAttachmentPoint()) ? boost::get<LLViewerJointAttachment*>(m_varOption) : NULL; }
ERlvAttachGroupType getAttachmentPointGroup() const
{ return (isAttachmentPointGroup()) ? boost::get<ERlvAttachGroupType>(m_varOption) : RLV_ATTACHGROUP_INVALID; }
LLViewerInventoryCategory* getSharedFolder() const
{ return (isSharedFolder()) ? boost::get<LLViewerInventoryCategory*>(m_varOption) : NULL; }
const std::string& getString() const
{ return (isString()) ? boost::get<std::string>(m_varOption) : LLStringUtil::null; }
const LLUUID& getUUID() const
{ return (isUUID()) ? boost::get<LLUUID>(m_varOption) : LLUUID::null; }
LLWearableType::EType getWearableType() const
{ return (isWearableType()) ? boost::get<LLWearableType::EType>(m_varOption) : LLWearableType::WT_INVALID; }
protected:
bool m_fEmpty;
boost::variant<LLViewerJointAttachment*, ERlvAttachGroupType, LLViewerInventoryCategory*, std::string, LLUUID, LLWearableType::EType> m_varOption;
};
class RlvCommandOptionGetPath : public RlvCommandOption
struct RlvCommandOptionGetPath : public RlvCommandOption
{
public:
RlvCommandOptionGetPath(const RlvCommand& rlvCmd);
/*virtual*/ ~RlvCommandOptionGetPath() {}
/*virtual*/ bool isEmpty() const { return m_idItems.empty(); }
/*virtual*/ bool isValid() const { return m_fValid; }
const uuid_vec_t& getItemIDs() const { return m_idItems; }
static bool getItemIDs(const LLViewerJointAttachment* pAttachPt, uuid_vec_t& idItems, bool fClear = true);
static bool getItemIDs(LLWearableType::EType wtType, uuid_vec_t& idItems, bool fClear = true);
protected:
bool m_fValid;
uuid_vec_t m_idItems;
};
struct RlvCommandOptionAdjustHeight : public RlvCommandOption
{
RlvCommandOptionAdjustHeight(const RlvCommand& rlvCmd);
F32 m_nPelvisToFoot;
F32 m_nPelvisToFootDeltaMult;
F32 m_nPelvisToFootOffset;
};
struct RlvCommandOptionTpTo : public RlvCommandOption
{
RlvCommandOptionTpTo(const RlvCommand& rlvCmd);
LLVector3d m_posGlobal;
};
// ============================================================================
// RlvObject
//
@@ -199,13 +196,16 @@ public:
const rlv_command_list_t* getCommandList() const { return &m_Commands; }
const LLUUID& getObjectID() const { return m_idObj; }
const LLUUID& getRootID() const { return m_idRoot; }
/*
* Member variables
*/
protected:
LLUUID m_UUID; // The object's UUID
S32 m_idxAttachPt; // The object's attachment point (or 0 if it's not an attachment)
LLUUID m_idRoot; // The UUID of the object's root (may or may not be different from m_UUID)
LLUUID m_idObj; // The object's UUID
LLUUID m_idRoot; // The UUID of the object's root (may or may not be different from m_idObj)
bool m_fLookup; // TRUE if the object existed in gObjectList at one point in time
S16 m_nLookupMisses; // Count of unsuccessful lookups in gObjectList by the GC
rlv_command_list_t m_Commands; // List of behaviours held by this object (in the order they were received)
@@ -396,6 +396,27 @@ public:
virtual BOOL tick();
};
class RlvCallbackTimerOnce : public LLEventTimer
{
public:
typedef boost::function<void ()> nullary_func_t;
public:
RlvCallbackTimerOnce(F32 nPeriod, nullary_func_t cb) : LLEventTimer(nPeriod), m_Callback(cb) {}
/*virtual*/ BOOL tick()
{
m_Callback();
return TRUE;
}
protected:
nullary_func_t m_Callback;
};
inline void rlvCallbackTimerOnce(F32 nPeriod, RlvCallbackTimerOnce::nullary_func_t cb)
{
// Timer will automatically delete itself after the callback
new RlvCallbackTimerOnce(nPeriod, cb);
}
// ============================================================================
// Various helper functions
//

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -62,7 +62,36 @@ public:
// RlvInventory member functions
//
// Checked: 2010-02-28 (RLVa-1.1.3a) | Modified: RLVa-1.0.0h
// Checked: 2011-03-28 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
RlvInventory::RlvInventory()
: m_fFetchStarted(false), m_fFetchComplete(false)
{
}
// Checked: 2011-03-28 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
RlvInventory::~RlvInventory()
{
if (gInventory.containsObserver(this))
gInventory.removeObserver(this);
}
// Checked: 2011-03-28 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
void RlvInventory::changed(U32 mask)
{
const std::set<LLUUID>& idsChanged = gInventory.getChangedIDs();
if (std::find(idsChanged.begin(), idsChanged.end(), m_idRlvRoot) != idsChanged.end())
{
gInventory.removeObserver(this);
LLUUID idRlvRootPrev = m_idRlvRoot;
m_idRlvRoot.setNull();
if (idRlvRootPrev != getSharedRootID())
m_OnSharedRootIDChanged();
}
}
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.0.0h
void RlvInventory::fetchSharedInventory()
{
// Sanity check - don't fetch if we're already fetching, or if we don't have a shared root
@@ -222,25 +251,29 @@ bool RlvInventory::getPath(const uuid_vec_t& idItems, LLInventoryModel::cat_arra
return (folders.count() != 0);
}
// Checked: 2010-02-28 (RLVa-1.1.3a) | Modified: RLVa-1.0.0h
LLViewerInventoryCategory* RlvInventory::getSharedRoot() const
// Checked: 2011-03-28 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
const LLUUID& RlvInventory::getSharedRootID() const
{
if (gInventory.isInventoryUsable())
if ( (m_idRlvRoot.isNull()) && (gInventory.isInventoryUsable()) )
{
LLInventoryModel::cat_array_t* pFolders; LLInventoryModel::item_array_t* pItems;
gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), pFolders, pItems);
if (pFolders)
{
// NOTE: we might have multiple #RLV folders so we'll just go with the first one we come across
LLViewerInventoryCategory* pFolder;
const LLViewerInventoryCategory* pFolder;
for (S32 idxFolder = 0, cntFolder = pFolders->count(); idxFolder < cntFolder; idxFolder++)
{
if ( ((pFolder = pFolders->get(idxFolder)) != NULL) && (RlvInventory::cstrSharedRoot == pFolder->getName()) )
return pFolder;
if ( ((pFolder = pFolders->get(idxFolder)) != NULL) && (cstrSharedRoot == pFolder->getName()) )
{
if (!gInventory.containsObserver((RlvInventory*)this))
gInventory.addObserver((RlvInventory*)this);
m_idRlvRoot = pFolder->getUUID();
}
}
}
}
return NULL;
return m_idRlvRoot;
}
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.0.1a

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -28,30 +28,37 @@
// RlvInventory class declaration
//
// TODO-RLVa: [RLVa-1.2.0] Make all of this static rather than a singleton?
class RlvInventory : public LLSingleton<RlvInventory>
class RlvInventory : public LLSingleton<RlvInventory>, public LLInventoryObserver
{
protected:
RlvInventory() : m_fFetchStarted(false), m_fFetchComplete(false) {}
RlvInventory();
public:
~RlvInventory();
// LLInventoryObserver override
/*virtual*/ void changed(U32 mask);
/*
* #RLV Shared inventory
*/
public:
typedef boost::signals2::signal<void (void)> callback_signal_t;
void addSharedRootIDChangedCallback(const callback_signal_t::slot_type& cb) { m_OnSharedRootIDChanged.connect(cb); }
// Find all folders that match a supplied criteria (clears the output array)
bool findSharedFolders(const std::string& strCriteria, LLInventoryModel::cat_array_t& folders) const;
bool findSharedFolders(const std::string& strCriteria, LLInventoryModel::cat_array_t& folders) const;
// Gets the shared path for any shared items present in idItems (clears the output array)
bool getPath(const uuid_vec_t& idItems, LLInventoryModel::cat_array_t& folders) const;
bool getPath(const uuid_vec_t& idItems, LLInventoryModel::cat_array_t& folders) const;
// Returns a pointer to the shared root folder (if there is one)
LLViewerInventoryCategory* getSharedRoot() const;
LLViewerInventoryCategory* getSharedRoot() const;
const LLUUID& getSharedRootID() const;
// Returns a subfolder of idParent that starts with strFolderName (exact match > partial match)
LLViewerInventoryCategory* getSharedFolder(const LLUUID& idParent, const std::string& strFolderName) const;
LLViewerInventoryCategory* getSharedFolder(const LLUUID& idParent, const std::string& strFolderName) const;
// Looks up a folder from a path (relative to the shared root)
LLViewerInventoryCategory* getSharedFolder(const std::string& strPath) const;
LLViewerInventoryCategory* getSharedFolder(const std::string& strPath) const;
// Returns the path of the supplied folder (relative to the shared root)
std::string getSharedPath(const LLViewerInventoryCategory* pFolder) const;
std::string getSharedPath(const LLViewerInventoryCategory* pFolder) const;
// Returns TRUE if the supplied folder is a descendent of the #RLV folder
bool isSharedFolder(const LLUUID& idFolder);
bool isSharedFolder(const LLUUID& idFolder);
/*
* Inventory fetching
@@ -76,8 +83,10 @@ public:
* Member variables
*/
protected:
bool m_fFetchStarted; // TRUE if we fired off an inventory fetch
bool m_fFetchComplete; // TRUE if everything was fetched
bool m_fFetchStarted; // TRUE if we fired off an inventory fetch
bool m_fFetchComplete; // TRUE if everything was fetched
mutable LLUUID m_idRlvRoot;
callback_signal_t m_OnSharedRootIDChanged;
private:
static const std::string cstrSharedRoot;
@@ -236,6 +245,13 @@ public:
// RlvInventory inlined member functions
//
// Checked: 2011-03-28 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
inline LLViewerInventoryCategory* RlvInventory::getSharedRoot() const
{
const LLUUID& idRlvRoot = getSharedRootID();
return (idRlvRoot.notNull()) ? gInventory.getCategory(idRlvRoot) : NULL;
}
// Checked: 2010-03-19 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
inline bool RlvInventory::isFoldedFolder(const LLInventoryCategory* pFolder, bool fCheckComposite)
{

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -18,9 +18,11 @@
#include "llattachmentsmgr.h"
#include "llviewerobjectlist.h"
#include "pipeline.h"
#include "cofmgr.h"
#include "llagentwearables.h"
#include "rlvhelper.h"
#include "rlvinventory.h"
#include "rlvlocks.h"
// ============================================================================
@@ -36,7 +38,8 @@ void RlvAttachPtLookup::initLookupTable()
if (!fInitialized)
{
LLVOAvatar* pAvatar = gAgentAvatarp;
if (pAvatar)
RLV_ASSERT( (pAvatar) && (pAvatar->mAttachmentPoints.size() > 0) );
if ( (pAvatar) && (pAvatar->mAttachmentPoints.size() > 0) )
{
std::string strAttachPtName;
for (LLVOAvatar::attachment_map_t::const_iterator itAttach = pAvatar->mAttachmentPoints.begin();
@@ -997,3 +1000,327 @@ void RlvWearableLocks::removeWearableTypeLock(LLWearableType::EType eType, const
}
// ============================================================================
// RlvFolderLocks member functions
//
class RlvLockedDescendentsCollector : public LLInventoryCollectFunctor
{
public:
RlvLockedDescendentsCollector(int eSourceTypeMask, RlvFolderLocks::ELockPermission ePermMask, ERlvLockMask eLockTypeMask)
: m_eSourceTypeMask(eSourceTypeMask), m_ePermMask(ePermMask), m_eLockTypeMask(eLockTypeMask) {}
/*virtual*/ ~RlvLockedDescendentsCollector() {}
/*virtual*/ bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem)
{
return (pFolder) && (RlvFolderLocks::instance().isLockedFolderEntry(pFolder->getUUID(), m_eSourceTypeMask, m_ePermMask, m_eLockTypeMask));
}
protected:
RlvFolderLocks::ELockPermission m_ePermMask;
int m_eSourceTypeMask;
ERlvLockMask m_eLockTypeMask;
};
// Checked: 2011-03-28 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
RlvFolderLocks::RlvFolderLocks()
: m_fLookupDirty(false), m_fLockedRoot(false)
{
LLCOFObserver::instance().addCOFChangedCallback(boost::bind(&RlvFolderLocks::onNeedsLookupRefresh, this));
RlvInventory::instance().addSharedRootIDChangedCallback(boost::bind(&RlvFolderLocks::onNeedsLookupRefresh, this));
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
void RlvFolderLocks::addFolderLock(const folderlock_source_t& lockSource, ELockPermission ePerm, ELockScope eScope,
const LLUUID& idRlvObj, ERlvLockMask eLockType)
{
// Sanity check - eLockType can be RLV_LOCK_ADD or RLV_LOCK_REMOVE but not both
RLV_ASSERT( (RLV_LOCK_ADD == eLockType) || (RLV_LOCK_REMOVE == eLockType) );
// NOTE: m_FolderXXX can contain duplicate folderlock_descr_t
m_FolderLocks.push_back(new folderlock_descr_t(idRlvObj, eLockType, lockSource, ePerm, eScope));
if (PERM_DENY == ePerm)
{
if (RLV_LOCK_REMOVE == eLockType)
m_cntLockRem++;
else if (RLV_LOCK_ADD == eLockType)
m_cntLockAdd++;
}
m_fLookupDirty = true;
}
// Checked: 2011-03-28 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
bool RlvFolderLocks::getLockedFolders(const folderlock_source_t& lockSource, LLInventoryModel::cat_array_t& lockFolders) const
{
S32 cntFolders = lockFolders.count();
switch (lockSource.first)
{
case ST_ATTACHMENT:
{
RLV_ASSERT(typeid(LLUUID) == lockSource.second.type())
const LLViewerObject* pObj = gObjectList.findObject(boost::get<LLUUID>(lockSource.second));
if ( (pObj) && (pObj->isAttachment()) )
{
const LLViewerInventoryItem* pItem = gInventory.getItem(pObj->getAttachmentItemID());
if ( (pItem) && (RlvInventory::instance().isSharedFolder(pItem->getParentUUID())) )
{
LLViewerInventoryCategory* pItemFolder = gInventory.getCategory(pItem->getParentUUID());
if (pItemFolder)
lockFolders.push_back(pItemFolder);
}
}
}
break;
case ST_FOLDER:
{
RLV_ASSERT(typeid(LLUUID) == lockSource.second.type())
LLViewerInventoryCategory* pFolder = gInventory.getCategory(boost::get<LLUUID>(lockSource.second));
if (pFolder)
lockFolders.push_back(pFolder);
}
break;
case ST_ROOTFOLDER:
{
LLViewerInventoryCategory* pFolder = gInventory.getCategory(gInventory.getRootFolderID());
if (pFolder)
lockFolders.push_back(pFolder);
}
break;
case ST_SHAREDPATH:
{
RLV_ASSERT(typeid(std::string) == lockSource.second.type())
LLViewerInventoryCategory* pSharedFolder = RlvInventory::instance().getSharedFolder(boost::get<std::string>(lockSource.second));
if (pSharedFolder)
lockFolders.push_back(pSharedFolder);
}
break;
case ST_ATTACHMENTPOINT:
case ST_WEARABLETYPE:
{
RLV_ASSERT( ((ST_ATTACHMENTPOINT == lockSource.first) && (typeid(S32) == lockSource.second.type())) ||
((ST_WEARABLETYPE == lockSource.first) && (typeid(EWearableType) == lockSource.second.type())) );
uuid_vec_t idItems;
if (ST_ATTACHMENTPOINT == lockSource.first)
RlvCommandOptionGetPath::getItemIDs(RlvAttachPtLookup::getAttachPoint(boost::get<S32>(lockSource.second)), idItems);
else if (ST_WEARABLETYPE == lockSource.first)
RlvCommandOptionGetPath::getItemIDs(boost::get<LLWearableType::EType>(lockSource.second), idItems);
LLInventoryModel::cat_array_t itemFolders;
if (RlvInventory::instance().getPath(idItems, itemFolders))
lockFolders.insert(lockFolders.end(), itemFolders.begin(), itemFolders.end());
}
break;
default:
return false;
};
return cntFolders != lockFolders.count();
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
bool RlvFolderLocks::getLockedItems(const LLUUID& idFolder, LLInventoryModel::item_array_t& lockItems, bool fFollowLinks) const
{
S32 cntItems = lockItems.count();
LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items;
LLFindWearablesEx f(true, true); // Collect all worn wearables and body parts
gInventory.collectDescendentsIf(idFolder, folders, items, FALSE, f);
LLUUID idPrev; bool fPrevLocked = false;
for (S32 idxItem = 0, cntItem = items.count(); idxItem < cntItem; idxItem++)
{
LLViewerInventoryItem* pItem = items.get(idxItem);
if ( (fFollowLinks) && (LLAssetType::AT_LINK == pItem->getActualType()) )
pItem = pItem->getLinkedItem();
if (!pItem)
continue;
if (pItem->getParentUUID() != idPrev)
{
idPrev = pItem->getParentUUID();
fPrevLocked = isLockedFolder(idPrev, RLV_LOCK_REMOVE);
}
if (fPrevLocked)
lockItems.push_back(pItem);
}
return cntItems != lockItems.count();
}
// Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
bool RlvFolderLocks::hasLockedFolderDescendent(const LLUUID& idFolder, int eSourceTypeMask, ELockPermission ePermMask,
ERlvLockMask eLockTypeMask, bool fCheckSelf) const
{
if (!hasLockedFolder(eLockTypeMask))
return false;
if (m_fLookupDirty)
refreshLockedLookups();
if ( (fCheckSelf) && (isLockedFolderEntry(idFolder, eSourceTypeMask, ePermMask, RLV_LOCK_ANY)) )
return true;
LLInventoryModel::cat_array_t folders; LLInventoryModel::item_array_t items;
RlvLockedDescendentsCollector f(eSourceTypeMask, ePermMask, eLockTypeMask);
gInventory.collectDescendentsIf(idFolder, folders, items, FALSE, f, FALSE);
return !folders.empty();
}
// Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
bool RlvFolderLocks::isLockedFolderEntry(const LLUUID& idFolder, int eSourceTypeMask, ELockPermission ePermMask, ERlvLockMask eLockTypeMask) const
{
for (folderlock_map_t::const_iterator itFolderLock = m_LockedFolderMap.lower_bound(idFolder),
endFolderLock = m_LockedFolderMap.upper_bound(idFolder); itFolderLock != endFolderLock; ++itFolderLock)
{
const folderlock_descr_t* pLockDescr = itFolderLock->second;
if ( (pLockDescr->lockSource.first & eSourceTypeMask) && (pLockDescr->eLockPermission & ePermMask) &&
(pLockDescr->eLockType & eLockTypeMask) )
{
return true;
}
}
return false;
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
bool RlvFolderLocks::isLockedFolder(const LLUUID& idFolder, ERlvLockMask eLockTypeMask, int eSourceTypeMask, folderlock_source_t* plockSource) const
{
// Sanity check - if there are no folder locks then we don't have to actually do anything
if (!hasLockedFolder(eLockTypeMask))
return false;
if (m_fLookupDirty)
refreshLockedLookups();
// Walk up the folder tree and check if anything has 'idFolder' locked
std::list<LLUUID> idsRlvObjRem, idsRlvObjAdd; const LLUUID& idFolderRoot = gInventory.getRootFolderID(); LLUUID idFolderCur = idFolder;
while (idFolderRoot != idFolderCur)
{
// Iterate over any folder locks for 'idFolderCur'
for (folderlock_map_t::const_iterator itFolderLock = m_LockedFolderMap.lower_bound(idFolderCur),
endFolderLock = m_LockedFolderMap.upper_bound(idFolderCur); itFolderLock != endFolderLock; ++itFolderLock)
{
const folderlock_descr_t* pLockDescr = itFolderLock->second;
// We can skip over the current lock if:
// - the current lock type doesn't match eLockTypeMask
// - it's a node lock and the current folder doesn't match
// - we encountered a PERM_ALLOW lock from the current lock owner before which supercedes any subsequent locks
// - the lock source type doesn't match the mask passed in eSourceTypeMask
ERlvLockMask eCurLockType = (ERlvLockMask)(pLockDescr->eLockType & eLockTypeMask);
std::list<LLUUID>* pidRlvObjList = (RLV_LOCK_REMOVE == eCurLockType) ? &idsRlvObjRem : &idsRlvObjAdd;
if ( (0 == eCurLockType) || ((SCOPE_NODE == pLockDescr->eLockScope) && (idFolder != idFolderCur)) ||
(pidRlvObjList->end() != std::find(pidRlvObjList->begin(), pidRlvObjList->end(), pLockDescr->idRlvObj)) ||
(0 == (pLockDescr->eLockType & eSourceTypeMask)) )
{
continue;
}
if (PERM_DENY == pLockDescr->eLockPermission)
{
if (plockSource)
*plockSource = pLockDescr->lockSource;
return true; // Folder is explicitly denied, indicate locked folder to our caller
}
else if (PERM_ALLOW == pLockDescr->eLockPermission)
{
pidRlvObjList->push_back(pLockDescr->idRlvObj); // Folder is explicitly allowed, save the owner so we can skip it from now on
}
}
// Move up to the folder tree
const LLViewerInventoryCategory* pParent = gInventory.getCategory(idFolderCur);
idFolderCur = (pParent) ? pParent->getParentUUID() : idFolderRoot;
}
// 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_fLockedRoot) && (idsRlvObjRem.empty()) && (idsRlvObjAdd.empty());
}
// Checked: 2010-11-30 (RLVa-1.3.0b) | Added: RLVa-1.3.0b
void RlvFolderLocks::onNeedsLookupRefresh()
{
// NOTE: when removeFolderLock() removes the last folder lock we still want to refresh everything so mind the conditional OR assignment
m_fLookupDirty |= !m_FolderLocks.empty();
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
void RlvFolderLocks::refreshLockedLookups() const
{
//
// Refresh locked folders
//
m_fLockedRoot = false;
m_LockedFolderMap.clear();
for (folderlock_list_t::const_iterator itFolderLock = m_FolderLocks.begin(); itFolderLock != m_FolderLocks.end(); ++itFolderLock)
{
const folderlock_descr_t* pLockDescr = *itFolderLock;
LLInventoryModel::cat_array_t lockedFolders; const LLUUID& idFolderRoot = gInventory.getRootFolderID();
if (getLockedFolders(pLockDescr->lockSource, lockedFolders))
{
for (S32 idxFolder = 0, cntFolder = lockedFolders.count(); idxFolder < cntFolder; idxFolder++)
{
const LLViewerInventoryCategory* pFolder = lockedFolders.get(idxFolder);
if (idFolderRoot != pFolder->getUUID())
m_LockedFolderMap.insert(std::pair<LLUUID, const folderlock_descr_t*>(pFolder->getUUID(), pLockDescr));
else
m_fLockedRoot |= (SCOPE_SUBTREE == pLockDescr->eLockScope);
}
}
}
m_fLookupDirty = false;
//
// Refresh locked items (iterate over COF and filter out any items residing in a RLV_LOCK_REMOVE locked PERM_DENY folder)
//
m_LockedAttachmentRem.clear();
m_LockedWearableRem.clear();
LLInventoryModel::item_array_t lockedItems;
if (getLockedItems(LLCOFMgr::instance().getCOF(), lockedItems, true))
{
for (S32 idxItem = 0, cntItem = lockedItems.count(); idxItem < cntItem; idxItem++)
{
const LLViewerInventoryItem* pItem = lockedItems.get(idxItem);
switch (pItem->getType())
{
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
m_LockedWearableRem.push_back(pItem->getLinkedUUID());
break;
case LLAssetType::AT_OBJECT:
m_LockedAttachmentRem.push_back(pItem->getLinkedUUID());
break;
}
}
}
// Remove any duplicate items we may have picked up
std::sort(m_LockedAttachmentRem.begin(), m_LockedAttachmentRem.end());
m_LockedAttachmentRem.erase(std::unique(m_LockedAttachmentRem.begin(), m_LockedAttachmentRem.end()), m_LockedAttachmentRem.end());
std::sort(m_LockedWearableRem.begin(), m_LockedWearableRem.end());
m_LockedWearableRem.erase(std::unique(m_LockedWearableRem.begin(), m_LockedWearableRem.end()), m_LockedWearableRem.end());
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
void RlvFolderLocks::removeFolderLock(const folderlock_source_t& lockSource, ELockPermission ePerm, ELockScope eScope,
const LLUUID& idRlvObj, ERlvLockMask eLockType)
{
// Sanity check - eLockType can be RLV_LOCK_ADD or RLV_LOCK_REMOVE but not both
RLV_ASSERT( (RLV_LOCK_ADD == eLockType) || (RLV_LOCK_REMOVE == eLockType) );
folderlock_descr_t lockDescr(idRlvObj, eLockType, lockSource, ePerm, eScope); RlvPredValuesEqual<folderlock_descr_t> f = { &lockDescr };
folderlock_list_t::iterator itFolderLock = std::find_if(m_FolderLocks.begin(), m_FolderLocks.end(), f);
RLV_ASSERT( m_FolderLocks.end() != itFolderLock ); // The lock should always exist
if (m_FolderLocks.end() != itFolderLock)
{
delete *itFolderLock;
m_FolderLocks.erase(itFolderLock);
if (PERM_DENY == ePerm)
{
if (RLV_LOCK_REMOVE == eLockType)
m_cntLockRem--;
else if (RLV_LOCK_ADD == eLockType)
m_cntLockAdd--;
}
m_fLookupDirty = true;
}
}
// ============================================================================

View File

@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2009-2010, Kitty Barnett
* Copyright (c) 2009-2011, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU General Public License, version 2.0, but WITHOUT ANY WARRANTY;
@@ -20,6 +20,15 @@
#include "rlvdefines.h"
#include "rlvcommon.h"
#ifdef LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4702) // warning C4702: unreachable code
#endif
#include <boost/variant.hpp>
#ifdef LL_WINDOWS
#pragma warning (pop)
#endif
// ============================================================================
// RlvAttachPtLookup class declaration
//
@@ -36,12 +45,13 @@
class RlvAttachPtLookup
{
public:
static LLViewerJointAttachment* getAttachPoint(S32 idxAttachPt);
static LLViewerJointAttachment* getAttachPoint(const std::string& strText);
static LLViewerJointAttachment* getAttachPoint(const LLInventoryItem* pItem);
static S32 getAttachPointIndex(std::string strText);
static S32 getAttachPointIndex(const LLViewerObject* pObj);
static S32 getAttachPointIndex(const LLViewerJointAttachment* pObj);
static S32 getAttachPointIndex(const LLViewerObject* pAttachObj);
static S32 getAttachPointIndex(const LLViewerJointAttachment* pAttachPt);
static S32 getAttachPointIndex(const LLInventoryCategory* pFolder);
static S32 getAttachPointIndex(const LLInventoryItem* pItem, bool fFollowLinks = true);
@@ -80,7 +90,7 @@ public:
bool hasLockedHUD() const { return m_fHasLockedHUD; }
// Returns TRUE if the attachment is RLV_LOCK_REMOVE locked
bool isLockedAttachment(const LLViewerObject* pObj) const;
bool isLockedAttachment(const LLViewerObject* pAttachObj) const;
// Returns TRUE if the attachment point is RLV_LOCK_REMOVE locked by anything other than idRlvObj
bool isLockedAttachmentExcept(const LLViewerObject* pObj, const LLUUID& idRlvObj) const;
// Returns TRUE if the attachment point is eLock type locked (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
@@ -276,10 +286,118 @@ protected:
extern RlvWearableLocks gRlvWearableLocks;
// ============================================================================
// RlvFolderLocks class declaration
//
class RlvFolderLocks : public LLSingleton<RlvFolderLocks>
{
friend class RlvLockedDescendentsCollector;
public:
RlvFolderLocks();
// Specifies the source of a folder lock
enum ELockSourceType
{
ST_ATTACHMENT = 0x01, ST_ATTACHMENTPOINT = 0x02, ST_FOLDER = 0x04, ST_ROOTFOLDER = 0x08,
ST_SHAREDPATH = 0x10, ST_WEARABLETYPE = 0x20, ST_NONE= 0x00, ST_MASK_ANY = 0xFF
};
typedef boost::variant<LLUUID, std::string, S32, LLWearableType::EType> lock_source_t;
typedef std::pair<ELockSourceType, lock_source_t> folderlock_source_t;
// Specifies options for the folder lock
enum ELockPermission { PERM_ALLOW = 0x1, PERM_DENY = 0x2, PERM_MASK_ANY = 0x3 };
enum ELockScope { SCOPE_NODE, SCOPE_SUBTREE } ;
protected:
struct folderlock_descr_t
{
LLUUID idRlvObj;
ERlvLockMask eLockType;
folderlock_source_t lockSource;
ELockPermission eLockPermission;
ELockScope eLockScope;
folderlock_descr_t(const LLUUID& rlvObj, ERlvLockMask lockType, folderlock_source_t source, ELockPermission perm, ELockScope scope);
bool operator ==(const folderlock_descr_t& rhs) const;
};
public:
// Adds an eLock type lock (held by idRlvObj) for the specified folder source (with ePerm and eScope lock options)
void addFolderLock(const folderlock_source_t& lockSource, ELockPermission ePerm, ELockScope eScope, const LLUUID& idRlvObj, ERlvLockMask eLockType);
// Returns TRUE if there is at least 1 non-detachable attachment as a result of a RLV_LOCK_REMOVE folder PERM_DENY lock
bool hasLockedAttachment() const;
// Returns TRUE if there is at least 1 eLock type PERM_DENY locked folder (RLV_LOCK_ANY = RLV_LOCK_ADD *or* RLV_LOCK_REMOVE)
bool hasLockedFolder(ERlvLockMask eLockTypeMask) const;
// Returns TRUE if the folder has a descendent folder lock with the specified charateristics
bool hasLockedFolderDescendent(const LLUUID& idFolder, int eSourceTypeMask, ELockPermission ePermMask,
ERlvLockMask eLockTypeMask, bool fCheckSelf) const;
// Returns TRUE if there is at least 1 non-removable wearable as a result of a RLV_LOCK_REMOVE folder PERM_DENY lock
bool hasLockedWearable() const;
// 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(const LLUUID& idFolder, ERlvLockMask eLock, int eSourceTypeMask = ST_MASK_ANY, folderlock_source_t* plockSource = NULL) 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;
// Removes an eLock type lock (held by idRlvObj) for the specified folder source (with ePerm and eScope lock options)
void removeFolderLock(const folderlock_source_t& lockSource, ELockPermission ePerm, ELockScope eScope, const LLUUID& idRlvObj, ERlvLockMask eLockType);
protected:
// Returns TRUE if the folder has an explicit folder lock entry with the specified charateristics
bool isLockedFolderEntry(const LLUUID& idFolder, int eSourceTypeMask, ELockPermission ePermMask, ERlvLockMask eLockTypeMask) const;
/*
* canXXX helper functions (note that a more approriate name might be userCanXXX)
*/
public:
bool canMoveFolder(const LLUUID& idFolder, const LLUUID& idFolderDest) const;
bool canRemoveFolder(const LLUUID& idFolder) const;
bool canRenameFolder(const LLUUID& idFolder) const;
bool canMoveItem(const LLUUID& idItem, const LLUUID& idFolderDest) const;
bool canRemoveItem(const LLUUID& idItem) const;
bool canRenameItem(const LLUUID& idItem) const;
/*
* Cached item/folder look-up helper functions
*/
protected:
bool getLockedFolders(const folderlock_source_t& lockSource, LLInventoryModel::cat_array_t& lockFolders) const;
bool getLockedItems(const LLUUID& idFolder, LLInventoryModel::item_array_t& lockItems, bool fFollowLinks) const;
void onNeedsLookupRefresh();
void refreshLockedLookups() const;
/*
* Member variables
*/
protected:
// Map of folder locks (idRlvObj -> lockDescr)
typedef std::list<const folderlock_descr_t*> folderlock_list_t;
folderlock_list_t m_FolderLocks; // List of add and remove locked folder descriptions
S32 m_cntLockAdd; // Number of RLV_LOCK_ADD locked folders in m_FolderLocks
S32 m_cntLockRem; // Number of RLV_LOCK_REMOVE locked folders in m_FolderLocks
// Cached item look-up variables
typedef std::multimap<LLUUID, const folderlock_descr_t*> folderlock_map_t;
mutable bool m_fLookupDirty;
mutable bool m_fLockedRoot;
mutable uuid_vec_t m_LockedAttachmentRem;
mutable folderlock_map_t m_LockedFolderMap;
mutable uuid_vec_t m_LockedWearableRem;
private:
friend class LLSingleton<RlvFolderLocks>;
};
// ============================================================================
// RlvAttachPtLookup inlined member functions
//
// Checked: 2010-11-30 (RLVa-1.4.0b) | Added: RLVa-1.4.0b
inline LLViewerJointAttachment* RlvAttachPtLookup::getAttachPoint(S32 idxAttachPt)
{
return (isAgentAvatarValid()) ? get_if_there(gAgentAvatarp->mAttachmentPoints, idxAttachPt, (LLViewerJointAttachment*)NULL) : NULL;
}
// Checked: 2010-03-03 (RLVa-1.1.3a) | Modified: RLVa-0.2.0d
inline LLViewerJointAttachment* RlvAttachPtLookup::getAttachPoint(const std::string& strText)
{
@@ -311,7 +429,7 @@ inline S32 RlvAttachPtLookup::getAttachPointIndex(const LLViewerObject* pObj)
// RlvAttachmentLocks inlined member functions
//
// Checked: 2010-08-07 (RLVa-1.2.0i) | Modified: RLVa-1.2.0i
// Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
inline ERlvWearMask RlvAttachmentLocks::canAttach(const LLInventoryItem* pItem, LLViewerJointAttachment** ppAttachPtOut /*=NULL*/) const
{
// The specified item can be attached if:
@@ -320,7 +438,8 @@ inline ERlvWearMask RlvAttachmentLocks::canAttach(const LLInventoryItem* pItem,
LLViewerJointAttachment* pAttachPt = RlvAttachPtLookup::getAttachPoint(pItem);
if (ppAttachPtOut)
*ppAttachPtOut = pAttachPt;
return (!pAttachPt) ? RLV_WEAR : canAttach(pAttachPt);
return ((pItem) && (!RlvFolderLocks::instance().isLockedFolder(pItem->getParentUUID(), RLV_LOCK_ADD)))
? ((!pAttachPt) ? RLV_WEAR : canAttach(pAttachPt)) : RLV_WEAR_LOCKED;
}
// Checked: 2010-08-07 (RLVa-1.2.0i) | Modified: RLVa-1.2.0i
@@ -345,28 +464,30 @@ inline bool RlvAttachmentLocks::canDetach(const LLInventoryItem* pItem) const
return (pAttachObj) && (!isLockedAttachment(pAttachObj));
}
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.3.0b
inline bool RlvAttachmentLocks::hasLockedAttachmentPoint(ERlvLockMask eLock) const
{
// Remove locks are more common so check those first
return
( (eLock & RLV_LOCK_REMOVE) && ((!m_AttachPtRem.empty()) || (!m_AttachObjRem.empty())) ) ||
( (eLock & RLV_LOCK_ADD) && (!m_AttachPtAdd.empty()) );
((eLock & RLV_LOCK_REMOVE) && ((!m_AttachPtRem.empty()) || (!m_AttachObjRem.empty()) || (RlvFolderLocks::instance().hasLockedAttachment()))) ||
((eLock & RLV_LOCK_ADD) && (!m_AttachPtAdd.empty()) );
}
// Checked: 2010-02-28 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
inline bool RlvAttachmentLocks::isLockedAttachment(const LLViewerObject* pObj) const
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.3.0b
inline bool RlvAttachmentLocks::isLockedAttachment(const LLViewerObject* pAttachObj) const
{
// 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()) );
RLV_ASSERT( (!pAttachObj) || (pAttachObj == pAttachObj->getRootEdit()) );
// Object is locked if:
// - it's specifically marked as non-detachable (ie @detach=n)
// - it's attached to an attachment point that is RLV_LOCK_REMOVE locked (ie @remattach:<attachpt>=n)
// - it's part of a locked folder
return
(pObj) && (pObj->isAttachment()) &&
( (m_AttachObjRem.find(pObj->getID()) != m_AttachObjRem.end()) ||
(isLockedAttachmentPoint(RlvAttachPtLookup::getAttachPointIndex(pObj), RLV_LOCK_REMOVE)) );
(pAttachObj) && (pAttachObj->isAttachment()) &&
( (m_AttachObjRem.find(pAttachObj->getID()) != m_AttachObjRem.end()) ||
(isLockedAttachmentPoint(RlvAttachPtLookup::getAttachPointIndex(pAttachObj), RLV_LOCK_REMOVE)) ||
(RlvFolderLocks::instance().isLockedAttachment(pAttachObj->getAttachmentItemID())) );
}
// Checked: 2010-02-28 (RLVa-1.2.0a) | Added: RLVa-1.0.5a
@@ -406,12 +527,13 @@ inline bool RlvWearableLocks::canRemove(const LLInventoryItem* pItem) const
return (pWearable) && (!isLockedWearable(pWearable));
}
// Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g
// Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
inline ERlvWearMask RlvWearableLocks::canWear(const LLViewerInventoryItem* pItem) const
{
// The specified item can be worn if the wearable type it specifies can be worn on
RLV_ASSERT( (pItem) && (LLInventoryType::IT_WEARABLE == pItem->getInventoryType()) );
return (pItem) ? canWear(pItem->getWearableType()) : RLV_WEAR_LOCKED;
return ((pItem) && (!RlvFolderLocks::instance().isLockedFolder(pItem->getParentUUID(), RLV_LOCK_ADD)))
? canWear(pItem->getWearableType()) : RLV_WEAR_LOCKED;
}
// Checked: 2010-05-14 (RLVa-1.2.0g) | Modified: RLVa-1.2.0g
@@ -435,15 +557,18 @@ inline bool RlvWearableLocks::hasLockedWearableType(ERlvLockMask eLock) const
return ( (eLock & RLV_LOCK_REMOVE) && (!m_WearableTypeRem.empty()) ) || ( (eLock & RLV_LOCK_ADD) && (!m_WearableTypeAdd.empty()) );
}
// Checked: 2010-03-19 (RLVa-1.2.0c) | Added: RLVa-1.2.0a
// Checked: 2010-11-30 (RLVa-1.3.0b) | Modified: RLVa-1.2.0a
inline bool RlvWearableLocks::isLockedWearable(const LLWearable* pWearable) const
{
// Wearable is locked if:
// - it's specifically marked as non-removable
// - it's worn on a wearable type that is RLV_LOCK_REMOVE locked
// - it's part of a locked folder
// TODO-RLVa: [RLVa-1.2.1] We don't have the ability to lock a specific wearable yet so rewrite this when we do
RLV_ASSERT(pWearable);
return (pWearable) && (isLockedWearableType(pWearable->getType(), RLV_LOCK_REMOVE));
return
(pWearable) &&
( (isLockedWearableType(pWearable->getType(), RLV_LOCK_REMOVE)) || (RlvFolderLocks::instance().isLockedWearable(pWearable->getItemID())) );
}
// Checked: 2010-03-19 (RLVa-1.2.0c) | Added: RLVa-1.2.0a
@@ -454,6 +579,134 @@ inline bool RlvWearableLocks::isLockedWearableType(LLWearableType::EType eType,
( (eLock & RLV_LOCK_ADD) && (m_WearableTypeAdd.find(eType) != m_WearableTypeAdd.end()) );
}
// ============================================================================
// RlvFolderLocks member functions
//
// Checked: 2011-03-27 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline RlvFolderLocks::folderlock_descr_t::folderlock_descr_t(const LLUUID& rlvObj, ERlvLockMask lockType, folderlock_source_t source,
ELockPermission perm, ELockScope scope)
: idRlvObj(rlvObj), eLockType(lockType), lockSource(source), eLockPermission(perm), eLockScope(scope)
{
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::folderlock_descr_t::operator ==(const folderlock_descr_t& rhs) const
{
return (idRlvObj == rhs.idRlvObj) && (eLockType == rhs.eLockType) && (lockSource == rhs.lockSource) &&
(eLockPermission == rhs.eLockPermission) && (eLockScope == rhs.eLockScope);
}
// Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::canMoveFolder(const LLUUID& idFolder, const LLUUID& idFolderDest) const
{
// Block moving the folder to destination if:
// - the folder (or one of its descendents) is explicitly locked
// - folder and destination are subject to different locks
// -> Possible combinations:
// * folder locked + destination unlocked => block move
// * folder unlocked + destination locked => block move
// * 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
(!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) );
}
// Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::canRemoveFolder(const LLUUID& idFolder) const
{
// Block removing a folder if:
// - the folder (or one of its descendents) is explicitly locked
// - the folder itself is locked (but disregard root folder locks)
return
(!hasLockedFolderDescendent(idFolder, ST_MASK_ANY, PERM_MASK_ANY, RLV_LOCK_ANY, true)) &&
(!isLockedFolder(idFolder, RLV_LOCK_ANY, ST_MASK_ANY & ~ST_ROOTFOLDER));
}
// Checked: 2011-03-29 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::canRenameFolder(const LLUUID& idFolder) const
{
// Block renaming a folder if:
// - the folder (or one of its descendents) is explicitly locked by:
// -> a "shared path" => renaming the folder would change the shared path and hence invalidate the lock
// -> an attachment point \
// -> an attachment |--> renaming the folder to a "dot" (=invisible) folder would invalidate the lock
// -> a wearable type /
return !hasLockedFolderDescendent(idFolder, ST_SHAREDPATH | ST_ATTACHMENT | ST_ATTACHMENTPOINT | ST_WEARABLETYPE, PERM_MASK_ANY, RLV_LOCK_ANY, true);
}
// Checked: 2011-03-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::canMoveItem(const LLUUID& idItem, const LLUUID& idFolderDest) const
{
// 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);
}
// Checked: 2011-03-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::canRemoveItem(const LLUUID& idItem) const
{
// Block removing items from locked folders (but disregard root folder locks)
const LLViewerInventoryItem* pItem = gInventory.getItem(idItem); const LLUUID& idFolder = (pItem) ? pItem->getParentUUID() : LLUUID::null;
int maskSource = ST_MASK_ANY & ~ST_ROOTFOLDER;
return (idFolder.notNull()) && (!isLockedFolder(idFolder, RLV_LOCK_ANY, maskSource));
}
// Checked: 2011-03-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0g
inline bool RlvFolderLocks::canRenameItem(const LLUUID& idItem) const
{
// Items can always be renamed, regardless of folder locks
return true;
}
// Checked: 2010-11-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0b
inline bool RlvFolderLocks::hasLockedAttachment() const
{
if (m_fLookupDirty)
refreshLockedLookups();
return !m_LockedAttachmentRem.empty();
}
// Checked: 2011-03-27 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g
inline bool RlvFolderLocks::hasLockedFolder(ERlvLockMask eLock) const
{
// Remove locks are more common so check those first
return ((eLock & RLV_LOCK_REMOVE) && (m_cntLockRem)) || ((eLock & RLV_LOCK_ADD) && (m_cntLockAdd));
}
// Checked: 2010-11-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0b
inline bool RlvFolderLocks::hasLockedWearable() const
{
if (m_fLookupDirty)
refreshLockedLookups();
return !m_LockedWearableRem.empty();
}
// Checked: 2010-11-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0b
inline bool RlvFolderLocks::isLockedAttachment(const LLUUID& idItem) const
{
if (m_fLookupDirty)
refreshLockedLookups();
return (std::find(m_LockedAttachmentRem.begin(), m_LockedAttachmentRem.end(), idItem) != m_LockedAttachmentRem.end());
}
// Checked: 2010-11-30 (RLVa-1.3.0g) | Added: RLVa-1.3.0b
inline bool RlvFolderLocks::isLockedWearable(const LLUUID& idItem) const
{
if (m_fLookupDirty)
refreshLockedLookups();
return (std::find(m_LockedWearableRem.begin(), m_LockedWearableRem.end(), idItem) != m_LockedWearableRem.end());
}
// ============================================================================
#endif // RLV_LOCKS_H

View File

@@ -23,7 +23,109 @@
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
#include "llgesturemgr.h"
#include "llviewerinventory.h"
#include "llvoavatar.h"
#include "cofmgr.h"
#include "rlvviewer2.h"
// ============================================================================
// From lloutfitobserver.cpp
LLCOFObserver::LLCOFObserver() :
mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN)
{
mItemNameHash.finalize();
gInventory.addObserver(this);
}
LLCOFObserver::~LLCOFObserver()
{
if (gInventory.containsObserver(this))
{
gInventory.removeObserver(this);
}
}
void LLCOFObserver::changed(U32 mask)
{
if (!gInventory.isInventoryUsable())
return;
checkCOF();
}
// static
S32 LLCOFObserver::getCategoryVersion(const LLUUID& cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (!cat)
return LLViewerInventoryCategory::VERSION_UNKNOWN;
return cat->getVersion();
}
// static
const std::string& LLCOFObserver::getCategoryName(const LLUUID& cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (!cat)
return LLStringUtil::null;
return cat->getName();
}
bool LLCOFObserver::checkCOF()
{
LLUUID cof = LLCOFMgr::getInstance()->getCOF();
if (cof.isNull())
return false;
bool cof_changed = false;
LLMD5 item_name_hash = hashDirectDescendentNames(cof);
if (item_name_hash != mItemNameHash)
{
cof_changed = true;
mItemNameHash = item_name_hash;
}
S32 cof_version = getCategoryVersion(cof);
if (cof_version != mCOFLastVersion)
{
cof_changed = true;
mCOFLastVersion = cof_version;
}
if (!cof_changed)
return false;
mCOFChanged();
return true;
}
LLMD5 LLCOFObserver::hashDirectDescendentNames(const LLUUID& cat_id)
{
LLInventoryModel::cat_array_t* cat_array;
LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(cat_id,cat_array,item_array);
LLMD5 item_name_hash;
if (!item_array)
{
item_name_hash.finalize();
return item_name_hash;
}
for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin();
iter != item_array->end();
iter++)
{
const LLViewerInventoryItem *item = (*iter);
if (!item)
continue;
item_name_hash.update(item->getName());
}
item_name_hash.finalize();
return item_name_hash;
}
// ============================================================================

View File

@@ -25,9 +25,39 @@
#define RLV_VIEWER2_H
#include "llcallbacklist.h"
#include "llinventoryobserver.h"
#include "boost/function.hpp"
// ============================================================================
// From lloutfitobserver.h
class LLCOFObserver : public LLInventoryObserver, public LLSingleton<LLCOFObserver>
{
friend class LLSingleton<LLCOFObserver>;
protected:
LLCOFObserver();
public:
virtual ~LLCOFObserver();
virtual void changed(U32 mask);
typedef boost::signals2::signal<void (void)> signal_t;
void addCOFChangedCallback(const signal_t::slot_type& cb) { mCOFChanged.connect(cb); }
void addCOFSavedCallback(const signal_t::slot_type& cb) { mCOFSaved.connect(cb); }
protected:
bool checkCOF();
static S32 getCategoryVersion(const LLUUID& cat_id);
static const std::string& getCategoryName(const LLUUID& cat_id);
static LLMD5 hashDirectDescendentNames(const LLUUID& cat_id);
private:
signal_t mCOFChanged;
signal_t mCOFSaved;
S32 mCOFLastVersion;
LLMD5 mItemNameHash;
};
#endif // RLV_VIEWER2_H