diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2023-11-10 23:36:33 +0200 |
---|---|---|
committer | akleshchev <117672381+akleshchev@users.noreply.github.com> | 2023-11-13 19:24:10 +0200 |
commit | aff01e2fd4fb5475eb42ce58d1ad997341cb7a94 (patch) | |
tree | 968058a22b9791f8cf776126c2b1d59d176014b8 /indra/newview | |
parent | 03e00dab6de28e447942fbb32b6c2604acbdc118 (diff) |
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.
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llappearancemgr.cpp | 48 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.h | 9 | ||||
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 42 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 76 | ||||
-rw-r--r-- | indra/newview/llinventoryfunctions.h | 1 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.cpp | 41 | ||||
-rw-r--r-- | indra/newview/llinventorygallerymenu.cpp | 43 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 6 |
8 files changed, 176 insertions, 90 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8673dc6a33..10b3f4b573 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1399,7 +1399,7 @@ const std::string LLAppearanceMgr::sExpectedTextureName = "OutfitPreview"; const LLUUID LLAppearanceMgr::getCOF() const { - return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + return mCOFID; } S32 LLAppearanceMgr::getCOFVersion() const @@ -1415,6 +1415,11 @@ S32 LLAppearanceMgr::getCOFVersion() const } } +void LLAppearanceMgr::initCOFID() +{ + mCOFID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); +} + const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() { const LLUUID& current_outfit_cat = getCOF(); @@ -3749,6 +3754,14 @@ LLSD LLAppearanceMgr::dumpCOF() const return result; } +void LLAppearanceMgr::cleanup() +{ + mIsInUpdateAppearanceFromCOF = false; + mOutstandingAppearanceBakeRequest = false; + mRerequestAppearanceBake = false; + mCOFID.setNull(); +} + // static void LLAppearanceMgr::onIdle(void *) { @@ -4387,20 +4400,45 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const return FALSE; } -BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const +bool LLAppearanceMgr::getIsInCOF(const LLInventoryObject* obj) const { - if (!getIsInCOF(obj_id)) return FALSE; + const LLUUID& cof = getCOF(); + if (obj->getUUID() == cof) + return true; + if (obj && obj->getParentUUID() == cof) + return true; + return false; +} + +bool LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const +{ + if (!getIsInCOF(obj_id)) return false; // If a non-link somehow ended up in COF, allow deletion. const LLInventoryObject *obj = gInventory.getObject(obj_id); if (obj && !obj->getIsLinkType()) { - return FALSE; + return false; } // For now, don't allow direct deletion from the COF. Instead, force users // to choose "Detach" or "Take Off". - return TRUE; + return true; +} + +bool LLAppearanceMgr::getIsProtectedCOFItem(const LLInventoryObject* obj) const +{ + if (!getIsInCOF(obj)) return false; + + // If a non-link somehow ended up in COF, allow deletion. + if (obj && !obj->getIsLinkType()) + { + return false; + } + + // For now, don't allow direct deletion from the COF. Instead, force users + // to choose "Detach" or "Take Off". + return true; } class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 80d6587ad3..02859dc12c 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -111,9 +111,11 @@ public: // Find the Current Outfit folder. const LLUUID getCOF() const; S32 getCOFVersion() const; + void initCOFID(); // Debugging - get truncated LLSD summary of COF contents. LLSD dumpCOF() const; + void cleanup(); // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); @@ -276,6 +278,7 @@ private: attachments_changed_signal_t mAttachmentsChangeSignal; LLUUID mCOFImageID; + LLUUID mCOFID; std::unique_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; @@ -290,8 +293,10 @@ private: public: // Is this in the COF? BOOL getIsInCOF(const LLUUID& obj_id) const; - // Is this in the COF and can the user delete it from the COF? - BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; + bool getIsInCOF(const LLInventoryObject* obj) const; + // Is this in the COF and can the user delete it from the COF? + bool getIsProtectedCOFItem(const LLUUID& obj_id) const; + bool getIsProtectedCOFItem(const LLInventoryObject* obj) const; // Outfits will prioritize textures with such name to use for preview in gallery static const std::string sExpectedTextureName; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a12c4f7f76..4fb60b4c55 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2399,49 +2399,19 @@ void LLFolderBridge::update() } } - -// Iterate through a folder's children to determine if -// all the children are removable. -class LLIsItemRemovable : public LLFolderViewFunctor -{ -public: - LLIsItemRemovable(bool check_worn = true) : mPassed(TRUE), mCheckWorn(check_worn) {} - virtual void doFolder(LLFolderViewFolder* folder) - { - mPassed &= folder->getViewModelItem()->isItemRemovable(mCheckWorn); - } - virtual void doItem(LLFolderViewItem* item) - { - mPassed &= item->getViewModelItem()->isItemRemovable(mCheckWorn); - } - BOOL mPassed; - bool mCheckWorn; -}; - // Can be destroyed (or moved to trash) BOOL LLFolderBridge::isItemRemovable(bool check_worn) const { - if (!get_is_category_removable(getInventoryModel(), mUUID)) + if (!get_is_category_and_children_removable(getInventoryModel(), mUUID, check_worn)) { return FALSE; } - LLInventoryPanel* panel = mInventoryPanel.get(); - LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL); - if (folderp) - { - LLIsItemRemovable folder_test(check_worn); - folderp->applyFunctorToChildren(folder_test); - if (!folder_test.mPassed) - { - return FALSE; - } - } - - if (isMarketplaceListingsFolder() && (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID))) - { - return FALSE; - } + if (isMarketplaceListingsFolder() + && (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID))) + { + return FALSE; + } return TRUE; } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index c2cbf4b8ac..5d6bf8ab4b 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -621,7 +621,7 @@ BOOL get_is_item_worn(const LLUUID& id, const LLViewerInventoryItem* item) BOOL get_is_item_worn(const LLUUID& id) { const LLViewerInventoryItem* item = gInventory.getItem(id); - return get_is_item_worn(item); + return get_is_item_worn(id, item); } BOOL get_is_item_worn(const LLViewerInventoryItem* item) @@ -711,20 +711,20 @@ bool get_is_item_removable(const LLInventoryModel* model, const LLUUID& id, bool // Disable delete from COF folder; have users explicitly choose "detach/take off", // unless the item is not worn but in the COF (i.e. is bugged). - if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id)) + const LLViewerInventoryItem* obj = model->getItem(id); + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(obj)) { - if (get_is_item_worn(id)) + if (get_is_item_worn(id, obj)) { return false; } } - const LLInventoryObject *obj = model->getItem(id); if (obj && obj->getIsLinkType()) { return true; } - if (check_worn && get_is_item_worn(id)) + if (check_worn && get_is_item_worn(id, obj)) { return false; } @@ -819,6 +819,72 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id) return TRUE; } +bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUID& folder_id, bool check_worn) +{ + if (!get_is_category_removable(model, folder_id)) + { + return false; + } + + const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) + { + return false; + } + + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + model->collectDescendents( + folder_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + + for (LLInventoryModel::item_array_t::value_type& item : item_array) + { + // Disable delete from COF folder; have users explicitly choose "detach/take off", + // unless the item is not worn but in the COF (i.e. is bugged). + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item)) + { + if (get_is_item_worn(item)) + { + return false; + } + } + + if (item && item->getIsLinkType()) + { + return true; + } + if (check_worn && get_is_item_worn(item)) + { + return false; + } + } + + const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + LLViewerInventoryCategory* outfit_linked_category = base_outfit_link ? base_outfit_link->getLinkedCategory() : nullptr; + for (LLInventoryModel::cat_array_t::value_type& cat : cat_array) + { + const LLFolderType::EType folder_type = cat->getPreferredType(); + if (LLFolderType::lookupIsProtectedType(folder_type)) + { + return false; + } + + // Can't delete the outfit that is currently being worn. + if (folder_type == LLFolderType::FT_OUTFIT) + { + if (cat == outfit_linked_category) + { + return false; + } + } + } + + return true; +} + BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id) { if (!model) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index a8a9bb9735..deacaced42 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -59,6 +59,7 @@ bool get_is_item_editable(const LLUUID& inv_item_id); void handle_item_edit(const LLUUID& inv_item_id); BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id); +bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUID& folder_id, bool check_worn); BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id); 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; } diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 2bca33dec4..4b47346473 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -388,43 +388,6 @@ bool is_inbox_folder(LLUUID item_id) return gInventory.isObjectDescendentOf(item_id, inbox_id); } -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; -} - void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* menu) { LLUUID selected_id = mUUIDs.front(); @@ -532,7 +495,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } } items.push_back(std::string("Purge Item")); - if (is_folder && !is_category_removable(selected_id, true)) + if (is_folder && !get_is_category_and_children_removable(&gInventory, selected_id, true)) { disabled_items.push_back(std::string("Purge Item")); } @@ -580,12 +543,12 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("Cut")); items.push_back(std::string("Delete")); - if(!is_category_removable(selected_id, false)) + if(!get_is_category_and_children_removable(&gInventory, selected_id, false)) { disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } - else if (!is_category_removable(selected_id, true)) + else if (!get_is_category_and_children_removable(&gInventory, selected_id, true)) { disabled_items.push_back(std::string("Cut")); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 916848ff5f..bb867f7b23 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1938,8 +1938,10 @@ bool idle_startup() display_startup(); return FALSE; } + LLInventoryModelBackgroundFetch::instance().start(); - LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::instance().initCOFID(); + LLUUID cof_id = LLAppearanceMgr::instance().getCOF(); LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); if (cof && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) @@ -2812,6 +2814,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); // Initiate creation of COF, since we're also bypassing that. gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::getInstance()->initCOFID(); ESex gender; if (gender_name == "male") @@ -2968,6 +2971,7 @@ void reset_login() gAgent.cleanup(); gSky.cleanup(); // mVOSkyp is an inworld object. LLWorld::getInstance()->resetClass(); + LLAppearanceMgr::getInstance()->cleanup(); if ( gViewerWindow ) { // Hide menus and normal buttons |