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

@@ -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;
}
}
// ============================================================================