summaryrefslogtreecommitdiff
path: root/indra/newview/llinventorygallerymenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llinventorygallerymenu.cpp')
-rw-r--r--indra/newview/llinventorygallerymenu.cpp294
1 files changed, 291 insertions, 3 deletions
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index 5f4b816b99..50a544db88 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -32,9 +32,11 @@
#include "llappearancemgr.h"
#include "llavataractions.h"
#include "llclipboard.h"
+#include "llenvironment.h"
#include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
+#include "llfriendcard.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@@ -48,6 +50,41 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
+
+void modify_outfit(bool append, const LLUUID& cat_id, LLInventoryModel* model)
+{
+ LLViewerInventoryCategory* cat = model->getCategory(cat_id);
+ if (!cat) return;
+
+ // checking amount of items to wear
+ static LLCachedControl<U32> max_items(gSavedSettings, "WearFolderLimit", 125);
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
+ model->collectDescendentsIf(cat_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ not_worn);
+
+ if (items.size() > max_items())
+ {
+ LLSD args;
+ args["AMOUNT"] = llformat("%u", max_items());
+ LLNotificationsUtil::add("TooManyWearables", args);
+ return;
+ }
+ if (model->isObjectDescendentOf(cat_id, gInventory.getRootFolderID()))
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(cat, false, append);
+ }
+ else
+ {
+ // Library, we need to copy content first
+ LLAppearanceMgr::instance().wearInventoryCategory(cat, true, append);
+ }
+}
+
LLContextMenu* LLInventoryGalleryContextMenu::createMenu()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -57,11 +94,33 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu()
registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2));
registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ registrar.add("Inventory.DoCreate", [this](LLUICtrl*, const LLSD& data)
+ {
+ if (mRootFolder)
+ {
+ mGallery->doCreate(mGallery->getRootFolder(), data);
+ }
+ else
+ {
+ mGallery->doCreate(mUUIDs.front(), data);
+ }
+ });
std::set<LLUUID> uuids(mUUIDs.begin(), mUUIDs.end());
registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery)));
enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2));
+ enable_registrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl*, const LLSD&)
+ {
+ return LLEnvironment::instance().isInventoryEnabled();
+ });
+ enable_registrar.add("Inventory.MaterialsEnabled", [](LLUICtrl*, const LLSD&)
+ {
+ std::string agent_url = gAgent.getRegionCapability("UpdateMaterialAgentInventory");
+ std::string task_url = gAgent.getRegionCapability("UpdateMaterialTaskInventory");
+
+ return (!agent_url.empty() && !task_url.empty());
+ });
LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml");
@@ -138,7 +197,11 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
}
else if ("thumbnail" == action)
{
- LLSD data(mUUIDs.front());
+ LLSD data;
+ for (const LLUUID& id : mUUIDs)
+ {
+ data.append(id);
+ }
LLFloaterReg::showInstance("change_item_thumbnail", data);
}
else if ("cut" == action)
@@ -186,6 +249,22 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
{
ungroup_folder_items(mUUIDs.front());
}
+ else if ("replaceoutfit" == action)
+ {
+ modify_outfit(false, mUUIDs.front(), &gInventory);
+ }
+ else if ("addtooutfit" == action)
+ {
+ modify_outfit(true, mUUIDs.front(), &gInventory);
+ }
+ else if ("removefromoutfit" == action)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(mUUIDs.front());
+ if (cat)
+ {
+ LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID());
+ }
+ }
else if ("take_off" == action || "detach" == action)
{
for (LLUUID& selected_id : mUUIDs)
@@ -295,6 +374,54 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
preview_texture->saveAs();
}
}
+ else if (("copy_to_marketplace_listings" == action)
+ || ("move_to_marketplace_listings" == action))
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(mUUIDs.front());
+ bool copy_operation = "copy_to_marketplace_listings" == action;
+ bool can_copy = itemp ? itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) : false;
+
+
+ if (can_copy)
+ {
+ const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ if (itemp)
+ {
+ move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation);
+ }
+ }
+ else
+ {
+ uuid_vec_t lamdba_list = mUUIDs;
+ LLNotificationsUtil::add(
+ "ConfirmCopyToMarketplace",
+ LLSD(),
+ LLSD(),
+ [lamdba_list](const LLSD& notification, const LLSD& response)
+ {
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ // option == 0 Move no copy item(s)
+ // option == 1 Don't move no copy item(s) (leave them behind)
+ bool copy_and_move = option == 0;
+ const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+
+ // main inventory only allows one item?
+ LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front());
+ if (itemp)
+ {
+ if (itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+ {
+ move_item_to_marketplacelistings(itemp, marketplacelistings_id, true);
+ }
+ else if (copy_and_move)
+ {
+ move_item_to_marketplacelistings(itemp, marketplacelistings_id, false);
+ }
+ }
+ }
+ );
+ }
+ }
}
void LLInventoryGalleryContextMenu::rename(const LLUUID& item_id)
@@ -388,6 +515,56 @@ bool is_inbox_folder(LLUUID item_id)
return gInventory.isObjectDescendentOf(item_id, inbox_id);
}
+bool can_list_on_marketplace(const LLUUID &id)
+{
+ const LLInventoryObject* obj = gInventory.getObject(id);
+ bool can_list = (obj != NULL);
+
+ if (can_list)
+ {
+ const LLUUID& object_id = obj->getLinkedUUID();
+ can_list = object_id.notNull();
+
+ if (can_list)
+ {
+ std::string error_msg;
+ const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ if (marketplacelistings_id.notNull())
+ {
+ LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id);
+ LLInventoryCategory* cat = gInventory.getCategory(id);
+ if (cat)
+ {
+ can_list = can_move_folder_to_marketplace(master_folder, master_folder, cat, error_msg);
+ }
+ else
+ {
+ LLInventoryItem* item = gInventory.getItem(id);
+ can_list = (item ? can_move_item_to_marketplace(master_folder, master_folder, item, error_msg) : false);
+ }
+ }
+ else
+ {
+ can_list = false;
+ }
+ }
+ }
+
+ return can_list;
+}
+
+bool check_folder_for_contents_of_type(const LLUUID &id, LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ model->collectDescendentsIf(id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_type);
+ return item_array.size() > 0;
+}
+
void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* menu)
{
LLUUID selected_id = mUUIDs.front();
@@ -409,6 +586,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
+ bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
//bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
bool is_system_folder = false;
@@ -456,6 +634,49 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
items.push_back(std::string("open_in_new_window"));
items.push_back(std::string("Open Folder Separator"));
}
+
+ // wearables related functionality for folders.
+ LLFindWearables is_wearable;
+ LLIsType is_object(LLAssetType::AT_OBJECT);
+ LLIsType is_gesture(LLAssetType::AT_GESTURE);
+
+ if (check_folder_for_contents_of_type(selected_id, &gInventory, is_wearable)
+ || check_folder_for_contents_of_type(selected_id, &gInventory, is_object)
+ || check_folder_for_contents_of_type(selected_id, &gInventory, is_gesture))
+ {
+ // Only enable add/replace outfit for non-system folders.
+ if (!is_system_folder)
+ {
+ // Adding an outfit onto another (versus replacing) doesn't make sense.
+ if (folder_type != LLFolderType::FT_OUTFIT)
+ {
+ items.push_back(std::string("Add To Outfit"));
+ if (!LLAppearanceMgr::instance().getCanAddToCOF(selected_id))
+ {
+ disabled_items.push_back(std::string("Add To Outfit"));
+ }
+ }
+
+ items.push_back(std::string("Replace Outfit"));
+ if (!LLAppearanceMgr::instance().getCanReplaceCOF(selected_id))
+ {
+ disabled_items.push_back(std::string("Replace Outfit"));
+ }
+ }
+ if (is_agent_inventory)
+ {
+ items.push_back(std::string("Folder Wearables Separator"));
+ // Note: If user tries to unwear "My Inventory", it's going to deactivate everything including gestures
+ // Might be safer to disable this for "My Inventory"
+ items.push_back(std::string("Remove From Outfit"));
+ if (folder_type != LLFolderType::FT_ROOT_INVENTORY // Unless COF is empty, whih shouldn't be, warrantied to have worn items
+ && !LLAppearanceMgr::getCanRemoveFromCOF(selected_id)) // expensive from root!
+ {
+ disabled_items.push_back(std::string("Remove From Outfit"));
+ }
+ }
+ items.push_back(std::string("Outfit Separator"));
+ }
}
else
{
@@ -503,11 +724,30 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
else
{
+ if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits)
+ {
+ LLViewerInventoryCategory* category = gInventory.getCategory(selected_id);
+ if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category))
+ {
+ items.push_back(std::string("New Folder"));
+ }
+
+ items.push_back(std::string("create_new"));
+ items.push_back(std::string("New Script"));
+ items.push_back(std::string("New Note"));
+ items.push_back(std::string("New Gesture"));
+ items.push_back(std::string("New Material"));
+ items.push_back(std::string("New Clothes"));
+ items.push_back(std::string("New Body Parts"));
+ items.push_back(std::string("New Settings"));
+ }
+
if(can_share_item(selected_id))
{
items.push_back(std::string("Share"));
}
- if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id))
+
+ if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox)
{
items.push_back(std::string("Paste"));
@@ -519,7 +759,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
if (is_folder && is_agent_inventory)
{
- if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id))
+ if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox)
{
if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD)) && !isRootFolder())
{
@@ -706,6 +946,54 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("upload_def"));
+ disabled_items.push_back(std::string("create_new"));
+ }
+
+ if (is_agent_inventory && !mRootFolder)
+ {
+ items.push_back(std::string("New folder from selected"));
+ items.push_back(std::string("Subfolder Separator"));
+ if (!is_only_items_selected(mUUIDs) && !is_only_cats_selected(mUUIDs))
+ {
+ disabled_items.push_back(std::string("New folder from selected"));
+ }
+ }
+
+ // Marketplace
+ bool can_list = false;
+ const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType())
+ {
+ if (is_folder)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id);
+ if (cat
+ && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
+ && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID()))
+ {
+ can_list = true;
+ }
+ }
+ else if (selected_item
+ && selected_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())
+ && selected_item->getPermissions().getOwner() != ALEXANDRIA_LINDEN_ID
+ && LLAssetType::AT_CALLINGCARD != selected_item->getType())
+ {
+ can_list = true;
+ }
+ }
+
+ if (can_list)
+ {
+ items.push_back(std::string("Marketplace Separator"));
+ items.push_back(std::string("Marketplace Copy"));
+ items.push_back(std::string("Marketplace Move"));
+
+ if (!can_list_on_marketplace(selected_id))
+ {
+ disabled_items.push_back(std::string("Marketplace Copy"));
+ disabled_items.push_back(std::string("Marketplace Move"));
+ }
}
}