summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-05-07 22:29:08 +0300
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-05-08 18:46:33 +0300
commit37134720bce619a754ff097aff764d9a44bb0893 (patch)
treefdde1922360f0d42ab1c660eaecfc04e56c1a66f
parent50108bf0b7953e1f44a13b0790fe8dd8e9f7d2ca (diff)
#3757 Smarter subfolders dragndrop
-rw-r--r--indra/newview/llinventorybridge.cpp38
-rw-r--r--indra/newview/llinventoryfunctions.cpp41
-rw-r--r--indra/newview/llinventoryfunctions.h3
-rw-r--r--indra/newview/llinventorygallery.cpp19
4 files changed, 87 insertions, 14 deletions
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 4018a89c5a..bff7138282 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2664,6 +2664,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
//
bool is_movable = true;
+ bool create_outfit = false;
if (is_movable && (marketplacelistings_id == cat_id))
{
@@ -2708,7 +2709,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;
}
@@ -2742,7 +2748,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 +2954,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,7 +2978,7 @@ 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);
@@ -4094,7 +4105,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())
@@ -4111,9 +4121,9 @@ void LLFolderBridge::perform_pasteFromClipboard()
}
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)
{
@@ -4133,6 +4143,18 @@ void LLFolderBridge::perform_pasteFromClipboard()
}
}
}
+ else if (cat && can_move_to_my_outfits_as_subfolder(model, cat))
+ {
+ if (LLClipboard::instance().isCutMode())
+ {
+ changeCategoryParent(model, cat, parent_id, false);
+ if (cb) cb->fire(item_id);
+ }
+ else
+ {
+ copy_inventory_category(model, cat, parent_id);
+ }
+ }
else
{
LLNotificationsUtil::add("MyOutfitsPasteFailed");
@@ -4181,7 +4203,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)
{
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 7fff88fba7..9967318e92 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2314,7 +2314,7 @@ bool can_move_to_landmarks(LLInventoryItem* inv_item)
}
// Returns true if folder's content can be moved to Current Outfit or any outfit folder.
-bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit)
+bool can_move_to_my_outfits_as_outfit(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit)
{
LLInventoryModel::cat_array_t *cats;
LLInventoryModel::item_array_t *items;
@@ -2353,6 +2353,45 @@ bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_ca
return true;
}
+bool can_move_to_my_outfits_as_subfolder(LLInventoryModel* model, LLInventoryCategory* inv_cat, S32 depth)
+{
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ model->getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
+
+ if (items->size() > 0)
+ {
+ // subfolders don't allow items
+ return false;
+ }
+
+ constexpr size_t MAX_CONTENT = 255;
+ if (cats->size() > MAX_CONTENT)
+ {
+ // don't allow massive folders
+ return false;
+ }
+
+ for (LLPointer<LLViewerInventoryCategory>& cat : *cats)
+ {
+ // outfits are valid to move, check non-outfit folders
+ if (cat->getPreferredType() != LLFolderType::FT_OUTFIT)
+ {
+ if (depth == 3)
+ {
+ // don't allow massive folders
+ return false;
+ }
+ if (!can_move_to_my_outfits_as_subfolder(model, cat, depth + 1))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
std::string get_localized_folder_name(LLUUID cat_uuid)
{
std::string localized_root_name;
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 0ab045f2a0..f56413bf5d 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -112,7 +112,8 @@ std::string get_category_path(LLUUID cat_id);
bool can_move_to_outfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit);
bool can_move_to_landmarks(LLInventoryItem* inv_item);
-bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit);
+bool can_move_to_my_outfits_as_outfit(LLInventoryModel* model, LLInventoryCategory* inv_cat, U32 wear_limit);
+bool can_move_to_my_outfits_as_subfolder(LLInventoryModel* model, LLInventoryCategory* inv_cat, S32 depth = 0);
std::string get_localized_folder_name(LLUUID cat_uuid);
void new_folder_window(const LLUUID& folder_id);
void ungroup_folder_items(const LLUUID& folder_id);
diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp
index eb47af85fd..3222dff1b2 100644
--- a/indra/newview/llinventorygallery.cpp
+++ b/indra/newview/llinventorygallery.cpp
@@ -3714,6 +3714,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
//
bool is_movable = true;
+ bool create_outfit = false;
if (is_movable && (marketplacelistings_id == cat_id))
{
@@ -3759,7 +3760,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, 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;
}
@@ -3793,7 +3799,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, 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;
}
@@ -3928,7 +3939,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
if (dest_id == 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)
{
gInventory.changeCategoryParent(
(LLViewerInventoryCategory*)inv_cat,
@@ -3950,7 +3961,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, 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, dest_id, LLFolderType::FT_OUTFIT);