diff options
| -rw-r--r-- | indra/newview/llappearancemgr.cpp | 69 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.h | 6 | ||||
| -rw-r--r-- | indra/newview/llcofwearables.cpp | 61 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 15 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.h | 6 | ||||
| -rw-r--r-- | indra/newview/lloutfitslist.cpp | 92 | ||||
| -rw-r--r-- | indra/newview/lloutfitslist.h | 8 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitedit.cpp | 82 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitedit.h | 1 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitsinventory.cpp | 113 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitsinventory.h | 6 | ||||
| -rw-r--r-- | indra/newview/llwearableitemslist.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_cof_body_part.xml | 11 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_cof_clothing.xml | 14 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_cof_gear.xml | 17 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_outfit_gear.xml | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_wearable_list_item.xml | 3 | 
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> | 
