Update RLVa to 1.4.0-compatible
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user