diff options
Diffstat (limited to 'indra/newview/llinventorybridge.cpp')
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 2126 |
1 files changed, 1190 insertions, 936 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 028505456b..e394b4dfc1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1,11 +1,11 @@ -/** +/** * @file llinventorybridge.cpp * @brief Implementation of the Inventory-Folder-View-Bridge classes. * * $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 @@ -13,17 +13,17 @@ * ("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. @@ -31,68 +31,46 @@ */ #include "llviewerprecompiledheaders.h" +#include "llinventorybridge.h" -#include <utility> // for std::pair<> +// external projects +#include "lltransfersourceasset.h" -#include "llfloaterinventory.h" -#include "llinventorybridge.h" -#include "message.h" #include "llagent.h" +#include "llagentcamera.h" #include "llagentwearables.h" -#include "llcallingcard.h" -#include "llcheckboxctrl.h" // for radio buttons -#include "llfloaterreg.h" -#include "llradiogroup.h" -#include "llspinctrl.h" -#include "lltextbox.h" -#include "llui.h" - -#include "llviewercontrol.h" -#include "llfirstuse.h" -#include "llfoldertype.h" -#include "llfloaterchat.h" +#include "llappearancemgr.h" +#include "llavataractions.h" #include "llfloatercustomize.h" -#include "llfloaterproperties.h" +#include "llfloateropenobject.h" +#include "llfloaterreg.h" #include "llfloaterworldmap.h" -#include "llfocusmgr.h" -#include "llfolderview.h" #include "llfriendcard.h" -#include "llavataractions.h" #include "llgesturemgr.h" -#include "lliconctrl.h" -#include "llinventorymodel.h" +#include "llimfloater.h" +#include "llimview.h" #include "llinventoryclipboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventorypanel.h" +#include "llnotifications.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 "llscrollcontainer.h" -#include "llimview.h" -#include "lltooldraganddrop.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llwearable.h" -#include "llwearablelist.h" -#include "llviewermessage.h" -#include "llviewerregion.h" -#include "llvoavatarself.h" -#include "lltabcontainer.h" -#include "lluictrlfactory.h" #include "llselectmgr.h" #include "llsidetray.h" -#include "llfloateropenobject.h" #include "lltrans.h" -#include "llappearancemgr.h" +#include "llviewerassettype.h" +#include "llviewermessage.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llvoavatarself.h" +#include "llwearablelist.h" +#include "llpaneloutfitsinventory.h" using namespace LLOldEvents; @@ -129,7 +107,7 @@ std::string ICON_NAME[ICON_NAME_COUNT] = "Inv_Script", "Inv_Clothing", "Inv_Object", - "Inv_Object", + "Inv_Object_Multi", "Inv_Notecard", "Inv_Skin", "Inv_Snapshot", @@ -147,28 +125,18 @@ std::string ICON_NAME[ICON_NAME_COUNT] = "Inv_Undershirt", "Inv_Underpants", "Inv_Skirt", - "inv_item_alpha.tga", - "inv_item_tattoo.tga", + "Inv_Alpha", + "Inv_Tattoo", "Inv_Animation", "Inv_Gesture", - "inv_item_linkitem.tga", - "inv_item_linkfolder.tga", + "Inv_LinkItem", + "Inv_LinkFolder", - "inv_item_mesh.tga" + "Inv_Mesh" }; - -// +=================================================+ -// | LLInventoryPanelObserver | -// +=================================================+ -void LLInventoryPanelObserver::changed(U32 mask) -{ - mIP->modelChanged(mask); -} - - // +=================================================+ // | LLInvFVBridge | // +=================================================+ @@ -202,9 +170,9 @@ PermissionMask LLInvFVBridge::getPermissionMask() const } // virtual -LLAssetType::EType LLInvFVBridge::getPreferredType() const +LLFolderType::EType LLInvFVBridge::getPreferredType() const { - return LLAssetType::AT_NONE; + return LLFolderType::FT_NONE; } @@ -214,47 +182,37 @@ time_t LLInvFVBridge::getCreationDate() const return 0; } -// Can be destoryed (or moved to trash) -BOOL LLInvFVBridge::isItemRemovable() +// Can be destroyed (or moved to trash) +BOOL LLInvFVBridge::isItemRemovable() const { - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + const LLInventoryModel* model = getInventoryModel(); + if(!model) { - return TRUE; + return FALSE; } - return FALSE; -} -// Sends an update to all link items that point to the base item. -void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; + // Can't delete an item that's in the library. + if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + { + return FALSE; + } - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; + // Disable delete from COF folder; have users explicitly choose "detach/take off". + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(mUUID)) + { + return FALSE; + } - if (itemp->getIsLinkType()) + const LLInventoryObject *obj = model->getItem(mUUID); + if (obj && obj->getIsLinkType()) { - return; + return TRUE; } - - LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id); - for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) + if (get_is_item_worn(mUUID)) { - LLViewerInventoryItem *linked_item = (*iter); - if (linked_item->getUUID() == item_id) continue; - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item); - new_item->rename(new_name); - new_item->updateServer(FALSE); - model->updateItem(new_item); - // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID()); + return FALSE; } - model->notifyObservers(); + return TRUE; } // Can be moved to another folder @@ -277,7 +235,14 @@ void LLInvFVBridge::cutToClipboard() // *TODO: make sure this does the right thing void LLInvFVBridge::showProperties() { + LLSD key; + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + // Disable old properties floater; this is replaced by the sidepanel. + /* LLFloaterReg::showInstance("properties", mUUID); + */ } void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) @@ -292,7 +257,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc S32 count = batch.count(); S32 i,j; for(i = 0; i < count; ++i) - { + { bridge = (LLInvFVBridge*)(batch.get(i)); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); @@ -300,12 +265,12 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc { if(LLAssetType::AT_GESTURE == item->getType()) { - LLGestureManager::instance().deactivateGesture(item->getUUID()); + LLGestureMgr::instance().deactivateGesture(item->getUUID()); } } } for(i = 0; i < count; ++i) - { + { bridge = (LLInvFVBridge*)(batch.get(i)); if(!bridge || !bridge->isItemRemovable()) continue; cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); @@ -316,7 +281,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc { if(LLAssetType::AT_GESTURE == descendent_items[j]->getType()) { - LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID()); + LLGestureMgr::instance().deactivateGesture(descendent_items[j]->getUUID()); } } } @@ -335,14 +300,29 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* LLInventoryModel* model = getInventoryModel(); if(!model) return; LLMessageSystem* msg = gMessageSystem; - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - std::vector<LLUUID> move_ids; + uuid_vec_t move_ids; LLInventoryModel::update_map_t update; bool start_new_message = true; S32 count = batch.count(); S32 i; + + // first, hide any 'preview' floaters that correspond to the items + // being deleted. + for(i = 0; i < count; ++i) + { + bridge = (LLInvFVBridge*)(batch.get(i)); + if(!bridge || !bridge->isItemRemovable()) continue; + item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); + if(item) + { + LLPreview::hide(item->getUUID()); + } + } + + // do the inventory move to trash + for(i = 0; i < count; ++i) { bridge = (LLInvFVBridge*)(batch.get(i)); @@ -352,7 +332,6 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* { if(item->getParentUUID() == trash_id) continue; move_ids.push_back(item->getUUID()); - LLPreview::hide(item->getUUID()); --update[item->getParentUUID()]; ++update[trash_id]; if(start_new_message) @@ -384,11 +363,12 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* gInventory.accountForUpdate(update); update.clear(); } + for(i = 0; i < count; ++i) { bridge = (LLInvFVBridge*)(batch.get(i)); if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); + LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if(cat) { if(cat->getParentUUID() == trash_id) continue; @@ -423,8 +403,8 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* } // move everything. - std::vector<LLUUID>::iterator it = move_ids.begin(); - std::vector<LLUUID>::iterator end = move_ids.end(); + uuid_vec_t::iterator it = move_ids.begin(); + uuid_vec_t::iterator end = move_ids.end(); for(; it != end; ++it) { gInventory.moveObject((*it), trash_id); @@ -500,7 +480,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const } } const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); - if (cat && !LLAssetType::lookupCanLink(cat->getPreferredType())) + if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { return FALSE; } @@ -508,12 +488,16 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const return TRUE; } -void hideContextEntries(LLMenuGL& menu, - const std::vector<std::string> &entries_to_show, - const std::vector<std::string> &disabled_entries) +void hide_context_entries(LLMenuGL& menu, + const menuentry_vec_t &entries_to_show, + const menuentry_vec_t &disabled_entries) { const LLView::child_list_t *list = menu.getChildList(); + // For removing double separators or leading separator. Start at true so that + // if the first element is a separator, it will not be shown. + BOOL is_previous_entry_separator = TRUE; + LLView::child_list_t::const_iterator itor; for (itor = list->begin(); itor != list->end(); ++itor) { @@ -523,12 +507,12 @@ void hideContextEntries(LLMenuGL& menu, LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor); if ((name == "More") && branchp) { - hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries); + hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); } - - + + bool found = false; - std::vector<std::string>::const_iterator itor2; + menuentry_vec_t::const_iterator itor2; for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) { if (*itor2 == name) @@ -536,12 +520,24 @@ void hideContextEntries(LLMenuGL& menu, found = true; } } + + // Don't allow multiple separators in a row (e.g. such as if there are no items + // between two separators). + if (found) + { + 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; + } + if (!found) { (*itor)->setVisible(FALSE); } else { + (*itor)->setVisible(TRUE); for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) { if (*itor2 == name) @@ -554,67 +550,111 @@ void hideContextEntries(LLMenuGL& menu, } // Helper for commonly-used entries -void LLInvFVBridge::getClipboardEntries(bool show_asset_id, - std::vector<std::string> &items, - std::vector<std::string> &disabled_items, U32 flags) +void LLInvFVBridge::getClipboardEntries(bool show_asset_id, + menuentry_vec_t &items, + menuentry_vec_t &disabled_items, U32 flags) { - items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + const LLInventoryObject *obj = getInventoryObject(); + + bool is_sidepanel = isInOutfitsSidePanel(); + if (is_sidepanel) { - disabled_items.push_back(std::string("Rename")); + // Sidepanel includes restricted menu. + if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) + { + items.push_back(std::string("Remove Link")); + } + return; } - if (show_asset_id) + if (obj) { - items.push_back(std::string("Copy Asset UUID")); - if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) - || (flags & FIRST_SELECTED_ITEM) == 0) + if (obj->getIsLinkType()) { - disabled_items.push_back(std::string("Copy Asset UUID")); + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } } - } + else + { + if (LLAssetType::lookupCanLink(obj->getType())) + { + items.push_back(std::string("Find Links")); + } + items.push_back(std::string("Rename")); + if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Rename")); + } + + if (show_asset_id) + { + items.push_back(std::string("Copy Asset UUID")); - items.push_back(std::string("Copy Separator")); + bool is_asset_knowable = false; - items.push_back(std::string("Copy")); - if (!isItemCopyable()) - { - disabled_items.push_back(std::string("Copy")); + LLViewerInventoryItem* inv_item = gInventory.getItem(mUUID); + if (inv_item) + { + is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(inv_item->getType()); + } + if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 + || (! ( isItemPermissive() || gAgent.isGodlike() ) ) + || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Copy Asset UUID")); + } + } + items.push_back(std::string("Copy Separator")); + + items.push_back(std::string("Copy")); + if (!isItemCopyable()) + { + disabled_items.push_back(std::string("Copy")); + } + } } - items.push_back(std::string("Paste")); - if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0) + // Don't allow items to be pasted directly into the COF. + if (!isCOFFolder()) + { + items.push_back(std::string("Paste")); + } + if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0)) { disabled_items.push_back(std::string("Paste")); } - items.push_back(std::string("Paste As Link")); - if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) + if (gAgent.isGodlike()) { - disabled_items.push_back(std::string("Paste As Link")); + items.push_back(std::string("Paste As Link")); + if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Paste As Link")); + } } + items.push_back(std::string("Paste Separator")); - items.push_back(std::string("Delete")); - if (!isItemRemovable()) + addDeleteContextMenuOptions(items, disabled_items); + + // If multiple items are selected, disable properties (if it exists). + if ((flags & FIRST_SELECTED_ITEM) == 0) { - disabled_items.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Properties")); } } void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) { - items.push_back(std::string("PurgeItem")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("PurgeItem")); - } - items.push_back(std::string("RestoreItem")); + addTrashContextMenuOptions(items, disabled_items); } else { @@ -623,7 +663,55 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); +} + +void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items, + menuentry_vec_t &disabled_items) +{ + const LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + items.push_back(std::string("Find Original")); + if (isLinkedObjectMissing()) + { + disabled_items.push_back(std::string("Find Original")); + } + } + items.push_back(std::string("Purge Item")); + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Purge Item")); + } + items.push_back(std::string("Restore Item")); +} + +void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, + menuentry_vec_t &disabled_items) +{ + + const LLInventoryObject *obj = getInventoryObject(); + + // Don't allow delete as a direct option from COF folder. + if (obj && obj->getIsLinkType() && isCOFFolder()) + { + return; + } + + // "Remove link" and "Delete" are the same operation. + if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) + { + items.push_back(std::string("Remove Link")); + } + else + { + items.push_back(std::string("Delete")); + } + + if (!isItemRemovable()) + { + disabled_items.push_back(std::string("Delete")); + } } // *TODO: remove this @@ -635,18 +723,18 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const if(obj) { - *type = LLAssetType::lookupDragAndDropType(obj->getActualType()); + *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); if(*type == DAD_NONE) { return FALSE; } - + *id = obj->getUUID(); //object_ids.put(obj->getUUID()); if (*type == DAD_CATEGORY) { - gInventory.startBackgroundFetch(obj->getUUID()); + LLInventoryModelBackgroundFetch::instance().start(obj->getUUID()); } rv = TRUE; @@ -672,29 +760,43 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const return panel ? panel->getModel() : NULL; } -BOOL LLInvFVBridge::isInTrash() const +BOOL LLInvFVBridge::isItemInTrash() const { LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); return model->isObjectDescendentOf(mUUID, trash_id); } BOOL LLInvFVBridge::isLinkedObjectInTrash() const { - if (isInTrash()) return TRUE; + if (isItemInTrash()) return TRUE; const LLInventoryObject *obj = getInventoryObject(); if (obj && obj->getIsLinkType()) { LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); } return FALSE; } +BOOL LLInvFVBridge::isLinkedObjectMissing() const +{ + const LLInventoryObject *obj = getInventoryObject(); + if (!obj) + { + return TRUE; + } + if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType())) + { + return TRUE; + } + return FALSE; +} + BOOL LLInvFVBridge::isAgentInventory() const { const LLInventoryModel* model = getInventoryModel(); @@ -705,14 +807,7 @@ BOOL LLInvFVBridge::isAgentInventory() const BOOL LLInvFVBridge::isCOFFolder() const { - const LLInventoryModel* model = getInventoryModel(); - if(!model) return TRUE; - const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); - if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) - { - return TRUE; - } - return FALSE; + return LLAppearanceMgr::instance().getIsInCOF(mUUID); } BOOL LLInvFVBridge::isItemPermissive() const @@ -723,20 +818,20 @@ BOOL LLInvFVBridge::isItemPermissive() const // static void LLInvFVBridge::changeItemParent(LLInventoryModel* model, LLViewerInventoryItem* item, - const LLUUID& new_parent, + const LLUUID& new_parent_id, BOOL restamp) { - if(item->getParentUUID() != new_parent) + 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, 1); + 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); + new_item->setParent(new_parent_id); new_item->updateParentOnServer(restamp); model->updateItem(new_item); model->notifyObservers(); @@ -746,24 +841,27 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model, // static void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, LLViewerInventoryCategory* cat, - const LLUUID& new_parent, + const LLUUID& new_parent_id, BOOL restamp) { - if(cat->getParentUUID() != new_parent) + // Can't move a folder into a child of itself. + if (model->isObjectDescendentOf(new_parent_id, cat->getUUID())) { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); + 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(); } @@ -810,7 +908,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, } new_listener = new LLLandmarkBridge(inventory, uuid, flags); break; - + case LLAssetType::AT_CALLINGCARD: if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) { @@ -876,7 +974,6 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags); break; case LLAssetType::AT_CATEGORY: - case LLAssetType::AT_ROOT_CATEGORY: if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) { // Create a link folder handler instead. @@ -886,9 +983,6 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, new_listener = new LLFolderBridge(inventory, uuid); break; case LLAssetType::AT_LINK: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; case LLAssetType::AT_LINK_FOLDER: // Only should happen for broken links. new_listener = new LLLinkItemBridge(inventory, uuid); @@ -931,6 +1025,16 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) } } +bool LLInvFVBridge::isInOutfitsSidePanel() const +{ + 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); +} + // +=================================================+ // | InventoryFVBridgeBuilder | // +=================================================+ @@ -959,6 +1063,7 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, { gotoItem(folder); } + if ("open" == action) { openItem(); @@ -987,9 +1092,9 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, else if ("copy_uuid" == action) { // Single item only - LLInventoryItem* item = model->getItem(mUUID); + LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem()); if(!item) return; - LLUUID asset_id = item->getAssetUUID(); + LLUUID asset_id = item->getProtectedAssetUUID(); std::string buffer; asset_id.toString(buffer); @@ -1029,7 +1134,7 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, void LLItemBridge::selectItem() { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); + LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem()); if(item && !item->isComplete()) { item->fetchFromServer(); @@ -1038,11 +1143,11 @@ void LLItemBridge::selectItem() void LLItemBridge::restoreItem() { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); + LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem()); if(item) { LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(item->getType()); + const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); // do not restamp on restore. LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); } @@ -1050,7 +1155,10 @@ void LLItemBridge::restoreItem() void LLItemBridge::restoreToWorld() { - LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem(); + //Similar functionality to the drag and drop rez logic + bool remove_from_inventory = false; + + LLViewerInventoryItem* itemp = static_cast<LLViewerInventoryItem*>(getItem()); if (itemp) { LLMessageSystem* msg = gMessageSystem; @@ -1062,23 +1170,20 @@ void LLItemBridge::restoreToWorld() msg->nextBlockFast(_PREHASH_InventoryData); itemp->packMessage(msg); msg->sendReliable(gAgent.getRegion()->getHost()); - } - - //Similar functionality to the drag and drop rez logic - BOOL remove_from_inventory = FALSE; - //remove local inventory copy, sim will deal with permissions and removing the item - //from the actual inventory if its a no-copy etc - if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - remove_from_inventory = TRUE; - } - - // Check if it's in the trash. (again similar to the normal rez logic) - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); - if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) - { - remove_from_inventory = TRUE; + //remove local inventory copy, sim will deal with permissions and removing the item + //from the actual inventory if its a no-copy etc + if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + remove_from_inventory = true; + } + + // Check if it's in the trash. (again similar to the normal rez logic) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) + { + remove_from_inventory = true; + } } if(remove_from_inventory) @@ -1093,7 +1198,7 @@ void LLItemBridge::gotoItem(LLFolderView *folder) LLInventoryObject *obj = getInventoryObject(); if (obj && obj->getIsLinkType()) { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); if (active_panel) { active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); @@ -1110,7 +1215,7 @@ PermissionMask LLItemBridge::getPermissionMask() const { LLViewerInventoryItem* item = getItem(); PermissionMask perm_mask = 0; - if(item) + if(item) { BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); @@ -1136,9 +1241,9 @@ const std::string& LLItemBridge::getDisplayName() const void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) { - if(item) + if(item) { - name.assign(item->getName()); + name.assign(item->getName()); } else { @@ -1147,10 +1252,10 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) } LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const -{ +{ U8 font = LLFontGL::NORMAL; - - if( gAgentWearables.isWearingItem( mUUID ) ) + + if (get_is_item_worn(mUUID)) { // llinfos << "BOLD" << llendl; font |= LLFontGL::BOLD; @@ -1175,7 +1280,7 @@ std::string LLItemBridge::getLabelSuffix() const static std::string BROKEN_LINK = LLTrans::getString("broken_link"); std::string suffix; LLInventoryItem* item = getItem(); - if(item) + if(item) { // it's a bit confusing to put nocopy/nomod/etc on calling cards. if(LLAssetType::AT_CALLINGCARD != item->getType() @@ -1270,7 +1375,7 @@ BOOL LLItemBridge::removeItem() LLPreview::hide(mUUID, TRUE); LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); LLViewerInventoryItem* item = getItem(); // if item is not already in trash @@ -1293,29 +1398,33 @@ BOOL LLItemBridge::isItemCopyable() const LLViewerInventoryItem* item = getItem(); if (item) { - // can't copy worn objects. DEV-15183 - LLVOAvatarSelf *avatarp = gAgent.getAvatarObject(); - if( !avatarp ) + // Can't copy worn objects. DEV-15183 + if(get_is_item_worn(mUUID)) { return FALSE; } - if(avatarp->isWearingAttachment(mUUID)) + // You can never copy a link. + if (item->getIsLinkType()) { return FALSE; } - - // All items can be copied, not all can be pasted. - // The only time an item can't be copied is if it's a link - // return (item->getPermissions().allowCopyBy(gAgent.getID())); - if (item->getIsLinkType()) + + if (gAgent.isGodlike()) { - return FALSE; + // All items can be copied in god mode since you can + // at least paste-as-link the item, though you + // still may not be able paste the item. + return TRUE; + } + else + { + return (item->getPermissions().allowCopyBy(gAgent.getID())); } - return TRUE; } return FALSE; } + BOOL LLItemBridge::copyToClipboard() const { if(isItemCopyable()) @@ -1342,15 +1451,21 @@ BOOL LLItemBridge::isItemPermissive() const LLViewerInventoryItem* item = getItem(); if(item) { - U32 mask = item->getPermissions().getMaskBase(); - if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - return TRUE; - } + return item->getIsFullPerm(); } return FALSE; } +bool LLItemBridge::isAddAction(std::string action) const +{ + return ("wear" == action || "attach" == action || "activate" == action); +} + +bool LLItemBridge::isRemoveAction(std::string action) const +{ + return ("take_off" == action || "detach" == action || "deactivate" == action); +} + // +=================================================+ // | LLFolderBridge | // +=================================================+ @@ -1358,12 +1473,12 @@ BOOL LLItemBridge::isItemPermissive() const LLFolderBridge* LLFolderBridge::sSelf=NULL; // Can be moved to another folder -BOOL LLFolderBridge::isItemMovable() const +BOOL LLFolderBridge::isItemMovable() const { LLInventoryObject* obj = getInventoryObject(); if(obj) { - return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType())); + return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); } return FALSE; } @@ -1373,11 +1488,28 @@ void LLFolderBridge::selectItem() } +// Iterate through a folder's children to determine if +// all the children are removable. +class LLIsItemRemovable : public LLFolderViewFunctor +{ +public: + LLIsItemRemovable() : mPassed(TRUE) {} + virtual void doFolder(LLFolderViewFolder* folder) + { + mPassed &= folder->getListener()->isItemRemovable(); + } + virtual void doItem(LLFolderViewItem* item) + { + mPassed &= item->getListener()->isItemRemovable(); + } + BOOL mPassed; +}; + // Can be destroyed (or moved to trash) -BOOL LLFolderBridge::isItemRemovable() +BOOL LLFolderBridge::isItemRemovable() const { LLInventoryModel* model = getInventoryModel(); - if(!model) + if(!model) { return FALSE; } @@ -1387,58 +1519,30 @@ BOOL LLFolderBridge::isItemRemovable() return FALSE; } - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( !avatar ) - { - return FALSE; - } + if (!isAgentAvatarValid()) return FALSE; LLInventoryCategory* category = model->getCategory(mUUID); - if( !category ) + if(!category) { return FALSE; } - if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) { return FALSE; } - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for( i = 0; i < descendent_categories.count(); i++ ) + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); + if (folderp) { - LLInventoryCategory* category = descendent_categories[i]; - if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) + LLIsItemRemovable folder_test; + folderp->applyFunctorToChildren(folder_test); + if (!folder_test.mPassed) { return FALSE; } } - - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if(gAgentWearables.isWearingItem(item->getUUID())) - { - return FALSE; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if(avatar->isWearingAttachment(item->getUUID())) - { - return FALSE; - } - } - } - return TRUE; } @@ -1457,7 +1561,7 @@ BOOL LLFolderBridge::isUpToDate() const BOOL LLFolderBridge::isItemCopyable() const { - return TRUE; + return FALSE; } BOOL LLFolderBridge::copyToClipboard() const @@ -1488,7 +1592,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const LLInventoryClipboard::instance().retrieve(objects); const LLViewerInventoryCategory *current_cat = getCategory(); - // Search for the direct descendent of current Friends subfolder among all pasted items, + // Search for the direct descendent of current Friends subfolder among all pasted items, // and return false if is found. for(S32 i = objects.count() - 1; i >= 0; --i) { @@ -1510,7 +1614,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const { return FALSE; } - + const LLInventoryModel* model = getInventoryModel(); if (!model) { @@ -1533,7 +1637,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const { const LLUUID &cat_id = cat->getUUID(); // Don't allow recursive pasting - if ((cat_id == current_cat_id) || + if ((cat_id == current_cat_id) || model->isObjectDescendentOf(current_cat_id, cat_id)) { return FALSE; @@ -1559,15 +1663,14 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, BOOL drop) { - // This should never happen, but if an inventory item is incorrectly parented, + // 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; - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; + if (!isAgentAvatarValid()) return FALSE; // cannot drag categories into library if(!isAgentInventory()) @@ -1589,20 +1692,20 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID& cat_id = inv_cat->getUUID(); // Is the destination the trash? - const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_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 = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType())); - LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + 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()==LLAssetType::AT_OUTFIT); + 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; } - if (mUUID == gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE)) + if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) { is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 } @@ -1614,14 +1717,14 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, for( i = 0; i < descendent_categories.count(); i++ ) { LLInventoryCategory* category = descendent_categories[i]; - if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())) + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) { // ...can't move "special folders" like Textures is_movable = FALSE; break; } } - + if( is_movable ) { if( move_is_into_trash ) @@ -1629,30 +1732,17 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, for( i = 0; i < descendent_items.count(); i++ ) { LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) + if (get_is_item_worn(item->getUUID())) { - if( gAgentWearables.isWearingItem( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if( avatar->isWearingAttachment( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } + 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 && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing @@ -1666,20 +1756,39 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { LLInventoryItem* item = descendent_items[i]; if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) + && LLGestureMgr::instance().isGestureActive(item->getUUID())) { - LLGestureManager::instance().deactivateGesture(item->getUUID()); + LLGestureMgr::instance().deactivateGesture(item->getUUID()); } } } // if target is an outfit or current outfit folder we use link - if (move_is_into_current_outfit || move_is_into_outfit) + if (move_is_into_current_outfit || move_is_into_outfit) { + if (inv_cat->getPreferredType() == LLFolderType::FT_NONE) + { + if (move_is_into_current_outfit) + { + // traverse category and add all contents to currently worn. + BOOL append = true; + LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append); + } + else + { + // Recursively create links in target outfit. + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); + LLAppearanceMgr::instance().linkAll(mUUID,items,NULL); + } + } + else + { #if SUPPORT_ENSEMBLES // BAP - should skip if dup. if (move_is_into_current_outfit) { - LLAppearanceManager::wearEnsemble(inv_cat); + LLAppearanceMgr::instance().addEnsembleLink(inv_cat); } else { @@ -1693,10 +1802,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, cb); } #endif + } } else { - + // Reparent the folder and restamp children if it's moving // into trash. LLInvFVBridge::changeCategoryParent( @@ -1728,12 +1838,12 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) { dialog = "MoveInventoryFromObject"; } - LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotificationsUtil::add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); } // Move/copy all inventory items from the Contents folder of an in-world // object to the agent's inventory, inside a given category. -BOOL move_inv_category_world_to_agent(const LLUUID& object_id, +BOOL move_inv_category_world_to_agent(const LLUUID& object_id, const LLUUID& category_id, BOOL drop, void (*callback)(S32, void*), @@ -1760,7 +1870,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, llinfos << "Object contents not found for drop." << llendl; return FALSE; } - + BOOL accept = TRUE; BOOL is_move = FALSE; @@ -1825,50 +1935,6 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, return accept; } -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(); // BAP - safe? - 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 - safe? - // BAP remove AT_NONE support after ensembles are fully working? - return (linked_category && - ((linked_category->getPreferredType() == LLAssetType::AT_NONE) || - (LLAssetType::lookupIsEnsembleCategoryType(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; -} - - - //Used by LLFolderBridge as callback for directory recursion. class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver { @@ -1888,7 +1954,7 @@ public: gInventory.removeObserver(this); delete this; } - + protected: LLUUID mCatID; @@ -1983,7 +2049,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done() //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryWearObserver // -// Observer for "copy and wear" operation to support knowing +// Observer for "copy and wear" operation to support knowing // when the all of the contents have been added to inventory. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryCopyAndWearObserver : public LLInventoryObserver @@ -2005,7 +2071,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) { if((mask & (LLInventoryObserver::ADD)) != 0) { - if (!mFolderAdded) + if (!mFolderAdded) { const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); @@ -2013,7 +2079,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) std::set<LLUUID>::const_iterator id_end = changed_items.end(); for (;id_it != id_end; ++id_it) { - if ((*id_it) == mCatID) + if ((*id_it) == mCatID) { mFolderAdded = TRUE; break; @@ -2021,7 +2087,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) } } - if (mFolderAdded) + if (mFolderAdded) { LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); @@ -2036,10 +2102,10 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) mContentsCount) { gInventory.removeObserver(this); - LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE); + LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, TRUE); delete this; } - } + } } } @@ -2051,7 +2117,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model { if ("open" == action) { - openItem(); + LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(folder->getItemByID(mUUID)); + if (f) + { + f->setOpen(TRUE); + } + return; } else if ("paste" == action) @@ -2081,7 +2152,7 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model if(!model) return; LLViewerInventoryCategory* cat = getCategory(); if(!cat) return; - LLAppearanceManager::wearEnsemble(cat,true); + LLAppearanceMgr::instance().addEnsembleLink(cat,true); return; } #endif @@ -2101,12 +2172,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model if(!model) return; LLViewerInventoryCategory* cat = getCategory(); if(!cat) return; - + remove_inventory_category_from_avatar ( cat ); return; - } + } else if ("purge" == action) - { + { purgeItem(model, mUUID); return; } @@ -2115,6 +2186,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model restoreItem(); return; } +#ifndef LL_RELEASE_FOR_DOWNLOAD + else if ("delete_system_folder" == action) + { + removeSystemFolder(); + } +#endif } void LLFolderBridge::openItem() @@ -2122,6 +2199,7 @@ void LLFolderBridge::openItem() lldebugs << "LLFolderBridge::openItem()" << llendl; LLInventoryModel* model = getInventoryModel(); if(!model) return; + if(mUUID.isNull()) return; bool fetching_inventory = model->fetchDescendentsOf(mUUID); // Only change folder type if we have the folder contents. if (!fetching_inventory) @@ -2143,14 +2221,17 @@ void LLFolderBridge::determineFolderType() { LLInventoryModel* model = getInventoryModel(); LLViewerInventoryCategory* category = model->getCategory(mUUID); - category->determineFolderType(); + if (category) + { + category->determineFolderType(); + } } } BOOL LLFolderBridge::isItemRenameable() const { LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); - if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()) + if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) && (cat->getOwnerID() == gAgent.getID())) { return TRUE; @@ -2165,15 +2246,15 @@ void LLFolderBridge::restoreItem() if(cat) { LLInventoryModel* model = getInventoryModel(); - LLUUID new_parent = model->findCategoryUUIDForType(cat->getType()); + const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); // do not restamp children on restore LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); } } -LLAssetType::EType LLFolderBridge::getPreferredType() const +LLFolderType::EType LLFolderBridge::getPreferredType() const { - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; LLViewerInventoryCategory* cat = getCategory(); if(cat) { @@ -2186,7 +2267,7 @@ LLAssetType::EType LLFolderBridge::getPreferredType() const // Icons for folders are based on the preferred type LLUIImagePtr LLFolderBridge::getIcon() const { - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; LLViewerInventoryCategory* cat = getCategory(); if(cat) { @@ -2195,15 +2276,28 @@ LLUIImagePtr LLFolderBridge::getIcon() const return getIcon(preferred_type); } -LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type) +LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) { // we only have one folder image now + if (preferred_type == LLFolderType::FT_OUTFIT) + { + return LLUI::getUIImage("Inv_LookFolderClosed"); + } return LLUI::getUIImage("Inv_FolderClosed"); /*case LLAssetType::AT_MESH: control = "inv_folder_mesh.tga"; break;*/ } +LLUIImagePtr LLFolderBridge::getOpenIcon() const +{ + if (getPreferredType() == LLFolderType::FT_OUTFIT) + { + return LLUI::getUIImage("Inv_LookFolderOpen"); + } + return LLUI::getUIImage("Inv_FolderOpen"); +} + BOOL LLFolderBridge::renameItem(const std::string& new_name) { if(!isItemRenameable()) @@ -2232,60 +2326,110 @@ BOOL LLFolderBridge::removeItem() { return FALSE; } - // move it to the trash - LLPreview::hide(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; + const LLViewerInventoryCategory *cat = getCategory(); + + LLSD payload; + LLSD args; + args["FOLDERNAME"] = cat->getName(); - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + LLNotification::Params params("ConfirmDeleteProtectedCategory"); + params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); + LLNotifications::instance().forceResponse(params, 0); + return TRUE; +} - // Look for any gestures and deactivate them - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - S32 i; - for (i = 0; i < descendent_items.count(); i++) +BOOL LLFolderBridge::removeSystemFolder() +{ + const LLViewerInventoryCategory *cat = getCategory(); + if (!LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } + return FALSE; } - // go ahead and do the normal remove if no 'last calling - // cards' are being removed. - LLViewerInventoryCategory* cat = getCategory(); - if(cat) + LLSD payload; + LLSD args; + args["FOLDERNAME"] = cat->getName(); + + LLNotification::Params params("ConfirmDeleteProtectedCategory"); + params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2)); { - LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); + LLNotifications::instance().add(params); } - return TRUE; } +bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + // if they choose delete, do it. Otherwise, don't do anything + if(option == 0) + { + // move it to the trash + LLPreview::hide(mUUID); + LLInventoryModel* model = getInventoryModel(); + if(!model) return FALSE; + + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + + // Look for any gestures and deactivate them + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); + + for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin(); + iter != descendent_items.end(); + ++iter) + { + const LLViewerInventoryItem* item = (*iter); + const LLUUID& item_id = item->getUUID(); + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(item_id)) + { + LLGestureMgr::instance().deactivateGesture(item_id); + } + } + + // go ahead and do the normal remove if no 'last calling + // cards' are being removed. + LLViewerInventoryCategory* cat = getCategory(); + if(cat) + { + LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); + } + return TRUE; + } + return FALSE; +} + void LLFolderBridge::pasteFromClipboard() { LLInventoryModel* model = getInventoryModel(); if(model && isClipboardPasteable()) { - LLInventoryItem* item = NULL; + const LLUUID parent_id(mUUID); + LLDynamicArray<LLUUID> objects; LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - const LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) + for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) { - item = model->getItem(objects.get(i)); + const LLUUID& item_id = (*iter); + LLInventoryItem *item = model->getItem(item_id); if (item) { if(LLInventoryClipboard::instance().isCutMode()) { - // move_inventory_item() is not enough, + // move_inventory_item() is not enough, //we have to update inventory locally too - changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE); + LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item); + llassert(viitem); + if (viitem) + { + changeItemParent(model, viitem, parent_id, FALSE); + } } else { @@ -2307,13 +2451,15 @@ void LLFolderBridge::pasteLinkFromClipboard() const LLInventoryModel* model = getInventoryModel(); if(model) { + const LLUUID parent_id(mUUID); + LLDynamicArray<LLUUID> objects; LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) + for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) { - const LLUUID &object_id = objects.get(i); + const LLUUID &object_id = (*iter); #if SUPPORT_ENSEMBLES if (LLInventoryCategory *cat = model->getCategory(object_id)) { @@ -2331,7 +2477,7 @@ void LLFolderBridge::pasteLinkFromClipboard() { link_inventory_item( gAgent.getID(), - item->getUUID(), + item->getLinkedUUID(), parent_id, item->getName(), LLAssetType::AT_LINK, @@ -2349,22 +2495,31 @@ void LLFolderBridge::staticFolderOptionsMenu() void LLFolderBridge::folderOptionsMenu() { - std::vector<std::string> disabled_items; + menuentry_vec_t disabled_items; LLInventoryModel* model = getInventoryModel(); if(!model) return; const LLInventoryCategory* category = model->getCategory(mUUID); - LLAssetType::EType type = category->getPreferredType(); - const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type); + if(!category) 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 = category && (type == LLAssetType::AT_NONE || - LLAssetType::lookupIsEnsembleCategoryType(type)); - + const bool is_ensemble = (type == LLFolderType::FT_NONE || + LLFolderType::lookupIsEnsembleType(type)); + // calling card related functionality for folders. - // Only enable calling-card related options for non-default folders. - if (!is_default_folder) + 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_sidepanel && !is_system_folder) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) @@ -2374,7 +2529,14 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("IM All Contacts In Folder")); } } - + +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (LLFolderType::lookupIsProtectedType(type)) + { + mItems.push_back(std::string("Delete System Folder")); + } +#endif + // wearables related functionality for folders. //is_wearable LLFindWearables is_wearable; @@ -2386,21 +2548,37 @@ 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-default folders. - if (!is_default_folder) + // Only enable add/replace outfit for non-system folders. + if (!is_system_folder) { - mItems.push_back(std::string("Add To Outfit")); + // Adding an outfit onto another (versus replacing) doesn't make sense. + if (type != LLFolderType::FT_OUTFIT) + { + mItems.push_back(std::string("Add To Outfit")); + } mItems.push_back(std::string("Replace Outfit")); } if (is_ensemble) { mItems.push_back(std::string("Wear As Ensemble")); } - mItems.push_back(std::string("Take Off Items")); + mItems.push_back(std::string("Remove From Outfit")); + if (!areAnyContentsWorn(model)) + { + disabled_items.push_back(std::string("Remove From Outfit")); + } + mItems.push_back(std::string("Outfit Separator")); } - hideContextEntries(*mMenu, mItems, disabled_items); + hide_context_entries(*mMenu, mItems, disabled_items); + + // 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) @@ -2415,6 +2593,35 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv return ((item_array.count() > 0) ? TRUE : FALSE ); } +class LLFindWorn : public LLInventoryCollectFunctor +{ +public: + LLFindWorn() {} + virtual ~LLFindWorn() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + if (item && get_is_item_worn(item->getUUID())) + { + return TRUE; + } + return 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) { @@ -2422,14 +2629,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.clear(); lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; -// std::vector<std::string> disabled_items; + +// menuentry_vec_t disabled_items; LLInventoryModel* model = getInventoryModel(); if(!model) return; - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) - mDisabledItems.clear(); //adding code to clear out disabled members from previous if (lost_and_found_id == mUUID) { // This is the lost+found folder. @@ -2441,26 +2647,18 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // This is the trash. mItems.push_back(std::string("Empty Trash")); } - else if(model->isObjectDescendentOf(mUUID, trash_id)) + else if(isItemInTrash()) { // This is a folder in the trash. mItems.clear(); // clear any items that used to exist - mItems.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - mDisabledItems.push_back(std::string("Purge Item")); - } - - mItems.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(mItems, mDisabledItems); } else if(isAgentInventory()) // do not allow creating in library { LLViewerInventoryCategory *cat = getCategory(); - // BAP removed protected check to re-enable standard ops in untyped folders. // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat /*&& - LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) + if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) @@ -2470,51 +2668,61 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mItems.push_back(std::string("New Gesture")); mItems.push_back(std::string("New Clothes")); mItems.push_back(std::string("New Body Parts")); + + // 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")); - - LLViewerInventoryCategory *cat = getCategory(); - if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())) + const LLViewerInventoryCategory *cat = getCategory(); + if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { mDisabledItems.push_back(std::string("Change Type")); } - +#endif getClipboardEntries(false, mItems, mDisabledItems, flags); } else { // Want some but not all of the items from getClipboardEntries for outfits. - if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT) + if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) { mItems.push_back(std::string("Rename")); - mItems.push_back(std::string("Delete")); + + addDeleteContextMenuOptions(mItems, mDisabledItems); + // EXT-4030: disallow deletion of currently worn outfit + const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) + { + mDisabledItems.push_back(std::string("Delete")); + } } } //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 mCallingCards = mWearables = FALSE; - + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (checkFolderForContentsOfType(model, is_callingcard)) { mCallingCards=TRUE; } - + LLFindWearables is_wearable; LLIsType is_object( LLAssetType::AT_OBJECT ); LLIsType is_gesture( LLAssetType::AT_GESTURE ); - + if (checkFolderForContentsOfType(model, is_wearable) || checkFolderForContentsOfType(model, is_object) || checkFolderForContentsOfType(model, is_gesture) ) { mWearables=TRUE; } - + mMenu = &menu; sSelf = this; LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); - LLInventoryFetchDescendentsObserver::folder_ref_t folders; + uuid_vec_t folders; LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); if (category) { @@ -2539,7 +2747,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mItems.push_back(std::string("--no options--")); mDisabledItems.push_back(std::string("--no options--")); } - hideContextEntries(menu, mItems, mDisabledItems); + + // Preemptively disable system folder removal if more than one item selected. + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + mDisabledItems.push_back(std::string("Delete System Folder")); + } + + hide_context_entries(menu, mItems, mDisabledItems); } BOOL LLFolderBridge::hasChildren() const @@ -2620,7 +2835,7 @@ void LLFolderBridge::createNewCategory(void* user_data) if(!model) return; LLUUID id; id = model->createNewCategory(bridge->getUUID(), - LLAssetType::AT_NONE, + LLFolderType::FT_NONE, LLStringUtil::null); model->notifyObservers(); @@ -2705,7 +2920,7 @@ void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) // Separate function so can be called by global menu as well as right-click // menu. // static -void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type) +void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type) { LLWearable* wearable = LLWearableList::instance().createNewWearable(type); LLAssetType::EType asset_type = wearable->getAssetType(); @@ -2723,10 +2938,8 @@ void LLFolderBridge::modifyOutfit(BOOL append) if(!model) return; LLViewerInventoryCategory* cat = getCategory(); if(!cat) return; - - // BAP - was: - // wear_inventory_category_on_avatar( cat, append ); - LLAppearanceManager::wearInventoryCategory( cat, FALSE, append ); + + LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, append ); } // helper stuff @@ -2734,7 +2947,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response { LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(option == 0 && object) { @@ -2749,8 +2962,8 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response } two_uuids_list_t::iterator move_it; - for (move_it = move_inv->mMoveList.begin(); - move_it != move_inv->mMoveList.end(); + for (move_it = move_inv->mMoveList.begin(); + move_it != move_inv->mMoveList.end(); ++move_it) { object->moveInventory(move_it->first, move_it->second); @@ -2769,61 +2982,11 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response return false; } -/* -Next functions intended to reorder items in the inventory folder and save order on server -Is now used for Favorites folder. - -*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel -*/ -void saveItemsOrder(LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - gInventory.updateItem(item); - } - - gInventory.notifyObservers(); -} - -LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) -{ - LLInventoryModel::item_array_t::iterator result = items.end(); - - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - if ((*i)->getUUID() == id) - { - result = i; - break; - } - } - - return result; -} - -void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) -{ - LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); - LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); - - items.erase(findItemByUUID(items, srcItem->getUUID())); - items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); -} - BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop) { LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; + if(!model || !inv_item) return FALSE; // cannot drag into library if(!isAgentInventory()) @@ -2831,50 +2994,39 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, return FALSE; } - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; + if (!isAgentAvatarValid()) return FALSE; LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); BOOL accept = FALSE; LLViewerObject* object = NULL; if(LLToolDragAndDrop::SOURCE_AGENT == source) { - BOOL is_movable = TRUE; switch( inv_item->getActualType() ) { - case LLAssetType::AT_ROOT_CATEGORY: - is_movable = FALSE; - break; - case LLAssetType::AT_CATEGORY: - is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType()); + is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); break; default: break; } - LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT); + 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(is_movable && move_is_into_trash) { - switch(inv_item->getType()) - { - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID()); - break; - - case LLAssetType::AT_OBJECT: - is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); - break; - default: - break; - } + is_movable = inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID()); } if ( is_movable ) @@ -2887,25 +3039,26 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, is_movable = ! LLFriendCardsManager::instance() .isObjDirectDescendentOfCategory (inv_item, getCategory()); } - - LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + 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()) || (mUUID == favorites_id)); + accept = is_movable && ((mUUID != inv_item->getParentUUID()) || folder_allows_reorder); if(accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) + && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) { - LLGestureManager::instance().deactivateGesture(inv_item->getUUID()); + 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 (LLFloaterInventory::getActiveInventory()) + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + if (active_panel) { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); if (active_panel && (panel != active_panel)) { @@ -2914,51 +3067,52 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // if dragging from/into favorites folder only reorder items - if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID)) + if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; if (itemp) { LLUUID srcItemId = inv_item->getUUID(); LLUUID destItemId = itemp->getListener()->getUUID(); - - // update order - updateItemsOrder(items, srcItemId, destItemId); - - saveItemsOrder(items); + gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } 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. + LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (drag_over_item && drag_over_item->getListener()) + { + cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); + } + copy_inventory_item( gAgent.getID(), inv_item->getPermissions().getOwner(), inv_item->getUUID(), mUUID, std::string(), - LLPointer<LLInventoryCallback>(NULL)); + cb); } else if (move_is_into_current_outfit || move_is_into_outfit) { // BAP - should skip if dup. if (move_is_into_current_outfit) { - LLAppearanceManager::wearItem(inv_item); + LLAppearanceMgr::instance().addCOFItemLink(inv_item); } else { LLPointer<LLInventoryCallback> cb = NULL; link_inventory_item( gAgent.getID(), - inv_item->getUUID(), + inv_item->getLinkedUUID(), mUUID, - std::string(), + inv_item->getName(), LLAssetType::AT_LINK, cb); } @@ -2993,7 +3147,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) - + { accept = TRUE; } @@ -3024,7 +3178,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLNotifications::instance().forceResponse(params, 0); } } - + } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) { @@ -3077,17 +3231,74 @@ LLUIImagePtr LLTextureBridge::getIcon() const { return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE); } - + void LLTextureBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); } } +bool LLTextureBridge::canSaveTexture(void) +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return false; + } + + const LLViewerInventoryItem *item = model->getItem(mUUID); + if (item) + { + return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + } + return false; +} + +void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) + { + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + + getClipboardEntries(true, items, disabled_items, flags); + + items.push_back(std::string("Texture Separator")); + items.push_back(std::string("Save As")); + if (!canSaveTexture()) + { + disabled_items.push_back(std::string("Save As")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +// virtual +void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) +{ + if ("save_as" == action) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID); + if (preview_texture) + { + preview_texture->openToSave(); + } + } + else LLItemBridge::performAction(folder, model, action); +} + // +=================================================+ // | LLSoundBridge | // +=================================================+ @@ -3100,7 +3311,7 @@ LLUIImagePtr LLSoundBridge::getIcon() const void LLSoundBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -3136,19 +3347,13 @@ void LLSoundBridge::openSoundPreview(void* which) void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; + lldebugs << "LLSoundBridge::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; - if(isInTrash()) + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { @@ -3161,7 +3366,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Sound Separator")); items.push_back(std::string("Sound Play")); - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } // +=================================================+ @@ -3169,7 +3374,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // +=================================================+ LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : -LLItemBridge(inventory, uuid) +LLItemBridge(inventory, uuid) { mVisited = FALSE; if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) @@ -3185,19 +3390,13 @@ LLUIImagePtr LLLandmarkBridge::getIcon() const void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - std::vector<std::string> items; - std::vector<std::string> disabled_items; + menuentry_vec_t items; + menuentry_vec_t disabled_items; lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isInTrash()) + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { @@ -3218,7 +3417,7 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) disabled_items.push_back(std::string("About Landmark")); } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } // Convenience function for the two functions below. @@ -3258,7 +3457,7 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod LLSideTray::getInstance()->showPanel("panel_places", key); } } - else + else { LLItemBridge::performAction(folder, model, action); } @@ -3266,7 +3465,7 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod static bool open_landmark_callback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); if (option == 0) @@ -3282,7 +3481,7 @@ static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFro void LLLandmarkBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -3296,7 +3495,7 @@ void LLLandmarkBridge::openItem() // open_landmark(item); LLSD payload; payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + LLNotificationsUtil::add("TeleportFromLandmark", LLSD(), payload); } */ } @@ -3348,7 +3547,11 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* { std::string callingcard_name; gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); - gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); + LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } } } else if ("lure" == action) @@ -3390,7 +3593,7 @@ std::string LLCallingCardBridge::getLabelSuffix() const void LLCallingCardBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -3407,18 +3610,12 @@ void LLCallingCardBridge::openItem() void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; + menuentry_vec_t items; + menuentry_vec_t disabled_items; - if(isInTrash()) + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { @@ -3429,9 +3626,13 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLInventoryItem* item = getItem(); BOOL good_card = (item - && (LLUUID::null != item->getCreatorUUID()) - && (item->getCreatorUUID() != gAgent.getID())); - BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); + && (LLUUID::null != item->getCreatorUUID()) + && (item->getCreatorUUID() != gAgent.getID())); + BOOL user_online = FALSE; + if (item) + { + user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); + } items.push_back(std::string("Send Instant Message Separator")); items.push_back(std::string("Send Instant Message")); items.push_back(std::string("Offer Teleport...")); @@ -3447,7 +3648,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) disabled_items.push_back(std::string("Conference Chat")); } } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, @@ -3523,18 +3724,6 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, return rv; } -BOOL LLCallingCardBridge::removeItem() -{ - if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) - { - LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); - return FALSE; - } - else - { - return LLItemBridge::removeItem(); - } -} // +=================================================+ // | LLNotecardBridge | // +=================================================+ @@ -3547,7 +3736,7 @@ LLUIImagePtr LLNotecardBridge::getIcon() const void LLNotecardBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -3574,7 +3763,7 @@ LLUIImagePtr LLGestureBridge::getIcon() const LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const { - if( LLGestureManager::instance().isGestureActive(mUUID) ) + if( LLGestureMgr::instance().isGestureActive(mUUID) ) { return LLFontGL::BOLD; } @@ -3586,9 +3775,11 @@ LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const std::string LLGestureBridge::getLabelSuffix() const { - if( LLGestureManager::instance().isGestureActive(mUUID) ) + if( LLGestureMgr::instance().isGestureActive(mUUID) ) { - return LLItemBridge::getLabelSuffix() + " (active)"; + LLStringUtil::format_map_t args; + args["[GESLABEL]"] = LLItemBridge::getLabelSuffix(); + return LLTrans::getString("ActiveGesture", args); } else { @@ -3599,9 +3790,9 @@ std::string LLGestureBridge::getLabelSuffix() const // virtual void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) { - if ("activate" == action) + if (isAddAction(action)) { - LLGestureManager::instance().activateGesture(mUUID); + LLGestureMgr::instance().activateGesture(mUUID); LLViewerInventoryItem* item = gInventory.getItem(mUUID); if (!item) return; @@ -3611,9 +3802,9 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode gInventory.updateItem(item); gInventory.notifyObservers(); } - else if ("deactivate" == action) + else if (isRemoveAction(action)) { - LLGestureManager::instance().deactivateGesture(mUUID); + LLGestureMgr::instance().deactivateGesture(mUUID); LLViewerInventoryItem* item = gInventory.getItem(mUUID); if (!item) return; @@ -3623,13 +3814,33 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode gInventory.updateItem(item); gInventory.notifyObservers(); } + else if("play" == action) + { + if(!LLGestureMgr::instance().isGestureActive(mUUID)) + { + // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList. + BOOL inform_server = TRUE; + BOOL deactivate_similar = FALSE; + LLGestureMgr::instance().setGestureLoadedCallback(mUUID, boost::bind(&LLGestureBridge::playGesture, mUUID)); + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + llassert(item); + if (item) + { + LLGestureMgr::instance().activateGestureWithAsset(mUUID, item->getAssetUUID(), inform_server, deactivate_similar); + } + } + else + { + playGesture(mUUID); + } + } else LLItemBridge::performAction(folder, model, action); } void LLGestureBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -3646,40 +3857,76 @@ void LLGestureBridge::openItem() BOOL LLGestureBridge::removeItem() { - // Force close the preview window, if it exists - LLGestureManager::instance().deactivateGesture(mUUID); + // Grab class information locally since *this may be deleted + // within this function. Not a great pattern... + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + const LLUUID item_id = mUUID; + + // This will also force close the preview window, if it exists. + // This may actually delete *this, if mUUID is in the COF. + LLGestureMgr::instance().deactivateGesture(item_id); + + // If deactivateGesture deleted *this, then return out immediately. + if (!model->getObject(item_id)) + { + return TRUE; + } + return LLItemBridge::removeItem(); } void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); + bool is_sidepanel = isInOutfitsSidePanel(); + + if (!is_sidepanel) + { + items.push_back(std::string("Open")); + items.push_back(std::string("Properties")); + } getClipboardEntries(true, items, disabled_items, flags); items.push_back(std::string("Gesture Separator")); - items.push_back(std::string("Activate")); - items.push_back(std::string("Deactivate")); + if (LLGestureMgr::instance().isGestureActive(getUUID())) + { + items.push_back(std::string("Deactivate")); + } + else + { + items.push_back(std::string("Activate")); + } + } + hide_context_entries(menu, items, disabled_items); +} + +// static +void LLGestureBridge::playGesture(const LLUUID& item_id) +{ + if (LLGestureMgr::instance().isGesturePlaying(item_id)) + { + LLGestureMgr::instance().stopGesture(item_id); + } + else + { + LLGestureMgr::instance().playGesture(item_id); } - hideContextEntries(menu, items, disabled_items); } + // +=================================================+ // | LLAnimationBridge | // +=================================================+ @@ -3691,19 +3938,13 @@ LLUIImagePtr LLAnimationBridge::getIcon() const void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - std::vector<std::string> items; - std::vector<std::string> disabled_items; + menuentry_vec_t items; + menuentry_vec_t disabled_items; lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isInTrash()) + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { @@ -3717,7 +3958,7 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Animation Play")); items.push_back(std::string("Animation Audition")); - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } @@ -3731,7 +3972,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; if ("playworld" == action) activate = LLPreviewAnim::PLAY; if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; - + LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID)); if (preview) { @@ -3748,7 +3989,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo void LLAnimationBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -3777,14 +4018,6 @@ LLItemBridge(inventory, uuid), mInvType(type) mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; } -BOOL LLObjectBridge::isItemRemovable() -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - if(avatar->isWearingAttachment(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - LLUIImagePtr LLObjectBridge::getIcon() const { return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); @@ -3804,7 +4037,7 @@ LLInventoryObject* LLObjectBridge::getObject() const // virtual void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) { - if ("attach" == action) + if (isAddAction(action)) { LLUUID object_id = mUUID; LLViewerInventoryItem* item; @@ -3827,7 +4060,7 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model } gFocusMgr.setKeyboardFocus(NULL); } - else if ("detach" == action) + else if (isRemoveAction(action)) { LLInventoryItem* item = gInventory.getItem(mUUID); if(item) @@ -3837,17 +4070,13 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - } - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = - gObjectList.findObject(item->getUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - else - { - llwarns << "object not found - ignoring" << llendl; + + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID()); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } } } else LLItemBridge::performAction(folder, model, action); @@ -3856,23 +4085,27 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model void LLObjectBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); } + LLSD key; + key["id"] = mUUID; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + + // Disable old properties floater; this is replaced by the sidepanel. /* LLFloaterReg::showInstance("properties", mUUID); */ } LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const -{ +{ U8 font = LLFontGL::NORMAL; - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) + if(get_is_item_worn( mUUID ) ) { font |= LLFontGL::BOLD; } @@ -3882,18 +4115,20 @@ LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const { font |= LLFontGL::ITALIC; } - + return (LLFontGL::StyleFlags)font; } std::string LLObjectBridge::getLabelSuffix() const { - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) + if (get_is_item_worn(mUUID)) { - std::string attachment_point_name = avatar->getAttachedPointName(mUUID); - LLStringUtil::toLower(attachment_point_name); - return LLItemBridge::getLabelSuffix() + std::string(" (worn on ") + attachment_point_name + std::string(")"); + std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); + + // e.g. "(worn on ...)" / "(attached to ...)" + LLStringUtil::format_map_t args; + args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); + return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); } else { @@ -3907,10 +4142,10 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. S32 attach_pt = 0; - if (gAgent.getAvatarObject() && attachment) + if (isAgentAvatarValid() && attachment) { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin(); - iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter) + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) { if (iter->second == attachment) { @@ -3925,7 +4160,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach #if !ENABLE_MULTIATTACHMENTS if (attachment && attachment->getNumObjects() > 0) { - LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); + LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); } else #endif @@ -3936,21 +4171,19 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response) { - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - - if (!avatarp->canAttachMoreObjects()) + if (!gAgentAvatarp->canAttachMoreObjects()) { LLSD args; args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); - LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); + LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args); return false; } - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0/*YES*/) { LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - + if (itemp) { LLMessageSystem* msg = gMessageSystem; @@ -3978,46 +4211,36 @@ static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("Rep void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { - LLInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) + bool is_sidepanel = isInOutfitsSidePanel(); + + if (!is_sidepanel) { - items.push_back(std::string("Goto Link")); + items.push_back(std::string("Properties")); } - items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); LLObjectBridge::sContextMenuItemID = mUUID; + LLInventoryItem *item = getItem(); if(item) { - LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return; - } - - if( avatarp->isWearingAttachment( mUUID ) ) + if (!isAgentAvatarValid()) return; + + if( get_is_item_worn( mUUID ) ) { + items.push_back(std::string("Attach Separator")); items.push_back(std::string("Detach From Yourself")); } - else - if( !isInTrash() && !isLinkedObjectInTrash() ) + else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder()) { items.push_back(std::string("Attach Separator")); items.push_back(std::string("Object Wear")); @@ -4026,7 +4249,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // commented out for DEV-32347 //items.push_back(std::string("Restore to Last Position")); - if (!avatarp->canAttachMoreObjects()) + if (!gAgentAvatarp->canAttachMoreObjects()) { disabled_items.push_back(std::string("Object Wear")); disabled_items.push_back(std::string("Attach To")); @@ -4034,15 +4257,14 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - if (attach_menu - && (attach_menu->getChildCount() == 0) - && attach_hud_menu - && (attach_hud_menu->getChildCount() == 0) - && avatarp) + if (attach_menu + && (attach_menu->getChildCount() == 0) + && attach_hud_menu + && (attach_hud_menu->getChildCount() == 0) + && isAgentAvatarValid()) { - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ) { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; @@ -4070,7 +4292,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } } } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } BOOL LLObjectBridge::renameItem(const std::string& new_name) @@ -4092,11 +4314,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) model->notifyObservers(); - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar ) + if (isAgentAvatarValid()) { - LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); - if( obj ) + LLViewerObject* obj = gAgentAvatarp->getWornAttachment( item->getUUID() ); + if(obj) { LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); @@ -4122,7 +4343,7 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const void LLLSLTextBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); @@ -4148,7 +4369,7 @@ void wear_inventory_item_on_avatar( LLInventoryItem* item ) lldebugs << "wear_inventory_item_on_avatar( " << item->getName() << " )" << llendl; - LLAppearanceManager::wearItem(item); + LLAppearanceMgr::instance().addCOFItemLink(item); } } @@ -4158,7 +4379,7 @@ void wear_add_inventory_item_on_avatar( LLInventoryItem* item ) { lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName() << " )" << llendl; - + LLWearableList::instance().getAsset(item->getAssetUUID(), item->getName(), item->getType(), @@ -4172,8 +4393,8 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category ) if(!category) return; lldebugs << "remove_inventory_category_from_avatar( " << category->getName() << " )" << llendl; - - + + if( gFloaterCustomize ) { gFloaterCustomize->askToSaveIfDirty( @@ -4237,39 +4458,43 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ { for(i = 0; i < wearable_count; ++i) { - if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) ) + LLViewerInventoryItem *item = item_array.get(i); + if (item->getType() == LLAssetType::AT_BODYPART) + continue; + if (gAgent.isTeen() && item->isWearableType() && + (item->getWearableType() == WT_UNDERPANTS || item->getWearableType() == WT_UNDERSHIRT)) + continue; + if (get_is_item_worn(item->getUUID())) { - LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(), - item_array.get(i)->getName(), - item_array.get(i)->getType(), + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item_array.get(i)->getUUID())); - + new OnRemoveStruct(item->getLinkedUUID())); } } } - - + if (obj_count > 0) { for(i = 0; i < obj_count; ++i) { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() ); - - gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); - if (found_obj) + LLViewerInventoryItem *obj_item = obj_item_array.get(i); + if (get_is_item_worn(obj_item->getUUID())) { - LLSelectMgr::getInstance()->remove(found_obj); - } - else - { - llwarns << "object not found, ignoring" << llendl; + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() ); + + gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); + + // this object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID()); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } } } } @@ -4278,10 +4503,11 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ { for(i = 0; i < gest_count; ++i) { - if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) ) + LLViewerInventoryItem *gest_item = gest_item_array.get(i); + if (get_is_item_worn(gest_item->getUUID())) { - LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() ); - gInventory.updateItem( gest_item_array.get(i) ); + LLGestureMgr::instance().deactivateGesture( gest_item->getLinkedUUID() ); + gInventory.updateItem( gest_item ); gInventory.notifyObservers(); } @@ -4292,24 +4518,19 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ BOOL LLWearableBridge::renameItem(const std::string& new_name) { - if( gAgentWearables.isWearingItem( mUUID ) ) + if (get_is_item_worn(mUUID)) { gAgentWearables.setWearableName( mUUID, new_name ); } return LLItemBridge::renameItem(new_name); } -BOOL LLWearableBridge::isItemRemovable() -{ - if (gAgentWearables.isWearingItem(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - std::string LLWearableBridge::getLabelSuffix() const { - if( gAgentWearables.isWearingItem( mUUID ) ) + if (get_is_item_worn(mUUID)) { - return LLItemBridge::getLabelSuffix() + " (worn)"; + // e.g. "(worn)" + return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); } else { @@ -4325,7 +4546,7 @@ LLUIImagePtr LLWearableBridge::getIcon() const // virtual void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) { - if ("wear" == action) + if (isAddAction(action)) { wearOnAvatar(); } @@ -4338,20 +4559,10 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod editOnAvatar(); return; } - else if ("take_off" == action) + else if (isRemoveAction(action)) { - if(gAgentWearables.isWearingItem(mUUID)) - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(mUUID)); - } - } + removeFromAvatar(); + return; } else LLItemBridge::performAction(folder, model, action); } @@ -4359,19 +4570,19 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod void LLWearableBridge::openItem() { LLViewerInventoryItem* item = getItem(); - + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); } /* - if( isInTrash() ) + if( isItemInTrash() ) { - LLNotifications::instance().add("CannotWearTrash"); + LLNotificationsUtil::add("CannotWearTrash"); } else if(isAgentInventory()) { - if( !gAgentWearables.isWearingItem( mUUID ) ) + if( !get_is_item_worn( mUUID ) ) { wearOnAvatar(); } @@ -4396,7 +4607,7 @@ void LLWearableBridge::openItem() { // *TODO: We should fetch the item details, and then do // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); + LLNotificationsUtil::add("CannotWearInfoNotComplete"); } } */ @@ -4405,47 +4616,47 @@ void LLWearableBridge::openItem() void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) + menuentry_vec_t items; + menuentry_vec_t disabled_items; + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere - BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM); + BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM); // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 LLViewerInventoryItem* item = getItem(); - if( !no_open && item ) + if (can_open && item) { - no_open = (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART); + can_open = (item->getType() != LLAssetType::AT_CLOTHING) && + (item->getType() != LLAssetType::AT_BODYPART); } - if (!no_open) + if (isLinkedObjectMissing()) { - items.push_back(std::string("Open")); + can_open = FALSE; } - if (item && item->getIsLinkType()) + bool is_sidepanel = isInOutfitsSidePanel(); + + if (can_open && !is_sidepanel) { - items.push_back(std::string("Goto Link")); + items.push_back(std::string("Open")); } - items.push_back(std::string("Properties")); + if (!is_sidepanel) + { + items.push_back(std::string("Properties")); + } getClipboardEntries(true, items, disabled_items, flags); - items.push_back(std::string("Wearable Separator")); - - items.push_back(std::string("Wearable Wear")); - items.push_back(std::string("Wearable Add")); + if (!is_sidepanel) + { + items.push_back(std::string("Wearable Separator")); + } + items.push_back(std::string("Wearable Edit")); if ((flags & FIRST_SELECTED_ITEM) == 0) @@ -4453,7 +4664,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) disabled_items.push_back(std::string("Wearable Edit")); } // Don't allow items to be worn if their baseobj is in the trash. - if (isLinkedObjectInTrash()) + if (isLinkedObjectInTrash() || isLinkedObjectMissing() || isCOFFolder()) { disabled_items.push_back(std::string("Wearable Wear")); disabled_items.push_back(std::string("Wearable Add")); @@ -4467,14 +4678,17 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { case LLAssetType::AT_CLOTHING: items.push_back(std::string("Take Off")); + // Fallthrough since clothing and bodypart share wear options case LLAssetType::AT_BODYPART: - if (gAgentWearables.isWearingItem(item->getUUID())) + if (get_is_item_worn(item->getUUID())) { disabled_items.push_back(std::string("Wearable Wear")); disabled_items.push_back(std::string("Wearable Add")); } else - { + { + items.push_back(std::string("Wearable Wear")); + items.push_back(std::string("Wearable Add")); disabled_items.push_back(std::string("Take Off")); } break; @@ -4483,7 +4697,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } } } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } // Called from menus @@ -4497,7 +4711,7 @@ BOOL LLWearableBridge::canWearOnAvatar(void* user_data) LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); if(!item || !item->isComplete()) return FALSE; } - return (!gAgentWearables.isWearingItem(self->mUUID)); + return (!get_is_item_worn(self->mUUID)); } // Called from menus @@ -4513,9 +4727,9 @@ void LLWearableBridge::wearOnAvatar() { // Don't wear anything until initial wearables are loaded, can // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) + if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return; } @@ -4544,9 +4758,9 @@ void LLWearableBridge::wearAddOnAvatar() { // Don't wear anything until initial wearables are loaded, can // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) + if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return; } @@ -4629,10 +4843,10 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data) LLWearableBridge* self = (LLWearableBridge*)user_data; if(!self) return FALSE; - return (gAgentWearables.isWearingItem(self->mUUID)); + return (get_is_item_worn(self->mUUID)); } -// static +// static void LLWearableBridge::onEditOnAvatar(void* user_data) { LLWearableBridge* self = (LLWearableBridge*)user_data; @@ -4644,17 +4858,18 @@ void LLWearableBridge::onEditOnAvatar(void* user_data) void LLWearableBridge::editOnAvatar() { - const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); + LLUUID linked_id = gInventory.getLinkedItemID(mUUID); + const LLWearable* wearable = gAgentWearables.getWearableFromItemID(linked_id); if( wearable ) { // Set the tab to the right wearable. if (gFloaterCustomize) gFloaterCustomize->setCurrentWearableType( wearable->getType() ); - if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() ) + if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() ) { // Start Avatar Customization - gAgent.changeCameraToCustomizeAvatar(); + gAgentCamera.changeCameraToCustomizeAvatar(); } } } @@ -4665,17 +4880,17 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) LLWearableBridge* self = (LLWearableBridge*)user_data; if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) { - return gAgentWearables.isWearingItem( self->mUUID ); + return get_is_item_worn( self->mUUID ); } return FALSE; } -// static +// static void LLWearableBridge::onRemoveFromAvatar(void* user_data) { LLWearableBridge* self = (LLWearableBridge*)user_data; if(!self) return; - if(gAgentWearables.isWearingItem(self->mUUID)) + if(get_is_item_worn(self->mUUID)) { LLViewerInventoryItem* item = self->getItem(); if (item) @@ -4698,34 +4913,75 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); if(wearable) { - if( gAgentWearables.isWearingItem( item_id ) ) + if( get_is_item_worn( item_id ) ) { EWearableType type = wearable->getType(); - + if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&& //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) { - // MULTI_WEARABLE: FIXME HACK - always remove all bool do_remove_all = false; - gAgentWearables.removeWearable( type, do_remove_all, 0 ); + U32 index = gAgentWearables.getWearableIndex(wearable); + gAgentWearables.removeWearable( type, do_remove_all, index ); } } } // Find and remove this item from the COF. - LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF()); - llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. - for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); - iter != items.end(); - ++iter) + LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); + gInventory.notifyObservers(); + + delete on_remove_struct; +} + +/* static */ +void LLWearableBridge::removeAllClothesFromAvatar() +{ + // Remove COF links. + for (S32 itype = WT_SHAPE; itype < WT_COUNT; ++itype) { - const LLViewerInventoryItem *linked_item = (*iter); - const LLUUID &item_id = linked_item->getUUID(); - gInventory.purgeObject(item_id); + if (itype == WT_SHAPE || itype == WT_SKIN || itype == WT_HAIR || itype == WT_EYES) + continue; + + // MULTI-WEARABLES: fixed to index 0 + LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>( + gAgentWearables.getWearableInventoryItem((EWearableType)itype, 0)); + if (!item) + continue; + const LLUUID &item_id = gInventory.getLinkedItemID(item->getUUID()); + const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id); + if (!wearable) + continue; + + // Find and remove this item from the COF. + LLAppearanceMgr::instance().removeCOFItemLinks(item_id,false); } gInventory.notifyObservers(); - delete on_remove_struct; + // Remove wearables from gAgentWearables + LLAgentWearables::userRemoveAllClothes(); +} + +/* static */ +void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item) +{ + if (item) + { + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item->getUUID())); + } +} + +void LLWearableBridge::removeFromAvatar() +{ + if (get_is_item_worn(mUUID)) + { + LLViewerInventoryItem* item = getItem(); + removeItemFromAvatar(item); + } } @@ -4764,7 +5020,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) std::vector<std::string> items; std::vector<std::string> disabled_items; - if(isInTrash()) + if(isItemInTrash()) { items.push_back(std::string("Purge Item")); if (!isItemRemovable()) @@ -4782,7 +5038,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } @@ -4804,7 +5060,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_ case LLAssetType::AT_LANDMARK: action = new LLLandmarkBridgeAction(uuid,model); break; - + case LLAssetType::AT_CALLINGCARD: action = new LLCallingCardBridgeAction(uuid,model); break; @@ -4847,7 +5103,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_ return action; } -//static +//static void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, const LLUUID& uuid,LLInventoryModel* model) { @@ -4859,15 +5115,21 @@ void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, } } -//static +//static void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) { - LLAssetType::EType asset_type = model->getItem(uuid)->getType(); - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) + llassert(model); + LLViewerInventoryItem* item = model->getItem(uuid); + llassert(item); + if (item) { - action->doIt(); - delete action; + LLAssetType::EType asset_type = item->getType(); + LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + if(action) + { + action->doIt(); + delete action; + } } } @@ -4878,8 +5140,8 @@ LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const return NULL; } -//virtual -void LLTextureBridgeAction::doIt() +//virtual +void LLTextureBridgeAction::doIt() { if (getItem()) { @@ -4890,20 +5152,20 @@ void LLTextureBridgeAction::doIt() } //virtual -void LLSoundBridgeAction::doIt() +void LLSoundBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if(item) { LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); } - + LLInvFVBridgeAction::doIt(); } -//virtual -void LLLandmarkBridgeAction::doIt() +//virtual +void LLLandmarkBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if( item ) @@ -4911,16 +5173,20 @@ void LLLandmarkBridgeAction::doIt() // Opening (double-clicking) a landmark immediately teleports, // but warns you the first time. LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + payload["asset_id"] = item->getAssetUUID(); + + LLSD args; + args["LOCATION"] = item->getName(); + + LLNotificationsUtil::add("TeleportFromLandmark", args, payload); } LLInvFVBridgeAction::doIt(); } -//virtual -void LLCallingCardBridgeAction::doIt() +//virtual +void LLCallingCardBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if(item && item->getCreatorUUID().notNull()) @@ -4931,9 +5197,9 @@ void LLCallingCardBridgeAction::doIt() LLInvFVBridgeAction::doIt(); } -//virtual -void -LLNotecardBridgeAction::doIt() +//virtual +void +LLNotecardBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if (item) @@ -4944,8 +5210,8 @@ LLNotecardBridgeAction::doIt() LLInvFVBridgeAction::doIt(); } -//virtual -void LLGestureBridgeAction::doIt() +//virtual +void LLGestureBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if (item) @@ -4957,8 +5223,8 @@ void LLGestureBridgeAction::doIt() LLInvFVBridgeAction::doIt(); } -//virtual -void LLAnimationBridgeAction::doIt() +//virtual +void LLAnimationBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if (item) @@ -4970,17 +5236,18 @@ void LLAnimationBridgeAction::doIt() } -//virtual +//virtual void LLObjectBridgeAction::doIt() { + /* LLFloaterReg::showInstance("properties", mUUID); - + */ LLInvFVBridgeAction::doIt(); } -//virtual -void LLLSLTextBridgeAction::doIt() +//virtual +void LLLSLTextBridgeAction::doIt() { LLViewerInventoryItem* item = getItem(); if (item) @@ -4992,10 +5259,10 @@ void LLLSLTextBridgeAction::doIt() } -BOOL LLWearableBridgeAction::isInTrash() const +BOOL LLWearableBridgeAction::isItemInTrash() const { if(!mModel) return FALSE; - LLUUID trash_id = mModel->findCategoryUUIDForType(LLAssetType::AT_TRASH); + const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH); return mModel->isObjectDescendentOf(mUUID, trash_id); } @@ -5010,9 +5277,9 @@ void LLWearableBridgeAction::wearOnAvatar() { // Don't wear anything until initial wearables are loaded, can // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) + if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return; } @@ -5037,16 +5304,16 @@ void LLWearableBridgeAction::wearOnAvatar() } } -//virtual +//virtual void LLWearableBridgeAction::doIt() { - if(isInTrash()) + if(isItemInTrash()) { - LLNotifications::instance().add("CannotWearTrash"); + LLNotificationsUtil::add("CannotWearTrash"); } else if(isAgentInventory()) { - if(!gAgentWearables.isWearingItem(mUUID)) + if(!get_is_item_worn(mUUID)) { wearOnAvatar(); } @@ -5071,7 +5338,7 @@ void LLWearableBridgeAction::doIt() { // *TODO: We should fetch the item details, and then do // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); + LLNotificationsUtil::add("CannotWearInfoNotComplete"); } } @@ -5102,7 +5369,10 @@ LLUIImagePtr LLLinkItemBridge::getIcon() const { if (LLViewerInventoryItem *item = getItem()) { - return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE); + U32 attachment_point = (item->getFlags() & 0xff); // low byte of inventory flags + bool is_multi = LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS & item->getFlags(); + + return get_item_icon(item->getActualType(), item->getInventoryType(), attachment_point, is_multi); } return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); } @@ -5111,28 +5381,22 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { // *TODO: Translate lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; + menuentry_vec_t items; + menuentry_vec_t disabled_items; - if(isInTrash()) + items.push_back(std::string("Find Original")); + disabled_items.push_back(std::string("Find Original")); + + if(isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else - { - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } + { + items.push_back(std::string("Properties")); + addDeleteContextMenuOptions(items, disabled_items); } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } @@ -5146,7 +5410,7 @@ std::string LLLinkFolderBridge::sPrefix("Link: "); LLUIImagePtr LLLinkFolderBridge::getIcon() const { - LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLFolderType::EType preferred_type = LLFolderType::FT_NONE; if (LLViewerInventoryItem *item = getItem()) { if (const LLViewerInventoryCategory* cat = item->getLinkedCategory()) @@ -5161,29 +5425,19 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { // *TODO: Translate lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; + menuentry_vec_t items; + menuentry_vec_t disabled_items; - if(isInTrash()) + if (isItemInTrash()) { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); + addTrashContextMenuOptions(items, disabled_items); } else - { - items.push_back(std::string("Goto Link")); - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } + { + items.push_back(std::string("Find Original")); + addDeleteContextMenuOptions(items, disabled_items); } - hideContextEntries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); } void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) |