summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorVadim Savchuk <vsavchuk@productengine.com>2010-06-02 20:46:16 +0300
committerVadim Savchuk <vsavchuk@productengine.com>2010-06-02 20:46:16 +0300
commit142a6c3b8fa9e286c0336236d1eccd9a6725f06a (patch)
tree1fdaaccdf2e5e0c9d13a93a4953fd9c16987797e /indra
parent671625695fc44adc430a7ddf3be158ce26a61cc6 (diff)
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
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llappearancemgr.cpp69
-rw-r--r--indra/newview/llappearancemgr.h6
-rw-r--r--indra/newview/llcofwearables.cpp61
-rw-r--r--indra/newview/llinventoryfunctions.cpp15
-rw-r--r--indra/newview/llinventoryfunctions.h6
-rw-r--r--indra/newview/lloutfitslist.cpp92
-rw-r--r--indra/newview/lloutfitslist.h8
-rw-r--r--indra/newview/llpaneloutfitedit.cpp82
-rw-r--r--indra/newview/llpaneloutfitedit.h1
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp113
-rw-r--r--indra/newview/llpaneloutfitsinventory.h6
-rw-r--r--indra/newview/llwearableitemslist.cpp1
-rw-r--r--indra/newview/skins/default/xui/en/menu_cof_body_part.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_cof_clothing.xml14
-rw-r--r--indra/newview/skins/default/xui/en/menu_cof_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearable_list_item.xml3
17 files changed, 343 insertions, 164 deletions
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)
{
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index dbde055c3a..f1beef5857 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -59,6 +59,7 @@ public:
void wearOutfitByName(const std::string& name);
void changeOutfit(bool proceed, const LLUUID& category, bool append);
void replaceCurrentOutfit(const LLUUID& new_outfit);
+ void renameOutfit(const LLUUID& outfit_id);
void takeOffOutfit(const LLUUID& cat_id);
void addCategoryToCurrentOutfit(const LLUUID& cat_id);
@@ -69,6 +70,9 @@ public:
// Return whether this folder contains minimal contents suitable for making a full outfit.
BOOL getCanMakeFolderIntoOutfit(const LLUUID& folder_id);
+ // Determine whether a given outfit can be removed.
+ bool getCanRemoveOutfit(const LLUUID& outfit_cat_id);
+
// Copy all items in a category.
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb);
@@ -180,6 +184,8 @@ private:
void purgeCategory(const LLUUID& category, bool keep_outfit_links);
void purgeBaseOutfitLink(const LLUUID& category);
+ static void onOutfitRename(const LLSD& notification, const LLSD& response);
+
std::set<LLUUID> mRegisteredAttachments;
bool mAttachmentInvLinkEnabled;
bool mOutfitIsDirty;
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 6acd16326a..79ce2f8f6b 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -45,6 +45,7 @@
#include "llwearableitemslist.h"
#include "llpaneloutfitedit.h"
#include "llsidetray.h"
+#include "lltrans.h"
static LLRegisterPanelClassWrapper<LLCOFWearables> t_cof_wearables("cof_wearables");
@@ -52,6 +53,39 @@ const LLSD REARRANGE = LLSD().with("rearrange", LLSD());
static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR;
+//////////////////////////////////////////////////////////////////////////
+
+class CofContextMenu : public LLListContextMenu
+{
+protected:
+ static void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)
+ {
+ LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new");
+
+ // Hide the "Create new <WEARABLE_TYPE>" if it's irrelevant.
+ LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
+ if (!item || !item->isWearableType())
+ {
+ menu_item->setVisible(FALSE);
+ return;
+ }
+
+ // Set proper label for the "Create new <WEARABLE_TYPE>" menu item.
+ LLStringUtil::format_map_t args;
+ LLWearableType::EType w_type = item->getWearableType();
+ args["[WEARABLE_TYPE]"] = LLWearableType::getTypeDefaultNewName(w_type);
+ std::string new_label = LLTrans::getString("CreateNewWearable", args);
+ menu_item->setLabel(new_label);
+ }
+
+ static void createNew(const LLUUID& item_id)
+ {
+ LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
+ if (!item || !item->isWearableType()) return;
+
+ LLAgentWearables::createWearable(item->getWearableType(), true);
+ }
+};
//////////////////////////////////////////////////////////////////////////
@@ -72,7 +106,7 @@ protected:
//////////////////////////////////////////////////////////////////////////
-class CofClothingContextMenu : public LLListContextMenu
+class CofClothingContextMenu : public CofContextMenu
{
protected:
@@ -87,10 +121,17 @@ protected:
registrar.add("Clothing.MoveUp", boost::bind(moveWearable, selected_id, false));
registrar.add("Clothing.MoveDown", boost::bind(moveWearable, selected_id, true));
registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
+ registrar.add("Clothing.Create", boost::bind(createNew, selected_id));
enable_registrar.add("Clothing.OnEnable", boost::bind(&CofClothingContextMenu::onEnable, this, _2));
- return createFromFile("menu_cof_clothing.xml");
+ LLContextMenu* menu = createFromFile("menu_cof_clothing.xml");
+ llassert(menu);
+ if (menu)
+ {
+ updateCreateWearableLabel(menu, selected_id);
+ }
+ return menu;
}
bool onEnable(const LLSD& data)
@@ -106,6 +147,10 @@ protected:
{
return gAgentWearables.canMoveWearable(selected_id, true);
}
+ else if ("take_off" == param)
+ {
+ return get_is_item_worn(selected_id);
+ }
else if ("edit" == param)
{
return gAgentWearables.isWearableModifiable(selected_id);
@@ -120,12 +165,11 @@ protected:
LLViewerInventoryItem* item = gInventory.getItem(item_id);
return LLAppearanceMgr::instance().moveWearable(item, closer_to_body);
}
-
};
//////////////////////////////////////////////////////////////////////////
-class CofBodyPartContextMenu : public LLListContextMenu
+class CofBodyPartContextMenu : public CofContextMenu
{
protected:
@@ -140,10 +184,17 @@ protected:
LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));
registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));
registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
+ registrar.add("BodyPart.Create", boost::bind(createNew, selected_id));
enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2));
- return createFromFile("menu_cof_body_part.xml");
+ LLContextMenu* menu = createFromFile("menu_cof_body_part.xml");
+ llassert(menu);
+ if (menu)
+ {
+ updateCreateWearableLabel(menu, selected_id);
+ }
+ return menu;
}
bool onEnable(const LLSD& data)
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 9fe9d2de8e..817da34c61 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -542,6 +542,21 @@ bool LLFindWorn::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
return item && get_is_item_worn(item->getUUID());
}
+bool LLFindNonRemovableObjects::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;
+}
+
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 5c07a3190f..33b52cfd5e 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -333,6 +333,12 @@ public:
virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
};
+// Collect non-removable folders and items.
+class LLFindNonRemovableObjects : public LLInventoryCollectFunctor
+{
+public:
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+};
/** Inventory Collector Functions
** **
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 5c8b3d1894..94bf2f4c7a 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -55,28 +55,6 @@ 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:
@@ -129,7 +107,7 @@ protected:
}
else if ("delete" == param)
{
- return canDeleteOutfit(outfit_cat_id);
+ return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
}
return true;
@@ -142,68 +120,7 @@ protected:
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;
+ LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
}
static void deleteOutfit(const LLUUID& outfit_cat_id)
@@ -443,6 +360,10 @@ void LLOutfitsList::performAction(std::string action)
{
LLAppearanceMgr::instance().wearInventoryCategory( cat, FALSE, TRUE );
}
+ else if ("rename_outfit" == action)
+ {
+ LLAppearanceMgr::instance().renameOutfit(mSelectedOutfitUUID);
+ }
}
void LLOutfitsList::setFilterSubString(const std::string& string)
@@ -717,4 +638,5 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
S32 header_bottom = tab->getLocalRect().getHeight() - tab->getHeaderHeight();
return y >= header_bottom;
}
+
// EOF
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index d3da850e19..4784ee777b 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -66,12 +66,12 @@ public:
void refreshList(const LLUUID& category_id);
- void onSelectionChange(LLUICtrl* ctrl);
-
void performAction(std::string action);
void setFilterSubString(const std::string& string);
+ const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
+
private:
/**
* Reads xml with accordion tab and Flat list from xml file.
@@ -110,6 +110,10 @@ private:
void onAccordionTabDoubleClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
+ void onSelectionChange(LLUICtrl* ctrl);
+
+ static void onOutfitRename(const LLSD& notification, const LLSD& response);
+
LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 85b4259a29..42de6d1ef4 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -79,6 +79,70 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
static const std::string REVERT_BTN("revert_btn");
+class LLPanelOutfitEditGearMenu
+{
+public:
+ static LLMenuGL* create()
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("Wearable.Create", boost::bind(onCreate, _2));
+
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ "menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+ llassert(menu);
+ if (menu)
+ {
+ populateCreateWearableSubmenus(menu);
+ menu->buildDrawLabels();
+ }
+
+ return menu;
+ }
+
+private:
+ static void onCreate(const LLSD& param)
+ {
+ LLWearableType::EType type = LLWearableType::typeNameToType(param.asString());
+ if (type == LLWearableType::WT_NONE)
+ {
+ llwarns << "Invalid wearable type" << llendl;
+ return;
+ }
+
+ LLAgentWearables::createWearable(type, true);
+ }
+
+ // Populate the menu with items like "New Skin", "New Pants", etc.
+ static void populateCreateWearableSubmenus(LLMenuGL* menu)
+ {
+ LLView* menu_clothes = gMenuHolder->findChildView("COF.Gear.New_Clothes", FALSE);
+ LLView* menu_bp = gMenuHolder->findChildView("COF.Geear.New_Body_Parts", FALSE);
+
+ if (!menu_clothes || !menu_bp)
+ {
+ llassert(menu_clothes && menu_bp);
+ return;
+ }
+
+ for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i)
+ {
+ LLWearableType::EType type = (LLWearableType::EType) i;
+ const std::string& type_name = LLWearableType::getTypeName(type);
+
+ LLMenuItemCallGL::Params p;
+ p.name = type_name;
+ p.label = LLWearableType::getTypeDefaultNewName(type);
+ p.on_click.function_name = "Wearable.Create";
+ p.on_click.parameter = LLSD(type_name);
+
+ LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ?
+ menu_clothes : menu_bp;
+ LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
+ }
+ }
+};
+
class LLCOFObserver : public LLInventoryObserver
{
public:
@@ -719,29 +783,13 @@ void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)
{
if(!mGearMenu)
{
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
- registrar.add("Gear.OnClick", boost::bind(&LLPanelOutfitEdit::onGearMenuItemClick, this, _2));
-
- mGearMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
- "menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
- mGearMenu->buildDrawLabels();
- mGearMenu->updateParent(LLMenuGL::sMenuContainer);
+ mGearMenu = LLPanelOutfitEditGearMenu::create();
}
S32 menu_y = mGearMenu->getRect().getHeight() + clicked_button->getRect().getHeight();
LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y);
}
-void LLPanelOutfitEdit::onGearMenuItemClick(const LLSD& data)
-{
- std::string param = data.asString();
- if("add" == param)
- {
- // TODO
- }
-}
-
void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type)
{
mWearableListTypeCollector->setType(type);
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 6ce581f5f7..802386c573 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -132,7 +132,6 @@ public:
private:
void onGearButtonClick(LLUICtrl* clicked_button);
- void onGearMenuItemClick(const LLSD& data);
void showFilteredWearableItemsList(LLWearableType::EType type);
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 6fb016cdfd..74631c03df 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -71,50 +71,89 @@ static const std::string COF_TAB_NAME = "cof_tab";
static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
-// Context-dependent menu actions are not implemented
-// because accordions don't properly support selection yet.
class LLOutfitListGearMenu
{
public:
- static LLMenuGL* createMenu()
+ LLOutfitListGearMenu(LLOutfitsList* olist)
+ : mOutfitList(olist),
+ mMenu(NULL)
{
+ llassert_always(mOutfitList);
+
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
- registrar.add("Gear.Wear", boost::bind(onWear));
- registrar.add("Gear.TakeOff", boost::bind(onTakeOff));
- registrar.add("Gear.Rename", boost::bind(onRename));
- registrar.add("Gear.Delete", boost::bind(onDelete));
- registrar.add("Gear.Create", boost::bind(onCreate, _2));
+ registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this));
+ registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this));
+ registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this));
+ registrar.add("Gear.Delete", boost::bind(&LLOutfitListGearMenu::onDelete, this));
+ registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2));
- enable_registrar.add("Gear.OnEnable", boost::bind(onEnable, _2));
+ enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2));
- return LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
"menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ llassert(mMenu);
}
+ LLMenuGL* getMenu() { return mMenu; }
+
private:
- static void onWear()
+ const LLUUID& getSelectedOutfitID()
{
- // *TODO: not implemented
+ return mOutfitList->getSelectedOutfitUUID();
}
- static void onTakeOff()
+ LLViewerInventoryCategory* getSelectedOutfit()
{
- // *TODO: not implemented
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.isNull())
+ {
+ return NULL;
+ }
+
+ LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
+ return cat;
}
- static void onRename()
+ void onWear()
{
- // *TODO: not implemented
+ LLViewerInventoryCategory* selected_outfit = getSelectedOutfit();
+ if (selected_outfit)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(
+ selected_outfit, /*copy=*/ FALSE, /*append=*/ FALSE);
+ }
}
- static void onDelete()
+ void onTakeOff()
{
- // *TODO: not implemented
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ LLAppearanceMgr::instance().takeOffOutfit(selected_outfit_id);
+ }
}
- static void onCreate(const LLSD& data)
+ void onRename()
+ {
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ LLAppearanceMgr::instance().renameOutfit(selected_outfit_id);
+ }
+ }
+
+ void onDelete()
+ {
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ if (selected_outfit_id.notNull())
+ {
+ remove_category(&gInventory, selected_outfit_id);
+ }
+ }
+
+ void onCreate(const LLSD& data)
{
LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
if (type == LLWearableType::WT_NONE)
@@ -126,39 +165,40 @@ private:
LLAgentWearables::createWearable(type, true);
}
- static bool onEnable(const LLSD& data)
+ bool onEnable(LLSD::String param)
{
- std::string param = data.asString();
+ const LLUUID& selected_outfit_id = getSelectedOutfitID();
+ bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id;
if ("wear" == param)
{
- // *TODO: not implemented
- return false;
+ return !is_worn;
}
else if ("take_off" == param)
{
- // *TODO: not implemented
- return false;
+ return is_worn;
}
else if ("rename" == param)
{
- // *TODO: not implemented
- return false;
+ return get_is_category_renameable(&gInventory, selected_outfit_id);
}
else if ("delete" == param)
{
- // *TODO: not implemented
- return false;
+ return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id);
}
return true;
}
+
+ LLOutfitsList* mOutfitList;
+ LLMenuGL* mMenu;
};
LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mMyOutfitsPanel(NULL),
mCurrentOutfitPanel(NULL),
mParent(NULL),
+ mGearMenu(NULL),
mInitialized(false)
{
mSavedFolderState = new LLSaveFolderState();
@@ -168,6 +208,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
{
+ delete mGearMenu;
delete mSavedFolderState;
}
@@ -458,7 +499,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
{
mListCommands = getChild<LLPanel>("bottom_panel");
- mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::showGearMenu, this));
mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
@@ -469,7 +510,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
, _7 // EAcceptance* accept
));
- mGearMenu = LLOutfitListGearMenu::createMenu();
+ mGearMenu = new LLOutfitListGearMenu(mMyOutfitsPanel);
}
void LLPanelOutfitsInventory::updateListCommands()
@@ -484,18 +525,14 @@ void LLPanelOutfitsInventory::updateListCommands()
mSaveComboBtn->setSaveBtnEnabled(make_outfit_enabled);
}
-void LLPanelOutfitsInventory::onGearButtonClick()
-{
- showActionMenu(mGearMenu, "options_gear_btn");
-}
-
-void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+void LLPanelOutfitsInventory::showGearMenu()
{
+ LLMenuGL* menu = mGearMenu ? mGearMenu->getMenu() : NULL;
if (menu)
{
menu->buildDrawLabels();
menu->updateParent(LLMenuGL::sMenuContainer);
- LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ LLView* spawning_view = getChild<LLView>("options_gear_btn");
S32 menu_x, menu_y;
//show menu in co-ordinates of panel
spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index 8e76688de5..aff7839bcc 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -47,6 +47,7 @@ class LLMenuGL;
class LLSidepanelAppearance;
class LLTabContainer;
class LLSaveOutfitComboBtn;
+class LLOutfitListGearMenu;
class LLPanelOutfitsInventory : public LLPanel
{
@@ -116,9 +117,8 @@ private:
protected:
void initListCommandsHandlers();
void updateListCommands();
- void onGearButtonClick();
void onWearButtonClick();
- void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void showGearMenu();
void onTrashButtonClick();
void onClipboardAction(const LLSD& userdata);
BOOL isActionEnabled(const LLSD& command_name);
@@ -129,7 +129,7 @@ protected:
void onWearablesLoaded();
private:
LLPanel* mListCommands;
- LLMenuGL* mGearMenu;
+ LLOutfitListGearMenu* mGearMenu;
LLMenuGL* mMenuAdd;
// List Commands //
////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 78c784e4df..c35b45d446 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -671,7 +671,6 @@ void LLWearableItemsList::ContextMenu::updateMask(U32& mask, LLAssetType::EType
// static
void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id)
{
- // *TODO: proper implementation of creating new wearables.
LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id);
if (!item || !item->isWearableType()) return;
diff --git a/indra/newview/skins/default/xui/en/menu_cof_body_part.xml b/indra/newview/skins/default/xui/en/menu_cof_body_part.xml
index 01008ef203..f0e8461360 100644
--- a/indra/newview/skins/default/xui/en/menu_cof_body_part.xml
+++ b/indra/newview/skins/default/xui/en/menu_cof_body_part.xml
@@ -19,4 +19,15 @@
function="BodyPart.OnEnable"
parameter="edit" />
</menu_item_call>
+ <menu_item_call
+ label="Create New"
+ layout="topleft"
+ name="create_new"
+ translate="false">
+ <on_click
+ function="BodyPart.Create"/>
+ <on_enable
+ function="BodyPart.OnEnable"
+ parameter="create" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_cof_clothing.xml b/indra/newview/skins/default/xui/en/menu_cof_clothing.xml
index f9cb29f0d7..12ee9b045b 100644
--- a/indra/newview/skins/default/xui/en/menu_cof_clothing.xml
+++ b/indra/newview/skins/default/xui/en/menu_cof_clothing.xml
@@ -8,6 +8,9 @@
name="take_off">
<on_click
function="Clothing.TakeOff" />
+ <on_enable
+ function="Clothing.OnEnable"
+ parameter="take_off" />
</menu_item_call>
<menu_item_call
label="Move Up a Layer"
@@ -39,4 +42,15 @@
function="Clothing.OnEnable"
parameter="edit" />
</menu_item_call>
+ <menu_item_call
+ label="Create New"
+ layout="topleft"
+ name="create_new"
+ translate="false">
+ <on_click
+ function="Clothing.Create"/>
+ <on_enable
+ function="Clothing.OnEnable"
+ parameter="create" />
+ </menu_item_call>
</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_cof_gear.xml b/indra/newview/skins/default/xui/en/menu_cof_gear.xml
index 982d4f2015..c2a11a64ec 100644
--- a/indra/newview/skins/default/xui/en/menu_cof_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_cof_gear.xml
@@ -2,15 +2,12 @@
<menu
layout="topleft"
name="Gear COF">
- <menu_item_call
- label="Add To Outfit"
+ <menu
+ label="New Clothes"
layout="topleft"
- name="add">
- <on_click
- function="Gear.OnClick"
- parameter="add"/>
- <on_enable
- function="Gear.OnEnable"
- parameter="add" />
- </menu_item_call>
+ name="COF.Gear.New_Clothes" />
+ <menu
+ label="New Body Parts"
+ layout="topleft"
+ name="COF.Geear.New_Body_Parts" />
</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 3cae12e30c..b5eda8e999 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -13,7 +13,7 @@
parameter="wear" />
</menu_item_call>
<menu_item_call
- label="Take Off - Remove Current Outfit"
+ label="Take Off - Remove from Current Outfit"
layout="topleft"
name="take_off">
<on_click
diff --git a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml
index 46aca54eee..e645702f93 100644
--- a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml
@@ -61,7 +61,8 @@
<menu_item_call
label="Create New"
layout="topleft"
- name="create_new">
+ name="create_new"
+ translate="false">
<on_click
function="Wearable.CreateNew" />
</menu_item_call>