diff options
| author | Tofu Linden <tofu.linden@lindenlab.com> | 2010-05-05 19:16:05 +0100 | 
|---|---|---|
| committer | Tofu Linden <tofu.linden@lindenlab.com> | 2010-05-05 19:16:05 +0100 | 
| commit | 8d9c7855ddbe3f4666a293f29f4d6c89730d10c5 (patch) | |
| tree | 6d84364e513f68908f2fddcbd1a4a68ca1958062 /indra | |
| parent | 447bffcb532694fcc3bc3b046051f02ac4550fd3 (diff) | |
| parent | f290e9e851e1af694cd8df86e171b79ed4186e90 (diff) | |
merge from viewer-public
Diffstat (limited to 'indra')
32 files changed, 667 insertions, 281 deletions
| diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 2629237f7e..a29e9a348e 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -404,7 +404,7 @@ void LLWorkerClass::scheduleDelete()  void LLWorkerClass::setPriority(U32 priority)  {  	mMutex.lock(); -	if (mRequestHandle != LLWorkerThread::nullHandle()) +	if (mRequestHandle != LLWorkerThread::nullHandle() && mRequestPriority != priority)  	{  		mRequestPriority = priority;  		mWorkerThread->setPriority(mRequestHandle, priority); diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index dd56e18caf..964cbd1026 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -79,8 +79,10 @@ namespace  		{  			if (mResponder.get())  			{ -				mResponder->completedRaw(mStatus, mReason, channels, buffer); +				// Allow clients to parse headers before we attempt to parse +				// the body and provide completed/result/error calls.  				mResponder->completedHeader(mStatus, mReason, mHeaderOutput); +				mResponder->completedRaw(mStatus, mReason, channels, buffer);  			}  		}  		virtual void header(const std::string& header, const std::string& value) diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp index 390504234d..6c80275713 100644 --- a/indra/llui/llfiltereditor.cpp +++ b/indra/llui/llfiltereditor.cpp @@ -39,6 +39,7 @@  LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p)  :	LLSearchEditor(p)  { +	setCommitOnFocusLost(FALSE); // we'll commit on every keystroke, don't re-commit when we take focus away (i.e. we go to interact with the actual results!)  } diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index bea2572ff8..6bd16c9ee6 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -379,6 +379,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)    , mCommitOnSelectionChange(false)    , mPrevNotifyParentRect(LLRect())    , mNoItemsCommentTextbox(NULL) +  , mIsConsecutiveSelection(false)  {  	mBorderThickness = getBorderWidth(); @@ -536,6 +537,7 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)  			return;  		bool grab_items = false; +		bool reverse = false;  		pairs_list_t pairs_to_select;  		// Pick out items from list between last selected and current clicked item_pair. @@ -547,6 +549,8 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)  			item_pair_t* cur = *iter;  			if (cur == last_selected_pair || cur == item_pair)  			{ +				// We've got reverse selection if last grabed item isn't a new selection. +				reverse = grab_items && (cur != item_pair);  				grab_items = !grab_items;  				// Skip last selected and current clicked item pairs.  				continue; @@ -562,26 +566,35 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)  			}  		} -		if (select_item) +		if (reverse)  		{ -			pairs_to_select.push_back(item_pair); +			pairs_to_select.reverse();  		} +		pairs_to_select.push_back(item_pair); +  		for (pairs_iterator_t  				 iter = pairs_to_select.begin(),  				 iter_end = pairs_to_select.end();  			 iter != iter_end; ++iter)  		{  			item_pair_t* pair_to_select = *iter; -			selectItemPair(pair_to_select, true); +			if (isSelected(pair_to_select)) +			{ +				// Item was already selected but there is a need to keep order from last selected pair to new selection. +				// Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). +				mSelectedItemPairs.remove(pair_to_select); +				mSelectedItemPairs.push_back(pair_to_select); +			} +			else +			{ +				selectItemPair(pair_to_select, true); +			}  		}  		if (!select_item)  		{ -			// Item was already selected but there is a need to update last selected item and its border. -			// Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). -			mSelectedItemPairs.remove(item_pair); -			mSelectedItemPairs.push_back(item_pair); +			// Update last selected item border.  			mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));  		}  		return; @@ -749,6 +762,8 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)  	// Stretch selected item rect to ensure it won't be clipped  	mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); +	// By default mark it as not consecutive selection +	mIsConsecutiveSelection = false;  	return true;  } @@ -823,6 +838,17 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti  	if ( 0 == size() )  		return false; +	if (!mIsConsecutiveSelection) +	{ +		// Leave only one item selected if list has not consecutive selection +		if (mSelectedItemPairs.size() && !reset_selection) +		{ +			item_pair_t* cur_sel_pair = mSelectedItemPairs.back(); +			resetSelection(); +			selectItemPair (cur_sel_pair, true); +		} +	} +  	if ( mSelectedItemPairs.size() )  	{  		item_pair_t* to_sel_pair = NULL; @@ -877,6 +903,8 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti  			}  			// Select/Deselect next item  			selectItemPair(select ? to_sel_pair : cur_sel_pair, select); +			// Mark it as consecutive selection +			mIsConsecutiveSelection = true;  			return true;  		}  	} @@ -888,6 +916,8 @@ bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selecti  			selectLastItem();  		else  			selectFirstItem(); +		// Mark it as consecutive selection +		mIsConsecutiveSelection = true;  		return true;  	} diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 6395805aab..f4e0426f15 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -410,6 +410,8 @@ private:  	bool mKeepOneItemSelected; +	bool mIsConsecutiveSelection; +  	/** All pairs of the list */  	pairs_list_t mItemPairs; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index be32d92ea1..0106e9a78f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1652,6 +1652,17 @@        <key>Value</key>        <string />      </map> +	<key>DebugAvatarRezTime</key> +	<map> +		<key>Comment</key> +		<string>Display times for avatars to resolve.</string> +		<key>Persist</key> +		<integer>1</integer> +		<key>Type</key> +		<string>Boolean</string> +		<key>Value</key> +		<integer>0</integer> +	</map>      <key>DebugBeaconLineWidth</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index b5fde0baca..47735e7179 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1164,6 +1164,7 @@ void LLAgentWearables::createStandardWearablesAllDone()  	mWearablesLoaded = TRUE;   	checkWearablesLoaded(); +	mLoadedSignal();  	updateServer(); @@ -1567,6 +1568,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it  	// Start rendering & update the server  	mWearablesLoaded = TRUE;   	checkWearablesLoaded(); +	mLoadedSignal();  	queryWearableCache();  	updateServer(); @@ -2012,6 +2014,10 @@ BOOL LLAgentWearables::areWearablesLoaded() const  void LLAgentWearables::updateWearablesLoaded()  {  	mWearablesLoaded = (itemUpdatePendingCount()==0); +	if (mWearablesLoaded) +	{ +		mLoadedSignal(); +	}  }  bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const @@ -2091,3 +2097,8 @@ void LLAgentWearables::populateMyOutfitsFolder(void)  		outfits->done();  	}  } + +boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_t cb) +{ +	return mLoadedSignal.connect(cb); +} diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index d3b18f68f1..a28cba0343 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -209,6 +209,17 @@ public:  	U32				itemUpdatePendingCount() const;  	//-------------------------------------------------------------------- +	// Signals +	//-------------------------------------------------------------------- +public: +	typedef boost::function<void()>			loaded_callback_t; +	typedef boost::signals2::signal<void()>	loaded_signal_t; +	boost::signals2::connection				addLoadedCallback(loaded_callback_t cb); + +private: +	loaded_signal_t							mLoadedSignal; // emitted when all agent wearables get loaded + +	//--------------------------------------------------------------------  	// Member variables  	//--------------------------------------------------------------------  private: diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 002d417e4c..0e802e9736 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -70,11 +70,6 @@ public:  		  completeAny(status, mime_type);  	  } -	  virtual void error( U32 status, const std::string& reason ) -	  { -		  completeAny(status, LLMIMETypes::getDefaultMimeType()); -	  } -  	  void completeAny(U32 status, const std::string& mime_type)  	  {  		  // Set empty type to none/none.  Empty string is reserved for legacy parcels diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 874723bb1a..38d7a47eba 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -230,6 +230,7 @@ public:  								   EAcceptance* accept,  								   std::string& tooltip_msg);  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +	/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); }  	virtual void draw();  	virtual void deleteAllChildren(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2d08c0a01a..228ab7ebd6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -5525,3 +5525,67 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_  /**                    Bridge Actions   **   ********************************************************************************/ + +/************************************************************************/ +/* Recent Inventory Panel related classes                               */ +/************************************************************************/ +void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) +{ +	LLFolderBridge::buildContextMenu(menu, flags); + +	menuentry_vec_t disabled_items, items = getMenuItems(); + +	items.erase(std::find(items.begin(), items.end(), std::string("New Folder"))); +	items.erase(std::find(items.begin(), items.end(), std::string("New Script"))); +	items.erase(std::find(items.begin(), items.end(), std::string("New Note"))); +	items.erase(std::find(items.begin(), items.end(), std::string("New Gesture"))); +	items.erase(std::find(items.begin(), items.end(), std::string("New Clothes"))); +	items.erase(std::find(items.begin(), items.end(), std::string("New Body Parts"))); + +	hide_context_entries(menu, items, disabled_items); +} + +LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( +	LLAssetType::EType asset_type, +	LLAssetType::EType actual_asset_type, +	LLInventoryType::EType inv_type, +	LLInventoryPanel* inventory, +	LLFolderView* root, +	const LLUUID& uuid, +	U32 flags /*= 0x00*/ ) const +{ +	LLInvFVBridge* new_listener = NULL; +	switch(asset_type) +	{ +	case LLAssetType::AT_CATEGORY: +		if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) +		{ +			// *TODO: Create a link folder handler instead if it is necessary +			new_listener = LLInventoryFVBridgeBuilder::createBridge( +				asset_type, +				actual_asset_type, +				inv_type, +				inventory, +				root, +				uuid, +				flags); +			break; +		} +		new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); +		break; +	default: +		new_listener = LLInventoryFVBridgeBuilder::createBridge( +			asset_type, +			actual_asset_type, +			inv_type, +			inventory, +			root, +			uuid, +			flags); +	} +	return new_listener; + +} + + +// EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index de63bdd76b..c45e376cab 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -349,6 +349,11 @@ protected:  	void modifyOutfit(BOOL append);  	void determineFolderType(); +	/** +	 * Returns a copy of current menu items. +	 */ +	menuentry_vec_t getMenuItems() { return mItems; } +  public:  	static LLFolderBridge* sSelf;  	static void staticFolderOptionsMenu(); @@ -659,6 +664,58 @@ protected:  }; +/************************************************************************/ +/* Recent Inventory Panel related classes                               */ +/************************************************************************/ +class LLRecentInventoryBridgeBuilder; +/** + * Overridden version of the Inventory-Folder-View-Bridge for Folders + */ +class LLRecentItemsFolderBridge : public LLFolderBridge +{ +	friend class LLRecentInventoryBridgeBuilder; + +public: +	/** +	 * Creates context menu for Folders related to Recent Inventory Panel. +	 * +	 * It uses base logic and than removes from visible items "New..." menu items. +	 */ +	/*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags); + +protected: +	LLRecentItemsFolderBridge(LLInventoryType::EType type, +						 LLInventoryPanel* inventory, +						 LLFolderView* root, +						 const LLUUID& uuid) : +		LLFolderBridge(inventory, root, uuid) +	{ +		mInvType = type; +	} +}; + +/** + * Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel + */ +class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder +{ +	/** +	 * Overrides FolderBridge for Recent Inventory Panel. +	 * +	 * It use base functionality for bridges other than FolderBridge. +	 */ +	virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type, +		LLAssetType::EType actual_asset_type, +		LLInventoryType::EType inv_type, +		LLInventoryPanel* inventory, +		LLFolderView* root, +		const LLUUID& uuid, +		U32 flags = 0x00) const; + +}; + + +  void wear_inventory_item_on_avatar(LLInventoryItem* item);  void rez_attachment(LLViewerInventoryItem* item,  diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index cfbc2c3e05..0ff6ab2644 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -46,26 +46,11 @@  const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;  const S32 MAX_FETCH_RETRIES = 10; -// RN: for some reason, using std::queue in the header file confuses the compiler which thinks it's an xmlrpc_queue -static std::deque<LLUUID> sFetchQueue; -bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) -{ -	for (std::deque<LLUUID>::iterator it = sFetchQueue.begin(); -		 it != sFetchQueue.end(); ++it) -	{ -		const LLUUID& fetch_id = *it; -		if (gInventory.isObjectDescendentOf(fetch_id, cat_id)) -			return false; -	} -	return true; -} - -  LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :  	mBackgroundFetchActive(FALSE),  	mAllFoldersFetched(FALSE), -	mInventoryFetchStarted(FALSE), -	mLibraryFetchStarted(FALSE), +	mRecursiveInventoryFetchStarted(FALSE), +	mRecursiveLibraryFetchStarted(FALSE),  	mNumFetchRetries(0),  	mMinTimeBetweenFetches(0.3f),  	mMaxTimeBetweenFetches(10.f), @@ -80,12 +65,12 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()  bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete()  { -	return sFetchQueue.empty() && mBulkFetchCount<=0; +	return mFetchQueue.empty() && mBulkFetchCount<=0;  }  bool LLInventoryModelBackgroundFetch::libraryFetchStarted()  { -	return mLibraryFetchStarted; +	return mRecursiveLibraryFetchStarted;  }  bool LLInventoryModelBackgroundFetch::libraryFetchCompleted() @@ -100,7 +85,7 @@ bool LLInventoryModelBackgroundFetch::libraryFetchInProgress()  bool LLInventoryModelBackgroundFetch::inventoryFetchStarted()  { -	return mInventoryFetchStarted; +	return mRecursiveInventoryFetchStarted;  }  bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() @@ -123,41 +108,41 @@ BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive()  	return mBackgroundFetchActive;  } -void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id) +void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive)  {  	if (!mAllFoldersFetched)  	{  		mBackgroundFetchActive = TRUE;  		if (cat_id.isNull())  		{ -			if (!mInventoryFetchStarted) +			if (!mRecursiveInventoryFetchStarted)  			{ -				mInventoryFetchStarted = TRUE; -				sFetchQueue.push_back(gInventory.getRootFolderID()); +				mRecursiveInventoryFetchStarted |= recursive; +				mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));  				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);  			} -			if (!mLibraryFetchStarted) +			if (!mRecursiveLibraryFetchStarted)  			{ -				mLibraryFetchStarted = TRUE; -				sFetchQueue.push_back(gInventory.getLibraryRootFolderID()); +				mRecursiveLibraryFetchStarted |= recursive; +				mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));  				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);  			}  		}  		else  		{  			// specific folder requests go to front of queue -			if (sFetchQueue.empty() || sFetchQueue.front() != cat_id) +			if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)  			{ -				sFetchQueue.push_front(cat_id); +				mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive));  				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);  			}  			if (cat_id == gInventory.getLibraryRootFolderID())  			{ -				mLibraryFetchStarted = TRUE; +				mRecursiveLibraryFetchStarted |= recursive;  			}  			if (cat_id == gInventory.getRootFolderID())  			{ -				mInventoryFetchStarted = TRUE; +				mRecursiveInventoryFetchStarted |= recursive;  			}  		}  	} @@ -166,7 +151,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id)  void LLInventoryModelBackgroundFetch::findLostItems()  {  	mBackgroundFetchActive = TRUE; -    sFetchQueue.push_back(LLUUID::null); +    mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE));      gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);  } @@ -183,8 +168,8 @@ void LLInventoryModelBackgroundFetch::stopBackgroundFetch()  void LLInventoryModelBackgroundFetch::setAllFoldersFetched()  { -	if (mInventoryFetchStarted && -		mLibraryFetchStarted) +	if (mRecursiveInventoryFetchStarted && +		mRecursiveLibraryFetchStarted)  	{  		mAllFoldersFetched = TRUE;  	} @@ -210,7 +195,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  		//DEPRECATED OLD CODE FOLLOWS.  		// no more categories to fetch, stop fetch process -		if (sFetchQueue.empty()) +		if (mFetchQueue.empty())  		{  			llinfos << "Inventory fetch completed" << llendl; @@ -232,7 +217,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  		while(1)  		{ -			if (sFetchQueue.empty()) +			if (mFetchQueue.empty())  			{  				break;  			} @@ -243,12 +228,13 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  				break;  			} -			LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front()); +			const FetchQueueInfo info = mFetchQueue.front(); +			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID);  			// category has been deleted, remove from queue.  			if (!cat)  			{ -				sFetchQueue.pop_front(); +				mFetchQueue.pop_front();  				continue;  			} @@ -271,10 +257,10 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  				}  			}  			// do I have all my children? -			else if (gInventory.isCategoryComplete(sFetchQueue.front())) +			else if (gInventory.isCategoryComplete(info.mCatUUID))  			{  				// finished with this category, remove from queue -				sFetchQueue.pop_front(); +				mFetchQueue.pop_front();  				// add all children to queue  				LLInventoryModel::cat_array_t* categories; @@ -284,7 +270,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  					 it != categories->end();  					 ++it)  				{ -					sFetchQueue.push_back((*it)->getUUID()); +					mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));  				}  				// we received a response in less than the fast time @@ -303,13 +289,12 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			{  				// received first packet, but our num descendants does not match db's num descendants  				// so try again later -				LLUUID fetch_id = sFetchQueue.front(); -				sFetchQueue.pop_front(); +				mFetchQueue.pop_front();  				if (mNumFetchRetries++ < MAX_FETCH_RETRIES)  				{  					// push on back of queue -					sFetchQueue.push_back(fetch_id); +					mFetchQueue.push_back(info);  				}  				mTimelyFetchPending = FALSE;  				mFetchTimer.reset(); @@ -334,20 +319,25 @@ void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching)  class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder  { -	public: -		LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; -		//LLInventoryModelFetchDescendentsResponder() {}; -		void result(const LLSD& content); -		void error(U32 status, const std::string& reason); -	public: -		typedef std::vector<LLViewerInventoryCategory*> folder_ref_t; -	protected: -		LLSD mRequestSD; +public: +	LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats) :  +		mRequestSD(request_sd), +		mRecursiveCatUUIDs(recursive_cats) +	{}; +	//LLInventoryModelFetchDescendentsResponder() {}; +	void result(const LLSD& content); +	void error(U32 status, const std::string& reason); +protected: +	BOOL getIsRecursive(const LLUUID& cat_id) const; +private: +	LLSD mRequestSD; +	uuid_vec_t mRecursiveCatUUIDs; // Hack for storing away which cat fetches are recursive.  };  //If we get back a normal response, handle it here -void  LLInventoryModelFetchDescendentsResponder::result(const LLSD& content) +void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  { +	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();  	if (content.has("folders"))	  	{ @@ -412,11 +402,12 @@ void  LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  			{	  				LLSD category = *category_it;  				tcategory->fromLLSD(category);  -							 -				if (LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted() || -					LLInventoryModelBackgroundFetch::instance().libraryFetchStarted()) +				 +				const BOOL recursive = getIsRecursive(tcategory->getUUID()); +				 +				if (recursive)  				{ -					sFetchQueue.push_back(tcategory->getUUID()); +					fetcher->mFetchQueue.push_back(LLInventoryModelBackgroundFetch::FetchQueueInfo(tcategory->getUUID(), recursive));  				}  				else if ( !gInventory.isCategoryComplete(tcategory->getUUID()) )  				{ @@ -461,12 +452,12 @@ void  LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  		}  	} -	LLInventoryModelBackgroundFetch::instance().incrBulkFetch(-1); +	fetcher->incrBulkFetch(-1); -	if (LLInventoryModelBackgroundFetch::instance().isBulkFetchProcessingComplete()) +	if (fetcher->isBulkFetchProcessingComplete())  	{  		llinfos << "Inventory fetch completed" << llendl; -		LLInventoryModelBackgroundFetch::instance().setAllFoldersFetched(); +		fetcher->setAllFoldersFetched();  	}  	gInventory.notifyObservers("fetchDescendents"); @@ -475,12 +466,14 @@ void  LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  //If we get back an error (not found, etc...), handle it here  void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason)  { +	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); +  	llinfos << "LLInventoryModelFetchDescendentsResponder::error "  		<< status << ": " << reason << llendl; -	LLInventoryModelBackgroundFetch::instance().incrBulkFetch(-1); +	fetcher->incrBulkFetch(-1); -	if (status==499)		//timed out.  Let's be awesome! +	if (status==499) // Timed out.  	{  		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();  			folder_it != mRequestSD["folders"].endArray(); @@ -488,24 +481,30 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str  		{	  			LLSD folder_sd = *folder_it;  			LLUUID folder_id = folder_sd["folder_id"]; -			sFetchQueue.push_front(folder_id); +			const BOOL recursive = getIsRecursive(folder_id); +			fetcher->mFetchQueue.push_front(LLInventoryModelBackgroundFetch::FetchQueueInfo(folder_id, recursive));  		}  	}  	else  	{ -		if (LLInventoryModelBackgroundFetch::instance().isBulkFetchProcessingComplete()) +		if (fetcher->isBulkFetchProcessingComplete())  		{ -			LLInventoryModelBackgroundFetch::instance().setAllFoldersFetched(); +			fetcher->setAllFoldersFetched();  		}  	}  	gInventory.notifyObservers("fetchDescendents");  } +BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat_id) const +{ +	return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end()); +} +  //static   Bundle up a bunch of requests to send all at once.  void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  {  	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. -	//If there are items in sFetchQueue, we want to check the time since the last bulkFetch was  +	//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was   	//sent.  If it exceeds our retry time, go ahead and fire off another batch.    	//Stopbackgroundfetch will be run from the Responder instead of here.   @@ -528,11 +527,16 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  	U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1; +	uuid_vec_t recursive_cats; +  	LLSD body;  	LLSD body_lib; -	while (!(sFetchQueue.empty()) && (folder_count < max_batch_size)) + +	while (!(mFetchQueue.empty()) && (folder_count < max_batch_size))  	{ -        if (sFetchQueue.front().isNull()) //DEV-17797 +		const FetchQueueInfo& fetch_info = mFetchQueue.front(); +		const LLUUID &cat_id = fetch_info.mCatUUID; +        if (cat_id.isNull()) //DEV-17797          {  			LLSD folder_sd;  			folder_sd["folder_id"]		= LLUUID::null.asString(); @@ -545,7 +549,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)          }          else          { -		    LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front()); +		    const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);  		    if (cat)  		    { @@ -564,9 +568,9 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  					    body["folders"].append(folder_sd);  				    folder_count++;  			    } -			    if (mInventoryFetchStarted || mLibraryFetchStarted) -			    {	//Already have this folder but append child folders to list. -				    // add all children to queue +				// May already have this folder, but append child folders to list. +			    if (fetch_info.mRecursive) +			    {	  					LLInventoryModel::cat_array_t* categories;  					LLInventoryModel::item_array_t* items;  					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); @@ -574,12 +578,15 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  						 it != categories->end();  						 ++it)  					{ -						sFetchQueue.push_back((*it)->getUUID()); +						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));  				    }  			    }  		    }          } -		sFetchQueue.pop_front(); +		if (fetch_info.mRecursive) +			recursive_cats.push_back(cat_id); + +		mFetchQueue.pop_front();  	}  	if (folder_count > 0) @@ -587,12 +594,15 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  		mBulkFetchCount++;  		if (body["folders"].size())  		{ -			LLHTTPClient::post(url, body, new LLInventoryModelFetchDescendentsResponder(body),300.0); +			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats); +			LLHTTPClient::post(url, body, fetcher, 300.0);  		}  		if (body_lib["folders"].size())  		{  			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); -			LLHTTPClient::post(url_lib, body_lib, new LLInventoryModelFetchDescendentsResponder(body_lib),300.0); +			 +			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats); +			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);  		}  		mFetchTimer.reset();  	} @@ -601,3 +611,17 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  		setAllFoldersFetched();  	}  } + +bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const +{ +	for (fetch_queue_t::const_iterator it = mFetchQueue.begin(); +		 it != mFetchQueue.end(); ++it) +	{ +		const LLUUID& fetch_id = (*it).mCatUUID; +		if (gInventory.isObjectDescendentOf(fetch_id, cat_id)) +			return false; +	} +	return true; +} + + diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 94606fae23..c1e37eda8f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -68,13 +68,15 @@ class LLInventoryCollectFunctor;  class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch>  { +	friend class LLInventoryModelFetchDescendentsResponder; +  public:  	LLInventoryModelBackgroundFetch();  	~LLInventoryModelBackgroundFetch();  	// Start and stop background breadth-first fetching of inventory contents.  	// This gets triggered when performing a filter-search -	void start(const LLUUID& cat_id = LLUUID::null); +	void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE);  	BOOL backgroundFetchActive();  	bool isEverythingFetched();  	void incrBulkFetch(S16 fetching); @@ -98,9 +100,20 @@ public:  	static void backgroundFetchCB(void*); // background fetch idle function  	void backgroundFetch(); +	struct FetchQueueInfo +	{ +		FetchQueueInfo(const LLUUID& id, BOOL recursive) : +			mCatUUID(id), mRecursive(recursive) +		{ +		} +		LLUUID mCatUUID; +		BOOL mRecursive; +	}; +protected: +	bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;  private: - 	BOOL mInventoryFetchStarted; -	BOOL mLibraryFetchStarted; + 	BOOL mRecursiveInventoryFetchStarted; +	BOOL mRecursiveLibraryFetchStarted;  	BOOL mAllFoldersFetched;  	// completing the fetch once per session should be sufficient @@ -113,6 +126,8 @@ private:  	F32 mMinTimeBetweenFetches;  	F32 mMaxTimeBetweenFetches; +	typedef std::deque<FetchQueueInfo> fetch_queue_t; +	fetch_queue_t mFetchQueue;  };  #endif // LL_LLINVENTORYMODELBACKGROUNDFETCH_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 15c872a7c4..dd1e039cb1 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1001,3 +1001,30 @@ BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) co  {  	return (std::find(mHiddenFolderTypes.begin(), mHiddenFolderTypes.end(), folder_type) != mHiddenFolderTypes.end());  } + + +/************************************************************************/ +/* Recent Inventory Panel related class                                 */ +/************************************************************************/ +class LLInventoryRecentItemsPanel; +static LLDefaultChildRegistry::Register<LLInventoryRecentItemsPanel> t_recent_inventory_panel("recent_inventory_panel"); + +static const LLRecentInventoryBridgeBuilder RECENT_ITEMS_BUILDER; +class LLInventoryRecentItemsPanel : public LLInventoryPanel +{ +public: +	struct Params :	public LLInitParam::Block<Params, LLInventoryPanel::Params> +	{}; + +protected: +	LLInventoryRecentItemsPanel (const Params&); +	friend class LLUICtrlFactory; +}; + +LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params) +: LLInventoryPanel(params) +{ +	// replace bridge builder to have necessary View bridges. +	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER; +} + diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 0ba373c51b..a84280c213 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -167,7 +167,7 @@ BOOL LLPanelMainInventory::postBuild()  	// Now load the stored settings from disk, if available.  	std::ostringstream filterSaveName;  	filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); -	llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl; +	llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName.str() << llendl;  	llifstream file(filterSaveName.str());  	LLSD savedFilterState;  	if (file.is_open()) @@ -492,6 +492,10 @@ void LLPanelMainInventory::onFilterSelected()  	{  		return;  	} + +	BOOL recent_active = ("Recent Items" == mActivePanel->getName()); +	childSetVisible("add_btn_panel", !recent_active); +  	setFilterSubString(mFilterSubString);  	LLInventoryFilter* filter = mActivePanel->getFilter();  	LLFloaterInventoryFinder *finder = getFinder(); diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 59c1fb4f3c..e36e63521e 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -77,6 +77,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :  {  	mSavedFolderState = new LLSaveFolderState();  	mSavedFolderState->setApply(FALSE); +	gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this));  }  LLPanelOutfitsInventory::~LLPanelOutfitsInventory() @@ -190,6 +191,7 @@ void LLPanelOutfitsInventory::onWearButtonClick()  	if (!isCOFPanelActive())  	{  		mMyOutfitsPanel->performAction("replaceoutfit"); +		setWearablesLoading(true);  	}  	else  	{ @@ -642,3 +644,19 @@ BOOL LLPanelOutfitsInventory::isCOFPanelActive() const  {  	return (childGetVisibleTab("appearance_tabs")->getName() == COF_TAB_NAME);  } + +void LLPanelOutfitsInventory::setWearablesLoading(bool val) +{ +	mListCommands->childSetEnabled("wear_btn", !val); + +	llassert(mParent); +	if (mParent) +	{ +		mParent->setWearablesLoading(val); +	} +} + +void LLPanelOutfitsInventory::onWearablesLoaded() +{ +	setWearablesLoading(false); +} diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index 975d99f834..6b4d1dbd84 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -123,6 +123,8 @@ protected:  	void onCustomAction(const LLSD& command_name);  	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);  	bool hasItemsSelected(); +	void setWearablesLoading(bool val); +	void onWearablesLoaded();  private:  	LLPanel*					mListCommands;  	LLMenuGL*					mMenuGearDefault; diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index a058548459..8c908449a0 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -719,8 +719,10 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata,  	{  		return;  	} +	LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)); +	if (NULL == item) return; -	name = speakerp->mDisplayName; +	name = item->getAvatarName();  	LLMute::EType mute_type;  	switch (speakerp->mType) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 08098e2adb..18f12955ce 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -439,3 +439,9 @@ void LLSidepanelAppearance::inventoryFetched()  {  	mNewOutfitBtn->setEnabled(true);  } + +void LLSidepanelAppearance::setWearablesLoading(bool val) +{ +	childSetVisible("wearables_loading_indicator", val); +	childSetVisible("edit_outfit_btn", !val); +} diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 0a2d882a0b..2900831099 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -65,6 +65,7 @@ public:  	void showOutfitsInventoryPanel();  	void showOutfitEditPanel(); +	void setWearablesLoading(bool val);  private:  	void onFilterEdit(const std::string& search_string); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 3d447dd411..7fa04ce574 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -166,6 +166,9 @@ public:  		mGetReason = reason;  	} +	void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} +	bool getCanUseHTTP()const {return mCanUseHTTP ;} +  protected:  	LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,  						 F32 priority, S32 discard, S32 size); @@ -247,15 +250,16 @@ private:  	S32 mRequestedSize;  	S32 mDesiredSize;  	S32 mFileSize; -	S32 mCachedSize; -	BOOL mLoaded; +	S32 mCachedSize;	  	e_request_state mSentRequest;  	handle_t mDecodeHandle; +	BOOL mLoaded;  	BOOL mDecoded;  	BOOL mWritten;  	BOOL mNeedsAux;  	BOOL mHaveAllData;  	BOOL mInLocalCache; +	bool mCanUseHTTP ;  	S32 mHTTPFailCount;  	S32 mRetryAttempt;  	S32 mActiveCount; @@ -411,6 +415,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,  	  mNeedsAux(FALSE),  	  mHaveAllData(FALSE),  	  mInLocalCache(FALSE), +	  mCanUseHTTP(true),  	  mHTTPFailCount(0),  	  mRetryAttempt(0),  	  mActiveCount(0), @@ -640,11 +645,12 @@ bool LLTextureFetchWorker::doWork(S32 param)  				return false;  			}  			mFileSize = 0; -			mLoaded = FALSE; -			setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it +			mLoaded = FALSE;			  			if (mUrl.compare(0, 7, "file://") == 0)  			{ +				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it +  				// read file from local disk  				std::string filename = mUrl.substr(7, std::string::npos);  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); @@ -653,11 +659,13 @@ bool LLTextureFetchWorker::doWork(S32 param)  			}  			else if (mUrl.empty())  			{ +				setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it +  				CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);  				mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,  																		  offset, size, responder);  			} -			else +			else if(mCanUseHTTP)  			{  				if (!(mUrl.compare(0, 7, "http://") == 0))  				{ @@ -667,6 +675,11 @@ bool LLTextureFetchWorker::doWork(S32 param)  				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);  				mState = SEND_HTTP_REQ;  			} +			else +			{ +				setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +				mState = LOAD_FROM_NETWORK; +			}  		}  		if (mLoaded) @@ -727,7 +740,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  		static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP");  // 		if (mHost != LLHost::invalid) get_url = false; -		if ( use_http && mUrl.empty())//get http url. +		if ( use_http && mCanUseHTTP && mUrl.empty())//get http url.  		{  			LLViewerRegion* region = NULL;  			if (mHost == LLHost::invalid) @@ -750,7 +763,7 @@ bool LLTextureFetchWorker::doWork(S32 param)  				//llwarns << "Region not found for host: " << mHost << llendl;  			}  		} -		if (!mUrl.empty()) +		if (mCanUseHTTP && !mUrl.empty())  		{  			mState = LLTextureFetchWorker::SEND_HTTP_REQ;  			setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); @@ -891,7 +904,13 @@ bool LLTextureFetchWorker::doWork(S32 param)  				if (mGetStatus == HTTP_NOT_FOUND)  				{  					mHTTPFailCount = max_attempts = 1; // Don't retry -					llinfos << "Texture missing from server (404): " << mUrl << llendl; +					//llinfos << "Texture missing from server (404): " << mUrl << llendl; + +					//roll back to try UDP +					mState = INIT ; +					mCanUseHTTP = false ; +					setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +					return false ;  				}  				else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE)  				{ @@ -1471,7 +1490,7 @@ LLTextureFetch::~LLTextureFetch()  }  bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, -								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux) +								   S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http)  {  	if (mDebugPause)  	{ @@ -1533,6 +1552,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con  		worker->mNeedsAux = needs_aux;  		worker->setImagePriority(priority);  		worker->setDesiredDiscard(desired_discard, desired_size); +		worker->setCanUseHTTP(can_use_http) ;  		if (!worker->haveWork())  		{  			worker->mState = LLTextureFetchWorker::INIT; @@ -1555,6 +1575,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con  		worker->lockWorkMutex();  		worker->mActiveCount++;  		worker->mNeedsAux = needs_aux; +		worker->setCanUseHTTP(can_use_http) ;  		worker->unlockWorkMutex();  	} @@ -2215,7 +2236,7 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id)  }  S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p, -								  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p) +								  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http)  {  	S32 state = LLTextureFetchWorker::INVALID;  	F32 data_progress = 0.0f; @@ -2253,6 +2274,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r  			requested_priority = worker->mImagePriority;  		}  		fetch_priority = worker->getPriority(); +		can_use_http = worker->getCanUseHTTP() ;  		worker->unlockWorkMutex();  	}  	data_progress_p = data_progress; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index ef2ec520bf..634e590fe0 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -62,7 +62,7 @@ public:  	void shutDownImageDecodeThread() ;  //called in the main thread after the ImageDecodeThread shuts down.  	bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, -					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux); +					   S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);  	void deleteRequest(const LLUUID& id, bool cancel);  	bool getRequestFinished(const LLUUID& id, S32& discard_level,  							LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux); @@ -77,7 +77,7 @@ public:  	// Debug  	BOOL isFromLocalCache(const LLUUID& id);  	S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, -					  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p); +					  U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http);  	void dump();  	S32 getNumRequests() ;  	S32 getNumHTTPRequests() ; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b39ee8b2e0..ed3d6a0464 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -587,7 +587,7 @@ bool LLViewerInventoryCategory::fetch()  		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");  		if (!url.empty()) //Capability found.  Build up LLSD and use it.  		{ -			LLInventoryModelBackgroundFetch::instance().start(mUUID);			 +			LLInventoryModelBackgroundFetch::instance().start(mUUID, false);			  		}  		else  		{	//Deprecated, but if we don't have a capability, use the old system. diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index c883087cf2..d925ab0d90 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -492,6 +492,7 @@ void LLViewerTexture::init(bool firstinit)  	mTextureState = NO_DELETE ;  	mDontDiscard = FALSE; +	mCanResetMaxVirtualSize = true ;  	mMaxVirtualSize = 0.f;  	mNeedsGLTexture = FALSE ;  	mNeedsResetMaxVirtualSize = FALSE ; @@ -540,6 +541,11 @@ void LLViewerTexture::setBoostLevel(S32 level)  		if(mBoostLevel != LLViewerTexture::BOOST_NONE)  		{  			setNoDelete() ;		 + +			if(LLViewerTexture::BOOST_AVATAR_BAKED_SELF == mBoostLevel || LLViewerTexture::BOOST_AVATAR_BAKED == mBoostLevel) +			{ +				mCanResetMaxVirtualSize = false ; +			}  		}  		if(gAuditTexture)  		{ @@ -613,7 +619,7 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co  void LLViewerTexture::resetTextureStats()  { -	mMaxVirtualSize = 0.0f; +	mMaxVirtualSize = 0.0f ;  	mAdditionalDecodePriority = 0.f ;	  	mNeedsResetMaxVirtualSize = FALSE ;  } @@ -1071,6 +1077,7 @@ void LLViewerFetchedTexture::init(bool firstinit)  	mRequestedDiscardLevel = -1;  	mRequestedDownloadPriority = 0.f;  	mFullyLoaded = FALSE; +	mCanUseHTTP = true ;  	mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;  	mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; @@ -1665,7 +1672,11 @@ void LLViewerFetchedTexture::updateVirtualSize()  			setAdditionalDecodePriority(facep->getImportanceToCamera()) ;  		}  	} -	mNeedsResetMaxVirtualSize = TRUE ; + +	if(mCanResetMaxVirtualSize) +	{ +		mNeedsResetMaxVirtualSize = TRUE ; +	}  	reorganizeFaceList() ;  	reorganizeVolumeList();  } @@ -1746,7 +1757,7 @@ bool LLViewerFetchedTexture::updateFetch()  		else  		{  			mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, -																		mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); +																		mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);  		}  		// We may have data ready regardless of whether or not we are finished (e.g. waiting on write) @@ -1886,7 +1897,7 @@ bool LLViewerFetchedTexture::updateFetch()  		// bypass texturefetch directly by pulling from LLTextureCache  		bool fetch_request_created = false;  		fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, -																			  w, h, c, desired_discard, needsAux()); +																			  w, h, c, desired_discard, needsAux(), mCanUseHTTP);  		if (fetch_request_created)  		{ @@ -1894,7 +1905,7 @@ bool LLViewerFetchedTexture::updateFetch()  			mIsFetching = TRUE;  			mRequestedDiscardLevel = desired_discard;  			mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, -													   mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); +													   mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);  		}  		// if createRequest() failed, we're finishing up a request for this UUID, @@ -3291,7 +3302,10 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()  		}  	} -	mNeedsResetMaxVirtualSize = TRUE ; +	if(mCanResetMaxVirtualSize) +	{ +		mNeedsResetMaxVirtualSize = TRUE ; +	}  	reorganizeFaceList() ;  	reorganizeVolumeList(); diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index a09a711cc7..74c46f3070 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -263,6 +263,7 @@ protected:  	S32 mFullHeight;  	BOOL  mUseMipMaps ;  	S8  mComponents; +	bool mCanResetMaxVirtualSize;  	mutable F32 mMaxVirtualSize;	// The largest virtual size of the image, in pixels - how much data to we need?  	mutable S8  mNeedsGLTexture;  	mutable BOOL mNeedsResetMaxVirtualSize ; @@ -456,6 +457,8 @@ public:  	BOOL		isFullyLoaded() const;  	BOOL        hasFetcher() const { return mHasFetcher;} +	void        setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} +  protected:  	/*virtual*/ void switchToCachedImage();  	S32 getCurrentDiscardLevelForFetching() ; @@ -505,6 +508,7 @@ protected:  	S8  mIsRawImageValid;  	S8  mHasFetcher;				// We've made a fecth request  	S8  mIsFetching;				// Fetch request is active +	bool mCanUseHTTP ;              //This texture can be fetched through http if true.  	mutable S8 mIsMissingAsset;		// True if we know that there is no image asset with this image id in the database.		 diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bef1d63fcf..9ff871370d 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -102,8 +102,6 @@  #include <boost/lexical_cast.hpp> -#define DISPLAY_AVATAR_LOAD_TIMES -  using namespace LLVOAvatarDefines;  //----------------------------------------------------------------------------- @@ -4045,6 +4043,7 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel  {  	mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);  	mMinPixelArea = llmin(pixel_area, mMinPixelArea); +	imagep->resetTextureStats();  	imagep->addTextureStats(pixel_area / texel_area_ratio);  	imagep->setBoostLevel(boost_level);  } @@ -5316,6 +5315,14 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi  {  	S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState()); +	// This should never happen unless the server didn't process the attachment point +	// correctly, but putting this check in here to be safe. +	if (attachmentID & ATTACHMENT_ADD) +	{ +		llwarns << "Got an attachment with ATTACHMENT_ADD mask, removing ( attach pt:" << attachmentID << " )" << llendl; +		attachmentID &= ~ATTACHMENT_ADD; +	} +	  	LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);  	if (!attachment) @@ -5727,16 +5734,17 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading)  	mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); -#ifdef DISPLAY_AVATAR_LOAD_TIMES -	if (!mPreviousFullyLoaded && !loading && mFullyLoaded) +	if (gSavedSettings.getBOOL("DebugAvatarRezTime"))  	{ -		llinfos << "Avatar '" << getFullname() << "' resolved in " << mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; -		LLSD args; -		args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); -		args["NAME"] = getFullname(); -		LLNotificationsUtil::add("AvatarRezNotification",args); +		if (!mPreviousFullyLoaded && !loading && mFullyLoaded) +		{ +			llinfos << "Avatar '" << getFullname() << "' resolved in " << mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; +			LLSD args; +			args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); +			args["NAME"] = getFullname(); +			LLNotificationsUtil::add("AvatarRezNotification",args); +		}  	} -#endif  	// did our loading state "change" from last call?  	const S32 UPDATE_RATE = 30; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4fbc6bb5da..086c2f702c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -266,7 +266,7 @@ BOOL	LLPipeline::sRenderParticleBeacons = FALSE;  BOOL	LLPipeline::sRenderSoundBeacons = FALSE;  BOOL	LLPipeline::sRenderBeacons = FALSE;  BOOL	LLPipeline::sRenderHighlight = TRUE; -BOOL	LLPipeline::sForceOldBakedUpload = FALSE; +BOOL	LLPipeline::sForceOldBakedUpload = TRUE;  S32		LLPipeline::sUseOcclusion = 0;  BOOL	LLPipeline::sDelayVBUpdate = TRUE;  BOOL	LLPipeline::sAutoMaskAlphaDeferred = TRUE; diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml index 2515b60868..6a90e92eca 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -6,31 +6,31 @@       label="Sort by Name"       layout="topleft"       name="SortByName"> -        <menu_item_check.on_click -         function="ParticipantList.Sort" -         parameter="sort_by_name" /> -        <menu_item_check.on_check +        <on_check           function="ParticipantList.CheckItem"           parameter="is_sorted_by_name" /> +        <on_click +         function="ParticipantList.Sort" +         parameter="sort_by_name" />      </menu_item_check>      <menu_item_check       label="Sort by Recent Speakers"       layout="topleft"       name="SortByRecentSpeakers"> -        <menu_item_check.on_click -         function="ParticipantList.Sort" -         parameter="sort_by_recent_speakers" /> -        <menu_item_check.on_check +        <on_check           function="ParticipantList.CheckItem"           parameter="is_sorted_by_recent_speakers" /> +        <on_click +         function="ParticipantList.Sort" +         parameter="sort_by_recent_speakers" />      </menu_item_check>      <menu_item_call       label="View Profile"       layout="topleft"       name="View Profile"> -        <menu_item_call.on_click +        <on_click           function="Avatar.Profile" /> -        <menu_item_call.on_enable +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_view_profile" />      </menu_item_call> @@ -38,9 +38,9 @@       label="Add Friend"       layout="topleft"       name="Add Friend"> -        <menu_item_call.on_click +        <on_click           function="Avatar.AddFriend" /> -        <menu_item_call.on_enable +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_add" />      </menu_item_call> @@ -48,9 +48,9 @@       label="IM"       layout="topleft"       name="IM"> -        <menu_item_call.on_click +        <on_click           function="Avatar.IM" /> -        <menu_item_call.on_enable +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_im" />      </menu_item_call> @@ -58,20 +58,19 @@       label="Call"       layout="topleft"       name="Call"> -         <menu_item_call.on_click +        <on_click           function="Avatar.Call" /> -        <menu_item_call.on_enable +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_call" />      </menu_item_call>      <menu_item_call -     enabled="true"       label="Share"       layout="topleft"       name="Share"> -        <menu_item_call.on_click +        <on_click           function="Avatar.Share" /> -        <menu_item_call.on_enable +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_share" />      </menu_item_call> @@ -79,37 +78,38 @@       label="Pay"       layout="topleft"       name="Pay"> -        <menu_item_call.on_click +        <on_click           function="Avatar.Pay" /> -        <menu_item_call.on_enable +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_pay" />      </menu_item_call>      <menu_item_separator -        layout="topleft" -        name="View Icons Separator" /> +     layout="topleft" +     name="View Icons Separator" />      <menu_item_check -        label="View People Icons" -        name="View Icons"> -      <on_click -          function="ToggleControl" -          parameter="ParticipantListShowIcons"/> -      <on_check -          function="CheckControl" -          parameter="ParticipantListShowIcons" /> +     label="View People Icons" +     layout="topleft" +     name="View Icons"> +        <on_check +         function="CheckControl" +         parameter="ParticipantListShowIcons" /> +        <on_click +         function="ToggleControl" +         parameter="ParticipantListShowIcons" />      </menu_item_check>      <menu_item_separator -        layout="topleft" /> +     layout="topleft" />      <menu_item_check       label="Block Voice"       layout="topleft"       name="Block/Unblock"> -        <menu_item_check.on_click -         function="Avatar.BlockUnblock" /> -        <menu_item_check.on_check +        <on_check           function="ParticipantList.CheckItem"           parameter="is_blocked" /> -        <menu_item_check.on_enable +        <on_click +         function="Avatar.BlockUnblock" /> +        <on_enable           function="ParticipantList.EnableItem"           parameter="can_block" />      </menu_item_check> @@ -126,71 +126,71 @@           function="ParticipantList.EnableItem"           parameter="can_mute_text" />      </menu_item_check> -        <menu_item_separator -         layout="topleft" /> +    <menu_item_separator +     layout="topleft" />      <context_menu       label="Moderator Options >"       layout="topleft" -     name="Moderator Options" > -    <menu_item_check -     label="Allow text chat" -     layout="topleft" -     name="AllowTextChat"> -        <on_check -         function="ParticipantList.CheckItem" -         parameter="is_allowed_text_chat" /> -        <on_click -         function="ParticipantList.ToggleAllowTextChat" /> -        <on_enable -         function="ParticipantList.EnableItem" -         parameter="can_allow_text_chat" /> -    </menu_item_check> -    <menu_item_separator -     layout="topleft" -     name="moderate_voice_separator" /> -    <menu_item_call -     label="Mute this participant" -     layout="topleft" -     name="ModerateVoiceMuteSelected"> -        <on_click -         function="ParticipantList.ModerateVoice" -         parameter="selected" /> -        <on_enable -         function="ParticipantList.EnableItem.Moderate" -         parameter="can_moderate_voice" /> -    </menu_item_call> -    <menu_item_call -     label="Mute everyone else" -     layout="topleft" -     name="ModerateVoiceMuteOthers"> -        <on_click -         function="ParticipantList.ModerateVoice" -         parameter="others" /> -        <on_enable -         function="ParticipantList.EnableItem.Moderate" -         parameter="can_moderate_voice" /> -    </menu_item_call> -    <menu_item_call -     label="Unmute this participant" -     layout="topleft" -     name="ModerateVoiceUnMuteSelected"> -        <on_click -         function="ParticipantList.ModerateVoice" -         parameter="selected" /> -        <on_enable -         function="ParticipantList.EnableItem.Moderate" -         parameter="can_moderate_voice" /> -    </menu_item_call> -    <menu_item_call -     label="Unmute everyone else" -     layout="topleft" -     name="ModerateVoiceUnMuteOthers"> -        <on_click -         function="ParticipantList.ModerateVoice" -         parameter="others" /> -        <on_enable -         function="ParticipantList.EnableItem.Moderate" -         parameter="can_moderate_voice" /> -    </menu_item_call> +     name="Moderator Options"> +        <menu_item_check +         label="Allow text chat" +         layout="topleft" +         name="AllowTextChat"> +            <on_check +             function="ParticipantList.CheckItem" +             parameter="is_allowed_text_chat" /> +            <on_click +             function="ParticipantList.ToggleAllowTextChat" /> +            <on_enable +             function="ParticipantList.EnableItem" +             parameter="can_allow_text_chat" /> +        </menu_item_check> +        <menu_item_separator +         layout="topleft" +         name="moderate_voice_separator" /> +        <menu_item_call +         label="Mute this participant" +         layout="topleft" +         name="ModerateVoiceMuteSelected"> +            <on_click +             function="ParticipantList.ModerateVoice" +             parameter="selected" /> +            <on_enable +             function="ParticipantList.EnableItem.Moderate" +             parameter="can_moderate_voice" /> +        </menu_item_call> +        <menu_item_call +         label="Mute everyone else" +         layout="topleft" +         name="ModerateVoiceMuteOthers"> +            <on_click +             function="ParticipantList.ModerateVoice" +             parameter="others" /> +            <on_enable +             function="ParticipantList.EnableItem.Moderate" +             parameter="can_moderate_voice" /> +        </menu_item_call> +        <menu_item_call +         label="Unmute this participant" +         layout="topleft" +         name="ModerateVoiceUnMuteSelected"> +            <on_click +             function="ParticipantList.ModerateVoice" +             parameter="selected" /> +            <on_enable +             function="ParticipantList.EnableItem.Moderate" +             parameter="can_moderate_voice" /> +        </menu_item_call> +        <menu_item_call +         label="Unmute everyone else" +         layout="topleft" +         name="ModerateVoiceUnMuteOthers"> +            <on_click +             function="ParticipantList.ModerateVoice" +             parameter="others" /> +            <on_enable +             function="ParticipantList.EnableItem.Moderate" +             parameter="can_moderate_voice" /> +        </menu_item_call>      </context_menu>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 479629f6ea..19fe2ea874 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -210,9 +210,23 @@ Maximum 200 per group daily          <button           follows="left|top"           layout="topleft" +         left="20" +         top_delta="50" +         height="23" +         width="100" +         name="open_inventory" +         label="Inventory" +         tool_tip="Open Inventory"> +			<button.init_callback +				 function="Button.SetFloaterToggle" +				 parameter="inventory"/> +		</button> +        <button +         follows="left|top" +         layout="topleft"           left="140"           name="remove_attachment" -         top_delta="50" +         top_delta="0"                   height="18"                   image_selected="TrashItem_Press"                   image_unselected="TrashItem_Off" @@ -230,7 +244,7 @@ Maximum 200 per group daily           name="send_notice"           width="100" />        <group_drop_target -         height="95" +         height="75"           top="160"           left="10"           layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 46625144e1..d65b86f007 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -84,7 +84,7 @@       sort_order_setting="InventorySortOrder"       top="16"       width="288" /> -    <inventory_panel +    <recent_inventory_panel          bg_opaque_color="DkGray2"     bg_alpha_color="DkGray2"     background_visible="true" @@ -100,62 +100,94 @@       name="Recent Items"       width="290" />    </tab_container> - -  <panel -     background_visible="true" +  <layout_stack +   animate="false" +   background_visible="true"     bevel_style="none" +   border_size="0"     follows="left|right|bottom" -   height="27" +   height="25"     layout="topleft" -   top_pad="-1" +   orientation="horizontal" +   top_pad="0"     left="10"     name="bottom_panel" -   width="310"> -    <button -     follows="bottom|left" -     tool_tip="Show additional options" -     height="25" -     image_hover_unselected="Toolbar_Left_Over" -     image_overlay="OptionsMenu_Off" -     image_selected="Toolbar_Left_Selected" -     image_unselected="Toolbar_Left_Off" -     layout="topleft" -     left="0" -     name="options_gear_btn" -     top="1" -     width="31" /> -    <button -     follows="bottom|left" -     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="1" -     name="add_btn" -     tool_tip="Add new item" -     width="31" /> -    <icon -     follows="bottom|left" -     height="25" -     image_name="Toolbar_Middle_Off" -     layout="topleft" -     left_pad="1" -     name="dummy_icon" -     width="209" -       /> -    <dnd_button -     follows="bottom|left" -     height="25" -     image_hover_unselected="Toolbar_Right_Over" -     image_overlay="TrashItem_Off" -     image_selected="Toolbar_Right_Selected" -     image_unselected="Toolbar_Right_Off" -     left_pad="1" -     layout="topleft" -     name="trash_btn" -     tool_tip="Remove selected item" -     width="31"/> -  </panel> +   width="307"> +      <layout_panel +       auto_resize="false" +       height="25" +       layout="topleft" +       name="options_gear_btn_panel" +       width="32"> +          <button +           follows="bottom|left" +           tool_tip="Show additional options" +           height="25" +           image_hover_unselected="Toolbar_Left_Over" +           image_overlay="OptionsMenu_Off" +           image_selected="Toolbar_Left_Selected" +           image_unselected="Toolbar_Left_Off" +           layout="topleft" +           left="0" +           name="options_gear_btn" +           top="0" +           width="31" /> +      </layout_panel> +      <layout_panel +       auto_resize="false" +       height="25" +       layout="topleft" +       name="add_btn_panel" +       width="32"> +          <button +           follows="bottom|left" +           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="0" +           name="add_btn" +           tool_tip="Add new item" +           top="0" +           width="31" /> +      </layout_panel> +      <layout_panel +       auto_resize="true" +       height="25" +       layout="topleft" +       name="dummy_panel" +       width="212"> +          <icon +           follows="bottom|left|right" +           height="25" +           image_name="Toolbar_Middle_Off" +           layout="topleft" +           left="0" +           top="0" +           name="dummy_icon" +           width="211" /> +      </layout_panel> +      <layout_panel +       auto_resize="false" +       height="25" +       layout="topleft" +       name="trash_btn_panel" +       width="31"> +          <dnd_button +           follows="bottom|left" +           height="25" +           image_hover_unselected="Toolbar_Right_Over" +           image_overlay="TrashItem_Off" +           image_selected="Toolbar_Right_Selected" +           image_unselected="Toolbar_Right_Off" +           left="0" +           layout="topleft" +           name="trash_btn" +           tool_tip="Remove selected item" +           top="0" +           width="31"/> +      </layout_panel> +  </layout_stack>  </panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index e74c70789f..6a3c148456 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -94,6 +94,14 @@ width="333">        name="edit_outfit_btn"        top="7"        width="30" /> +      <loading_indicator +      follows="left|top" +      height="24" +      layout="topleft" +      left="268" +      name="wearables_loading_indicator" +      top="6" +      width="24" />     </panel>     <filter_editor     height="23" | 
