diff options
Diffstat (limited to 'indra/newview/llinventorybridge.cpp')
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 563 |
1 files changed, 296 insertions, 267 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index beeac86f94..7ce96a6ac1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2,25 +2,31 @@ * @file llinventorybridge.cpp * @brief Implementation of the Inventory-Folder-View-Bridge classes. * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * * 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 + * 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$ */ @@ -66,6 +72,7 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" +#include "llpaneloutfitsinventory.h" typedef std::pair<LLUUID, LLUUID> two_uuids_t; typedef std::list<two_uuids_t> two_uuids_list_t; @@ -438,8 +445,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, - const menuentry_vec_t &disabled_entries, - BOOL append) // If append is TRUE, then new enabled entries + const menuentry_vec_t &disabled_entries) { const LLView::child_list_t *list = menu.getChildList(); @@ -447,15 +453,13 @@ void hide_context_entries(LLMenuGL& menu, // if the first element is a separator, it will not be shown. BOOL is_previous_entry_separator = TRUE; - for (LLView::child_list_t::const_iterator itor = list->begin(); - itor != list->end(); - ++itor) + LLView::child_list_t::const_iterator itor; + for (itor = list->begin(); itor != list->end(); ++itor) { - LLView *menu_item = (*itor); - std::string name = menu_item->getName(); + std::string name = (*itor)->getName(); // descend into split menus: - LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item); + LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor); if ((name == "More") && branchp) { hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); @@ -476,7 +480,7 @@ void hide_context_entries(LLMenuGL& menu, // between two separators). if (found) { - const BOOL is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(menu_item) != NULL); + const BOOL is_entry_separator = (dynamic_cast<LLMenuItemSeparatorGL *>(*itor) != NULL); if (is_entry_separator && is_previous_entry_separator) found = false; is_previous_entry_separator = is_entry_separator; @@ -484,27 +488,16 @@ void hide_context_entries(LLMenuGL& menu, if (!found) { - if (!menu_item->getLastVisible()) - { - menu_item->setVisible(FALSE); - } - menu_item->setEnabled(FALSE); + (*itor)->setVisible(FALSE); } else { - menu_item->setVisible(TRUE); - // A bit of a hack so we can remember that some UI element explicitly set this to be visible - // so that some other UI element from multi-select doesn't later set this invisible. - menu_item->pushVisible(TRUE); - if (append) - { - menu_item->setEnabled(TRUE); - } + (*itor)->setVisible(TRUE); for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) { if (*itor2 == name) { - menu_item->setEnabled(FALSE); + (*itor)->setEnabled(FALSE); } } } @@ -518,6 +511,17 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { const LLInventoryObject *obj = getInventoryObject(); + bool is_sidepanel = isInOutfitsSidePanel(); + if (is_sidepanel) + { + // Sidepanel includes restricted menu. + if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) + { + items.push_back(std::string("Remove Link")); + } + return; + } + if (obj) { if (obj->getIsLinkType()) @@ -944,10 +948,18 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) } } -BOOL LLInvFVBridge::canShare() const +BOOL LLInvFVBridge::isInOutfitsSidePanel() const { - if (!isAgentInventory()) return FALSE; + LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLPanelOutfitsInventory *outfit_panel = + dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); + if (!outfit_panel) + return FALSE; + return outfit_panel->isTabPanel(my_panel); +} +BOOL LLInvFVBridge::canShare() const +{ const LLInventoryModel* model = getInventoryModel(); if (!model) return FALSE; @@ -959,10 +971,9 @@ BOOL LLInvFVBridge::canShare() const return (BOOL)LLGiveInventory::isInventoryGiveAcceptable(item); } - // Categories can be given. - if (model->getCategory(mUUID)) return TRUE; - - return FALSE; + // All categories can be given. + const LLViewerInventoryCategory* cat = model->getCategory(mUUID); + return (cat != NULL); } // +=================================================+ @@ -1441,7 +1452,7 @@ bool LLItemBridge::isRemoveAction(std::string action) const // | LLFolderBridge | // +=================================================+ -LLHandle<LLFolderBridge> LLFolderBridge::sSelf; +LLFolderBridge* LLFolderBridge::sSelf=NULL; // Can be moved to another folder BOOL LLFolderBridge::isItemMovable() const @@ -1621,70 +1632,84 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, BOOL drop) { + // This should never happen, but if an inventory item is incorrectly parented, + // the UI will get confused and pass in a NULL. + if(!inv_cat) return FALSE; LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; - if (!inv_cat) return FALSE; // shouldn't happen, but in case item is incorrectly parented in which case inv_cat will be NULL - if (!model) return FALSE; if (!isAgentAvatarValid()) return FALSE; - if (!isAgentInventory()) return FALSE; // cannot drag categories into library + // cannot drag categories into library + if(!isAgentInventory()) + { + return FALSE; + } // check to make sure source is agent inventory, and is represented there. LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) + BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) && (LLToolDragAndDrop::SOURCE_AGENT == source); BOOL accept = FALSE; - if (is_agent_inventory) + S32 i; + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + if(is_agent_inventory) { - const LLUUID &cat_id = inv_cat->getUUID(); - const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - - const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const LLUUID& cat_id = inv_cat->getUUID(); - //-------------------------------------------------------------------------------- - // Determine if folder can be moved. - // + // Is the destination the trash? + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + BOOL move_is_into_trash = (mUUID == trash_id) + || model->isObjectDescendentOf(mUUID, trash_id); + BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())); + const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + if (move_is_into_current_outfit || move_is_into_outfit) + { + // BAP - restrictions? + is_movable = true; + } - BOOL is_movable = TRUE; - if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) - is_movable = FALSE; - if (move_is_into_outfit) - is_movable = FALSE; if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) - is_movable = FALSE; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); - for (S32 i=0; i < descendent_categories.count(); ++i) { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - // Can't move "special folders" (e.g. Textures Folder). - is_movable = FALSE; - break; - } + is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 } - if (move_is_into_trash) + + if( is_movable ) { - for (S32 i=0; i < descendent_items.count(); ++i) + gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); + + for( i = 0; i < descendent_categories.count(); i++ ) { - LLInventoryItem* item = descendent_items[i]; - if (get_is_item_worn(item->getUUID())) + LLInventoryCategory* category = descendent_categories[i]; + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) { + // ...can't move "special folders" like Textures is_movable = FALSE; - break; // It's generally movable, but not into the trash. + break; } } - } - // - //-------------------------------------------------------------------------------- + if( is_movable ) + { + if( move_is_into_trash ) + { + for( i = 0; i < descendent_items.count(); i++ ) + { + LLInventoryItem* item = descendent_items[i]; + if (get_is_item_worn(item->getUUID())) + { + is_movable = FALSE; + break; // It's generally movable, but not into the trash! + } + } + } + } + } accept = is_movable && (mUUID != cat_id) // Can't move a folder into itself @@ -1695,7 +1720,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // Look for any gestures and deactivate them if (move_is_into_trash) { - for (S32 i=0; i < descendent_items.count(); i++) + for (i = 0; i < descendent_items.count(); i++) { LLInventoryItem* item = descendent_items[i]; if (item->getType() == LLAssetType::AT_GESTURE @@ -2056,7 +2081,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) mContentsCount) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, FALSE); + LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, TRUE); delete this; } } @@ -2385,11 +2410,8 @@ void LLFolderBridge::pasteLinkFromClipboard() void LLFolderBridge::staticFolderOptionsMenu() { - LLFolderBridge* selfp = sSelf.get(); - if (selfp) - { - selfp->folderOptionsMenu(); - } + if (!sSelf) return; + sSelf->folderOptionsMenu(); } void LLFolderBridge::folderOptionsMenu() @@ -2402,19 +2424,23 @@ void LLFolderBridge::folderOptionsMenu() const LLInventoryCategory* category = model->getCategory(mUUID); if(!category) return; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - if (trash_id == mUUID) return; - if (isItemInTrash()) return; - if (!isAgentInventory()) return; - LLFolderType::EType type = category->getPreferredType(); const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); // BAP change once we're no longer treating regular categories as ensembles. const bool is_ensemble = (type == LLFolderType::FT_NONE || LLFolderType::lookupIsEnsembleType(type)); + // calling card related functionality for folders. + + const bool is_sidepanel = isInOutfitsSidePanel(); + if (is_sidepanel) + { + mItems.push_back("Rename"); + addDeleteContextMenuOptions(mItems, disabled_items); + } + // Only enable calling-card related options for non-system folders. - if (!is_system_folder) + if (!is_sidepanel && !is_system_folder) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) @@ -2443,7 +2469,10 @@ void LLFolderBridge::folderOptionsMenu() checkFolderForContentsOfType(model, is_object) || checkFolderForContentsOfType(model, is_gesture) ) { - mItems.push_back(std::string("Folder Wearables Separator")); + if (!is_sidepanel) + { + mItems.push_back(std::string("Folder Wearables Separator")); + } // Only enable add/replace outfit for non-system folders. if (!is_system_folder) @@ -2460,21 +2489,17 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("Wear As Ensemble")); } mItems.push_back(std::string("Remove From Outfit")); - if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) + if (!areAnyContentsWorn(model)) { disabled_items.push_back(std::string("Remove From Outfit")); } mItems.push_back(std::string("Outfit Separator")); } - LLMenuGL* menup = dynamic_cast<LLMenuGL*>(mMenu.get()); - if (menup) - { - hide_context_entries(*menup, mItems, disabled_items, TRUE); + hide_context_entries(*mMenu, mItems, disabled_items); - // Reposition the menu, in case we're adding items to an existing menu. - menup->needsArrange(); - menup->arrangeAndClear(); - } + // Reposition the menu, in case we're adding items to an existing menu. + mMenu->needsArrange(); + mMenu->arrangeAndClear(); } BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) @@ -2489,6 +2514,19 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv return ((item_array.count() > 0) ? TRUE : FALSE ); } +BOOL LLFolderBridge::areAnyContentsWorn(LLInventoryModel* model) const +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + LLFindWorn is_worn; + model->collectDescendentsIf(mUUID, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_worn); + return (item_array.size() > 0); +} + // Flags unused void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { @@ -2516,10 +2554,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.push_back(std::string("New Body Parts")); } - // clear out old menu and folder pointers - mMenu.markDead(); - sSelf.markDead(); - if(trash_id == mUUID) { // This is the trash. @@ -2547,9 +2581,9 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mItems.push_back(std::string("New Clothes")); mItems.push_back(std::string("New Body Parts")); -#if SUPPORT_ENSEMBLES - // Changing folder types is an unfinished unsupported feature + // Changing folder types is just a debug feature; this is fairly unsupported // and can lead to unexpected behavior if enabled. +#if !LL_RELEASE_FOR_DOWNLOAD mItems.push_back(std::string("Change Type")); const LLViewerInventoryCategory *cat = getCategory(); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) @@ -2595,6 +2629,36 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { mWearables=TRUE; } + + mMenu = &menu; + sSelf = this; + + + uuid_vec_t folders; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (category) + { + folders.push_back(category->getUUID()); + } + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + fetch->startFetch(); + inc_busy_count(); + if(fetch->isFinished()) + { + // everything is already here - call done. + fetch->done(); + } + else + { + // it's all on it's way - add an observer, and the inventory + // will call done for us when everything is here. + gInventory.addObserver(fetch); + } + } + else + { + mItems.push_back(std::string("--no options--")); + mDisabledItems.push_back(std::string("--no options--")); } // Preemptively disable system folder removal if more than one item selected. @@ -2610,30 +2674,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } hide_context_entries(menu, mItems, mDisabledItems); - - // Add menu items that are dependent on the contents of the folder. - uuid_vec_t folders; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if (category) - { - folders.push_back(category->getUUID()); - } - - mMenu = menu.getHandle(); - sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); - fetch->startFetch(); - inc_busy_count(); - if(fetch->isFinished()) - { - // everything is already here - call done. - fetch->done(); - } - else - { - // it's all on its way - add an observer, and the inventory will call done for us when everything is here. - gInventory.addObserver(fetch); - } } BOOL LLFolderBridge::hasChildren() const @@ -2845,16 +2885,18 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response return false; } -// This is used both for testing whether an item can be dropped -// into the folder, as well as performing the actual drop, depending -// if drop == TRUE. BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop) { LLInventoryModel* model = getInventoryModel(); - if(!model || !inv_item) return FALSE; - if(!isAgentInventory()) return FALSE; // cannot drag into library + + // cannot drag into library + if(!isAgentInventory()) + { + return FALSE; + } + if (!isAgentAvatarValid()) return FALSE; LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); @@ -2862,23 +2904,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLViewerObject* object = NULL; if(LLToolDragAndDrop::SOURCE_AGENT == source) { - const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); - - const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); - const BOOL folder_allows_reorder = (mUUID == favorites_id); - - //-------------------------------------------------------------------------------- - // Determine if item can be moved. - // - BOOL is_movable = TRUE; - - switch (inv_item->getActualType()) + switch( inv_item->getActualType() ) { case LLAssetType::AT_CATEGORY: is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); @@ -2886,50 +2913,41 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, default: break; } + + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); + const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); + // Can't explicitly drag things out of the COF. if (move_is_outof_current_outfit) { is_movable = FALSE; } - if (move_is_into_trash) + + if(is_movable && move_is_into_trash) { - is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID()); + is_movable = inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID()); } - if (is_movable) + + if ( is_movable ) { // Don't allow creating duplicates in the Calling Card/Friends // subfolders, see bug EXT-1599. Check is item direct descendent // of target folder and forbid item's movement if it so. // Note: isItemDirectDescendentOfCategory checks if // passed category is in the Calling Card/Friends folder - is_movable &= !LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(inv_item, getCategory()); - } - - // - //-------------------------------------------------------------------------------- - - //-------------------------------------------------------------------------------- - // Determine if item can be moved & dropped - // - - accept = TRUE; - - if (!is_movable) - accept = FALSE; - if ((mUUID == inv_item->getParentUUID()) && !folder_allows_reorder) - accept = FALSE; - if (move_is_into_current_outfit || move_is_into_outfit) - { - if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) && - (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) && - (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT)) - accept = FALSE; - } - if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID())) - { - accept = FALSE; + is_movable = ! LLFriendCardsManager::instance() + .isObjDirectDescendentOfCategory (inv_item, getCategory()); } + const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const BOOL folder_allows_reorder = (mUUID == favorites_id); + + // we can move item inside a folder only if this folder is Favorites. See EXT-719 + accept = is_movable && ((mUUID != inv_item->getParentUUID()) || folder_allows_reorder); if(accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE @@ -2937,8 +2955,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { LLGestureMgr::instance().deactivateGesture(inv_item->getUUID()); } - // If an item is being dragged between windows, unselect everything in the active window - // so that we don't follow the selection to its new location (which is very annoying). + // If an item is being dragged between windows, unselect + // everything in the active window so that we don't follow + // the selection to its new location (which is very + // annoying). LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); if (active_panel) { @@ -2949,12 +2969,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } } - //-------------------------------------------------------------------------------- - // Destination folder logic - // - - // REORDER - // (only reorder the item) + // if dragging from/into favorites folder only reorder items if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) { LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); @@ -2966,10 +2981,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } - - // FAVORITES folder - // (copy the item) - else if (favorites_id == mUUID) + else if (favorites_id == mUUID) // if target is the favorites folder we use copy { // use callback to rearrange favorite landmarks after adding // to have new one placed before target (on which it was dropped). See EXT-4312. @@ -2989,50 +3001,38 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, std::string(), cb); } - // CURRENT OUTFIT or OUTFIT folder - // (link the item) else if (move_is_into_current_outfit || move_is_into_outfit) { - if ((inv_item->getInventoryType() == LLInventoryType::IT_WEARABLE) || - (inv_item->getInventoryType() == LLInventoryType::IT_GESTURE) || - (inv_item->getInventoryType() == LLInventoryType::IT_OBJECT)) + // BAP - should skip if dup. + if (move_is_into_current_outfit) { - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceMgr::instance().wearItemOnAvatar(inv_item->getUUID(), true, true); - } - else - { - LLPointer<LLInventoryCallback> cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_item->getLinkedUUID(), - mUUID, - inv_item->getName(), - inv_item->getDescription(), - LLAssetType::AT_LINK, - cb); - } + LLAppearanceMgr::instance().addCOFItemLink(inv_item); + } + else + { + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_item( + gAgent.getID(), + inv_item->getLinkedUUID(), + mUUID, + inv_item->getName(), + inv_item->getDescription(), + LLAssetType::AT_LINK, + cb); } } - // NORMAL or TRASH folder - // (move the item, restamp if into trash) else { + // restamp if the move is into the trash. LLInvFVBridge::changeItemParent( model, (LLViewerInventoryItem*)inv_item, mUUID, move_is_into_trash); } - - // - //-------------------------------------------------------------------------------- - } } - else if (LLToolDragAndDrop::SOURCE_WORLD == source) + else if(LLToolDragAndDrop::SOURCE_WORLD == source) { // Make sure the object exists. If we allowed dragging from // anonymous objects, it would be possible to bypass @@ -3050,7 +3050,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL is_move = FALSE; if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) - // || gAgent.isGodlike()) +// || gAgent.isGodlike()) { accept = TRUE; @@ -3776,9 +3776,13 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { disabled_items.push_back(std::string("Share")); } + bool is_sidepanel = isInOutfitsSidePanel(); - addOpenRightClickMenuOption(items); - items.push_back(std::string("Properties")); + if (!is_sidepanel) + { + addOpenRightClickMenuOption(items); + items.push_back(std::string("Properties")); + } getClipboardEntries(true, items, disabled_items, flags); @@ -4013,12 +4017,13 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach payload["attachment_point"] = attach_pt; - if (!gSavedSettings.getBOOL("MultipleAttachments") && - (attachment && attachment->getNumObjects() > 0)) +#if !ENABLE_MULTIATTACHMENTS + if (attachment && attachment->getNumObjects() > 0) { LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); } else +#endif { LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); } @@ -4041,10 +4046,6 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon if (itemp) { - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); - if (gSavedSettings.getBOOL("MultipleAttachments")) - attachment_pt |= ATTACHMENT_ADD; - LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); msg->nextBlockFast(_PREHASH_AgentData); @@ -4053,6 +4054,10 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon msg->nextBlockFast(_PREHASH_ObjectData); msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); + U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); +#if ENABLE_MULTIATTACHMENTS + attachment_pt |= ATTACHMENT_ADD; +#endif msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); msg->addStringFast(_PREHASH_Name, itemp->getName()); @@ -4079,8 +4084,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { disabled_items.push_back(std::string("Share")); } + bool is_sidepanel = isInOutfitsSidePanel(); - items.push_back(std::string("Properties")); + if (!is_sidepanel) + { + items.push_back(std::string("Properties")); + } getClipboardEntries(true, items, disabled_items, flags); @@ -4093,13 +4102,13 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if( get_is_item_worn( mUUID ) ) { - items.push_back(std::string("Wearable And Object Separator")); + items.push_back(std::string("Attach Separator")); items.push_back(std::string("Detach From Yourself")); } else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder()) { - items.push_back(std::string("Wearable And Object Separator")); - items.push_back(std::string("Wearable And Object Wear")); + items.push_back(std::string("Attach Separator")); + items.push_back(std::string("Object Wear")); items.push_back(std::string("Attach To")); items.push_back(std::string("Attach To HUD")); // commented out for DEV-32347 @@ -4107,7 +4116,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if (!gAgentAvatarp->canAttachMoreObjects()) { - disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Object Wear")); disabled_items.push_back(std::string("Attach To")); disabled_items.push_back(std::string("Attach To HUD")); } @@ -4136,7 +4145,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } LLSD cbparams; cbparams["index"] = curiter->first; - cbparams["label"] = p.name; + cbparams["label"] = attachment->getName(); p.on_click.function_name = "Inventory.AttachObject"; p.on_click.parameter = LLSD(attachment->getName()); p.on_enable.function_name = "Attachment.Label"; @@ -4429,27 +4438,30 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { can_open = FALSE; } + items.push_back(std::string("Share")); if (!canShare()) { disabled_items.push_back(std::string("Share")); } + bool is_sidepanel = isInOutfitsSidePanel(); - if (can_open) + if (can_open && !is_sidepanel) { addOpenRightClickMenuOption(items); } - else + + if (!is_sidepanel) { - disabled_items.push_back(std::string("Open")); - disabled_items.push_back(std::string("Open Original")); + items.push_back(std::string("Properties")); } - items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - items.push_back(std::string("Wearable And Object Separator")); + if (!is_sidepanel) + { + items.push_back(std::string("Wearable Separator")); + } items.push_back(std::string("Wearable Edit")); @@ -4460,7 +4472,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // Don't allow items to be worn if their baseobj is in the trash. if (isLinkedObjectInTrash() || isLinkedObjectMissing() || isCOFFolder()) { - disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Wear")); disabled_items.push_back(std::string("Wearable Add")); disabled_items.push_back(std::string("Wearable Edit")); } @@ -4476,15 +4488,14 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) case LLAssetType::AT_BODYPART: if (get_is_item_worn(item->getUUID())) { - disabled_items.push_back(std::string("Wearable And Object Wear")); + disabled_items.push_back(std::string("Wearable Wear")); disabled_items.push_back(std::string("Wearable Add")); } else { - items.push_back(std::string("Wearable And Object Wear")); + items.push_back(std::string("Wearable Wear")); items.push_back(std::string("Wearable Add")); disabled_items.push_back(std::string("Take Off")); - disabled_items.push_back(std::string("Wearable Edit")); } break; default: @@ -4520,7 +4531,13 @@ void LLWearableBridge::onWearOnAvatar(void* user_data) void LLWearableBridge::wearOnAvatar() { - // TODO: investigate wearables may not be loaded at this point EXT-8231 + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); + return; + } LLViewerInventoryItem* item = getItem(); if(item) @@ -4531,7 +4548,13 @@ void LLWearableBridge::wearOnAvatar() void LLWearableBridge::wearAddOnAvatar() { - // TODO: investigate wearables may not be loaded at this point EXT-8231 + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); + return; + } LLViewerInventoryItem* item = getItem(); if(item) @@ -5089,7 +5112,13 @@ BOOL LLWearableBridgeAction::isAgentInventory() const void LLWearableBridgeAction::wearOnAvatar() { - // TODO: investigate wearables may not be loaded at this point EXT-8231 + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); + return; + } LLViewerInventoryItem* item = getItem(); if(item) @@ -5155,12 +5184,12 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items, items = getMenuItems(); - items.erase(std::remove(items.begin(), items.end(), std::string("New Body Parts")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Clothes")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Note")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Gesture")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Script")), items.end()); - items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); + items.erase(std::find(items.begin(), items.end(), std::string("New Folder"))); + items.erase(std::find(items.begin(), items.end(), std::string("New Script"))); + items.erase(std::find(items.begin(), items.end(), std::string("New Note"))); + items.erase(std::find(items.begin(), items.end(), std::string("New Gesture"))); + items.erase(std::find(items.begin(), items.end(), std::string("New Clothes"))); + items.erase(std::find(items.begin(), items.end(), std::string("New Body Parts"))); hide_context_entries(menu, items, disabled_items); } |