/** * @file llfloaterinventory.cpp * @brief Implementation of the inventory view and associated stuff. * * $LicenseInfo:firstyear=2001&license=viewergpl$ * * Copyright (c) 2001-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * 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. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include // for std::pair<> #include "llinventoryfunctions.h" // library includes #include "llagent.h" #include "llagentwearables.h" #include "llcallingcard.h" #include "llfloaterreg.h" #include "llinventorydefines.h" #include "llsdserialize.h" #include "llfiltereditor.h" #include "llspinctrl.h" #include "llui.h" #include "message.h" // newview includes #include "llappearancemgr.h" #include "llappviewer.h" //#include "llfirstuse.h" #include "llfloatercustomize.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 "llinventorypanel.h" #include "lllineeditor.h" #include "llmenugl.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" BOOL LLInventoryState::sWearNewClothing = FALSE; LLUUID LLInventoryState::sWearNewClothingTransactionID; ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- // static bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(LLInventoryItem* item) { if (!item) return false; bool allowed = false; switch(item->getType()) { case LLAssetType::AT_CALLINGCARD: // not allowed break; case LLAssetType::AT_OBJECT: if (isAgentAvatarValid() && !gAgentAvatarp->isWearingAttachment(item->getUUID())) { allowed = true; } break; case LLAssetType::AT_BODYPART: case LLAssetType::AT_CLOTHING: if(!gAgentWearables.isWearingItem(item->getUUID())) { allowed = true; } break; default: allowed = true; break; } return allowed; } 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 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; } bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { // Valid COF items are: // - links to wearables (body parts or clothing) // - links to attachments // - links to gestures // - links to ensemble folders LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); if (linked_item) { LLAssetType::EType type = linked_item->getType(); return (type == LLAssetType::AT_CLOTHING || type == LLAssetType::AT_BODYPART || type == LLAssetType::AT_GESTURE || type == LLAssetType::AT_OBJECT); } else { LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP remove AT_NONE support after ensembles are fully working? return (linked_category && ((linked_category->getPreferredType() == LLFolderType::FT_NONE) || (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType())))); } } bool LLFindWearables::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if(item) { if((item->getType() == LLAssetType::AT_CLOTHING) || (item->getType() == LLAssetType::AT_BODYPART)) { 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. } void LLSaveFolderState::setApply(BOOL apply) { mApply = apply; // before generating new list of open folders, clear the old one if(!apply) { clearOpenFolders(); } } void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) { LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); if(mApply) { // we're applying the open state LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); if(!bridge) return; LLUUID id(bridge->getUUID()); if(mOpenFolders.find(id) != mOpenFolders.end()) { folder->setOpen(TRUE); } else { // keep selected filter in its current state, this is less jarring to user if (!folder->isSelected()) { folder->setOpen(FALSE); } } } else { // we're recording state at this point if(folder->isOpen()) { LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); if(!bridge) return; mOpenFolders.insert(bridge->getUUID()); } } } void LLOpenFilteredFolders::doItem(LLFolderViewItem *item) { if (item->getFiltered()) { item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } } void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder) { if (folder->getFiltered() && folder->getParentFolder()) { folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } // if this folder didn't pass the filter, and none of its descendants did else if (!folder->getFiltered() && !folder->hasFilteredDescendants()) { folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO); } } void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item) { if (item->getFiltered() && !mItemSelected) { item->getRoot()->setSelection(item, FALSE, FALSE); if (item->getParentFolder()) { item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } item->getRoot()->scrollToShowSelection(); mItemSelected = TRUE; } } void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) { if (folder->getFiltered() && !mItemSelected) { folder->getRoot()->setSelection(folder, FALSE, FALSE); if (folder->getParentFolder()) { folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } folder->getRoot()->scrollToShowSelection(); mItemSelected = TRUE; } } void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item) { if (item->getParentFolder() && item->isSelected()) { item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } } void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder) { if (folder->getParentFolder() && folder->isSelected()) { folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); } } static void assign_clothing_bodypart_icon(EInventoryIcon &idx, U32 attachment_point) { const EWearableType wearable_type = EWearableType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & attachment_point); switch(wearable_type) { case WT_SHAPE: idx = BODYPART_SHAPE_ICON_NAME; break; case WT_SKIN: idx = BODYPART_SKIN_ICON_NAME; break; case WT_HAIR: idx = BODYPART_HAIR_ICON_NAME; break; case WT_EYES: idx = BODYPART_EYES_ICON_NAME; break; case WT_SHIRT: idx = CLOTHING_SHIRT_ICON_NAME; break; case WT_PANTS: idx = CLOTHING_PANTS_ICON_NAME; break; case WT_SHOES: idx = CLOTHING_SHOES_ICON_NAME; break; case WT_SOCKS: idx = CLOTHING_SOCKS_ICON_NAME; break; case WT_JACKET: idx = CLOTHING_JACKET_ICON_NAME; break; case WT_GLOVES: idx = CLOTHING_GLOVES_ICON_NAME; break; case WT_UNDERSHIRT: idx = CLOTHING_UNDERSHIRT_ICON_NAME; break; case WT_UNDERPANTS: idx = CLOTHING_UNDERPANTS_ICON_NAME; break; case WT_SKIRT: idx = CLOTHING_SKIRT_ICON_NAME; break; case WT_ALPHA: idx = CLOTHING_ALPHA_ICON_NAME; break; case WT_TATTOO: idx = CLOTHING_TATTOO_ICON_NAME; break; default: break; } } const std::string& get_item_icon_name(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type, U32 attachment_point, BOOL item_is_multi ) { EInventoryIcon idx = OBJECT_ICON_NAME; if ( item_is_multi ) { idx = OBJECT_MULTI_ICON_NAME; } switch(asset_type) { case LLAssetType::AT_TEXTURE: if(LLInventoryType::IT_SNAPSHOT == inventory_type) { idx = SNAPSHOT_ICON_NAME; } else { idx = TEXTURE_ICON_NAME; } break; case LLAssetType::AT_SOUND: idx = SOUND_ICON_NAME; break; case LLAssetType::AT_CALLINGCARD: if(attachment_point!= 0) { idx = CALLINGCARD_ONLINE_ICON_NAME; } else { idx = CALLINGCARD_OFFLINE_ICON_NAME; } break; case LLAssetType::AT_LANDMARK: if(attachment_point!= 0) { idx = LANDMARK_VISITED_ICON_NAME; } else { idx = LANDMARK_ICON_NAME; } break; case LLAssetType::AT_SCRIPT: case LLAssetType::AT_LSL_TEXT: case LLAssetType::AT_LSL_BYTECODE: idx = SCRIPT_ICON_NAME; break; case LLAssetType::AT_CLOTHING: idx = CLOTHING_ICON_NAME; assign_clothing_bodypart_icon(idx, attachment_point); break; case LLAssetType::AT_BODYPART: idx = BODYPART_ICON_NAME; assign_clothing_bodypart_icon(idx, attachment_point); break; case LLAssetType::AT_NOTECARD: idx = NOTECARD_ICON_NAME; break; case LLAssetType::AT_ANIMATION: idx = ANIMATION_ICON_NAME; break; case LLAssetType::AT_GESTURE: idx = GESTURE_ICON_NAME; break; case LLAssetType::AT_LINK: idx = LINKITEM_ICON_NAME; break; case LLAssetType::AT_LINK_FOLDER: idx = LINKFOLDER_ICON_NAME; break; case LLAssetType::AT_MESH: idx = MESH_ICON_NAME; break; default: break; } return ICON_NAME[idx]; } LLUIImagePtr get_item_icon(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type, U32 attachment_point, BOOL item_is_multi) { const std::string& icon_name = get_item_icon_name(asset_type, inventory_type, attachment_point, item_is_multi ); return LLUI::getUIImage(icon_name); } BOOL get_is_item_worn(const LLUUID& id) { const LLViewerInventoryItem* item = gInventory.getItem(id); if (!item) return FALSE; 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; }