From 08a3b56669880101aa705c98e60b76e92d26c93b Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Thu, 5 Oct 2023 20:08:36 +0300 Subject: SL-19826 Fix mac build issue (unused variable) --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 4838ba7a47..0e4c64a641 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2420,7 +2420,7 @@ void LLInventoryGallery::startDrag() ids.push_back(selected_id); } } - LLToolDragAndDrop::getInstance()->beginMultiDrag(types, ids, LLToolDragAndDrop::SOURCE_AGENT); + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, ids, src); } bool LLInventoryGallery::areViewsInitialized() -- cgit v1.2.3 From 2968e8bea5cde5b27ae806cf4bb2d36b254e94d8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 6 Oct 2023 23:27:11 +0300 Subject: SL-20411 Don't load all thumnails at once for large folders #2 --- indra/newview/llinventorygallery.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 0e4c64a641..d4ca58f778 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -58,6 +58,7 @@ static LLPanelInjector t_inventory_gallery("inventory_gallery"); const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; +const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately // Helper dnd functions BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL drop, std::string& tooltip_msg, BOOL is_link); @@ -106,6 +107,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mGalleryWidthFactor(p.gallery_width_factor), mIsInitialized(false), mRootDirty(false), + mLoadThumbnailsImmediately(true), mNeedsArrange(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), mSortOrder(LLInventoryFilter::SO_DATE) @@ -540,6 +542,12 @@ void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item) int n_prev = n - 1; int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + // Avoid loading too many items. + // Intent is for small folders to display all content fast + // and for large folders to load content mostly as needed + // Todo: ideally needs to unload images outside visible area + mLoadThumbnailsImmediately = mItemsAddedCount < FAST_LOAD_THUMBNAIL_TRSHOLD; + bool add_row = row_count != row_count_prev; int pos = 0; if (add_row) @@ -573,6 +581,8 @@ void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item, boo mItemsAddedCount--; mIndexToItemMap.erase(mItemsAddedCount); + mLoadThumbnailsImmediately = mItemsAddedCount < FAST_LOAD_THUMBNAIL_TRSHOLD; + bool remove_row = row_count != row_count_prev; removeFromLastRow(mItems[mItemsAddedCount]); mItems.pop_back(); @@ -636,6 +646,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setUUID(item_id); gitem->setGallery(this); gitem->setType(type, inventory_type, flags, is_link); + gitem->setLoadImmediately(mLoadThumbnailsImmediately); gitem->setThumbnail(thumbnail_id); gitem->setWorn(is_worn); gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); @@ -997,6 +1008,7 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) if (mItemMap[item_id]) { + mItemMap[item_id]->setLoadImmediately(mLoadThumbnailsImmediately); mItemMap[item_id]->setThumbnail(thumbnail_id); bool passes_filter = checkAgainstFilters(mItemMap[item_id], mFilterSubString); @@ -2568,6 +2580,7 @@ BOOL LLInventoryGalleryItem::postBuild() { mNameText = getChild("item_name"); mTextBgPanel = getChild("text_bg_panel"); + mThumbnailCtrl = getChild("preview_thumbnail"); return TRUE; } @@ -2643,14 +2656,19 @@ void LLInventoryGalleryItem::setThumbnail(LLUUID id) mDefaultImage = id.isNull(); if(mDefaultImage) { - getChild("preview_thumbnail")->clearTexture(); + mThumbnailCtrl->clearTexture(); } else { - getChild("preview_thumbnail")->setValue(id); + mThumbnailCtrl->setValue(id); } } +void LLInventoryGalleryItem::setLoadImmediately(bool val) +{ + mThumbnailCtrl->setInitImmediately(val); +} + void LLInventoryGalleryItem::draw() { if (isFadeItem()) @@ -2665,7 +2683,7 @@ void LLInventoryGalleryItem::draw() // Draw border LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); - LLRect border = getChildView("preview_thumbnail")->getRect(); + LLRect border = mThumbnailCtrl->getRect(); border.mRight = border.mRight + 1; border.mTop = border.mTop + 1; gl_rect_2d(border, border_color.get(), FALSE); @@ -2887,7 +2905,7 @@ void LLInventoryGalleryItem::updateNameText() mNameText->setFont(getTextFont()); mNameText->setText(mItemName + mPermSuffix + mWornSuffix); mNameText->setToolTip(mItemName + mPermSuffix + mWornSuffix); - getChild("preview_thumbnail")->setToolTip(mItemName + mPermSuffix + mWornSuffix); + mThumbnailCtrl->setToolTip(mItemName + mPermSuffix + mWornSuffix); } bool LLInventoryGalleryItem::isFadeItem() -- cgit v1.2.3 From a62f5bfac1e55455c67e1c36eb388af99795dab6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 14 Oct 2023 02:40:59 +0300 Subject: SL-20232 Allow deletion of worn items #1 --- indra/newview/llinventorygallery.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index d4ca58f778..9074c8466a 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1685,7 +1685,7 @@ BOOL LLInventoryGallery::canCut() const return FALSE; } } - else if (!get_is_item_removable(&gInventory, id)) + else if (!get_is_item_removable(&gInventory, id, true)) { return FALSE; } @@ -1880,7 +1880,7 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response } else { - if (get_is_item_removable(&gInventory, id)) + if (get_is_item_removable(&gInventory, id, true)) { gInventory.removeItem(id); } @@ -1925,7 +1925,7 @@ bool LLInventoryGallery::canDeleteSelection() return false; } } - else if (!get_is_item_removable(&gInventory, id)) + else if (!get_is_item_removable(&gInventory, id, true)) { return false; } -- cgit v1.2.3 From 813b0e7675f0f9fb682831bdf60319f8b584b882 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 14 Oct 2023 12:14:51 +0300 Subject: SL-20232 Allow deletion of worn items #2 --- indra/newview/llinventorygallery.cpp | 64 ++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 9074c8466a..23a00e2e51 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1864,6 +1864,8 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { + bool has_worn = notification["payload"]["has_worn"].asBoolean(); + uuid_vec_t worn; for (const LLUUID& id : selected_ids) { LLInventoryObject* obj = gInventory.getObject(id); @@ -1884,22 +1886,72 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response { gInventory.removeItem(id); } + else if (has_worn && get_is_item_worn(id)) + { + worn.push_back(id); + } } } + + if (!worn.empty()) + { + // should fire once after every item gets detached + LLAppearanceMgr::instance().removeItemsFromAvatar(worn, + [worn]() + { + for (const LLUUID& id : worn) + { + remove_inventory_item(id, NULL); + } + }); + } } } void LLInventoryGallery::deleteSelection() { - if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + bool has_worn = false; + bool needs_replacement = false; + for (const LLUUID& id : mSelectedItemIDs) { - LLNotifications::instance().setIgnored("DeleteItems", false); - LLInventoryAction::sDeleteConfirmationDisplayed = true; + if (get_is_item_worn(id)) + { + has_worn = true; + const LLViewerInventoryItem* item = gInventory.getItem(id); + LLWearableType::EType type = item->getWearableType(); + if (type == LLWearableType::WT_SHAPE + || type == LLWearableType::WT_SKIN + || type == LLWearableType::WT_HAIR + || type == LLWearableType::WT_EYES) + { + needs_replacement = true; + break; + } + } } - LLSD args; - args["QUESTION"] = LLTrans::getString("DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); + if (needs_replacement) + { + LLNotificationsUtil::add("CantDeleteRequiredClothing"); + } + else if (has_worn) + { + LLSD payload; + payload["has_worn"] = true; + LLNotificationsUtil::add("DeleteWornItems", LLSD(), payload, boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); + } + else + { + if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + { + LLNotifications::instance().setIgnored("DeleteItems", false); + LLInventoryAction::sDeleteConfirmationDisplayed = true; + } + + LLSD args; + args["QUESTION"] = LLTrans::getString("DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); + } } bool LLInventoryGallery::canDeleteSelection() -- cgit v1.2.3 From 7d82ee8075e81a6d3640103b68e98a6a2cbbe623 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 17 Oct 2023 01:17:51 +0300 Subject: SL-20232 Allow deletion of folders with worn content in gallery view #4 --- indra/newview/llinventorygallery.cpp | 86 ++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 18 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 23a00e2e51..058bbde8b9 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1866,29 +1866,49 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response { bool has_worn = notification["payload"]["has_worn"].asBoolean(); uuid_vec_t worn; - for (const LLUUID& id : selected_ids) + uuid_vec_t deletion_list; + for (const LLUUID& obj_id : selected_ids) { - LLInventoryObject* obj = gInventory.getObject(id); - if (!obj) + LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id); + if (cat) { - return; - } - if (obj->getType() == LLAssetType::AT_CATEGORY) - { - if (get_is_category_removable(&gInventory, id)) + bool cat_has_worn = false; + if (has_worn) { - gInventory.removeCategory(id); + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + + gInventory.collectDescendents(obj_id, categories, items, FALSE); + + for (LLInventoryModel::item_array_t::value_type& item : items) + { + if (get_is_item_worn(item)) + { + worn.push_back(item->getUUID()); + cat_has_worn = true; + } + } + } + if (cat_has_worn) + { + deletion_list.push_back(obj_id); + } + else + { + gInventory.removeCategory(obj_id); } } - else + LLViewerInventoryItem* item = gInventory.getItem(obj_id); + if (item) { - if (get_is_item_removable(&gInventory, id, true)) + if (has_worn && get_is_item_worn(item)) { - gInventory.removeItem(id); + worn.push_back(item->getUUID()); + deletion_list.push_back(item->getUUID()); } - else if (has_worn && get_is_item_worn(id)) + else { - worn.push_back(id); + gInventory.removeItem(obj_id); } } } @@ -1897,9 +1917,9 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response { // should fire once after every item gets detached LLAppearanceMgr::instance().removeItemsFromAvatar(worn, - [worn]() + [deletion_list]() { - for (const LLUUID& id : worn) + for (const LLUUID& id : deletion_list) { remove_inventory_item(id, NULL); } @@ -1914,10 +1934,40 @@ void LLInventoryGallery::deleteSelection() bool needs_replacement = false; for (const LLUUID& id : mSelectedItemIDs) { - if (get_is_item_worn(id)) + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + + gInventory.collectDescendents(id, categories, items, FALSE); + + for (LLInventoryModel::item_array_t::value_type& item : items) + { + if (get_is_item_worn(item)) + { + has_worn = true; + LLWearableType::EType type = item->getWearableType(); + if (type == LLWearableType::WT_SHAPE + || type == LLWearableType::WT_SKIN + || type == LLWearableType::WT_HAIR + || type == LLWearableType::WT_EYES) + { + needs_replacement = true; + break; + } + } + } + if (needs_replacement) + { + break; + } + } + + LLViewerInventoryItem* item = gInventory.getItem(id); + if (item && get_is_item_worn(item)) { has_worn = true; - const LLViewerInventoryItem* item = gInventory.getItem(id); LLWearableType::EType type = item->getWearableType(); if (type == LLWearableType::WT_SHAPE || type == LLWearableType::WT_SKIN -- cgit v1.2.3 From e233e4fb50e513b58f4452086182b60b25440fac Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 17 Oct 2023 01:35:47 +0300 Subject: SL-20232 Allow deletion of worn items #5 --- indra/newview/llinventorygallery.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 058bbde8b9..d5fce2cda7 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1866,7 +1866,8 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response { bool has_worn = notification["payload"]["has_worn"].asBoolean(); uuid_vec_t worn; - uuid_vec_t deletion_list; + uuid_vec_t item_deletion_list; + uuid_vec_t cat_deletion_list; for (const LLUUID& obj_id : selected_ids) { LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id); @@ -1891,7 +1892,7 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response } if (cat_has_worn) { - deletion_list.push_back(obj_id); + cat_deletion_list.push_back(obj_id); } else { @@ -1904,7 +1905,7 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response if (has_worn && get_is_item_worn(item)) { worn.push_back(item->getUUID()); - deletion_list.push_back(item->getUUID()); + item_deletion_list.push_back(item->getUUID()); } else { @@ -1917,12 +1918,16 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response { // should fire once after every item gets detached LLAppearanceMgr::instance().removeItemsFromAvatar(worn, - [deletion_list]() + [item_deletion_list, cat_deletion_list]() { - for (const LLUUID& id : deletion_list) + for (const LLUUID& id : item_deletion_list) { remove_inventory_item(id, NULL); } + for (const LLUUID& id : cat_deletion_list) + { + remove_inventory_category(id, NULL); + } }); } } -- cgit v1.2.3 From bf740d67a6c68a94cc79fd25478bdb6fb6443fa3 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 9 Nov 2023 22:08:39 +0200 Subject: SL-20576 FIXED Viewer crashes when clicking scroll bar after switching views --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index d5fce2cda7..ad6c3909ef 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1435,7 +1435,7 @@ void LLInventoryGallery::onFocusReceived() LLInventoryGalleryItem* focus_item = NULL; for (const LLUUID& id : mSelectedItemIDs) { - if (mItemMap[id]) + if (mItemMap[id] && !mItemMap[id]->isHidden()) { focus_item = mItemMap[id]; focus_item->setSelected(true); -- cgit v1.2.3 From aff01e2fd4fb5475eb42ce58d1ad997341cb7a94 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Nov 2023 23:36:33 +0200 Subject: SL-20575 Fix some deletion issues - Fixes 'cut' checks for gallery - Checking if large folder is deletable should be faster now - For large flat root folders eliminated delay of looking for cof Might be a good idea to start cashing isItemRemovable if category version hasn't changed. --- indra/newview/llinventorygallery.cpp | 41 +++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index ad6c3909ef..3c3da253d3 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1668,6 +1668,45 @@ void LLInventoryGallery::cut() mFilterSubString.clear(); } + + +bool is_category_removable(const LLUUID& folder_id, bool check_worn) +{ + if (!get_is_category_removable(&gInventory, folder_id)) + { + return false; + } + + // check children + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(folder_id, cat_array, item_array); + + for (LLInventoryModel::item_array_t::value_type& item : *item_array) + { + if (!get_is_item_removable(&gInventory, item->getUUID(), check_worn)) + { + return false; + } + } + + for (LLInventoryModel::cat_array_t::value_type& cat : *cat_array) + { + if (!is_category_removable(cat->getUUID(), check_worn)) + { + return false; + } + } + + const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) + { + return false; + } + + return true; +} + BOOL LLInventoryGallery::canCut() const { if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty()) @@ -1680,7 +1719,7 @@ BOOL LLInventoryGallery::canCut() const LLViewerInventoryCategory* cat = gInventory.getCategory(id); if (cat) { - if (!get_is_category_removable(&gInventory, id)) + if (!get_is_category_and_children_removable(&gInventory, id, true)) { return FALSE; } -- cgit v1.2.3