diff options
author | Vadim Savchuk <vsavchuk@productengine.com> | 2010-06-02 20:46:16 +0300 |
---|---|---|
committer | Vadim Savchuk <vsavchuk@productengine.com> | 2010-06-02 20:46:16 +0300 |
commit | 671625695fc44adc430a7ddf3be158ce26a61cc6 (patch) | |
tree | 660eebb8544495a1653310c52663e7443920ff70 /indra/newview/lloutfitslist.cpp | |
parent | 5a29fb38312d1a8ae39d1f408754475ecffaebc8 (diff) |
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
Diffstat (limited to 'indra/newview/lloutfitslist.cpp')
-rw-r--r-- | indra/newview/lloutfitslist.cpp | 142 |
1 files changed, 139 insertions, 3 deletions
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 98ec272e96..5c8b3d1894 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -43,6 +43,8 @@ #include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "lllistcontextmenu.h" +#include "llnotificationsutil.h" +#include "llsidetray.h" #include "lltransutil.h" #include "llviewermenu.h" #include "llvoavatar.h" @@ -53,6 +55,28 @@ static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y); ////////////////////////////////////////////////////////////////////////// +// Collect non-removable folders and items. +class LLFindNonRemovableObjects : public LLInventoryCollectFunctor +{ +public: + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if (item) + { + return !get_is_item_removable(&gInventory, item->getUUID()); + } + if (cat) + { + return !get_is_category_removable(&gInventory, cat->getUUID()); + } + + llwarns << "Not a category and not an item?" << llendl; + return false; + } +}; + +////////////////////////////////////////////////////////////////////////// + class OutfitContextMenu : public LLListContextMenu { protected: @@ -68,12 +92,124 @@ protected: boost::bind(&LLAppearanceMgr::addCategoryToCurrentOutfit, &LLAppearanceMgr::instance(), selected_id)); registrar.add("Outfit.TakeOff", boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); - // *TODO: implement this - // registrar.add("Outfit.Rename", boost::bind()); - // registrar.add("Outfit.Delete", boost::bind()); + registrar.add("Outfit.Edit", boost::bind(editOutfit)); + registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); + registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id)); + + enable_registrar.add("Outfit.OnEnable", boost::bind(&OutfitContextMenu::onEnable, this, _2)); return createFromFile("menu_outfit_tab.xml"); } + + bool onEnable(const LLSD& data) + { + std::string param = data.asString(); + LLUUID outfit_cat_id = mUUIDs.back(); + bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; + + if ("wear_replace" == param) + { + return !is_worn; + } + else if ("wear_add" == param) + { + return !is_worn; + } + else if ("take_off" == param) + { + return is_worn; + } + else if ("edit" == param) + { + return is_worn; + } + else if ("rename" == param) + { + return get_is_category_renameable(&gInventory, outfit_cat_id); + } + else if ("delete" == param) + { + return canDeleteOutfit(outfit_cat_id); + } + + return true; + } + + static void editOutfit() + { + LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit")); + } + + static void renameOutfit(const LLUUID& outfit_cat_id) + { + LLViewerInventoryCategory* outfit_cat = gInventory.getCategory(outfit_cat_id); + llassert(outfit_cat); + if (!outfit_cat) return; + + LLSD args; + args["NAME"] = outfit_cat->getName(); + + LLSD payload; + payload["cat_id"] = outfit_cat_id; + + LLNotificationsUtil::add("RenameOutfit", args, payload, boost::bind(onRename, _1, _2)); + } + + // User typed new outfit name. + static void onRename(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); + } + } + + static bool canDeleteOutfit(const LLUUID& outfit_cat_id) + { + // Disallow removing the base outfit. + if (outfit_cat_id == LLAppearanceMgr::instance().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; + } + + static void deleteOutfit(const LLUUID& outfit_cat_id) + { + remove_category(&gInventory, outfit_cat_id); + } }; ////////////////////////////////////////////////////////////////////////// |