diff options
| author | Rye <rye@alchemyviewer.org> | 2025-08-20 18:04:55 -0400 |
|---|---|---|
| committer | Rye <rye@alchemyviewer.org> | 2025-08-20 18:04:55 -0400 |
| commit | ba30737d8f4add8ddd8c77d18df6497b46583fe9 (patch) | |
| tree | 81e5412a364ff80b5250fe6db9e653d35621c20e /indra/newview/llinventorybridge.cpp | |
| parent | f0db568bf8d313a00e10c1c4ee4dd7f716a9d987 (diff) | |
| parent | d5f748c91c650a2ec534c497b9e098ccb317d70b (diff) | |
Merge branch 'develop' of github.com:secondlife/viewer into rye/infinitemac
Diffstat (limited to 'indra/newview/llinventorybridge.cpp')
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 220 |
1 files changed, 182 insertions, 38 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5bd17d4d5b..331754d009 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -829,6 +829,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { const LLInventoryObject *obj = getInventoryObject(); bool single_folder_root = (mRoot == NULL); + bool is_cof = isCOFFolder(); + bool is_inbox = isInboxFolder(); if (obj) { @@ -843,7 +845,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } - if (isAgentInventory() && !single_folder_root && !isMarketplaceListingsFolder()) + bool is_agent_inventory = isAgentInventory(); + if (is_agent_inventory && !single_folder_root && !is_cof && !is_inbox) { items.push_back(std::string("New folder from selected")); items.push_back(std::string("Subfolder Separator")); @@ -856,6 +859,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } + if (isFavorite()) + { + items.push_back(std::string("Remove from Favorites")); + } + else if (is_agent_inventory && !gInventory.isObjectDescendentOf(mUUID, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH))) + { + items.push_back(std::string("Add to Favorites")); + if (gInventory.getRootFolderID() == mUUID) + { + disabled_items.push_back(std::string("Add to Favorites")); + } + } + if (obj->getIsLinkType()) { items.push_back(std::string("Find Original")); @@ -868,6 +884,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if (!isItemMovable() || !canMenuCut()) { disabled_items.push_back(std::string("Cut")); + disabled_items.push_back(std::string("New folder from selected")); } } else @@ -877,7 +894,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, items.push_back(std::string("Find Links")); } - if (!isInboxFolder() && !single_folder_root) + if (!is_inbox && !single_folder_root) { items.push_back(std::string("Rename")); if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) @@ -917,6 +934,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if (!isItemMovable() || !canMenuCut()) { disabled_items.push_back(std::string("Cut")); + disabled_items.push_back(std::string("New folder from selected")); } if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder()) @@ -939,7 +957,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } // Don't allow items to be pasted directly into the COF or the inbox - if (!isCOFFolder() && !isInboxFolder()) + if (!is_cof && !is_inbox) { items.push_back(std::string("Paste")); } @@ -1333,6 +1351,13 @@ bool LLInvFVBridge::isAgentInventory() const return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); } +bool LLInvFVBridge::isAgentInventoryRoot() const +{ + const LLInventoryModel* model = getInventoryModel(); + if(!model) return false; + return gInventory.getRootFolderID() == mUUID; +} + bool LLInvFVBridge::isCOFFolder() const { return LLAppearanceMgr::instance().getIsInCOF(mUUID); @@ -2280,7 +2305,21 @@ const LLUUID& LLItemBridge::getThumbnailUUID() const return LLUUID::null; } -// virtual +bool LLItemBridge::isFavorite() const +{ + LLViewerInventoryItem* item = NULL; + LLInventoryModel* model = getInventoryModel(); + if (model) + { + item = model->getItem(mUUID); + } + if (item) + { + return get_is_favorite(item); + } + return false; +} + bool LLItemBridge::isItemPermissive() const { if (LLViewerInventoryItem* item = getItem()) @@ -2425,6 +2464,16 @@ const LLUUID& LLFolderBridge::getThumbnailUUID() const return LLUUID::null; } +bool LLFolderBridge::isFavorite() const +{ + LLViewerInventoryCategory* cat = getCategory(); + if (cat) + { + return cat->getIsFavorite(); + } + return false; +} + void LLFolderBridge::update() { // we know we have children but haven't fetched them (doesn't obey filter) @@ -2664,6 +2713,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // bool is_movable = true; + bool create_outfit = false; if (is_movable && (marketplacelistings_id == cat_id)) { @@ -2708,7 +2758,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, tooltip_msg = LLTrans::getString("TooltipOutfitNotInInventory"); is_movable = false; } - else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) + else if (can_move_to_my_outfits_as_outfit(model, inv_cat, max_items_to_wear)) + { + is_movable = true; + create_outfit = true; + } + else if (can_move_to_my_outfits_as_subfolder(model, inv_cat)) { is_movable = true; } @@ -2732,7 +2787,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit"); } - else if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_SUBFOLDER) + else if (dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) { is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); @@ -2742,7 +2797,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); } - else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) + else if (can_move_to_my_outfits_as_outfit(model, inv_cat, max_items_to_wear)) + { + is_movable = true; + create_outfit = true; + } + else if (can_move_to_my_outfits_as_subfolder(model, inv_cat)) { is_movable = true; } @@ -2943,7 +3003,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (mUUID == my_outifts_id) { EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); - if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT) + if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT || !create_outfit) { LLInvFVBridge::changeCategoryParent( model, @@ -2967,15 +3027,19 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { case MY_OUTFITS_NO: // Moning from outside outfits into outfits - if (dest_res == MY_OUTFITS_SUBFOLDER) + if (dest_res == MY_OUTFITS_SUBFOLDER && create_outfit) { // turn it into outfit - dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb); + dropToMyOutfitsSubfolder(inv_cat, mUUID, cb); } else { - // or link it? - dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb); + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + move_is_into_trash); + if (cb) cb->fire(inv_cat->getUUID()); } break; case MY_OUTFITS_SUBFOLDER: @@ -4094,7 +4158,6 @@ void LLFolderBridge::perform_pasteFromClipboard() LLInventoryObject *obj = model->getObject(item_id); if (obj) { - if (move_is_into_lost_and_found) { if (LLAssetType::AT_CATEGORY == obj->getType()) @@ -4104,41 +4167,57 @@ void LLFolderBridge::perform_pasteFromClipboard() } if (move_is_into_outfit) { - if (!move_is_into_my_outfits && item && can_move_to_outfit(item, move_is_into_current_outfit)) + bool handled = false; + if (mUUID != my_outifts_id + && dest_folder->getPreferredType() == LLFolderType::FT_OUTFIT + && item + && can_move_to_outfit(item, move_is_into_current_outfit)) { - // todo: this is going to create dupplicate folders? dropToOutfit(item, move_is_into_current_outfit, cb); + handled = true; } else if (move_is_into_my_outfits && LLAssetType::AT_CATEGORY == obj->getType()) { - LLInventoryCategory* cat = model->getCategory(item_id); + LLViewerInventoryCategory* cat = model->getCategory(item_id); U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit"); - if (cat && can_move_to_my_outfits(model, cat, max_items_to_wear)) + if (cat && can_move_to_my_outfits_as_outfit(model, cat, max_items_to_wear)) { if (mUUID == my_outifts_id) { dropToMyOutfits(cat, cb); + handled = true; } - else if (move_is_into_my_outfits) + else { - EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); - if (res == MY_OUTFITS_SUBFOLDER) + EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + if (dest_res == MY_OUTFITS_SUBFOLDER) { // turn it into outfit - dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_OUTFIT, cb); + dropToMyOutfitsSubfolder(cat, mUUID, cb); + handled = true; + } + } + } + if (!handled && cat && can_move_to_my_outfits_as_subfolder(model, cat)) + { + EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + if (dest_res == MY_OUTFITS_SUBFOLDER || mUUID == my_outifts_id) + { + if (LLClipboard::instance().isCutMode()) + { + changeCategoryParent(model, cat, parent_id, false); } else { - dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_NONE, cb); + copy_inventory_category(model, cat, parent_id); } + if (cb) cb->fire(item_id); + handled = true; } } - else - { - LLNotificationsUtil::add("MyOutfitsPasteFailed"); - } } - else + + if (!handled) { LLNotificationsUtil::add("MyOutfitsPasteFailed"); } @@ -4181,7 +4260,7 @@ void LLFolderBridge::perform_pasteFromClipboard() // move_inventory_item() is not enough, as we have to update inventory locally too if (LLAssetType::AT_CATEGORY == obj->getType()) { - LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); + LLViewerInventoryCategory* vicat = model->getCategory(item_id); llassert(vicat); if (vicat) { @@ -4390,6 +4469,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items } disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("upload_options")); disabled_items.push_back(std::string("upload_def")); disabled_items.push_back(std::string("create_new")); } @@ -4415,6 +4495,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { disabled_items.push_back(std::string("New Folder")); disabled_items.push_back(std::string("New Listing Folder")); + disabled_items.push_back(std::string("upload_options")); disabled_items.push_back(std::string("upload_def")); disabled_items.push_back(std::string("create_new")); } @@ -4471,10 +4552,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items if (cat->getPreferredType() == LLFolderType::FT_OUTFIT) { // Want some but not all of the items from getClipboardEntries for outfits. - items.push_back(std::string("New Outfit Folder")); items.push_back(std::string("Rename")); items.push_back(std::string("thumbnail")); + addInventoryFavoritesMenuOptions(items); addDeleteContextMenuOptions(items, disabled_items); // EXT-4030: disallow deletion of currently worn outfit const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); @@ -4492,16 +4573,17 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id); if (in_my_outfits != MY_OUTFITS_NO) { + // Either an outfit or a subfolder inside MY_OUTFITS if (in_my_outfits == MY_OUTFITS_SUBFOLDER) { // Not inside an outfit, but inside 'my outfits' items.push_back(std::string("New Outfit")); + items.push_back(std::string("New Outfit Folder")); } - - items.push_back(std::string("New Outfit Folder")); items.push_back(std::string("Rename")); items.push_back(std::string("thumbnail")); + addInventoryFavoritesMenuOptions(items); addDeleteContextMenuOptions(items, disabled_items); } else @@ -4518,6 +4600,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items } if (!isMarketplaceListingsFolder()) { + items.push_back(std::string("upload_options")); items.push_back(std::string("upload_def")); items.push_back(std::string("create_new")); items.push_back(std::string("New Script")); @@ -4549,6 +4632,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID) { items.push_back(std::string("Copy outfit list to clipboard")); + addInventoryFavoritesMenuOptions(items); + addOpenFolderMenuOptions(flags, items); } @@ -4807,6 +4892,18 @@ void LLFolderBridge::addOpenFolderMenuOptions(U32 flags, menuentry_vec_t& items) } } +void LLFolderBridge::addInventoryFavoritesMenuOptions(menuentry_vec_t& items) +{ + if (isFavorite()) + { + items.push_back(std::string("Remove from Favorites")); + } + else + { + items.push_back(std::string("Add to Favorites")); + } +} + bool LLFolderBridge::hasChildren() const { LLInventoryModel* model = getInventoryModel(); @@ -5480,12 +5577,11 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI inv_cat->getThumbnailUUID()); } -void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb) +void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLPointer<LLInventoryCallback> cb) { - const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel); getInventoryModel()->createNewCategory(dest_id, - preferred_type, + LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); @@ -7062,12 +7158,13 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) item = (LLViewerInventoryItem*)gInventory.getItem(object_id); if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) { - rez_attachment(item, NULL, true); // Replace if "Wear"ing. + static LLCachedControl<bool> replace_item(gSavedSettings, "InventoryAddAttachmentBehavior", false); + rez_attachment(item, NULL, ("attach" == action) ? replace_item() : true); // Replace if "Wear"ing. } else if(item && item->isFinished()) { // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0)); + LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0, true)); copy_inventory_item( gAgent.getID(), item->getPermissions().getOwner(), @@ -8192,7 +8289,8 @@ void LLObjectBridgeAction::attachOrDetach() } else { - LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. + static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryAddAttachmentBehavior", false); + LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, inventory_linking()); // Don't replace if adding. } } @@ -8383,6 +8481,7 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) buildContextMenuOptions(flags, items, disabled_items); items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New folder from selected")), items.end()); hide_context_entries(menu, items, disabled_items); } @@ -8417,6 +8516,51 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( return new_listener; } +/************************************************************************/ +/* Favorites Inventory Panel related classes */ +/************************************************************************/ +void LLFavoritesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + // todo: consider things that should be disabled + menuentry_vec_t disabled_items, items; + buildContextMenuOptions(flags, items, disabled_items); + + items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); + items.erase(std::remove(items.begin(), items.end(), std::string("New folder from selected")), items.end()); + + hide_context_entries(menu, items, disabled_items); +} + +LLInvFVBridge* LLFavoritesInventoryBridgeBuilder::createBridge( + LLAssetType::EType asset_type, + LLAssetType::EType actual_asset_type, + LLInventoryType::EType inv_type, + LLInventoryPanel* inventory, + LLFolderViewModelInventory* view_model, + LLFolderView* root, + const LLUUID& uuid, + U32 flags /*= 0x00*/) const +{ + LLInvFVBridge* new_listener = NULL; + if (asset_type == LLAssetType::AT_CATEGORY + && actual_asset_type != LLAssetType::AT_LINK_FOLDER) + { + new_listener = new LLFavoritesFolderBridge(inv_type, inventory, root, uuid); + } + else + { + new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type, + actual_asset_type, + inv_type, + inventory, + view_model, + root, + uuid, + flags); + } + return new_listener; +} + LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge() { } @@ -8427,7 +8571,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ menuentry_vec_t disabled_items; if (get_selection_item_uuids(selected_items, ids)) { - if (!LLAppearanceMgr::instance().canAddWearables(ids) && canWearSelected(ids)) + if (!LLAppearanceMgr::instance().canAddWearables(ids, false) && canWearSelected(ids)) { disabled_items.push_back(std::string("Wearable And Object Wear")); disabled_items.push_back(std::string("Wearable Add")); |
