Files
SingularityViewer/indra/newview/llinventoryfunctions.cpp

477 lines
11 KiB
C++

/**
* @file llinventoryfunctions.cpp
* @brief Implementation of the inventory view and associated stuff.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include <utility> // for std::pair<>
#include "llinventoryfunctions.h"
// library includes
#include "llagent.h"
#include "llagentwearables.h"
#include "llcallingcard.h"
#include "llinventorydefines.h"
#include "llsdserialize.h"
#include "llspinctrl.h"
#include "llui.h"
#include "message.h"
// newview includes
#include "llappviewer.h"
//#include "llfirstuse.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
#include "lliconctrl.h"
#include "llimview.h"
#include "llinventorybridge.h"
#include "llinventoryclipboard.h"
#include "llinventorymodel.h"
#include "llinventoryview.h"
#include "lllineeditor.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
#include "llpreviewscript.h"
#include "llpreviewsound.h"
#include "llpreviewtexture.h"
#include "llresmgr.h"
#include "llscrollbar.h"
#include "llscrollcontainer.h"
#include "llselectmgr.h"
#include "lltabcontainer.h"
#include "lltooldraganddrop.h"
#include "lluictrlfactory.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llwearablelist.h"
#include "cofmgr.h"
BOOL LLInventoryState::sWearNewClothing = FALSE;
LLUUID LLInventoryState::sWearNewClothingTransactionID;
// Generates a string containing the path to the item specified by
// item_id.
void append_path(const LLUUID& id, std::string& path)
{
std::string temp;
LLInventoryObject* obj = gInventory.getObject(id);
LLUUID parent_id;
if(obj) parent_id = obj->getParentUUID();
std::string forward_slash("/");
while(obj)
{
obj = gInventory.getCategory(parent_id);
if(obj)
{
temp.assign(forward_slash + obj->getName() + temp);
parent_id = obj->getParentUUID();
}
}
path.append(temp);
}
void change_item_parent(LLInventoryModel* model,
LLViewerInventoryItem* item,
const LLUUID& new_parent_id,
BOOL restamp)
{
if (item->getParentUUID() != new_parent_id)
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
update.push_back(old_folder);
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
gInventory.accountForUpdate(update);
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setParent(new_parent_id);
new_item->updateParentOnServer(restamp);
model->updateItem(new_item);
model->notifyObservers();
}
}
void change_category_parent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
const LLUUID& new_parent_id,
BOOL restamp)
{
if (!model || !cat)
{
return;
}
// Can't move a folder into a child of itself.
if (model->isObjectDescendentOf(new_parent_id, cat->getUUID()))
{
return;
}
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
update.push_back(old_folder);
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
model->accountForUpdate(update);
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
new_cat->setParent(new_parent_id);
new_cat->updateParentOnServer(restamp);
model->updateCategory(new_cat);
model->notifyObservers();
}
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
{
public:
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return true;
}
};
BOOL get_is_parent_to_worn_item(const LLUUID& id)
{
const LLViewerInventoryCategory* cat = gInventory.getCategory(id);
if (!cat)
{
return FALSE;
}
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLInventoryCollectAllItems collect_all;
gInventory.collectDescendentsIf(LLCOFMgr::instance().getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH, collect_all);
for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it)
{
const LLViewerInventoryItem * const item = *it;
llassert(item->getIsLinkType());
LLUUID linked_id = item->getLinkedUUID();
const LLViewerInventoryItem * const linked_item = gInventory.getItem(linked_id);
if (linked_item)
{
LLUUID parent_id = linked_item->getParentUUID();
while (!parent_id.isNull())
{
LLInventoryCategory * parent_cat = gInventory.getCategory(parent_id);
if (cat == parent_cat)
{
return TRUE;
}
parent_id = parent_cat->getParentUUID();
}
}
}
return FALSE;
}
BOOL get_is_item_worn(const LLInventoryItem *item)
{
if (!item)
return FALSE;
// Consider the item as worn if it has links in COF.
if (LLCOFMgr::instance().isLinkInCOF(item->getUUID()))
{
return TRUE;
}
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
{
if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
return TRUE;
break;
}
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
return TRUE;
break;
case LLAssetType::AT_GESTURE:
if (LLGestureMgr::instance().isGestureActive(item->getLinkedUUID()))
return TRUE;
break;
default:
break;
}
return FALSE;
}
BOOL get_is_item_worn(const LLUUID& id)
{
return get_is_item_worn(gInventory.getItem(id));
}
BOOL get_can_item_be_worn(const LLUUID& id)
{
const LLViewerInventoryItem* item = gInventory.getItem(id);
if (!item)
return FALSE;
if (LLCOFMgr::instance().isLinkInCOF(item->getLinkedUUID()))
{
// an item having links in COF (i.e. a worn item)
return FALSE;
}
if (gInventory.isObjectDescendentOf(id, LLCOFMgr::instance().getCOF()))
{
// a non-link object in COF (should not normally happen)
return FALSE;
}
const LLUUID trash_id = gInventory.findCategoryUUIDForType(
LLFolderType::FT_TRASH);
// item can't be worn if base obj in trash, see EXT-7015
if (gInventory.isObjectDescendentOf(item->getLinkedUUID(),
trash_id))
{
return false;
}
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
{
if (isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(item->getLinkedUUID()))
{
// Already being worn
return FALSE;
}
else
{
// Not being worn yet.
return TRUE;
}
break;
}
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
{
// Already being worn
return FALSE;
}
else
{
// Not being worn yet.
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
///----------------------------------------------------------------------------
/// LLInventoryCollectFunctor implementations
///----------------------------------------------------------------------------
// static
bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryItem* item)
{
if (!item)
return false;
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
if (!get_is_item_worn(item->getUUID()))
return true;
break;
default:
return true;
break;
}
return false;
}
bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat) return TRUE;
}
if(item)
{
if(item->getType() == mType) return TRUE;
}
return FALSE;
}
bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat) return FALSE;
}
if(item)
{
if(item->getType() == mType) return FALSE;
else return TRUE;
}
return TRUE;
}
bool LLIsOfAssetType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat) return TRUE;
}
if(item)
{
if(item->getActualType() == mType) return TRUE;
}
return FALSE;
}
bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
{
if(cat)
{
return TRUE;
}
}
if(item)
{
if(item->getType() == mType)
{
LLPermissions perm = item->getPermissions();
if ((perm.getMaskBase() & mPerm) == mPerm)
{
return TRUE;
}
}
}
return FALSE;
}
bool LLBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((LLAssetType::AT_CALLINGCARD == item->getType())
&& (!item->getCreatorUUID().isNull())
&& (item->getCreatorUUID() != gAgent.getID()))
{
return true;
}
}
return false;
}
bool LLUniqueBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((LLAssetType::AT_CALLINGCARD == item->getType())
&& (item->getCreatorUUID().notNull())
&& (item->getCreatorUUID() != gAgent.getID()))
{
mSeen.insert(item->getCreatorUUID());
return true;
}
}
return false;
}
bool LLParticularBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if(item)
{
if((LLAssetType::AT_CALLINGCARD == item->getType())
&& (item->getCreatorUUID() == mBuddyID))
{
return TRUE;
}
}
return FALSE;
}
bool LLNameCategoryCollector::operator()(
LLInventoryCategory* cat, LLInventoryItem* item)
{
if(cat)
{
if (!LLStringUtil::compareInsensitive(mName, cat->getName()))
{
return true;
}
}
return false;
}
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------
bool LLAssetIDMatches ::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return (item && item->getAssetUUID() == mAssetID);
}
///----------------------------------------------------------------------------
/// LLLinkedItemIDMatches
///----------------------------------------------------------------------------
bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return (item &&
(item->getIsLinkType()) &&
(item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
}