diff options
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.cpp | 18 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.h | 8 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llinventoryfilter.cpp | 17 | ||||
| -rw-r--r-- | indra/newview/llinventorypanel.cpp | 35 | ||||
| -rw-r--r-- | indra/newview/llinventorypanel.h | 4 | ||||
| -rw-r--r-- | indra/newview/llpanelmaininventory.cpp | 48 | ||||
| -rw-r--r-- | indra/newview/llpanelmaininventory.h | 29 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitsinventory.cpp | 347 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitsinventory.h | 102 | ||||
| -rw-r--r-- | indra/newview/llsidepanelappearance.cpp | 372 | ||||
| -rw-r--r-- | indra/newview/llsidepanelappearance.h | 102 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_inventory.xml | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_outfits_inventory.xml | 81 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml | 42 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_side_tray.xml | 6 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/sidepanel_appearance.xml | 104 | 
18 files changed, 1251 insertions, 84 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4adef84cd3..e7458529be 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -297,8 +297,6 @@ set(viewer_SOURCE_FILES      llnotify.cpp      lloutputmonitorctrl.cpp      lloverlaybar.cpp -    llpanelappearance.cpp -    llpanelappearancetab.cpp      llpanelavatar.cpp      llpanelavatarrow.cpp      llpanelavatartag.cpp @@ -322,7 +320,6 @@ set(viewer_SOURCE_FILES      llpanellandmedia.cpp      llpanellogin.cpp      llpanellookinfo.cpp -    llpanellooks.cpp      llpanelmaininventory.cpp      llpanelmediasettingsgeneral.cpp      llpanelmediasettingspermissions.cpp @@ -330,6 +327,7 @@ set(viewer_SOURCE_FILES      llpanelmeprofile.cpp      llpanelobject.cpp      llpanelobjectinventory.cpp +    llpaneloutfitsinventory.cpp      llpanelpeople.cpp      llpanelpeoplemenus.cpp      llpanelpermissions.cpp @@ -370,6 +368,7 @@ set(viewer_SOURCE_FILES      llsearchcombobox.cpp      llsearchhistory.cpp      llselectmgr.cpp +    llsidepanelappearance.cpp      llsidepanelinventory.cpp      llsidepanelinventorysubpanel.cpp      llsidepaneliteminfo.cpp @@ -792,8 +791,6 @@ set(viewer_HEADER_FILES      llnotify.h      lloutputmonitorctrl.h      lloverlaybar.h -    llpanelappearance.h -    llpanelappearancetab.h      llpanelavatar.h      llpanelavatarrow.h      llpanelavatartag.h @@ -817,7 +814,6 @@ set(viewer_HEADER_FILES      llpanellandmedia.h      llpanellogin.h      llpanellookinfo.h -    llpanellooks.h      llpanelmaininventory.h      llpanelmediasettingsgeneral.h      llpanelmediasettingspermissions.h @@ -825,6 +821,7 @@ set(viewer_HEADER_FILES      llpanelmeprofile.h      llpanelobject.h      llpanelobjectinventory.h +    llpaneloutfitsinventory.h      llpanelpeople.h      llpanelpeoplemenus.h      llpanelpermissions.h @@ -867,6 +864,7 @@ set(viewer_HEADER_FILES      llsearchcombobox.h      llsearchhistory.h      llselectmgr.h +    llsidepanelappearance.h      llsidepanelinventory.h      llsidepanelinventorysubpanel.h      llsidepaneliteminfo.h diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a23d21f84b..60c6061e96 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -40,7 +40,7 @@  #include "llinventorybridge.h"  #include "llinventoryobserver.h"  #include "llnotifications.h" -#include "llpanelappearance.h" +#include "llsidepanelappearance.h"  #include "llsidetray.h"  #include "llvoavatar.h"  #include "llvoavatarself.h" @@ -95,7 +95,7 @@ public:  		mCopyItems(copy_items),  		mAppend(append)  	{} -	~LLOutfitObserver(); +	~LLOutfitObserver() {}  	virtual void done();  	void doWearCategory(); @@ -105,12 +105,6 @@ protected:  	bool mAppend;  }; -LLOutfitObserver::~LLOutfitObserver() -{ -	llinfos << "~LLOutfitObserver" << llendl; -} - -// BAP is LLOutfitObserver getting deleted here?  void LLOutfitObserver::done()  {  	gInventory.removeObserver(this); @@ -236,7 +230,6 @@ void LLOutfitFetch::done()  	// loop.  	//dec_busy_count();  	gInventory.removeObserver(this); -	delete this;  	// increment busy count and either tell the inventory to check &  	// call done, or add this object to the inventory for observation. @@ -255,6 +248,7 @@ void LLOutfitFetch::done()  		// will call done for us when everything is here.  		gInventory.addObserver(outfit_observer);  	} +	delete this;  }  class LLUpdateAppearanceOnDestroy: public LLInventoryCallback @@ -471,7 +465,7 @@ void LLAppearanceManager::filterWearableItems(  // Create links to all listed items.  void LLAppearanceManager::linkAll(const LLUUID& category,  								  LLInventoryModel::item_array_t& items, -											   LLPointer<LLInventoryCallback> cb) +								  LLPointer<LLInventoryCallback> cb)  {  	for (S32 i=0; i<items.count(); i++)  	{ @@ -544,10 +538,10 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)  							LLAssetType::AT_LINK_FOLDER, link_waiter);  		// Update the current outfit name of the appearance sidepanel. -		LLPanelAppearance* panel_appearance = dynamic_cast<LLPanelAppearance *>(LLSideTray::getInstance()->getPanel("panel_appearance")); +		LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance *>(LLSideTray::getInstance()->getPanel("sidepanel_appearance"));  		if (panel_appearance)  		{ -			panel_appearance->refreshCurrentLookName(catp->getName()); +			panel_appearance->refreshCurrentOutfitName(catp->getName());  		}  	} diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f39fbd7b1a..12ffa336b4 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -82,6 +82,11 @@ public:  	void setAttachmentInvLinkEnable(bool val);  	void linkRegisteredAttachments(); +	// utility function for bulk linking. +	void linkAll(const LLUUID& category, +				 LLInventoryModel::item_array_t& items, +				 LLPointer<LLInventoryCallback> cb); +  protected:  	LLAppearanceManager();  	~LLAppearanceManager(); @@ -89,9 +94,6 @@ protected:  private:  	void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type); -	void linkAll(const LLUUID& category, -						LLInventoryModel::item_array_t& items, -						LLPointer<LLInventoryCallback> cb);  	void getDescendentsOfAssetType(const LLUUID& category,   										  LLInventoryModel::item_array_t& items, diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index aa38b19c5e..8b7a84a3d3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1680,6 +1680,14 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  						BOOL append = true;
  						LLAppearanceManager::instance().wearInventoryCategory(inv_cat, false, append);
  					}
 +					else
 +					{
 +						// Recursively create links in target outfit.
 +						LLInventoryModel::cat_array_t cats;
 +						LLInventoryModel::item_array_t items;
 +						gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
 +						LLAppearanceManager::instance().linkAll(mUUID,items,NULL);
 +					}
  				}
  				else
  				{
 diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 3e4b3327db..085c96c93d 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -100,17 +100,18 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item)  	bool passed_type = false;  	if (mFilterOps.mFilterForCategories)  	{ -		if (listener->getInventoryType() == LLInventoryType::IT_CATEGORY) +		// Pass if this item is a category of the filter type, or +		// if its parent is a category of the filter type. +		LLUUID uuid = listener->getUUID(); +		if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)  		{ -			LLViewerInventoryCategory *cat = gInventory.getCategory(listener->getUUID()); -			if (cat) -			{ -				passed_type |= ((1LL << cat->getPreferredType() & mFilterOps.mFilterTypes) != U64(0)); -			} +			const LLInventoryObject *obj = gInventory.getObject(uuid); +			uuid = obj->getParentUUID();  		} -		else +		LLViewerInventoryCategory *cat = gInventory.getCategory(uuid); +		if (cat)  		{ -			passed_type = TRUE; +			passed_type |= ((1LL << cat->getPreferredType() & mFilterOps.mFilterTypes) != U64(0));  		}  	}  	else diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 7b7090d10d..450ce92412 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -145,23 +145,10 @@ BOOL LLInventoryPanel::postBuild()  	mInventoryObserver = new LLInventoryPanelObserver(this);
  	mInventory->addObserver(mInventoryObserver);
 -	// determine the root folder, if any, so inventory contents show just the children
 -	// of that folder (i.e. not including the folder itself).
 -	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
 -
 -	if ("LIBRARY" == mStartFolderString)
 -	{
 -		mStartFolderID = gInventory.getLibraryRootFolderID();
 -	}
 -	else
 -	{
 -		mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
 -	}
 -
  	// build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
  	if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
  	{
 -		rebuildViewsFor(mStartFolderID);
 +		rebuildViews();
  		mHasInventoryConnection = true;
  		defaultOpenInventory();
  	}
 @@ -268,7 +255,7 @@ void LLInventoryPanel::modelChanged(U32 mask)  	// inventory just initialized, do complete build
  	if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
  	{
 -		rebuildViewsFor(mStartFolderID);
 +		rebuildViews();
  		mHasInventoryConnection = true;
  		defaultOpenInventory();
  		return;
 @@ -388,6 +375,24 @@ void LLInventoryPanel::modelChanged(U32 mask)  }
 +void LLInventoryPanel::rebuildViews()
 +{
 +	// Determine the root folder and rebuild the views starting
 +	// at that folder.
 +	const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
 +
 +	if ("LIBRARY" == mStartFolderString)
 +	{
 +		mStartFolderID = gInventory.getLibraryRootFolderID();
 +	}
 +	else
 +	{
 +		mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
 +	}
 +	
 +	rebuildViewsFor(mStartFolderID);
 +}
 +
  void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
  {
  	LLFolderViewItem* old_view = NULL;
 diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index e398c44105..0ccee337c9 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -162,6 +162,10 @@ public:  	void unSelectAll()	{ mFolders->setSelection(NULL, FALSE, FALSE); }  protected: +	// Destroys the old views, and regenerates them based on the +	// start folder ID. +	void rebuildViews(); +  	// Given the id and the parent, build all of the folder views.  	void rebuildViewsFor(const LLUUID& id);  	virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719 diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index e3b2ab77aa..9f723169e1 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -49,7 +49,7 @@  #include "llviewermenu.h"
  #include "llviewertexturelist.h"
 -static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor?
 +static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory");
  void on_file_loaded_for_save(BOOL success, 
  							 LLViewerFetchedTexture *src_vi,
 @@ -197,28 +197,6 @@ BOOL LLPanelMainInventory::postBuild()  	return TRUE;
  }
 -void LLPanelMainInventory::initListCommandsHandlers()
 -{
 -	mListCommands = getChild<LLPanel>("bottom_panel");
 -
 -	mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
 -	mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
 -	mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
 -
 -	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
 -	trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
 -			,	_4 // BOOL drop
 -			,	_5 // EDragAndDropType cargo_type
 -			,	_7 // EAcceptance* accept
 -			));
 -
 -	mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
 -	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
 -	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 -	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 -	
 -}
 -
  // Destroys the object
  LLPanelMainInventory::~LLPanelMainInventory( void )
  {
 @@ -863,9 +841,30 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)  	self->childSetValue("check_snapshot", FALSE);
  }
 +//////////////////////////////////////////////////////////////////////////////////
 +// List Commands                                                                //
 +void LLPanelMainInventory::initListCommandsHandlers()
 +{
 +	mListCommands = getChild<LLPanel>("bottom_panel");
 +	mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
 +	mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
 +	mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
 +	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
 +	trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
 +			,	_4 // BOOL drop
 +			,	_5 // EDragAndDropType cargo_type
 +			,	_7 // EAcceptance* accept
 +			));
 +
 +	mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
 +	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
 +	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 +	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 +	
 +}
  void LLPanelMainInventory::updateListCommands()
  {
 @@ -1018,3 +1017,6 @@ bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType  	}
  	return true;
  }
 +
 +// List Commands                                                              //
 +////////////////////////////////////////////////////////////////////////////////
 diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index fbc0f09c50..627be21577 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -111,7 +111,20 @@ protected:  	void resetFilters();
  	void setSortBy(const LLSD& userdata);
 -	// List Commands Handlers
 +private:
 +	LLFloaterInventoryFinder* getFinder();
 +
 +	LLFilterEditor*				mFilterEditor;
 +	LLTabContainer*				mFilterTabs;
 +	LLHandle<LLFloater>			mFinderHandle;
 +	LLInventoryPanel*			mActivePanel;
 +	LLSaveFolderState*			mSavedFolderState;
 +	std::string					mFilterText;
 +
 +
 +	//////////////////////////////////////////////////////////////////////////////////
 +	// List Commands                                                                //
 +protected:
  	void initListCommandsHandlers();
  	void updateListCommands();
  	void onGearButtonClick();
 @@ -122,22 +135,12 @@ protected:  	BOOL isActionEnabled(const LLSD& command_name);
  	void onCustomAction(const LLSD& command_name);
  	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
 -
 -
  private:
 -	LLFloaterInventoryFinder* getFinder();
 -
 -	LLFilterEditor*				mFilterEditor;
 -	LLTabContainer*				mFilterTabs;
 -	LLHandle<LLFloater>			mFinderHandle;
 -	LLInventoryPanel*			mActivePanel;
 -	LLSaveFolderState*			mSavedFolderState;
 -
  	LLPanel*					mListCommands;
  	LLMenuGL*					mMenuGearDefault;
  	LLMenuGL*					mMenuAdd;
 -
 -	std::string					mFilterText;
 +	// List Commands                                                              //
 +	////////////////////////////////////////////////////////////////////////////////
  };
  #endif // LL_LLPANELMAININVENTORY_H
 diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp new file mode 100644 index 0000000000..5ad9bf056e --- /dev/null +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -0,0 +1,347 @@ +/** + * @file llpaneloutfitsinventory.cpp + * @brief Outfits inventory panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpaneloutfitsinventory.h" + +#include "llagent.h" +#include "llagentwearables.h" + +#include "llbutton.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llfloaterinventory.h" +#include "llfoldervieweventlistener.h" +#include "llinventoryfunctions.h" +#include "llinventorypanel.h" +#include "lllandmark.h" +#include "llsidepanelappearance.h" +#include "llsidetray.h" +#include "lltabcontainer.h" +#include "llviewerfoldertype.h" +#include "llviewerjointattachment.h" +#include "llvoavatarself.h" + +// List Commands +#include "lldndbutton.h" +#include "llmenugl.h" +#include "llviewermenu.h" + +static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory"); + +LLPanelOutfitsInventory::LLPanelOutfitsInventory() : +	mInventoryPanel(NULL), +	mParent(NULL) +{ +	mSavedFolderState = new LLSaveFolderState(); +	mSavedFolderState->setApply(FALSE); +} + +LLPanelOutfitsInventory::~LLPanelOutfitsInventory() +{ +	delete mSavedFolderState; +} + +// virtual +BOOL LLPanelOutfitsInventory::postBuild() +{ +	mInventoryPanel = getChild<LLInventoryPanel>("outfits_list"); +	mInventoryPanel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, TRUE); +	mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); +	mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_MY_OUTFITS); +	mInventoryPanel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onSelectionChange, this, _1, _2)); +	 +	initListCommandsHandlers(); +	return TRUE; +} + +void LLPanelOutfitsInventory::updateParent() +{ +	if (mParent) +	{ +		mParent->updateVerbs(); +	} +} + +void LLPanelOutfitsInventory::setParent(LLSidepanelAppearance* parent) +{ +	mParent = parent; +} + +// virtual +void LLPanelOutfitsInventory::onSearchEdit(const std::string& string) +{ +	if (string == "") +	{ +		mInventoryPanel->setFilterSubString(LLStringUtil::null); + +		// re-open folders that were initially open +		mSavedFolderState->setApply(TRUE); +		getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +		LLOpenFoldersWithSelection opener; +		getRootFolder()->applyFunctorRecursively(opener); +		getRootFolder()->scrollToShowSelection(); +	} + +	gInventory.startBackgroundFetch(); + +	if (mInventoryPanel->getFilterSubString().empty() && string.empty()) +	{ +		// current filter and new filter empty, do nothing +		return; +	} + +	// save current folder open state if no filter currently applied +	if (getRootFolder()->getFilterSubString().empty()) +	{ +		mSavedFolderState->setApply(FALSE); +		getRootFolder()->applyFunctorRecursively(*mSavedFolderState); +	} + +	// set new filter string +	mInventoryPanel->setFilterSubString(string); +} + +void LLPanelOutfitsInventory::onWear() +{ +	LLFolderViewEventListener* listenerp = getCorrectListenerForAction(); +	if (listenerp) +	{ +		listenerp->performAction(NULL, NULL,"replaceoutfit"); +	} +} + +void LLPanelOutfitsInventory::onEdit() +{ +} + +void LLPanelOutfitsInventory::onNew() +{ +	const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); +	LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); +	getRootFolder()->setSelectionByID(outfit_folder, TRUE); +	getRootFolder()->setNeedsAutoRename(TRUE); +} + +void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) +{ +	updateParent(); +} + +void LLPanelOutfitsInventory::onSelectorButtonClicked() +{ +	/* +	  LLFolderViewItem* cur_item = getRootFolder()->getCurSelectedItem(); + +	  LLFolderViewEventListener* listenerp = cur_item->getListener(); +	  if (getIsCorrectType(listenerp)) +	  { +	  LLSD key; +	  key["type"] = "look"; +	  key["id"] = listenerp->getUUID(); + +	  LLSideTray::getInstance()->showPanel("sidepanel_appearance", key); +	  }  +	*/ +} + +LLFolderViewEventListener *LLPanelOutfitsInventory::getCorrectListenerForAction() +{ +	LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem(); +	if (!current_item) +		return NULL; + +	LLFolderViewEventListener* listenerp = current_item->getListener(); +	if (getIsCorrectType(listenerp)) +	{ +		return listenerp; +	} +	return NULL; +} + +bool LLPanelOutfitsInventory::getIsCorrectType(const LLFolderViewEventListener *listenerp) const +{ +	if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY) +	{ +		LLViewerInventoryCategory *cat = gInventory.getCategory(listenerp->getUUID()); +		if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) +		{ +			return true; +		} +	} +	return false; +} + +LLFolderView *LLPanelOutfitsInventory::getRootFolder() +{ +	return mInventoryPanel->getRootFolder(); +} + +////////////////////////////////////////////////////////////////////////////////// +// List Commands                                                                // + +void LLPanelOutfitsInventory::initListCommandsHandlers() +{ +	mListCommands = getChild<LLPanel>("bottom_panel"); + +	mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this)); +	mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this)); +	mListCommands->childSetAction("add_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, this)); + +	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn"); +	trash_btn->setDragAndDropHandler(boost::bind(&LLPanelOutfitsInventory::handleDragAndDropToTrash, this +			,	_4 // BOOL drop +			,	_5 // EDragAndDropType cargo_type +			,	_7 // EAcceptance* accept +			)); + +	mCommitCallbackRegistrar.add("panel_outfits_inventory_gear_default.Custom.Action", boost::bind(&LLPanelOutfitsInventory::onCustomAction, this, _2)); +	mEnableCallbackRegistrar.add("panel_outfits_inventory_gear_default.Enable", boost::bind(&LLPanelOutfitsInventory::isActionEnabled, this, _2)); +	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("panel_outfits_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +} + +void LLPanelOutfitsInventory::updateListCommands() +{ +	bool trash_enabled = isActionEnabled("delete"); + +	mListCommands->childSetEnabled("trash_btn", trash_enabled); +} + +void LLPanelOutfitsInventory::onGearButtonClick() +{ +	showActionMenu(mMenuGearDefault,"options_gear_btn"); +} + +void LLPanelOutfitsInventory::onAddButtonClick() +{ +	onNew(); +} + +void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) +{ +	if (menu) +	{ +		menu->buildDrawLabels(); +		menu->updateParent(LLMenuGL::sMenuContainer); +		LLView* spawning_view = getChild<LLView> (spawning_view_name); +		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); +		menu_y += menu->getRect().getHeight(); +		LLMenuGL::showPopup(this, menu, menu_x, menu_y); +	} +} + +void LLPanelOutfitsInventory::onTrashButtonClick() +{ +	onClipboardAction("delete"); +} + +void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata) +{ +	std::string command_name = userdata.asString(); +	getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); +} + +void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata) +{ +	if (!isActionEnabled(userdata)) +		return; + +	const std::string command_name = userdata.asString(); +	if (command_name == "new") +	{ +		onNew(); +	} +	if (command_name == "edit") +	{ +		onEdit(); +	} +	if (command_name == "wear") +	{ +		onWear(); +	} +	if (command_name == "delete") +	{ +		onClipboardAction("delete"); +	} +} + +BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) +{ +	const std::string command_name = userdata.asString(); +	if (command_name == "delete") +	{ +		BOOL can_delete = FALSE; +		LLFolderView *folder = getActivePanel()->getRootFolder(); +		if (folder) +		{ +			can_delete = TRUE; +			std::set<LLUUID> selection_set; +			folder->getSelectionList(selection_set); +			for (std::set<LLUUID>::iterator iter = selection_set.begin(); +				 iter != selection_set.end(); +				 ++iter) +			{ +				const LLUUID &item_id = (*iter); +				LLFolderViewItem *item = folder->getItemByID(item_id); +				can_delete &= item->getListener()->isItemRemovable(); +			} +			return can_delete; +		} +		return FALSE; +	} +	if (command_name == "edit" ||  +		command_name == "wear") +	{ +		return (getCorrectListenerForAction() != NULL); +	} +	return TRUE; +} + +bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept) +{ +	*accept = ACCEPT_NO; + +	const bool is_enabled = isActionEnabled("delete"); +	if (is_enabled) *accept = ACCEPT_YES_MULTI; + +	if (is_enabled && drop) +	{ +		onClipboardAction("delete"); +	} +	return true; +} + +// List Commands                                                              // +//////////////////////////////////////////////////////////////////////////////// + diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h new file mode 100644 index 0000000000..4d903a389b --- /dev/null +++ b/indra/newview/llpaneloutfitsinventory.h @@ -0,0 +1,102 @@ +/** + * @file llpaneloutfitsinventory.h + * @brief Outfits inventory panel + * class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELOUTFITSINVENTORY_H +#define LL_LLPANELOUTFITSINVENTORY_H + +#include "llpanel.h" +#include "llinventoryobserver.h" + +class LLFolderView; +class LLFolderViewItem; +class LLFolderViewEventListener; +class LLInventoryPanel; +class LLSaveFolderState; +class LLButton; +class LLMenuGL; +class LLSidepanelAppearance; + +class LLPanelOutfitsInventory : public LLPanel +{ +public: +	LLPanelOutfitsInventory(); +	virtual ~LLPanelOutfitsInventory(); + +	/*virtual*/ BOOL postBuild(); +	 +	void onSearchEdit(const std::string& string); +	void onWear(); +	void onEdit(); +	void onNew(); + +	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	void onSelectorButtonClicked(); + +	LLInventoryPanel* getActivePanel() { return mInventoryPanel; } + +	// If a compatible listener type is selected, then return a pointer to that. +	// Otherwise, return NULL. +	LLFolderViewEventListener* getCorrectListenerForAction(); +	void setParent(LLSidepanelAppearance *parent); +protected: +	void updateParent(); +	bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const; +	LLFolderView* getRootFolder(); + +private: +	LLSidepanelAppearance*      mParent; +	LLInventoryPanel*			mInventoryPanel; +	LLSaveFolderState*			mSavedFolderState; + + +	////////////////////////////////////////////////////////////////////////////////// +	// List Commands                                                                // +protected: +	void initListCommandsHandlers(); +	void updateListCommands(); +	void onGearButtonClick(); +	void onAddButtonClick(); +	void showActionMenu(LLMenuGL* menu, std::string spawning_view_name); +	void onTrashButtonClick(); +	void onClipboardAction(const LLSD& userdata); +	BOOL isActionEnabled(const LLSD& command_name); +	void onCustomAction(const LLSD& command_name); +	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept); +private: +	LLPanel*					mListCommands; +	LLMenuGL*					mMenuGearDefault; +	LLMenuGL*					mMenuAdd; +	//                                                                            // +	//////////////////////////////////////////////////////////////////////////////// +}; + +#endif //LL_LLPANELOUTFITSINVENTORY_H diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp new file mode 100644 index 0000000000..aeab3e2876 --- /dev/null +++ b/indra/newview/llsidepanelappearance.cpp @@ -0,0 +1,372 @@ +/** + * @file llsidepanelappearance.cpp + * @brief Side Bar "Appearance" panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llsidepanelappearance.h" + +#include "llagent.h" +#include "llagentwearables.h" +#include "llfiltereditor.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llpaneleditwearable.h" +#include "llpaneloutfitsinventory.h" +#include "lltextbox.h" +#include "lluictrlfactory.h" +#include "llviewerregion.h" +#include "llvoavatarself.h" +#include "llwearable.h" + +static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance"); + +class LLCurrentlyWornFetchObserver : public LLInventoryFetchObserver +{ +public: +	LLCurrentlyWornFetchObserver(LLSidepanelAppearance *panel) : +		mPanel(panel) +	{} +	~LLCurrentlyWornFetchObserver() {} +	virtual void done() +	{ +		mPanel->inventoryFetched(); +		gInventory.removeObserver(this); +	} +private: +	LLSidepanelAppearance *mPanel; +}; + +LLSidepanelAppearance::LLSidepanelAppearance() : +	LLPanel(), +	mFilterSubString(LLStringUtil::null), +	mFilterEditor(NULL), +	mLookInfo(NULL), +	mCurrLookPanel(NULL) +{ +	//LLUICtrlFactory::getInstance()->buildPanel(this, "panel_appearance.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder() +	mFetchWorn = new LLCurrentlyWornFetchObserver(this); +} + +LLSidepanelAppearance::~LLSidepanelAppearance() +{ +} + +// virtual +BOOL LLSidepanelAppearance::postBuild() +{ +	mEditAppearanceBtn = getChild<LLButton>("editappearance_btn"); +	mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); + +	mWearBtn = getChild<LLButton>("wear_btn"); +	mWearBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onWearButtonClicked, this)); + +	mEditBtn = getChild<LLButton>("edit_btn"); +	mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this)); + +	mNewLookBtn = getChild<LLButton>("newlook_btn"); +	mNewLookBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this)); +	mNewLookBtn->setEnabled(false); + +	mOverflowBtn = getChild<LLButton>("overflow_btn"); + +	mFilterEditor = getChild<LLFilterEditor>("Filter"); +	if (mFilterEditor) +	{ +		mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2)); +	} + +	mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory")); +	mPanelOutfitsInventory->setParent(this); + +	mLookInfo = dynamic_cast<LLPanelLookInfo*>(getChild<LLPanel>("panel_look_info")); +	if (mLookInfo) +	{ +		LLButton* back_btn = mLookInfo->getChild<LLButton>("back_btn"); +		if (back_btn) +		{ +			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onBackButtonClicked, this)); +		} + +		// *TODO: Assign the action to an appropriate event. +		// mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::toggleMediaPanel, this)); +	} + +	mEditWearable = dynamic_cast<LLPanelEditWearable*>(getChild<LLPanel>("panel_edit_wearable")); +	if (mEditWearable) +	{ +		LLButton* edit_wearable_back_btn = mEditWearable->getChild<LLButton>("back_btn"); +		if (edit_wearable_back_btn) +		{ +			edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditWearBackClicked, this)); +		} +	} + +	mCurrentLookName = getChild<LLTextBox>("currentlook_name"); +	 +	mCurrLookPanel = getChild<LLPanel>("panel_currentlook"); + +	return TRUE; +} + +// virtual +void LLSidepanelAppearance::onOpen(const LLSD& key) +{ +	fetchInventory(); +	refreshCurrentOutfitName(); + +	if(key.size() == 0) +		return; + +	toggleLookInfoPanel(TRUE); +	updateVerbs(); +	 +	mLookInfoType = key["type"].asString(); + +	if (mLookInfoType == "look") +	{ +		LLInventoryCategory *pLook = gInventory.getCategory(key["id"].asUUID()); +		if (pLook) +			mLookInfo->displayLookInfo(pLook); +	} +} + +void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) +{ +	if (mFilterSubString != search_string) +	{ +		mFilterSubString = search_string; + +		// Searches are case-insensitive +		LLStringUtil::toUpper(mFilterSubString); +		LLStringUtil::trimHead(mFilterSubString); + +		mPanelOutfitsInventory->onSearchEdit(mFilterSubString); +	} +} + +void LLSidepanelAppearance::onWearButtonClicked() +{ +	if (!mLookInfo->getVisible()) +	{ +		mPanelOutfitsInventory->onWear(); +	} +} + +void LLSidepanelAppearance::onEditAppearanceButtonClicked() +{ +	if (gAgentWearables.areWearablesLoaded()) +	{ +		gAgent.changeCameraToCustomizeAvatar(); +	} +} + +void LLSidepanelAppearance::onEditButtonClicked() +{ +	toggleLookInfoPanel(FALSE); +	toggleWearableEditPanel(TRUE, NULL); +	/*if (mLookInfo->getVisible()) +	  { +	  } +	  else +	  { +	  mPanelOutfitsInventory->onEdit(); +	  }*/ +} + +void LLSidepanelAppearance::onNewOutfitButtonClicked() +{ +	if (!mLookInfo->getVisible()) +	{ +		mPanelOutfitsInventory->onNew(); +	} +} + + +void LLSidepanelAppearance::onBackButtonClicked() +{ +	toggleLookInfoPanel(FALSE); +} + +void LLSidepanelAppearance::onEditWearBackClicked() +{ +	mEditWearable->saveChanges(); +	toggleWearableEditPanel(FALSE, NULL); +	toggleLookInfoPanel(TRUE); +} + +void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible) +{ +	if (!mLookInfo) +		return; + +	mLookInfo->setVisible(visible); +	mPanelOutfitsInventory->setVisible(!visible); +	mFilterEditor->setVisible(!visible); +	mWearBtn->setVisible(!visible); +	mEditBtn->setVisible(!visible); +	mNewLookBtn->setVisible(!visible); +	mOverflowBtn->setVisible(!visible); +	mCurrLookPanel->setVisible(!visible); +} + +void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable) +{ +	if (!wearable) +	{ +		wearable = gAgentWearables.getWearable(WT_SHAPE, 0); +	} +	if (!mEditWearable || !wearable) +	{ +		return; +	} + +	mEditWearable->setVisible(visible); +	mFilterEditor->setVisible(!visible); +	mPanelOutfitsInventory->setVisible(!visible); +} + +void LLSidepanelAppearance::updateVerbs() +{ +	bool is_look_info_visible = mLookInfo->getVisible(); +	mOverflowBtn->setEnabled(false); + +	if (!is_look_info_visible) +	{ +		const bool is_correct_type = (mPanelOutfitsInventory->getCorrectListenerForAction() != NULL); +		mEditBtn->setEnabled(is_correct_type); +		mWearBtn->setEnabled(is_correct_type); +	} +	else +	{ +		mEditBtn->setEnabled(FALSE); +		mWearBtn->setEnabled(FALSE); +	} +} + +void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string name) +{ +	if (name == "") +	{ +		const LLUUID current_outfit_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); +		LLInventoryModel::cat_array_t cat_array; +		LLInventoryModel::item_array_t item_array; +		// Can't search on AT_OUTFIT since links to categories return AT_CATEGORY for type since they don't +		// return preferred type. +		LLIsType is_category( LLAssetType::AT_CATEGORY );  +		gInventory.collectDescendentsIf(current_outfit_cat, +										cat_array, +										item_array, +										false, +										is_category, +										false); +		for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); +			 iter != item_array.end(); +			 iter++) +		{ +			const LLViewerInventoryItem *item = (*iter); +			const LLViewerInventoryCategory *cat = item->getLinkedCategory(); +			if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) +			{ +				mCurrentLookName->setText(cat->getName()); +				return; +			} +		} +		mCurrentLookName->setText(std::string("")); +	} +	else +	{ +		mCurrentLookName->setText(name); +	} +} + +//static +void LLSidepanelAppearance::editWearable(LLWearable *wearable, void *data) +{ +	LLSidepanelAppearance *panel = (LLSidepanelAppearance*) data; +	panel->toggleLookInfoPanel(FALSE); +	panel->toggleWearableEditPanel(TRUE, wearable); +} + +// Fetch currently worn items and only enable the New Look button after everything's been +// fetched.  Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks. +void LLSidepanelAppearance::fetchInventory() +{ + +	mNewLookBtn->setEnabled(false); +	LLInventoryFetchObserver::item_ref_t ids; +	LLUUID item_id; +	for(S32 type = (S32)WT_SHAPE; type < (S32)WT_COUNT; ++type) +	{ +		// MULTI_WEARABLE: +		item_id = gAgentWearables.getWearableItemID((EWearableType)type,0); +		if(item_id.notNull()) +		{ +			ids.push_back(item_id); +		} +	} + +	LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); +	if( avatar ) +	{ +		for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin();  +			 iter != avatar->mAttachmentPoints.end(); ++iter) +		{ +			LLViewerJointAttachment* attachment = iter->second; +			if (!attachment) continue; +			for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); +				 attachment_iter != attachment->mAttachedObjects.end(); +				 ++attachment_iter) +			{ +				LLViewerObject* attached_object = (*attachment_iter); +				if (!attached_object) continue; +				const LLUUID& item_id = attached_object->getItemID(); +				if (item_id.isNull()) continue; +				ids.push_back(item_id); +			} +		} +	} + +	mFetchWorn->fetchItems(ids); +	// If no items to be fetched, done will never be triggered. +	// TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition. +	if (mFetchWorn->isEverythingComplete()) +	{ +		mFetchWorn->done(); +	} +	else +	{ +		gInventory.addObserver(mFetchWorn); +	} +} + +void LLSidepanelAppearance::inventoryFetched() +{ +	mNewLookBtn->setEnabled(true); +} diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h new file mode 100644 index 0000000000..496a1fef72 --- /dev/null +++ b/indra/newview/llsidepanelappearance.h @@ -0,0 +1,102 @@ +/**  + * @file llsidepanelappearance.h + * @brief Side Bar "Appearance" panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + *  + * Copyright (c) 2004-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSIDEPANELAPPEARANCE_H +#define LL_LLSIDEPANELAPPEARANCE_H + +#include "llpanel.h" +#include "llinventoryobserver.h" + +#include "llinventory.h" +#include "llpanellookinfo.h" + +class LLFilterEditor; +class LLCurrentlyWornFetchObserver; +class LLPanelEditWearable; +class LLWearable; +class LLPanelOutfitsInventory; + +class LLSidepanelAppearance : public LLPanel +{ +public: +	LLSidepanelAppearance(); +	virtual ~LLSidepanelAppearance(); + +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +	void refreshCurrentOutfitName(const std::string name = ""); + +	static void editWearable(LLWearable *wearable, void *data); + +	void fetchInventory(); +	void inventoryFetched(); +	void updateVerbs(); + +private: +	void onFilterEdit(const std::string& search_string); + +	void onEditAppearanceButtonClicked(); +	void onWearButtonClicked(); +	void onEditButtonClicked(); +	void onNewOutfitButtonClicked(); +	void onBackButtonClicked(); +	void onEditWearBackClicked(); +	void toggleLookInfoPanel(BOOL visible); +	void toggleWearableEditPanel(BOOL visible, LLWearable* wearable); + +	LLFilterEditor*			mFilterEditor; +	LLPanelOutfitsInventory* mPanelOutfitsInventory; +	LLPanelLookInfo*		mLookInfo; +	LLPanelEditWearable*	mEditWearable; + +	LLButton*					mEditAppearanceBtn; +	LLButton*					mWearBtn; +	LLButton*					mEditBtn; +	LLButton*					mNewLookBtn; +	LLButton*					mOverflowBtn; +	LLPanel*					mCurrLookPanel; + +	LLTextBox*					mCurrentLookName; + +	// Used to make sure the user's inventory is in memory. +	LLCurrentlyWornFetchObserver* mFetchWorn; + +	// Search string for filtering landmarks and teleport +	// history locations +	std::string					mFilterSubString; + +	// Information type currently shown in Look Information panel +	std::string					mLookInfoType; + +}; + +#endif //LL_LLSIDEPANELAPPEARANCE_H diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index b48c962413..7cfcac8a9a 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -30,7 +30,7 @@       name="Fetched">          Fetched      </floater.string> -<panel +    <panel       bottom="560"  	 class="panel_main_inventory"  	 filename="panel_main_inventory.xml" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml new file mode 100644 index 0000000000..f511ec0d6f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel name="Outfits"  +	  bottom="0"  +	  height="326"  +	  left="0"  +	  width="310" +	  border="true" +	  follows="left|top|right|bottom"> +	 <inventory_panel  +	 	 allow_multi_select="true"  +		 border="true"  +		 bottom="0" +	     follows="left|top|right|bottom"  +		 height="326"  +		 left="0"  +		 mouse_opaque="true" +	     name="outfits_list" +		 width="310" +		 start_folder="My Outfits"/> +	<button bottom="0" +		 halign="center" +		 height="16" +		 label=">" +		 enabled="false" +	     mouse_opaque="false" +		 name="selector" +		 width="20" +		 left="0" +		 visible="false" +	     follows="right|bottom" +		 tool_tip="View outfit properties"/> +    <panel +     background_visible="true" +     bevel_style="none" +     bottom="0" +     follows="left|right|bottom" +     height="30" +     layout="bottomleft" +     left="0" +	 visible="true" +     name="bottom_panel" +     width="310"> +        <button +         follows="bottom|left" +         tool_tip="Show additional options" +         height="18" +         image_disabled="OptionsMenu_Disabled" +         image_selected="OptionsMenu_Press" +         image_unselected="OptionsMenu_Off" +         layout="topleft" +         left="10" +         name="options_gear_btn" +         picture_style="true" +         top="6" +         width="18" /> +        <button +         follows="bottom|left" +         height="18" +         image_selected="AddItem_Press" +         image_unselected="AddItem_Off" +         image_disabled="AddItem_Disabled" +         layout="topleft" +         left_pad="5" +         name="add_btn" +         picture_style="true" +         tool_tip="Add new item" +         width="18" /> +        <dnd_button +         follows="bottom|right" +         height="18" +         image_selected="TrashItem_Press" +         image_unselected="TrashItem_Off" +         layout="topleft" +         right="-5" +         name="trash_btn" +         picture_style="true" +         tool_tip="Remove selected item" +         top="6" +         width="18" /> +    </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml new file mode 100644 index 0000000000..c8c79f8761 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_gear_default" + visible="false"> +    <menu_item_call +     label="New Outfit" +     layout="topleft" +     name="new"> +        <on_click +         function="panel_outfits_inventory_gear_default.Custom.Action" +         parameter="new" /> +        <on_enable +		 function="panel_outfits_inventory_gear_default.Enable" +		 parameter="new" /> +    </menu_item_call> +    <menu_item_call +     label="Wear Outfit" +     layout="topleft" +     name="wear"> +        <on_click +         function="panel_outfits_inventory_gear_default.Custom.Action" +         parameter="wear" /> +        <on_enable +		 function="panel_outfits_inventory_gear_default.Enable" +		 parameter="wear" /> +    </menu_item_call> +    <menu_item_call +     label="Delete Outfit" +     layout="topleft" +     name="delete"> +        <on_click +         function="panel_outfits_inventory_gear_default.Custom.Action" +         parameter="delete" /> +        <on_enable +		 function="panel_outfits_inventory_gear_default.Enable" +		 parameter="delete" /> +    </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index a419a02d75..d02354a647 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -120,9 +120,9 @@      background_visible="true"    >        <panel -        class="panel_appearance" -        name="panel_appearance" -        filename="panel_appearance.xml" +        class="sidepanel_appearance" +        name="sidepanel_appearance" +        filename="sidepanel_appearance.xml"          label="Edit Appearance"          font="SansSerifBold"        /> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml new file mode 100644 index 0000000000..d87211d432 --- /dev/null +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel +	  background_visible="true" +	  follows="all" +	  height="400" +	  label="Appearance" +	  layout="topleft" +	  min_height="350" +	  min_width="240" +	  name="appearance panel" +	  width="333"> +     <string +		 name="looks_tab_title" +		 value="Looks" /> +     <panel +		 left="5" width="320" height="55" +		 background_visible="true" +		 background_opaque="false" +		 bg_alpha_color="0.2 0.2 0.2 1.0" +		 name="panel_currentlook" +		 follows="left|top|right"> +		<text +			 top="-5" width="200" left="5" height="10" follows="left|right|top" +        	 font="SansSerif" text_color="LtGray" word_wrap="true" +        	 mouse_opaque="false" name="currentlook_title"> +					Current Look +    	</text> +  		<text +			 top="-30" left="8" height="10" follows="left|right|top" +      		 font="SansSerifBold" text_color="white" word_wrap="true" +      		 mouse_opaque="false" name="currentlook_name" > +					MyLook +  		</text> +  	    <button +  	     	 follows="left|right|top" +  	     	 font="SansSerif" +  	     	 top="28" right="-105" width="60" height="20" +  	     	 layout="topleft" +  		 	 label="Edit" +  	     	 name="editappearance_btn"/> +	</panel> + +    <filter_editor +  	     follows="left|top|right" +  	     font="SansSerif" +  	     label="Filter" +  	     layout="topleft" +  	     left="15"  +		 width="313" +		 height="20" +  	     name="Filter" /> +    <panel +   	     class="panel_outfits_inventory" +   	     filename="panel_outfits_inventory.xml" + 	     name="panel_outfits_inventory" +  	     follows="all" +  	     height="271" +  	     halign="center" +  	     layout="topleft" +  	     left="10" +  	     top_pad="19" +  	     width="313" /> +    <button +  	     follows="bottom|left" +  	     font="SansSerifSmallBold" +  	     height="25" +  	     label="Wear" +  	     layout="topleft" +  	     left="10" +  	     name="wear_btn" +     	 top_pad="0" +       	 width="80" /> +    <button +    	 follows="bottom|left" +  	     font="SansSerifSmallBold" +  	     height="25" +  	     label="New Look" +  	     layout="topleft" +  	     left_pad="0" +  	     name="newlook_btn" +  	     top_delta="0" +   	     width="90" /> + +	<panel +       	 class="panel_look_info" +       	 filename="panel_look_info.xml" +       	 follows="all" +       	 layout="topleft" +       	 left="0" +       	 name="panel_look_info" +       	 top="-200" +       	 visible="false" /> + +	<panel +	   	 class="panel_edit_wearable" +	   	 filename="panel_edit_wearable.xml" +	   	 follows="all" +	   	 layout="topleft" +	   	 left="0" +	   	 name="panel_edit_wearable" +	   	 top="-200" +	   	 visible="false" +	   	 width="333" /> +</panel> | 
