Merge branch 'release/2025.04' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/llinventorybridge.cpp # indra/newview/lloutfitslist.cpp # indra/newview/skins/default/xui/en/strings.xmlmaster
commit
03f622d0d4
|
|
@ -176,14 +176,6 @@ void LLUUID::toString(std::string& out) const
|
|||
(U8)(mData[15]));
|
||||
}
|
||||
|
||||
// *TODO: deprecate
|
||||
void LLUUID::toString(char* out) const
|
||||
{
|
||||
std::string buffer;
|
||||
toString(buffer);
|
||||
strcpy(out, buffer.c_str()); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
void LLUUID::toCompressedString(std::string& out) const
|
||||
{
|
||||
char bytes[UUID_BYTES + 1];
|
||||
|
|
@ -192,13 +184,6 @@ void LLUUID::toCompressedString(std::string& out) const
|
|||
out.assign(bytes, UUID_BYTES);
|
||||
}
|
||||
|
||||
// *TODO: deprecate
|
||||
void LLUUID::toCompressedString(char* out) const
|
||||
{
|
||||
memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
|
||||
out[UUID_BYTES] = '\0';
|
||||
}
|
||||
|
||||
std::string LLUUID::getString() const
|
||||
{
|
||||
return asString();
|
||||
|
|
|
|||
|
|
@ -103,9 +103,7 @@ public:
|
|||
friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
|
||||
friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
|
||||
|
||||
void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
|
||||
void toString(std::string& out) const;
|
||||
void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
|
||||
void toCompressedString(std::string& out) const;
|
||||
|
||||
// last 4 chars for quick ref - Very lightweight, no nul-term added - provide your own, ensure min 4 bytes.
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ void LLAppearanceListener::getOutfitsList(LLSD const &data)
|
|||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
|
||||
LLIsType is_category(LLAssetType::AT_CATEGORY);
|
||||
LLIsFolderType is_category(LLFolderType::FT_OUTFIT);
|
||||
gInventory.collectDescendentsIf(outfits_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category);
|
||||
|
||||
response["outfits"] = llsd::toMap(cat_array,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ void teleport_via_landmark(const LLUUID& asset_id);
|
|||
// </FS:ND>
|
||||
|
||||
// Helper functions
|
||||
|
||||
bool isAddAction(const std::string& action)
|
||||
{
|
||||
return ("wear" == action || "attach" == action || "activate" == action);
|
||||
|
|
@ -2975,7 +2974,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
|
||||
if (is_movable && move_is_into_outfit)
|
||||
{
|
||||
if (mUUID == my_outifts_id)
|
||||
if ((inv_cat->getPreferredType() != LLFolderType::FT_NONE) && (inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT))
|
||||
{
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
is_movable = false;
|
||||
}
|
||||
else if (mUUID == my_outifts_id)
|
||||
{
|
||||
if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings)
|
||||
{
|
||||
|
|
@ -2992,13 +2996,39 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
is_movable = false;
|
||||
}
|
||||
}
|
||||
else if(getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_NONE)
|
||||
else if (!getCategory())
|
||||
{
|
||||
is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT));
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else
|
||||
{
|
||||
is_movable = false;
|
||||
EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_OUTFIT)
|
||||
{
|
||||
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)
|
||||
{
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else if (dest_res == MY_OUTFITS_SUBFOLDER && inv_res == MY_OUTFITS_SUBOUTFIT)
|
||||
{
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
|
||||
{
|
||||
is_movable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_movable && move_is_into_current_outfit && is_link)
|
||||
|
|
@ -3201,9 +3231,77 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
|
|||
|
||||
if (mUUID == my_outifts_id)
|
||||
{
|
||||
// Category can contains objects,
|
||||
// create a new folder and populate it with links to original objects
|
||||
dropToMyOutfits(inv_cat, cb);
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT)
|
||||
{
|
||||
LLInvFVBridge::changeCategoryParent(
|
||||
model,
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
mUUID,
|
||||
false);
|
||||
if (cb) cb->fire(inv_cat->getUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Moving from inventory
|
||||
// create a new folder and populate it with links to original objects
|
||||
dropToMyOutfits(inv_cat, cb);
|
||||
}
|
||||
}
|
||||
else if (move_is_into_my_outfits)
|
||||
{
|
||||
EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
switch (inv_res)
|
||||
{
|
||||
case MY_OUTFITS_NO:
|
||||
// Moning from outside outfits into outfits
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
{
|
||||
// turn it into outfit
|
||||
dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// or link it?
|
||||
dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb);
|
||||
}
|
||||
break;
|
||||
case MY_OUTFITS_SUBFOLDER:
|
||||
case MY_OUTFITS_OUTFIT:
|
||||
// only permit moving subfodlers and outfits into other subfolders
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
{
|
||||
LLInvFVBridge::changeCategoryParent(
|
||||
model,
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
mUUID,
|
||||
false);
|
||||
if (cb) cb->fire(inv_cat->getUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false); // mot permitted, shouldn't have accepted
|
||||
}
|
||||
break;
|
||||
case MY_OUTFITS_SUBOUTFIT:
|
||||
if (dest_res == MY_OUTFITS_SUBOUTFIT || dest_res == MY_OUTFITS_OUTFIT)
|
||||
{
|
||||
LLInvFVBridge::changeCategoryParent(
|
||||
model,
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
mUUID,
|
||||
false);
|
||||
if (cb) cb->fire(inv_cat->getUUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false); // mot permitted, shouldn't have accepted
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if target is current outfit folder we use link
|
||||
else if (move_is_into_current_outfit &&
|
||||
|
|
@ -4398,6 +4496,7 @@ void LLFolderBridge::perform_pasteFromClipboard()
|
|||
if (move_is_into_outfit && item && can_move_to_outfit(item, move_is_into_current_outfit))
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
// todo: this is going to create dupplicate folders?
|
||||
dropToOutfit(item, move_is_into_current_outfit, cb);
|
||||
}
|
||||
else if (/*move_is_into_my_outfits &&*/ LLAssetType::AT_CATEGORY == obj->getType()) // <FS:Ansariel> Unable to copy&paste into outfits anymore
|
||||
|
|
@ -4406,7 +4505,23 @@ void LLFolderBridge::perform_pasteFromClipboard()
|
|||
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
|
||||
if (cat && can_move_to_my_outfits(model, cat, max_items_to_wear))
|
||||
{
|
||||
dropToMyOutfits(cat, cb);
|
||||
if (mUUID == my_outifts_id)
|
||||
{
|
||||
dropToMyOutfits(cat, cb);
|
||||
}
|
||||
else if (move_is_into_my_outfits)
|
||||
{
|
||||
EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
if (res == MY_OUTFITS_SUBFOLDER)
|
||||
{
|
||||
// turn it into outfit
|
||||
dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_OUTFIT, cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_NONE, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4668,15 +4783,11 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
// <FS:Ansariel> Fix "outfits" context menu
|
||||
//if (outfits_id == mUUID)
|
||||
if (model->isObjectDescendentOf(mUUID, outfits_id) && getCategory() &&
|
||||
(getCategory()->getPreferredType() == LLFolderType::FT_NONE ||
|
||||
getCategory()->getPreferredType() == LLFolderType::FT_MY_OUTFITS))
|
||||
if (outfits_id == mUUID)
|
||||
{
|
||||
items.push_back(std::string("New Outfit Folder"));
|
||||
items.push_back(std::string("New Outfit"));
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
if (lost_and_found_id == mUUID)
|
||||
{
|
||||
|
|
@ -4789,61 +4900,19 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
) // do not allow creating in library
|
||||
{
|
||||
LLViewerInventoryCategory *cat = getCategory();
|
||||
// BAP removed protected check to re-enable standard ops in untyped folders.
|
||||
// Not sure what the right thing is to do here.
|
||||
if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
|
||||
|
||||
if (cat)
|
||||
{
|
||||
if (!isInboxFolder() // don't allow creation in inbox
|
||||
&& outfits_id != mUUID)
|
||||
{
|
||||
bool menu_items_added = false;
|
||||
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
|
||||
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
|
||||
{
|
||||
items.push_back(std::string("New Folder"));
|
||||
menu_items_added = true;
|
||||
}
|
||||
// <FS:Ansariel> Fix "outfits" context menu
|
||||
//if (!isMarketplaceListingsFolder())
|
||||
if (!isMarketplaceListingsFolder() && !model->isObjectDescendentOf(mUUID, outfits_id))
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
items.push_back(std::string("upload_def"));
|
||||
//items.push_back(std::string("create_new")); // <FS:Ansariel> Undo weird menu design
|
||||
items.push_back(std::string("New Script"));
|
||||
items.push_back(std::string("New Note"));
|
||||
items.push_back(std::string("New Gesture"));
|
||||
items.push_back(std::string("New Material"));
|
||||
items.push_back(std::string("New Clothes"));
|
||||
items.push_back(std::string("New Body Parts"));
|
||||
items.push_back(std::string("New Settings"));
|
||||
if (!LLEnvironment::instance().isInventoryEnabled())
|
||||
{
|
||||
disabled_items.push_back("New Settings");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
items.push_back(std::string("New Listing Folder"));
|
||||
}
|
||||
if (menu_items_added)
|
||||
{
|
||||
items.push_back(std::string("Create Separator"));
|
||||
}
|
||||
}
|
||||
getClipboardEntries(false, items, disabled_items, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Want some but not all of the items from getClipboardEntries for outfits.
|
||||
if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
|
||||
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")); // <FS:Ansariel> Normal subfolder underneath an outfit folder makes no sense
|
||||
items.push_back(std::string("Rename"));
|
||||
items.push_back(std::string("thumbnail"));
|
||||
|
||||
addDeleteContextMenuOptions(items, disabled_items);
|
||||
// EXT-4030: disallow deletion of currently worn outfit
|
||||
const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
|
||||
const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
|
||||
if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))
|
||||
{
|
||||
disabled_items.push_back(std::string("Delete"));
|
||||
|
|
@ -4857,6 +4926,67 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
}
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
else if (outfits_id == mUUID)
|
||||
{
|
||||
getClipboardEntries(false, items, disabled_items, flags);
|
||||
}
|
||||
else if (!isCOFFolder())
|
||||
{
|
||||
EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id);
|
||||
if (in_my_outfits != MY_OUTFITS_NO)
|
||||
{
|
||||
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("Rename"));
|
||||
items.push_back(std::string("thumbnail"));
|
||||
|
||||
addDeleteContextMenuOptions(items, disabled_items);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isInboxFolder() // don't allow creation in inbox
|
||||
&& outfits_id != mUUID)
|
||||
{
|
||||
bool menu_items_added = false;
|
||||
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
|
||||
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
|
||||
{
|
||||
items.push_back(std::string("New Folder"));
|
||||
menu_items_added = true;
|
||||
}
|
||||
if (!isMarketplaceListingsFolder())
|
||||
{
|
||||
items.push_back(std::string("upload_def"));
|
||||
//items.push_back(std::string("create_new")); // <FS:Ansariel> Undo weird menu design
|
||||
items.push_back(std::string("New Script"));
|
||||
items.push_back(std::string("New Note"));
|
||||
items.push_back(std::string("New Gesture"));
|
||||
items.push_back(std::string("New Material"));
|
||||
items.push_back(std::string("New Clothes"));
|
||||
items.push_back(std::string("New Body Parts"));
|
||||
items.push_back(std::string("New Settings"));
|
||||
if (!LLEnvironment::instance().isInventoryEnabled())
|
||||
{
|
||||
disabled_items.push_back("New Settings");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
items.push_back(std::string("New Listing Folder"));
|
||||
}
|
||||
if (menu_items_added)
|
||||
{
|
||||
items.push_back(std::string("Create Separator"));
|
||||
}
|
||||
}
|
||||
getClipboardEntries(false, items, disabled_items, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID)
|
||||
|
|
@ -5058,7 +5188,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
|
|||
|
||||
if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren() && (type != LLFolderType::FT_OUTFIT))
|
||||
{
|
||||
items.push_back(std::string("Ungroup folder items"));
|
||||
const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
if (!gInventory.isObjectDescendentOf(mUUID, my_outfits))
|
||||
{
|
||||
items.push_back(std::string("Ungroup folder items"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -5910,13 +6044,24 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI
|
|||
// Note: creation will take time, so passing folder id to callback is slightly unreliable,
|
||||
// but so is collecting and passing descendants' ids
|
||||
inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel);
|
||||
gInventory.createNewCategory(dest_id,
|
||||
getInventoryModel()->createNewCategory(dest_id,
|
||||
LLFolderType::FT_OUTFIT,
|
||||
inv_cat->getName(),
|
||||
func,
|
||||
inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type, 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,
|
||||
inv_cat->getName(),
|
||||
func,
|
||||
inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id,
|
||||
LLUUID cat_dest_id,
|
||||
LLPointer<LLInventoryCallback> cb,
|
||||
|
|
@ -6113,7 +6258,9 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
|
|||
}
|
||||
else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit))
|
||||
{
|
||||
accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
|
||||
EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
|
||||
// don't allow items in my outfits' subfodlers, only in outfits and outfit's subfolders
|
||||
accept = res != MY_OUTFITS_SUBFOLDER && can_move_to_outfit(inv_item, move_is_into_current_outfit);
|
||||
}
|
||||
// <FS:Ansariel> FIRE-1392: Allow dragging all asset types into Landmarks folder
|
||||
//else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks))
|
||||
|
|
|
|||
|
|
@ -397,6 +397,7 @@ protected:
|
|||
void dropToFavorites(LLInventoryItem* inv_item, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToOutfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb = NULL);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Messy hacks for handling folder options
|
||||
|
|
|
|||
|
|
@ -2654,6 +2654,40 @@ bool can_share_item(const LLUUID& item_id)
|
|||
|
||||
return can_share;
|
||||
}
|
||||
|
||||
EMyOutfitsSubfolderType myoutfit_object_subfolder_type(
|
||||
LLInventoryModel* model,
|
||||
const LLUUID& obj_id,
|
||||
const LLUUID& my_outfits_id)
|
||||
{
|
||||
if (obj_id == my_outfits_id) return MY_OUTFITS_NO;
|
||||
|
||||
const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id);
|
||||
if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
return MY_OUTFITS_OUTFIT;
|
||||
}
|
||||
while (test_cat)
|
||||
{
|
||||
if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
return MY_OUTFITS_SUBOUTFIT;
|
||||
}
|
||||
|
||||
const LLUUID& parent_id = test_cat->getParentUUID();
|
||||
if (parent_id.isNull())
|
||||
{
|
||||
return MY_OUTFITS_NO;
|
||||
}
|
||||
if (parent_id == my_outfits_id)
|
||||
{
|
||||
return MY_OUTFITS_SUBFOLDER;
|
||||
}
|
||||
test_cat = model->getCategory(parent_id);
|
||||
}
|
||||
|
||||
return MY_OUTFITS_NO;
|
||||
}
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLMarketplaceValidator implementations
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -2782,6 +2816,11 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryIte
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLIsFolderType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
return cat && cat->getPreferredType() == mType;
|
||||
}
|
||||
|
||||
bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
if(mType == LLAssetType::AT_CATEGORY)
|
||||
|
|
|
|||
|
|
@ -128,6 +128,18 @@ std::string get_searchable_creator_name(LLInventoryModel* model, const LLUUID& i
|
|||
std::string get_searchable_UUID(LLInventoryModel* model, const LLUUID& item_id);
|
||||
bool can_share_item(const LLUUID& item_id);
|
||||
|
||||
enum EMyOutfitsSubfolderType
|
||||
{
|
||||
MY_OUTFITS_NO,
|
||||
MY_OUTFITS_SUBFOLDER,
|
||||
MY_OUTFITS_OUTFIT,
|
||||
MY_OUTFITS_SUBOUTFIT,
|
||||
};
|
||||
EMyOutfitsSubfolderType myoutfit_object_subfolder_type(
|
||||
LLInventoryModel* model,
|
||||
const LLUUID& obj_id,
|
||||
const LLUUID& my_outfits_id);
|
||||
|
||||
/** Miscellaneous global functions
|
||||
** **
|
||||
*******************************************************************************/
|
||||
|
|
@ -241,6 +253,24 @@ protected:
|
|||
// the type is the type passed in during construction.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLIsFolderType : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLIsFolderType(LLFolderType::EType type) : mType(type) {}
|
||||
virtual ~LLIsFolderType() {}
|
||||
virtual bool operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item);
|
||||
protected:
|
||||
LLFolderType::EType mType;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLIsType
|
||||
//
|
||||
// Implementation of a LLInventoryCollectFunctor which returns true if
|
||||
// the type is the type passed in during construction.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLIsType : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -60,10 +60,12 @@ static LLPanelInjector<LLInventoryGallery> t_inventory_gallery("inventory_galler
|
|||
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);
|
||||
bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm);
|
||||
void dropToMyOutfits(LLInventoryCategory* inv_cat);
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type);
|
||||
|
||||
class LLGalleryPanel: public LLPanel
|
||||
{
|
||||
|
|
@ -3751,7 +3753,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
|
||||
if (is_movable && move_is_into_outfit)
|
||||
{
|
||||
if (dest_id == my_outifts_id)
|
||||
if ((inv_cat->getPreferredType() != LLFolderType::FT_NONE) && (inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT))
|
||||
{
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
is_movable = false;
|
||||
}
|
||||
else if (dest_id == my_outifts_id)
|
||||
{
|
||||
if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings)
|
||||
{
|
||||
|
|
@ -3768,13 +3775,39 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
is_movable = false;
|
||||
}
|
||||
}
|
||||
else if (dest_cat && dest_cat->getPreferredType() == LLFolderType::FT_NONE)
|
||||
else if (!dest_cat)
|
||||
{
|
||||
is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT));
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else
|
||||
{
|
||||
is_movable = false;
|
||||
EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id);
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_OUTFIT)
|
||||
{
|
||||
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)
|
||||
{
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else if (dest_res == MY_OUTFITS_SUBFOLDER && inv_res == MY_OUTFITS_SUBOUTFIT)
|
||||
{
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
|
||||
{
|
||||
is_movable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_movable = false;
|
||||
tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_movable && move_is_into_current_outfit && is_link)
|
||||
|
|
@ -3900,9 +3933,70 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
|
|||
|
||||
if (dest_id == my_outifts_id)
|
||||
{
|
||||
// Category can contains objects,
|
||||
// create a new folder and populate it with links to original objects
|
||||
dropToMyOutfits(inv_cat);
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT)
|
||||
{
|
||||
gInventory.changeCategoryParent(
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
dest_id,
|
||||
move_is_into_trash);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Category can contains objects,
|
||||
// create a new folder and populate it with links to original objects
|
||||
dropToMyOutfits(inv_cat);
|
||||
}
|
||||
}
|
||||
else if (move_is_into_my_outfits)
|
||||
{
|
||||
EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id);
|
||||
EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
|
||||
switch (inv_res)
|
||||
{
|
||||
case MY_OUTFITS_NO:
|
||||
// Moning from outside outfits into outfits
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
{
|
||||
// turn it into outfit
|
||||
dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE);
|
||||
}
|
||||
break;
|
||||
case MY_OUTFITS_SUBFOLDER:
|
||||
case MY_OUTFITS_OUTFIT:
|
||||
// only permit moving subfodlers and outfits into other subfolders
|
||||
if (dest_res == MY_OUTFITS_SUBFOLDER)
|
||||
{
|
||||
gInventory.changeCategoryParent(
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
dest_id,
|
||||
move_is_into_trash);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false); // mot permitted, shouldn't have accepted
|
||||
}
|
||||
break;
|
||||
case MY_OUTFITS_SUBOUTFIT:
|
||||
if (dest_res == MY_OUTFITS_SUBOUTFIT || dest_res == MY_OUTFITS_OUTFIT)
|
||||
{
|
||||
gInventory.changeCategoryParent(
|
||||
(LLViewerInventoryCategory*)inv_cat,
|
||||
dest_id,
|
||||
move_is_into_trash);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false); // mot permitted, shouldn't have accepted
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if target is current outfit folder we use link
|
||||
else if (move_is_into_current_outfit &&
|
||||
|
|
@ -4047,3 +4141,11 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat)
|
|||
inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1);
|
||||
gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
||||
void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id, LLFolderType::EType preferred_type)
|
||||
{
|
||||
// Note: creation will take time, so passing folder id to callback is slightly unreliable,
|
||||
// but so is collecting and passing descendants' ids
|
||||
inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1);
|
||||
gInventory.createNewCategory(dest_id, preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -598,7 +598,9 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
bool is_trash = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
|
||||
bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
|
||||
bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
|
||||
bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
|
||||
const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
bool is_outfits= (selected_id == my_outfits);
|
||||
bool is_in_outfits = is_outfits || gInventory.isObjectDescendentOf(selected_id, my_outfits);
|
||||
bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
|
||||
//bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
|
||||
|
||||
|
|
@ -737,7 +739,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
}
|
||||
else
|
||||
{
|
||||
if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits)
|
||||
if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits && !is_in_outfits)
|
||||
{
|
||||
LLViewerInventoryCategory* category = gInventory.getCategory(selected_id);
|
||||
if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category))
|
||||
|
|
@ -781,15 +783,26 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
|
|||
items.push_back(std::string("upload_def"));
|
||||
}
|
||||
|
||||
if(is_outfits && !isRootFolder())
|
||||
if(is_outfits)
|
||||
{
|
||||
items.push_back(std::string("New Outfit"));
|
||||
EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(&gInventory, selected_id, my_outfits);
|
||||
if (res != MY_OUTFITS_OUTFIT && res != MY_OUTFITS_SUBOUTFIT)
|
||||
{
|
||||
items.push_back(std::string("New Outfit"));
|
||||
}
|
||||
items.push_back(std::string("New Outfit Folder"));
|
||||
items.push_back(std::string("Delete"));
|
||||
items.push_back(std::string("Rename"));
|
||||
if (!get_is_category_and_children_removable(&gInventory, selected_id, false))
|
||||
{
|
||||
disabled_items.push_back(std::string("Delete"));
|
||||
}
|
||||
}
|
||||
|
||||
items.push_back(std::string("Subfolder Separator"));
|
||||
if (!is_system_folder && !isRootFolder())
|
||||
if (!is_system_folder && !isRootFolder() && !is_outfits)
|
||||
{
|
||||
if(has_children && (folder_type != LLFolderType::FT_OUTFIT))
|
||||
if(has_children && (folder_type != LLFolderType::FT_OUTFIT) && !is_in_outfits)
|
||||
{
|
||||
items.push_back(std::string("Ungroup folder items"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1093,7 +1093,8 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
|||
return;
|
||||
}
|
||||
|
||||
if (preferred_type != LLFolderType::FT_NONE)
|
||||
if (preferred_type != LLFolderType::FT_NONE
|
||||
&& preferred_type != LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
// Ultimately this should only be done for non-singleton
|
||||
// types. Requires back-end changes to guarantee that others
|
||||
|
|
@ -3805,7 +3806,7 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
|
|||
|
||||
fileXML.close();
|
||||
|
||||
LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
|
||||
LL_INFOS(LOG_INV) << "Inventory saved: " << (S32)cat_count << " categories, " << (S32)it_count << " items." << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1242,6 +1242,12 @@ void LLMeshRepoThread::run()
|
|||
LL_WARNS(LOG_MESH) << "Convex decomposition unable to be quit." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
void LLMeshRepoThread::cleanup()
|
||||
{
|
||||
mShuttingDown = true;
|
||||
mSignal->broadcast();
|
||||
mMeshThreadPool->close();
|
||||
}
|
||||
|
||||
// Mutex: LLMeshRepoThread::mMutex must be held on entry
|
||||
void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
|
||||
|
|
@ -1565,6 +1571,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
|
|||
[mesh_id, buffer, size]
|
||||
()
|
||||
{
|
||||
if (gMeshRepo.mThread->isShuttingDown())
|
||||
{
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
if (!gMeshRepo.mThread->skinInfoReceived(mesh_id, buffer, size))
|
||||
{
|
||||
// either header is faulty or something else overwrote the cache
|
||||
|
|
@ -2093,6 +2104,11 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
|||
[params, mesh_id, lod, buffer, size]
|
||||
()
|
||||
{
|
||||
if (gMeshRepo.mThread->isShuttingDown())
|
||||
{
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
if (gMeshRepo.mThread->lodReceived(params, lod, buffer, size) == MESH_OK)
|
||||
{
|
||||
LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh body for ID " << mesh_id << " - was retrieved from the cache." << LL_ENDL;
|
||||
|
|
@ -3899,6 +3915,11 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
|
|||
[shrd_handler, data, data_size]
|
||||
()
|
||||
{
|
||||
if (gMeshRepo.mThread->isShuttingDown())
|
||||
{
|
||||
delete[] data;
|
||||
return;
|
||||
}
|
||||
LLMeshLODHandler* handler = (LLMeshLODHandler * )shrd_handler.get();
|
||||
handler->processLod(data, data_size);
|
||||
delete[] data;
|
||||
|
|
@ -4012,6 +4033,11 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
|
|||
[shrd_handler, data, data_size]
|
||||
()
|
||||
{
|
||||
if (gMeshRepo.mThread->isShuttingDown())
|
||||
{
|
||||
delete[] data;
|
||||
return;
|
||||
}
|
||||
LLMeshSkinInfoHandler* handler = (LLMeshSkinInfoHandler*)shrd_handler.get();
|
||||
handler->processSkin(data, data_size);
|
||||
delete[] data;
|
||||
|
|
@ -4235,8 +4261,7 @@ void LLMeshRepository::shutdown()
|
|||
mUploads[i]->discard() ; //discard the uploading requests.
|
||||
}
|
||||
|
||||
mThread->mSignal->broadcast();
|
||||
mThread->mMeshThreadPool->close();
|
||||
mThread->cleanup();
|
||||
|
||||
while (!mThread->isStopped())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -531,6 +531,8 @@ public:
|
|||
~LLMeshRepoThread();
|
||||
|
||||
virtual void run();
|
||||
void cleanup();
|
||||
bool isShuttingDown() { return mShuttingDown; }
|
||||
|
||||
void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||
void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||
|
|
@ -611,6 +613,7 @@ private:
|
|||
U8* getDiskCacheBuffer(S32 size);
|
||||
S32 mDiskCacheBufferSize = 0;
|
||||
U8* mDiskCacheBuffer = nullptr;
|
||||
bool mShuttingDown = false;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -890,6 +890,50 @@ void LLOutfitListBase::observerCallback(const LLUUID& category_id)
|
|||
refreshList(category_id);
|
||||
}
|
||||
|
||||
class LLIsOutfitListFolder : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLIsOutfitListFolder()
|
||||
{
|
||||
mOutfitsId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
|
||||
}
|
||||
virtual ~LLIsOutfitListFolder() {}
|
||||
|
||||
bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override
|
||||
{
|
||||
if (cat)
|
||||
{
|
||||
if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (cat->getPreferredType() == LLFolderType::FT_NONE
|
||||
&& cat->getParentUUID() == mOutfitsId)
|
||||
{
|
||||
LLViewerInventoryCategory* inv_cat = dynamic_cast<LLViewerInventoryCategory*>(cat);
|
||||
if (inv_cat && inv_cat->getDescendentCount() > 3)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* cats;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
|
||||
if (cats->empty() // protection against outfits inside
|
||||
&& items->size() > 3) // eyes, skin, hair and shape are required
|
||||
{
|
||||
// For now assume this to be an old style outfit, not a subfolder
|
||||
// but ideally no such 'outfits' should be left in My Outfits
|
||||
// Todo: stop counting FT_NONE as outfits,
|
||||
// convert obvious outfits into FT_OUTFIT
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected:
|
||||
LLUUID mOutfitsId;
|
||||
};
|
||||
|
||||
void LLOutfitListBase::refreshList(const LLUUID& category_id)
|
||||
{
|
||||
bool wasNull = mRefreshListState.CategoryUUID.isNull();
|
||||
|
|
@ -899,36 +943,13 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
|
|||
LLInventoryModel::item_array_t item_array;
|
||||
|
||||
// Collect all sub-categories of a given category.
|
||||
// <FS:ND> FIRE-6958/VWR-2862; Make sure to only collect folders of type FT_OUTFIT
|
||||
class ndOutfitsCollector: public LLIsType
|
||||
{
|
||||
public:
|
||||
ndOutfitsCollector()
|
||||
: LLIsType( LLAssetType::AT_CATEGORY )
|
||||
{ }
|
||||
|
||||
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
|
||||
{
|
||||
if( !LLIsType::operator()( cat, item ) )
|
||||
return false;
|
||||
|
||||
if( cat && LLFolderType::FT_OUTFIT == cat->getPreferredType() )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// LLIsType is_category(LLAssetType::AT_CATEGORY);
|
||||
ndOutfitsCollector is_category;
|
||||
// </FS:ND>
|
||||
|
||||
LLIsOutfitListFolder is_outfit;
|
||||
gInventory.collectDescendentsIf(
|
||||
category_id,
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_category);
|
||||
is_outfit);
|
||||
|
||||
// Memorize item names for each UUID
|
||||
std::map<LLUUID, std::string> names;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
<menu_item_call label="Fundstücke ausleeren" name="Empty Lost And Found"/>
|
||||
<menu_item_call label="Neuer Ordner" name="New Folder"/>
|
||||
<menu_item_call label="Neuer Ordner" name="New Listing Folder"/>
|
||||
<menu_item_call label="Neuer Ordner" name="New Outfit Folder"/>
|
||||
<menu_item_call label="Neues Outfit" name="New Outfit"/>
|
||||
<menu_item_call label="Neues Skript" name="New Script"/>
|
||||
<menu_item_call label="Neue Notizkarte" name="New Note"/>
|
||||
|
|
|
|||
|
|
@ -667,6 +667,9 @@ Wenn Sie der Ansicht sind, dass Sie diese Meldung fälschlicherweise erhalten ha
|
|||
<string name="TooltipCantCreateOutfit">
|
||||
Ein oder mehrere Objekte können nicht innerhalb von „Outfits“ verwendet werden.
|
||||
</string>
|
||||
<string name="TooltipCantMoveOutfitIntoOutfit">
|
||||
Outfit kann nicht in ein anderes Outfit verschoben werden.
|
||||
</string>
|
||||
<string name="TooltipDragOntoOwnChild">
|
||||
Sie können einen Ordner nicht in einen seiner untergeordneten Ordner verschieben
|
||||
</string>
|
||||
|
|
|
|||
|
|
@ -159,6 +159,14 @@
|
|||
function="Inventory.DoCreate"
|
||||
parameter="category" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="New Folder"
|
||||
layout="topleft"
|
||||
name="New Outfit Folder">
|
||||
<menu_item_call.on_click
|
||||
function="Inventory.DoCreate"
|
||||
parameter="category" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="New Outfit"
|
||||
layout="topleft"
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
|
|||
<string name="TooltipOutboxMixedStock">All items in a stock folder must have the same type and permission</string>
|
||||
<string name="TooltipOutfitNotInInventory">You can only put items or outfits from your personal inventory into "Outfits"</string>
|
||||
<string name="TooltipCantCreateOutfit">One or more items can't be used inside "Outfits"</string>
|
||||
<string name="TooltipCantMoveOutfitIntoOutfit">Can not move an outfit into another outfit</string>
|
||||
|
||||
<string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string>
|
||||
<string name="TooltipDragOntoSelf">You can't move a folder into itself</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue