summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2023-11-10 23:36:33 +0200
committerakleshchev <117672381+akleshchev@users.noreply.github.com>2023-11-13 19:24:10 +0200
commitaff01e2fd4fb5475eb42ce58d1ad997341cb7a94 (patch)
tree968058a22b9791f8cf776126c2b1d59d176014b8 /indra/newview
parent03e00dab6de28e447942fbb32b6c2604acbdc118 (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.cpp48
-rw-r--r--indra/newview/llappearancemgr.h9
-rw-r--r--indra/newview/llinventorybridge.cpp42
-rw-r--r--indra/newview/llinventoryfunctions.cpp76
-rw-r--r--indra/newview/llinventoryfunctions.h1
-rw-r--r--indra/newview/llinventorygallery.cpp41
-rw-r--r--indra/newview/llinventorygallerymenu.cpp43
-rw-r--r--indra/newview/llstartup.cpp6
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