From 671625695fc44adc430a7ddf3be158ce26a61cc6 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Wed, 2 Jun 2010 20:46:16 +0300 Subject: EXT-6726 WIP Added more menus to the Appearance SP. Done: - Implemented creating new wearables via My Outfits gear menu. - Implemented renaming/removing/editing an outfit via My Outfits context menu. - Implemented "Attach to..." / "Attach to HUD..." context submenus. - Now disabling (instead of hiding) irrelevant wearable context menu items. - Added "Take Off / Detach" context menu item that's shown for clothes and attachments. Useful if you selected a bunch of items and want to take them all off. - Fixed taking off an outfit (not all wearables were taken off because of a wrong inventory collector). - Fixed crash when editing a skirt (reference to a missing string). - In LLWearableItemsList::ContextMenu::updateItemsVisibility renamed variables and introduced MASK_UNKNOWN per Nyx's request. Known issues: - "Attach to..." context menus may be displayed partially off-screen (there is the same bug in the inventory panel). - The way we invoke wearable editing panel after the wearable gets created is currently a hack. TODO: - Wear / take off / rename / delete an outfit via My Outfits gear menu (currently not implemented because of missing selection support in My Outfits). - Add "Create new..." to body part / clothing context menu in Edit Outfit. - Add "Create new..." submenus to the Edit Outfit gear menu. Reviewed by Nyx at https://codereview.productengine.com/secondlife/r/466/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f27e632180..cf45743a48 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -714,7 +714,7 @@ void LLAppearanceMgr::takeOffOutfit(const LLUUID& cat_id) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - LLFindWearables collector; + LLFindWorn collector; gInventory.collectDescendentsIf(cat_id, cats, items, FALSE, collector); -- cgit v1.2.3 From 142a6c3b8fa9e286c0336236d1eccd9a6725f06a Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Wed, 2 Jun 2010 20:46:16 +0300 Subject: EXT-6726 WIP Added missing menu items to the Appearance SP. - Hooked up Wear / Take off / Rename / Delete items in the My Outfits gear menu. - Added "Create new..." to body part / clothing context menu in Edit Outfit. - Added "Create new..." submenus to the Edit Outfit gear menu. - Disabling the "Take Off" menu item of the clothing context menu in the Edit Outfit panel when it's irrelevant. Reviewed by Nyx at https://codereview.productengine.com/secondlife/r/494/ --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index cf45743a48..75ffb9f329 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -704,6 +704,40 @@ void LLAppearanceMgr::replaceCurrentOutfit(const LLUUID& new_outfit) wearInventoryCategory(cat, false, false); } +// Open outfit renaming dialog. +void LLAppearanceMgr::renameOutfit(const LLUUID& outfit_id) +{ + LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_id); + if (!cat) + { + return; + } + + LLSD args; + args["NAME"] = cat->getName(); + + LLSD payload; + payload["cat_id"] = outfit_id; + + LLNotificationsUtil::add("RenameOutfit", args, payload, boost::bind(onOutfitRename, _1, _2)); +} + +// User typed new outfit name. +// static +void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + std::string outfit_name = response["new_name"].asString(); + LLStringUtil::trim(outfit_name); + if (!outfit_name.empty()) + { + LLUUID cat_id = notification["payload"]["cat_id"].asUUID(); + rename_category(&gInventory, cat_id, outfit_name); + } +} + void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id) { LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); @@ -842,6 +876,41 @@ BOOL LLAppearanceMgr::getCanMakeFolderIntoOutfit(const LLUUID& folder_id) return ((required_wearables & folder_wearables) == required_wearables); } +bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) +{ + // Disallow removing the base outfit. + if (outfit_cat_id == getBaseOutfitUUID()) + { + return false; + } + + // Check if the outfit folder itself is removable. + if (!get_is_category_removable(&gInventory, outfit_cat_id)) + { + return false; + } + + // Check if the folder contains worn items. + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWorn filter_worn; + gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_worn); + if (!items.empty()) + { + return false; + } + + // Check for the folder's non-removable descendants. + LLFindNonRemovableObjects filter_non_removable; + LLInventoryModel::item_array_t::const_iterator it; + gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_non_removable); + if (!cats.empty() || !items.empty()) + { + return false; + } + + return true; +} void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) { -- cgit v1.2.3 From 1e13fd9260696e10df05dcb81803649c805b95cd Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Wed, 2 Jun 2010 14:58:42 -0700 Subject: Partial fix for EXT-6255 (Fix ruthing/replacement wearables logic). This change should make the logic for missing wearables match what's in the doc linked from the jira. It doesn't address the case of missing attachments, which will be more complicated. Reviewed by Nyx and vir. --- indra/newview/llappearancemgr.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 75ffb9f329..e6f363028a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -276,12 +276,14 @@ void LLWearableHoldingPattern::checkMissingWearables() if (found_by_type[type] > 0) continue; if ( - // Need to recover if at least one wearable of that type - // was requested but none was found (prevent missing - // pants) - (requested_by_type[type] > 0) || - // or if type is a body part and no wearables were found. - ((type == LLWearableType::WT_SHAPE) || (type == LLWearableType::WT_SKIN) || (type == LLWearableType::WT_HAIR) || (type == LLWearableType::WT_EYES))) + // If at least one wearable of certain types (pants/shirt/skirt) + // was requested but none was found, create a default asset as a replacement. + // In all other cases, don't do anything. + // For critical types (shape/hair/skin/eyes), this will keep the avatar as a cloud + // due to logic in LLVOAvatarSelf::getIsCloud(). + // For non-critical types (tatoo, socks, etc.) the wearable will just be missing. + (requested_by_type[type] > 0) && + ((type == LLWearableType::WT_PANTS) || (type == LLWearableType::WT_SHIRT) || (type == LLWearableType::WT_SKIRT))) { mTypesToRecover.insert(type); mTypesToLink.insert(type); -- cgit v1.2.3 From 2caa710a46d3baa1e6a884961f1ff756d35ef5df Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Thu, 3 Jun 2010 20:06:25 -0400 Subject: VWR-19699 WIP Correct operations for wear and replace on wearables Resident-submitted patch, cleaned up so it matches style and compiles/builds well. Appears to work for stated goals but will need some more UI work to ensure consistency. WIP checkin, will be code reviewed before pushing. --- indra/newview/llappearancemgr.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e6f363028a..5071b1c14a 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -656,15 +656,40 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { if (item_id_to_wear.isNull()) return false; - //only the item from a user's inventory is allowed - if (!gInventory.isObjectDescendentOf(item_id_to_wear, gInventory.getRootFolderID())) return false; - LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); if (!item_to_wear) return false; + if (!item_to_wear->isFinished()) + { + LLNotificationsUtil::add("CannotWearInfoNotComplete"); + return false; + } + else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID())) + { + LLPointer cb = new WearOnAvatarCallback(replace); + copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb); + return false; + } + else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID())) + { + return false; // not in library and not in agent's inventory + } + else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH))) + { + LLNotificationsUtil::add("CannotWearTrash"); + } + switch (item_to_wear->getType()) { case LLAssetType::AT_CLOTHING: + if (replace && gAgentWearables.areWearablesLoaded()) + { + S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType()); + if (wearable_count != 0) + { + removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); + } + } case LLAssetType::AT_BODYPART: // Don't wear anything until initial wearables are loaded, can // destroy clothing items. @@ -676,7 +701,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. - if (replace || item_to_wear->getType() == LLAssetType::AT_BODYPART) + if (item_to_wear->getType() == LLAssetType::AT_BODYPART) { removeCOFLinksOfType(item_to_wear->getWearableType(), false); } -- cgit v1.2.3 From 47beb6dc9c4f7c1557536f8116cc98b8bbc24629 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Thu, 3 Jun 2010 21:09:49 -0400 Subject: AVP-44 WIP Multi-wearables architecture One step closer to full support of multi-wearables architecture code will be reviewed before pushing. --- indra/newview/llappearancemgr.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5071b1c14a..9da47c9214 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -682,14 +682,15 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up switch (item_to_wear->getType()) { case LLAssetType::AT_CLOTHING: - if (replace && gAgentWearables.areWearablesLoaded()) + if (gAgentWearables.areWearablesLoaded()) { S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType()); - if (wearable_count != 0) + if ((replace && wearable_count != 0) || + (wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) ) { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false); } - } + } case LLAssetType::AT_BODYPART: // Don't wear anything until initial wearables are loaded, can // destroy clothing items. @@ -1584,6 +1585,7 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update item_array, LLInventoryModel::EXCLUDE_TRASH); bool linked_already = false; + U32 count = 0; for (S32 i=0; iisWearableType()) && (vitem->getWearableType() == wearable_type)) + else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type)) { - if (inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type)) + if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type)) + { + gInventory.purgeObject(inv_item->getUUID()); + } + ++count; + + // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE + if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) { gInventory.purgeObject(inv_item->getUUID()); } } } + if (linked_already) { if (do_update) -- cgit v1.2.3 From 244321e70cf341ca0542a9963d9e1e68cafca8d5 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Fri, 4 Jun 2010 17:34:46 -0400 Subject: AVP-44 VWR-19699 FIX Multi-wearables and wearable replacement logic Cleaned up a few things upon code review. Code reviewed by vir for this checkin as well as following previous commits: a801af3728ee af42810b946c --- indra/newview/llappearancemgr.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 9da47c9214..a899926938 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -659,12 +659,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear); if (!item_to_wear) return false; - if (!item_to_wear->isFinished()) - { - LLNotificationsUtil::add("CannotWearInfoNotComplete"); - return false; - } - else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID())) + if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID())) { LLPointer cb = new WearOnAvatarCallback(replace); copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(),cb); @@ -677,6 +672,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH))) { LLNotificationsUtil::add("CannotWearTrash"); + return false; } switch (item_to_wear->getType()) @@ -1605,15 +1601,14 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update // type? If so, new item will replace old. else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type)) { + ++count; if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type)) { gInventory.purgeObject(inv_item->getUUID()); } - ++count; - - // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE - if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) + else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) { + // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE gInventory.purgeObject(inv_item->getUUID()); } } -- cgit v1.2.3