diff options
30 files changed, 662 insertions, 81 deletions
| diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index fc93793ed8..3a1e9f19fa 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -826,6 +826,24 @@ void	LLAccordionCtrl::setFilterSubString(const std::string& filter_string)  	mNoVisibleTabsHelpText->setValue(text);  } +const LLAccordionCtrlTab* LLAccordionCtrl::getExpandedTab() const +{ +	typedef std::vector<LLAccordionCtrlTab*>::const_iterator tabs_const_iterator; + +	const LLAccordionCtrlTab* result = 0; + +	for (tabs_const_iterator i = mAccordionTabs.begin(); i != mAccordionTabs.end(); ++i) +	{ +		if ((*i)->isExpanded()) +		{ +			result = *i; +			break; +		} +	} + +	return result; +} +  S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)  {  	if(tab_index < 0) diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index fc6f2d896c..677b598a32 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -129,6 +129,13 @@ public:  	 */  	void	setFilterSubString(const std::string& filter_string); +	/** +	 * This method returns the first expanded accordion tab. +	 * It is expected to be called for accordion which doesn't allow multiple +	 * tabs to be expanded. Use with care. +	 */ +	const LLAccordionCtrlTab* getExpandedTab() const; +  private:  	void	initNoTabsWidget(const LLTextBox::Params& tb_params);  	void	updateNoTabsHelpTextVisibility(); diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index be231fd8cf..54bb328a18 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -974,7 +974,7 @@ BOOL LLAccordionCtrlTab::handleScrollWheel		( S32 x, S32 y, S32 clicks )  	{  		return TRUE;  	} -	if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) +	if( mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )  	{  		return TRUE;  	} diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 19d4ec0a1c..7bf7eeef8f 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -171,7 +171,7 @@ public:  	virtual bool addChild(LLView* child, S32 tab_group); -	bool isExpanded() { return mDisplayChildren; } +	bool isExpanded() const { return mDisplayChildren; }  	S32 getHeaderHeight(); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 341debc9a8..9a56372e68 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -347,7 +347,7 @@ void LLFloater::layoutDragHandle()  	{  		rect = getLocalRect();  	} -	mDragHandle->setRect(rect); +	mDragHandle->setShape(rect);  	updateTitleButtons();  } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 1a4b804ce4..3c6c7d3e82 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2803,13 +2803,13 @@ S32	 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin  {  	LLUIImagePtr image = mStyle->getImage();  	S32 image_width = image->getWidth(); -	if(num_pixels>image_width + IMAGE_HPAD) +	if(line_offset == 0 || num_pixels>image_width + IMAGE_HPAD)  	{  		return 1;  	} -  	return 0;  } +  F32	LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)  {  	if ( (start >= 0) && (end <= mEnd - mStart)) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 53c6369534..24811db3cb 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1773,40 +1773,19 @@ if (DARWIN)          COMMAND ${PYTHON_EXECUTABLE}          ARGS            ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py -          --grid=${GRID} -          --buildtype=${CMAKE_BUILD_TYPE} -          --configuration=${CMAKE_CFG_INTDIR} -          --channel=${VIEWER_CHANNEL} -          --login_channel=${VIEWER_LOGIN_CHANNEL} -          --source=${CMAKE_CURRENT_SOURCE_DIR}            --artwork=${ARTWORK_DIR}            --build=${CMAKE_CURRENT_BINARY_DIR} -          --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app -          --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched -        DEPENDS -          ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py -      ) - - -      add_custom_command( -        TARGET package POST_BUILD -        COMMAND ${PYTHON_EXECUTABLE} -        ARGS -          ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py -          --grid=${GRID}            --buildtype=${CMAKE_BUILD_TYPE} -          --configuration=${CMAKE_CFG_INTDIR}            --channel=${VIEWER_CHANNEL} +          --configuration=${CMAKE_CFG_INTDIR} +          --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app +          --grid=${GRID}            --login_channel=${VIEWER_LOGIN_CHANNEL}            --source=${CMAKE_CURRENT_SOURCE_DIR} -          --artwork=${ARTWORK_DIR} -          --build=${CMAKE_CURRENT_BINARY_DIR} -          --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app            --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched          DEPENDS            ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py        ) -    endif (PACKAGE)  endif (DARWIN) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4506ee6e0c..f9a1dfb0dc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4667,7 +4667,381 @@        <string>String</string>        <key>Value</key>        <string>https://www.xstreetsl.com/modules.php?name=Marketplace</string> -    </map>     +    </map> +    <key>MarketplaceURL_objectFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Attachments Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/attachments</string> +    </map> +    <key>MarketplaceURL_objectMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Attachments Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/attachments</string> +    </map> +    <key>MarketplaceURL_clothingFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Clothing Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/clothing_female_avatar</string> +    </map> +    <key>MarketplaceURL_clothingMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Clothing Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/clothing_male_avatar</string> +    </map> +    <key>MarketplaceURL_bodypartFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Bodyparts Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>https://www.xstreetsl.com/modules.php?name=Marketplace</string> +    </map> +    <key>MarketplaceURL_bodypartMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Bodyparts Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>https://www.xstreetsl.com/modules.php?name=Marketplace</string> +    </map> +    <key>MarketplaceURL_glovesMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Gloves Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/gloves_both_women_and_men</string> +    </map> +    <key>MarketplaceURL_glovesFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Gloves Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/gloves_both_women_and_men</string> +    </map> +    <key>MarketplaceURL_jacketFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Jacket Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/jacket_womens</string> +    </map> +    <key>MarketplaceURL_jacketMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Jacket Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/jacket_mens</string> +    </map> +    <key>MarketplaceURL_shirtFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Shirt Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/shirt_womens</string> +    </map> +    <key>MarketplaceURL_shirtMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Shirt Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/shirt_mens</string> +    </map> +    <key>MarketplaceURL_undershirtFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Undershirt Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/undershirt_womens</string> +    </map> +    <key>MarketplaceURL_undershirtMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Undershirt Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/undershirt_mens</string> +    </map> +    <key>MarketplaceURL_skirtFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Skirt Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/skirts_women</string> +    </map> +    <key>MarketplaceURL_skirtMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Skirt Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/skirts_women</string> +    </map> +    <key>MarketplaceURL_pantsFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Pants Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/pants_women</string> +    </map> +    <key>MarketplaceURL_pantsMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Pants Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/pants_men</string> +    </map> +    <key>MarketplaceURL_underpantsFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Underwear Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/underwear_women</string> +    </map> +    <key>MarketplaceURL_underpantsMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Underwear Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/underwear_men</string> +    </map> +    <key>MarketplaceURL_shoesFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Shoes Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/shoes_women</string> +    </map> +    <key>MarketplaceURL_shoesMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Shoes Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/shoes_men</string> +    </map> +    <key>MarketplaceURL_socksFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Socks Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/socks_women</string> +    </map> +    <key>MarketplaceURL_socksMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Socks Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/socks_women</string> +    </map> +    <key>MarketplaceURL_tattooMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Tattoo Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/tattoo_both_women_and_men</string> +    </map> +    <key>MarketplaceURL_tattooFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Tattoo Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/tattoo_both_women_and_men</string> +    </map> +    <key>MarketplaceURL_hairFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Hair Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/womens_hair</string> +    </map> +    <key>MarketplaceURL_hairMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Hair Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/mens_hair</string> +    </map> +    <key>MarketplaceURL_eyesFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Eyes Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/womens_eyes</string> +    </map> +    <key>MarketplaceURL_eyesMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Eyes Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/mens_eyes</string> +    </map> +    <key>MarketplaceURL_shapeFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Shape Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/womens_shape</string> +    </map> +    <key>MarketplaceURL_shapeMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Shape Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/mens_shape</string> +    </map> +    <key>MarketplaceURL_skinFemale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Skin Female</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/womens_skin</string> +    </map> +    <key>MarketplaceURL_skinMale</key> +    <map> +      <key>Comment</key> +      <string>URL to the Marketplace Skins Male</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>http://marketplace.secondlife.com/trampoline/viewer21/mens_skin</string> +    </map>      <key>MaxDragDistance</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 342f9a5d80..557b3b0a77 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2099,7 +2099,19 @@ void LLAgentWearables::populateMyOutfitsFolder(void)  	}  } +boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb) +{ +	return mLoadingStartedSignal.connect(cb); +} +  boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_t cb)  {  	return mLoadedSignal.connect(cb);  } + +void LLAgentWearables::notifyLoadingStarted() +{ +	mLoadingStartedSignal(); +} + +// EOF diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index a41b949be6..3295544e04 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -224,11 +224,18 @@ public:  	// Signals  	//--------------------------------------------------------------------  public: +	typedef boost::function<void()>			loading_started_callback_t; +	typedef boost::signals2::signal<void()>	loading_started_signal_t; +	boost::signals2::connection				addLoadingStartedCallback(loading_started_callback_t cb); +  	typedef boost::function<void()>			loaded_callback_t;  	typedef boost::signals2::signal<void()>	loaded_signal_t;  	boost::signals2::connection				addLoadedCallback(loaded_callback_t cb); +	void									notifyLoadingStarted(); +  private: +	loading_started_signal_t				mLoadingStartedSignal; // should be called before wearables are changed  	loaded_signal_t							mLoadedSignal; // emitted when all agent wearables get loaded  	//-------------------------------------------------------------------- diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index bc17605202..a7206095d3 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1407,6 +1407,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category,  void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)  { +	gAgentWearables.notifyLoadingStarted();  	if(!category) return;  	llinfos << "wearInventoryCategory( " << category->getName() diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 611396b0e5..880d79222b 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -34,6 +34,8 @@  #include "llcofwearables.h" +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h"  #include "llagentdata.h"  #include "llagentwearables.h"  #include "llappearancemgr.h" @@ -557,6 +559,14 @@ LLPanel* LLCOFWearables::getSelectedItem()  	return mLastSelectedList->getSelectedItem();  } +void LLCOFWearables::getSelectedItems(std::vector<LLPanel*>& selected_items) const +{ +	if (mLastSelectedList) +	{ +		mLastSelectedList->getSelectedItems(selected_items); +	} +} +  void LLCOFWearables::clear()  {  	mAttachments->clear(); @@ -564,6 +574,29 @@ void LLCOFWearables::clear()  	mBodyParts->clear();  } +LLAssetType::EType LLCOFWearables::getExpandedAccordionAssetType() +{ +	static std::map<std::string, LLAssetType::EType> type_map; +	static LLAccordionCtrl* accordion_ctrl = getChild<LLAccordionCtrl>("cof_wearables_accordion"); + +	if (type_map.empty()) +	{ +		type_map["tab_clothing"] = LLAssetType::AT_CLOTHING; +		type_map["tab_attachments"] = LLAssetType::AT_OBJECT; +		type_map["tab_body_parts"] = LLAssetType::AT_BODYPART; +	} + +	const LLAccordionCtrlTab* tab = accordion_ctrl->getExpandedTab(); + +	if (!tab) +	{ +		llwarns << "No accordion is expanded" << llendl; +		return LLAssetType::AT_NONE; +	} + +	return type_map[tab->getName()]; +} +  void LLCOFWearables::onListRightClick(LLUICtrl* ctrl, S32 x, S32 y, LLListContextMenu* menu)  {  	if(menu) diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h index f99f2662e6..62f4cfc692 100644 --- a/indra/newview/llcofwearables.h +++ b/indra/newview/llcofwearables.h @@ -78,10 +78,13 @@ public:  	bool getSelectedUUIDs(uuid_vec_t& selected_ids);  	LLPanel* getSelectedItem(); +	void getSelectedItems(std::vector<LLPanel*>& selected_items) const;  	void refresh();  	void clear(); +	LLAssetType::EType getExpandedAccordionAssetType(); +  	LLCOFCallbacks& getCOFCallbacks() { return mCOFCallbacks; }  protected: diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index a2ef8c1d12..82f8a10cf3 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -37,6 +37,7 @@  #include "llinventorytype.h"  #include "llpermissionsflags.h"  #include "llpointer.h" +#include "llwearabletype.h"  class LLFolderViewItem; @@ -89,6 +90,7 @@ public:  	virtual BOOL hasChildren() const = 0;  	virtual LLInventoryType::EType getInventoryType() const = 0;  	virtual void performAction(LLInventoryModel* model, std::string action) = 0; +	virtual LLWearableType::EType getWearableType() const = 0;  	// This method should be called when a drag begins. returns TRUE  	// if the drag can begin, otherwise FALSE. diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index d97dfd535e..757808eb93 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -123,6 +123,7 @@ public:  							EDragAndDropType cargo_type,  							void* cargo_data) { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return mInvType; } +	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }  	//--------------------------------------------------------------------  	// Convenience functions for adding various common menu options. @@ -471,6 +472,7 @@ public:  	virtual void	buildContextMenu(LLMenuGL& menu, U32 flags);  	virtual std::string getLabelSuffix() const;  	virtual BOOL renameItem(const std::string& new_name); +	virtual LLWearableType::EType getWearableType() const { return mWearableType; }  	static void		onWearOnAvatar( void* userdata );	// Access to wearOnAvatar() from menu  	static BOOL		canWearOnAvatar( void* userdata ); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c90919e8fd..6e829f2dc2 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -49,6 +49,7 @@  LLInventoryFilter::FilterOps::FilterOps() :  	mFilterObjectTypes(0xffffffffffffffffULL),  	mFilterCategoryTypes(0xffffffffffffffffULL), +	mFilterWearableTypes(0xffffffffffffffffULL),  	mMinDate(time_min()),  	mMaxDate(time_max()),  	mHoursAgo(0), @@ -139,8 +140,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  			return FALSE;  		}  	} -	// -	////////////////////////////////////////////////////////////////////////////////  	//////////////////////////////////////////////////////////////////////////////// @@ -164,8 +163,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  		if ((1LL << cat->getPreferredType() & mFilterOps.mFilterCategoryTypes) == U64(0))  			return FALSE;  	} -	// -	////////////////////////////////////////////////////////////////////////////////  	//////////////////////////////////////////////////////////////////////////////// @@ -178,8 +175,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  		if (object->getLinkedUUID() != mFilterOps.mFilterUUID)  			return FALSE;  	} -	// -	////////////////////////////////////////////////////////////////////////////////  	//////////////////////////////////////////////////////////////////////////////// @@ -201,8 +196,18 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  			listener->getCreationDate() > mFilterOps.mMaxDate)  			return FALSE;  	} -	// +  	//////////////////////////////////////////////////////////////////////////////// +	// FILTERTYPE_WEARABLE +	// Pass if this item is a wearable of the appropriate type +	if (filterTypes & FILTERTYPE_WEARABLE) +	{ +		LLWearableType::EType type = listener->getWearableType(); +		if ((0x1LL << type & mFilterOps.mFilterWearableTypes) == 0) +		{ +			return FALSE; +		} +	}  	return TRUE;  } @@ -238,6 +243,8 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset() const  BOOL LLInventoryFilter::isNotDefault() const  {  	return mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes  +		|| mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes  +		|| mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes   		|| mFilterOps.mFilterTypes != FILTERTYPE_OBJECT  		|| mFilterSubString.size()   		|| mFilterOps.mPermissions != mDefaultFilterOps.mPermissions @@ -249,6 +256,8 @@ BOOL LLInventoryFilter::isNotDefault() const  BOOL LLInventoryFilter::isActive() const  {  	return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL +		|| mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL +		|| mFilterOps.mFilterWearableTypes != 0xffffffffffffffffULL  		|| mFilterOps.mFilterTypes != FILTERTYPE_OBJECT  		|| mFilterSubString.size()   		|| mFilterOps.mPermissions != PERM_NONE  @@ -322,7 +331,35 @@ void LLInventoryFilter::setFilterCategoryTypes(U64 types)  			setModified(FILTER_MORE_RESTRICTIVE);  		}  	} -	mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY; +	mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT; +} + +void LLInventoryFilter::setFilterWearableTypes(U64 types) +{ +	if (mFilterOps.mFilterWearableTypes != types) +	{ +		// keep current items only if no type bits getting turned off +		BOOL fewer_bits_set = (mFilterOps.mFilterWearableTypes & ~types); +		BOOL more_bits_set = (~mFilterOps.mFilterWearableTypes & types); + +		mFilterOps.mFilterWearableTypes = types; +		if (more_bits_set && fewer_bits_set) +		{ +			// neither less or more restrive, both simultaneously +			// so we need to filter from scratch +			setModified(FILTER_RESTART); +		} +		else if (more_bits_set) +		{ +			// target is only one of all requested types so more type bits == less restrictive +			setModified(FILTER_LESS_RESTRICTIVE); +		} +		else if (fewer_bits_set) +		{ +			setModified(FILTER_MORE_RESTRICTIVE); +		} +	} +	mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;  }  void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 3ef51baefc..f740a6b333 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -59,10 +59,11 @@ public:  	enum EFilterType  	{  		FILTERTYPE_NONE = 0, -		FILTERTYPE_OBJECT = 1,		// normal default search-by-object-type -		FILTERTYPE_CATEGORY = 2,	// search by folder type -		FILTERTYPE_UUID	= 4,		// find the object with UUID and any links to it -		FILTERTYPE_DATE = 8			// search by date range +		FILTERTYPE_OBJECT = 0x1 << 0,	// normal default search-by-object-type +		FILTERTYPE_CATEGORY = 0x1 << 1,	// search by folder type +		FILTERTYPE_UUID	= 0x1 << 2,		// find the object with UUID and any links to it +		FILTERTYPE_DATE = 0x1 << 3,		// search by date range +		FILTERTYPE_WEARABLE = 0x1 << 4	// search by wearable type  	};  	// REFACTOR: Change this to an enum. @@ -81,6 +82,7 @@ public:  	BOOL 				isFilterObjectTypesWith(LLInventoryType::EType t) const;  	void 				setFilterCategoryTypes(U64 types);  	void 				setFilterUUID(const LLUUID &object_id); +	void				setFilterWearableTypes(U64 types);  	void 				setFilterSubString(const std::string& string);  	const std::string& 	getFilterSubString(BOOL trim = FALSE) const; @@ -168,6 +170,7 @@ private:  		U32 			mFilterTypes;  		U64				mFilterObjectTypes; // For _OBJECT +		U64				mFilterWearableTypes;  		U64				mFilterCategoryTypes; // For _CATEGORY  		LLUUID      	mFilterUUID; // for UUID diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6b0103e0de..83c57d5bb2 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -226,6 +226,11 @@ void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)  	getFilter()->setFilterPermissions(filter_perm_mask);  } +void LLInventoryPanel::setFilterWearableTypes(U64 types) +{ +	getFilter()->setFilterWearableTypes(types); +} +  void LLInventoryPanel::setFilterSubString(const std::string& string)  {  	getFilter()->setFilterSubString(string); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 67c8904868..52e9ef799e 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -138,6 +138,7 @@ public:  	U32 getFilterObjectTypes() const { return mFolderRoot->getFilterObjectTypes(); }  	void setFilterPermMask(PermissionMask filter_perm_mask);  	U32 getFilterPermMask() const { return mFolderRoot->getFilterPermissions(); } +	void setFilterWearableTypes(U64 filter);  	void setFilterSubString(const std::string& string);  	const std::string getFilterSubString() { return mFolderRoot->getFilterSubString(); }  	void setSinceLogoff(BOOL sl); diff --git a/indra/newview/lloutfitobserver.cpp b/indra/newview/lloutfitobserver.cpp index efa01bade9..03414b9964 100644 --- a/indra/newview/lloutfitobserver.cpp +++ b/indra/newview/lloutfitobserver.cpp @@ -56,12 +56,9 @@ void LLOutfitObserver::changed(U32 mask)  	if (!gInventory.isInventoryUsable())  		return; -	bool COF_changed = checkCOF(); +	checkCOF(); -	if (!COF_changed) -	{ -		checkBaseOutfit(); -	} +	checkBaseOutfit();  }  // static diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index ad3a5c2380..da809b7baa 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -135,6 +135,8 @@ public:  	virtual BOOL isUpToDate() const { return TRUE; }  	virtual BOOL hasChildren() const { return FALSE; }  	virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } +	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } +  	// LLDragAndDropBridge functionality  	virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;  	virtual BOOL dragOrDrop(MASK mask, BOOL drop, @@ -184,6 +186,7 @@ void LLTaskInvFVBridge::showProperties()  		floater->setObjectID(mPanel->getTaskUUID());  	}  	*/ +	  }  struct LLBuyInvItemData diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 1454a2f6af..8da7432e0a 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -72,6 +72,8 @@  #include "lltoggleablemenu.h"  #include "llwearablelist.h"  #include "llwearableitemslist.h" +#include "llwearabletype.h" +#include "llweb.h"  static LLRegisterPanelClassWrapper<LLPanelOutfitEdit> t_outfit_edit("panel_outfit_edit"); @@ -81,6 +83,65 @@ const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;  static const std::string REVERT_BTN("revert_btn"); +class LLShopURLDispatcher +{ +public: +	std::string resolveURL(LLWearableType::EType wearable_type, ESex sex); +	std::string resolveURL(LLAssetType::EType asset_type, ESex sex); +}; + +std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type, ESex sex) +{ +	const std::string prefix = "MarketplaceURL"; +	const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female"; +	const std::string type_str = LLWearableType::getTypeName(wearable_type); + +	std::string setting_name = prefix; + +	switch (wearable_type) +	{ +	case LLWearableType::WT_ALPHA: +	case LLWearableType::WT_NONE: +	case LLWearableType::WT_INVALID:	// just in case, this shouldn't happen +	case LLWearableType::WT_COUNT:		// just in case, this shouldn't happen +		break; + +	default: +		setting_name += '_'; +		setting_name += type_str; +		setting_name += sex_str; +		break; +	} + +	return gSavedSettings.getString(setting_name); +} + +std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex sex) +{ +	const std::string prefix = "MarketplaceURL"; +	const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female"; +	const std::string type_str = LLAssetType::lookup(asset_type); + +	std::string setting_name = prefix; + +	switch (asset_type) +	{ +	case LLAssetType::AT_CLOTHING: +	case LLAssetType::AT_OBJECT: +	case LLAssetType::AT_BODYPART: +		setting_name += '_'; +		setting_name += type_str; +		setting_name += sex_str; +		break; + +	// to suppress warnings +	default: +		break; +	} + +	return gSavedSettings.getString(setting_name); +} +  class LLPanelOutfitEditGearMenu  {  public: @@ -262,6 +323,7 @@ BOOL LLPanelOutfitEdit::postBuild()  	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);  	childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);  	childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL); +	childSetCommitCallback("shop_btn", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);  	mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list");  	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, this)); @@ -530,6 +592,46 @@ void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id  	}  } +void LLPanelOutfitEdit::onShopButtonClicked() +{ +	static LLShopURLDispatcher url_resolver; + +	std::string url; +	std::vector<LLPanel*> selected_items; +	mCOFWearables->getSelectedItems(selected_items); + +	ESex sex = gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE; + +	if (selected_items.size() == 1) +	{ +		LLWearableType::EType type = LLWearableType::WT_NONE; +		LLPanel* item = selected_items.front(); + +		// LLPanelDummyClothingListItem is lower then LLPanelInventoryListItemBase in hierarchy tree +		if (LLPanelDummyClothingListItem* dummy_item = dynamic_cast<LLPanelDummyClothingListItem*>(item)) +		{ +			type = dummy_item->getWearableType(); +		} +		else if (LLPanelInventoryListItemBase* real_item = dynamic_cast<LLPanelInventoryListItemBase*>(item)) +		{ +			type = real_item->getWearableType(); +		} + +		// WT_INVALID comes for attachments +		if (type != LLWearableType::WT_INVALID) +		{ +			url = url_resolver.resolveURL(type, sex); +		} +	} + +	if (url.empty()) +	{ +		url = url_resolver.resolveURL(mCOFWearables->getExpandedAccordionAssetType(), sex); +	} + +	LLWeb::loadURLExternal(url); +} +  void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)  {  	LLUUID id_to_remove = mCOFWearables->getSelectedUUID(); diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 56c6c6d680..1705e3043b 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -163,6 +163,7 @@ public:  	void onEditWearableClicked(void);  	void onAddWearableClicked(void);  	void onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id); +	void onShopButtonClicked();  	void displayCurrentOutfit();  	void updateCurrentOutfitName(); diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 1157c40b39..7e1bff0961 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -86,7 +86,6 @@ public:  		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)); @@ -159,15 +158,6 @@ private:  		}  	} -	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(); @@ -197,11 +187,7 @@ private:  			return false;  		} -		if ("rename" == param) -		{ -			return get_is_category_renameable(&gInventory, selected_outfit_id); -		} -		else if ("delete" == param) +		if ("delete" == param)  		{  			return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id);  		} @@ -245,6 +231,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :  	mSavedFolderState = new LLSaveFolderState();  	mSavedFolderState->setApply(FALSE);  	gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this)); +	gAgentWearables.addLoadingStartedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoading, this));  	LLOutfitObserver& observer = LLOutfitObserver::instance();  	observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); @@ -382,7 +369,6 @@ void LLPanelOutfitsInventory::onWearButtonClick()  	if (!isCOFPanelActive())  	{  		mMyOutfitsPanel->performAction("replaceoutfit"); -		setWearablesLoading(true);  	}  	else  	{ @@ -854,6 +840,11 @@ void LLPanelOutfitsInventory::onWearablesLoaded()  	setWearablesLoading(false);  } +void LLPanelOutfitsInventory::onWearablesLoading() +{ +	setWearablesLoading(true); +} +  // static  LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP()  { diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index d58ae554b0..863dc9dd7c 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -127,6 +127,7 @@ protected:  	bool hasItemsSelected();  	void setWearablesLoading(bool val);  	void onWearablesLoaded(); +	void onWearablesLoading();  private:  	LLPanel*					mListCommands;  	LLOutfitListGearMenu*		mGearMenu; 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 8e7ef7f0b5..16b33eff89 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml @@ -176,19 +176,6 @@      <menu_item_separator name="sepatator2" />      <menu_item_call -     label="Rename Outfit" -     layout="topleft" -     name="rename"> -        <on_click -         function="Gear.Rename" /> -        <on_enable -         function="Gear.OnEnable" -         parameter="rename" /> -        <on_visible -         function="Gear.OnVisible" -         parameter="rename" /> -    </menu_item_call> -    <menu_item_call       label="Delete Outfit"       layout="topleft"       name="delete_outfit"> 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 430a7b6444..efea2ae3e8 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 @@ -2,7 +2,7 @@  <context_menu   name="Outfit Wearable Context Menu">      <menu_item_call -     label="Wear" +     label="Replace"       layout="topleft"       name="wear">          <on_click diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index aca3b750c8..cf3097cb06 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1397,8 +1397,7 @@ Unable to encode file: [FILE]     icon="alertmodal.tga"     name="CorruptedProtectedDataStore"     type="alertmodal"> -  We are unable to read your protected data so it is being reset. -   This may happen when you change network setup. +   We can't fill in your username and password.  This may happen when you change network setup      <usetemplate       name="okbutton" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index ed3b176267..528850a6ec 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -375,7 +375,19 @@ It is calculated as border_size + 2*UIResizeBarOverlap           layout="topleft"           left_pad="1"           name="dummy_right_icon" -         width="281" /> +         width="246" /> +        <button +         follows="bottom|right" +         height="25" +         image_hover_unselected="Toolbar_Middle_Over" +         image_overlay="AddItem_Off" +         image_selected="Toolbar_Middle_Selected" +         image_unselected="Toolbar_Middle_Off" +         layout="topleft" +         left_pad="0" +         name="shop_btn" +         top="1" +         width="31" />      </panel> @@ -490,7 +502,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap           follows="bottom|left|right"           height="23"           left_pad="12" -         label="Revert" +         label="Undo Changes"           layout="topleft"           name="revert_btn"           top="0" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 8d2525dd26..0fd3cf5b3b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -559,6 +559,10 @@ class WindowsManifest(ViewerManifest):  class DarwinManifest(ViewerManifest): +    def is_packaging_viewer(self): +        # darwin requires full app bundle packaging even for debugging. +        return True +      def construct(self):          # copy over the build result (this is a no-op if run within the xcode script)          self.path(self.args['configuration'] + "/Second Life.app", dst="") | 
