Files
SingularityViewer/indra/newview/rlvinventory.h
Lirusaito ed8e37ed89 [RLVa] Updates thanks to Kitty
1ea7389, 49be412, ed4c8e6 & 7ce9521
- changed : "Give to #RLV" agent-to-agent and script-to-agent offers can contain subfolders
-> limited to 3 levels (e.g. #RLV/~FolderA/FolderB/FolderC)
-> #RLV folder is auto-created if it doesn't currently exist

8780d84 - Incremented version number to RLVa-1.4.10
f078067 - internal : boolean (custom) debug settings should have a boolean type
72a8ad8 & 401ca14 - internal : added supporting code for "Detach Folder" RLVa lock checks

05718b5
- fixed : RenderResolutionDivisor is non-functional
-> RenderResolutionDivisor isn't actually taken into account when checking the new screen resolution against the current screen buffer size

4fa138b
- fixed : viewer clips mouse to its rectangle when switching into mouselook while it's not the active application
-> Repro:
* rez a prim with a script to llForceMouseLook(TRUE) and force-sit when clicked (with a slight delay)
* click the prim and give focus to another application
=> the viewer will center the mouse cursor on itself and restrict movement to within its own rectangle (requires alt-tab to escape)
+ Singu Note: Thanks to Kitty for this, it is possible that this would happen in our last release

14132c9
- fixed : region name and global coordinates are shown on the About floater when @showloc restricted
+ Singu Note: RLV version is now shown in help->about

9a2af62 - changed : llRegionSayTo messages are no longer subject to @recvchat(from) or @recvemote(from)

2dc4b89
- fixed : @getstatus and @getstatusall should specify an (optional) separator
-> added support for both @getstatus:tp;|=123 and @getstatus:;|=123

fbb3fb1 - Incremented API version number to 2.8.0
92c39b9 - internal : quick and dirty hack fix for RlvUtil::filterNames() but there's no time to do a proper backport from RLVa-1.5
2580f1c - internal : remove hack for legacy viewers without multi-attachment support
2014-03-12 19:41:15 -04:00

339 lines
13 KiB
C++

/**
*
* Copyright (c) 2009-2014, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt
* in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt
*
* By copying, modifying or distributing this software, you acknowledge that
* you have read and understood your obligations described above, and agree to
* abide by those obligations.
*
*/
#ifndef RLV_INVENTORY_H
#define RLV_INVENTORY_H
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llsingleton.h"
#include "llviewerinventory.h"
#include "rlvhelper.h"
#include "rlvlocks.h"
// ============================================================================
// RlvInventory class declaration
//
class RlvInventory : public LLSingleton<RlvInventory>, public LLInventoryObserver
{
protected:
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;
// 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;
// Returns a pointer to the shared root folder (if there is one)
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, bool fMatchPartial = true) const;
// Looks up a folder from a path (relative to the shared root)
LLViewerInventoryCategory* getSharedFolder(const std::string& strPath, bool fMatchPartial = true) const;
// Returns the path of the supplied folder (relative to the shared root)
std::string getSharedPath(const LLViewerInventoryCategory* pFolder) const;
std::string getSharedPath(const LLUUID& idFolder) const;
// Returns TRUE if the supplied folder is a descendent of the #RLV folder
bool isSharedFolder(const LLUUID& idFolder);
/*
* Inventory fetching
*/
public:
void fetchSharedInventory();
void fetchWornItems();
protected:
void fetchSharedLinks();
/*
* General purpose helper functions
*/
public:
// Returns the number of sub-folders of the specified folder
static S32 getDirectDescendentsFolderCount(const LLInventoryCategory* pFolder);
// Returns the number of direct descendents of the specified folder that have the specified type asset type
static S32 getDirectDescendentsItemCount(const LLInventoryCategory* pFolder, LLAssetType::EType filterType);
// Returns the folder the items of the specified folder should folded into (can be the folder itself)
static const LLUUID& getFoldedParent(const LLUUID& idFolder, bool fCheckComposite);
// A "folded folder" is a folder whose items logically belong to the grandparent rather than the parent
static bool isFoldedFolder(const LLInventoryCategory* pFolder, bool fCheckComposite);
/*
* Member variables
*/
protected:
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;
friend class RlvSharedInventoryFetcher;
friend class LLSingleton<RlvInventory>;
};
// ============================================================================
// RlvRenameOnWearObserver - Handles "auto-rename-on-wear" for (linked) items living under #RLV
//
class RlvRenameOnWearObserver : public LLInventoryFetchItemsObserver
{
public:
RlvRenameOnWearObserver(const LLUUID& idItem) : LLInventoryFetchItemsObserver(idItem) {}
virtual ~RlvRenameOnWearObserver() {}
virtual void done();
protected:
void doneIdle();
static void onCategoryCreate(const LLSD& sdData, void* pParam);
};
// ============================================================================
// "Give to #RLV" helper classes
//
class RlvGiveToRLVOffer
{
protected:
RlvGiveToRLVOffer(){}
virtual ~RlvGiveToRLVOffer() {}
protected:
bool createDestinationFolder(const std::string& strPath);
virtual void onDestinationCreated(const LLUUID& idFolder, const std::string& strName) = 0;
void moveAndRename(const LLUUID& idFolder, const LLUUID& idDestination, const std::string& strName);
private:
static void onCategoryCreateCallback(const LLSD& sdData, void* pInstance);
private:
std::list<std::string> m_DestPath;
};
// [See LLInventoryTransactionObserver which says it's not entirely complete?]
// NOTE: the offer may span mulitple BulkUpdateInventory messages so if we're no longer around then (ie due to "delete this") then
// we'll miss those; in this specific case we only care about the *folder* though and that will be in the very first message
class RlvGiveToRLVTaskOffer : public LLInventoryObserver, public RlvGiveToRLVOffer
{
public:
RlvGiveToRLVTaskOffer(const LLUUID& idTransaction) : RlvGiveToRLVOffer(), m_idTransaction(idTransaction) {}
/*virtual*/ void changed(U32 mask);
protected:
/*virtual*/ void done();
void doneIdle();
/*virtual*/ void onDestinationCreated(const LLUUID& idFolder, const std::string& strName);
protected:
typedef std::vector<LLUUID> folder_ref_t;
folder_ref_t m_Folders;
LLUUID m_idTransaction;
};
class RlvGiveToRLVAgentOffer : public LLInventoryFetchDescendentsObserver, public RlvGiveToRLVOffer
{
public:
RlvGiveToRLVAgentOffer(const LLUUID& idFolder) : LLInventoryFetchDescendentsObserver(idFolder), RlvGiveToRLVOffer() {}
/*virtual*/ ~RlvGiveToRLVAgentOffer() {}
public:
/*virtual*/ void done();
protected:
void doneIdle();
/*virtual*/ void onDestinationCreated(const LLUUID& idFolder, const std::string& strName);
};
// ============================================================================
// RlvCriteriaCategoryCollector - Criteria based folder matching filter used by @findfolder and @findfolders
//
class RlvCriteriaCategoryCollector : public LLInventoryCollectFunctor
{
public:
RlvCriteriaCategoryCollector(const std::string& strCriteria)
{
std::string::size_type idxIt, idxLast = 0;
while (idxLast < strCriteria.length())
{
idxIt = strCriteria.find("&&", idxLast);
if (std::string::npos == idxIt)
idxIt = strCriteria.length();
if (idxIt != idxLast)
m_Criteria.push_back(strCriteria.substr(idxLast, idxIt - idxLast));
idxLast = idxIt + 2;
}
}
virtual ~RlvCriteriaCategoryCollector() {}
virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem)
{
if ( (!pFolder) || (m_Criteria.empty()) ) // We're only interested in matching folders, we don't care about items
return false; // (if there are no criteria then we don't want to return a match)
std::string strFolderName = pFolder->getName();
LLStringUtil::toLower(strFolderName);
// NOTE: hidden or "give to #RLV" folders can never be a match
if ( (strFolderName.empty()) ||
(RLV_FOLDER_PREFIX_HIDDEN == strFolderName[0]) || (RLV_FOLDER_PREFIX_PUTINV == strFolderName[0]) )
{
return false;
}
for (std::list<std::string>::const_iterator itCrit = m_Criteria.begin(); itCrit != m_Criteria.end(); ++itCrit)
if (std::string::npos == strFolderName.find(*itCrit))
return false;
return true;
}
protected:
std::list<std::string> m_Criteria;
};
// ============================================================================
// RlvWearableItemCollector - Inventory item filter used by attach/detach/attachall/detachall/getinvworn
//
class RlvWearableItemCollector : public LLInventoryCollectFunctor
{
public:
RlvWearableItemCollector(const LLInventoryCategory* pFolder, RlvForceWear::EWearAction eAction, RlvForceWear::EWearFlags eFlags);
virtual ~RlvWearableItemCollector() {}
virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem);
const LLUUID& getFoldedParent(const LLUUID& idFolder) const;
RlvForceWear::EWearAction getWearAction(const LLUUID& idFolder) const;
RlvForceWear::EWearAction getWearActionNormal(const LLInventoryCategory* pFolder);
RlvForceWear::EWearAction getWearActionFolded(const LLInventoryCategory* pFolder);
bool isLinkedFolder(const LLUUID& idFolder);
protected:
const LLUUID m_idFolder;
RlvForceWear::EWearAction m_eWearAction;
RlvForceWear::EWearFlags m_eWearFlags;
bool onCollectFolder(const LLInventoryCategory* pFolder);
bool onCollectItem(const LLInventoryItem* pItem);
std::list<LLUUID> m_Folded;
std::list<LLUUID> m_Linked;
std::list<LLUUID> m_Wearable;
std::map<LLUUID, LLUUID> m_FoldingMap;
std::map<LLUUID, RlvForceWear::EWearAction> m_WearActionMap;
std::string m_strWearAddPrefix;
std::string m_strWearReplacePrefix;
};
// ============================================================================
// General purpose inventory helper classes
//
class RlvIsLinkType : public LLInventoryCollectFunctor
{
public:
RlvIsLinkType() {}
/*virtual*/ ~RlvIsLinkType() {}
virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem) { return (pItem) && (pItem->getIsLinkType()); }
};
// If the attachment item is linked in COF but isn't worn (or just detached) the function will return inconsistent information
class RlvFindAttachmentsOnPoint : public LLInventoryCollectFunctor
{
public:
RlvFindAttachmentsOnPoint(const LLViewerJointAttachment* pAttachPt) : m_pAttachPt(pAttachPt) {}
/*virtual*/ ~RlvFindAttachmentsOnPoint() {}
virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem);
protected:
const LLViewerJointAttachment* m_pAttachPt;
};
// ============================================================================
// 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: 2011-11-26 (RLVa-1.5.4a) | Added: RLVa-1.5.4a
inline const LLUUID& RlvInventory::getFoldedParent(const LLUUID& idFolder, bool fCheckComposite)
{
LLViewerInventoryCategory* pFolder = gInventory.getCategory(idFolder);
while ((pFolder) && (isFoldedFolder(pFolder, fCheckComposite)))
pFolder = gInventory.getCategory(pFolder->getParentUUID());
return (pFolder) ? pFolder->getUUID() : LLUUID::null;
}
// Checked: 2011-11-26 (RLVa-1.5.4a) | Added: RLVa-1.5.4a
inline std::string RlvInventory::getSharedPath(const LLUUID& idFolder) const
{
return getSharedPath(gInventory.getCategory(idFolder));
}
// Checked: 2010-03-19 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
inline bool RlvInventory::isFoldedFolder(const LLInventoryCategory* pFolder, bool fCheckComposite)
{
return
// If legacy naming isn't enabled we can return early if the folder name doesn't start with a '.' (= the most common case)
(pFolder) && ( (RlvSettings::getEnableLegacyNaming()) || (RLV_FOLDER_PREFIX_HIDDEN == pFolder->getName().at(0)) ) &&
(
// .(<attachpt>) type folder
(0 != RlvAttachPtLookup::getAttachPointIndex(pFolder))
// .(nostrip) folder
|| ( (pFolder) && (".("RLV_FOLDER_FLAG_NOSTRIP")" == pFolder->getName()) )
// Composite folder (if composite folders are enabled and we're asked to look for them)
#ifdef RLV_EXPERIMENTAL_COMPOSITEFOLDERS
|| ( (fCheckComposite) && (RlvSettings::getEnableComposites()) &&
(pFolder) && (RLV_FOLDER_PREFIX_HIDDEN == pFolder->getName().at(0)) && (isCompositeFolder(pFolder)) )
#endif // RLV_EXPERIMENTAL_COMPOSITEFOLDERS
);
}
// Checked: 2010-08-29 (RLVa-1.2.0c) | Added: RLVa-1.2.0c
inline bool RlvInventory::isSharedFolder(const LLUUID& idFolder)
{
const LLViewerInventoryCategory* pRlvRoot = getSharedRoot();
return (pRlvRoot) ? (pRlvRoot->getUUID() != idFolder) && (gInventory.isObjectDescendentOf(idFolder, pRlvRoot->getUUID())) : false;
}
// ============================================================================
// RlvWearableItemCollector inlined member functions
//
// Checked: 2010-09-30 (RLVa-1.2.1d) | Added: RLVa-1.2.1d
inline bool RlvWearableItemCollector::isLinkedFolder(const LLUUID& idFolder)
{
return (!m_Linked.empty()) && (m_Linked.end() != std::find(m_Linked.begin(), m_Linked.end(), idFolder));
}
// ============================================================================
#endif // RLV_INVENTORY_H