diff options
28 files changed, 635 insertions, 123 deletions
| diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index a40db0f8cc..2255e638c2 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -336,6 +336,7 @@ public:  	static void	addCRLF(string_type& string);  	static void	removeCRLF(string_type& string); +	static void removeWindowsCR(string_type& string);  	static void	replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab );  	static void	replaceNonstandardASCII( string_type& string, T replacement ); @@ -1322,6 +1323,28 @@ void LLStringUtilBase<T>::removeCRLF(string_type& string)  //static  template<class T>  +void LLStringUtilBase<T>::removeWindowsCR(string_type& string) +{ +    const T LF = 10; +    const T CR = 13; + +    size_type cr_count = 0; +    size_type len = string.size(); +    size_type i; +    for( i = 0; i < len - cr_count - 1; i++ ) +    { +        if( string[i+cr_count] == CR && string[i+cr_count+1] == LF) +        { +            cr_count++; +        } + +        string[i] = string[i+cr_count]; +    } +    string.erase(i, cr_count); +} + +//static +template<class T>  void LLStringUtilBase<T>::replaceChar( string_type& string, T target, T replacement )  {  	size_type found_pos = 0; diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 9f12d49244..758b98e143 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -40,7 +40,8 @@  #include <boost/algorithm/string/find_iterator.hpp>  #include <boost/algorithm/string/finder.hpp> -void encode_character(std::ostream& ostr, std::string::value_type val) +// static +void LLURI::encodeCharacter(std::ostream& ostr, std::string::value_type val)  {  	ostr << "%" @@ -95,7 +96,7 @@ std::string LLURI::escape(  			}  			else  			{ -				encode_character(ostr, c); +				encodeCharacter(ostr, c);  			}  		}  	} @@ -106,7 +107,7 @@ std::string LLURI::escape(  			c = *it;  			if(allowed.find(c) == std::string::npos)  			{ -				encode_character(ostr, c); +				encodeCharacter(ostr, c);  			}  			else  			{ diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index c82a666e48..9e44cc7da2 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -121,6 +121,14 @@ public:  	/** @name Escaping Utilities */  	//@{  	/** +	 * @brief 'Escape' symbol into stream +	 * +	 * @param ostr Output stream. +	 * @param val Symbol to encode. +	 */ +	static void encodeCharacter(std::ostream& ostr, std::string::value_type val); + +	/**  	 * @brief Escape the string passed except for unreserved  	 *  	 *  ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 76d3a405d8..768dc8284b 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -305,6 +305,8 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  			}  			face = LLVolumeFace(); +			face.mExtents[0].set(v[0], v[1], v[2]); +			face.mExtents[1].set(v[0], v[1], v[2]);  			point_map.clear();  		}  	} @@ -549,6 +551,8 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  				}  				face = LLVolumeFace(); +				face.mExtents[0].set(v[0], v[1], v[2]); +				face.mExtents[1].set(v[0], v[1], v[2]);  				verts.clear();  				indices.clear();  				point_map.clear(); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index f3a99dcef2..c570285856 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1505,8 +1505,8 @@ void LLTextBase::reflow()  		segment_set_t::iterator seg_iter = mSegments.begin();  		S32 seg_offset = 0;  		S32 line_start_index = 0; -		const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad;  // reserve room for margin -		S32 remaining_pixels = text_available_width; +		const F32 text_available_width = mVisibleTextRect.getWidth() - mHPad;  // reserve room for margin +		F32 remaining_pixels = text_available_width;  		S32 line_count = 0;  		// find and erase line info structs starting at start_index and going to end of document @@ -1532,14 +1532,15 @@ void LLTextBase::reflow()  			S32 cur_index = segment->getStart() + seg_offset;  			// ask segment how many character fit in remaining space -			S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX, +			S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, ll_round(remaining_pixels)) : S32_MAX,  														seg_offset,   														cur_index - line_start_index,   														S32_MAX,  														line_count - seg_line_offset); -			S32 segment_width, segment_height; -			bool force_newline = segment->getDimensions(seg_offset, character_count, segment_width, segment_height); +			F32 segment_width; +			S32 segment_height; +			bool force_newline = segment->getDimensionsF32(seg_offset, character_count, segment_width, segment_height);  			// grow line height as necessary based on reported height of this segment  			line_height = llmax(line_height, segment_height);  			remaining_pixels -= segment_width; @@ -1548,11 +1549,13 @@ void LLTextBase::reflow()  			S32 last_segment_char_on_line = segment->getStart() + seg_offset; -			S32 text_actual_width = text_available_width - remaining_pixels; +			// Note: make sure text will fit in width - use ceil, but also make sure +			// ceil is used only once per line +			S32 text_actual_width = llceil(text_available_width - remaining_pixels);  			S32 text_left = getLeftOffset(text_actual_width);  			LLRect line_rect(text_left,   							cur_top,  -							text_left + text_actual_width,  +							text_left + text_actual_width,  							cur_top - line_height);  			// if we didn't finish the current segment... @@ -3066,7 +3069,15 @@ boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_bloc  LLTextSegment::~LLTextSegment()  {} -bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; return false;} +bool LLTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { width = 0; height = 0; return false; } +bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +{ +	F32 fwidth = 0; +	bool result = getDimensionsF32(first_char, num_chars, fwidth, height); +	width = ll_round(fwidth); +	return result; +} +  S32	LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; }  S32	LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { return 0; }  void LLTextSegment::updateLayout(const LLTextBase& editor) {} @@ -3314,7 +3325,7 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip)  	mTooltip = tooltip;  } -bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const  {  	height = 0;  	width = 0; @@ -3323,7 +3334,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt  		height = mFontHeight;  		const LLWString &text = getWText();  		// if last character is a newline, then return true, forcing line break -		width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); +		width = mStyle->getFont()->getWidthF32(text.c_str(), mStart + first_char, num_chars);  	}  	return false;  } @@ -3491,7 +3502,7 @@ LLInlineViewSegment::~LLInlineViewSegment()  	mView->die();  } -bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const  {  	if (first_char == 0 && num_chars == 0)  	{ @@ -3578,7 +3589,7 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLT  LLLineBreakTextSegment::~LLLineBreakTextSegment()  {  } -bool LLLineBreakTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLLineBreakTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const  {  	width = 0;  	height = mFontHeight; @@ -3607,7 +3618,7 @@ LLImageTextSegment::~LLImageTextSegment()  static const S32 IMAGE_HPAD = 3; -bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLImageTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const  {  	width = 0;  	height = mStyle->getFont()->getLineHeight(); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index c7b6203445..5fdde445ef 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -61,8 +61,9 @@ public:  		mEnd(end)  	{}  	virtual ~LLTextSegment(); +	bool						getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; -	virtual bool				getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; +	virtual bool				getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;  	virtual S32					getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;  	/** @@ -126,7 +127,7 @@ public:  	LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);  	virtual ~LLNormalTextSegment(); -	/*virtual*/ bool				getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; +	/*virtual*/ bool				getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;  	/*virtual*/ S32					getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;  	/*virtual*/ S32					getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;  	/*virtual*/ F32					draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); @@ -212,7 +213,7 @@ public:  	LLInlineViewSegment(const Params& p, S32 start, S32 end);  	~LLInlineViewSegment(); -	/*virtual*/ bool		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; +	/*virtual*/ bool		getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;  	/*virtual*/ S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;  	/*virtual*/ void		updateLayout(const class LLTextBase& editor);  	/*virtual*/ F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); @@ -236,7 +237,7 @@ public:  	LLLineBreakTextSegment(LLStyleConstSP style,S32 pos);  	LLLineBreakTextSegment(S32 pos);  	~LLLineBreakTextSegment(); -	bool		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; +	/*virtual*/ bool		getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;  	S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const;  	F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); @@ -249,7 +250,7 @@ class LLImageTextSegment : public LLTextSegment  public:  	LLImageTextSegment(LLStyleConstSP style,S32 pos,class LLTextBase& editor);  	~LLImageTextSegment(); -	bool		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const; +	/*virtual*/ bool		getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const;  	S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 char_offset, S32 max_chars, S32 line_ind) const;  	F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 321792eb14..b5ed53fd4f 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2801,7 +2801,7 @@ BOOL LLWindowWin32::pasteTextFromClipboard(LLWString &dst)  				if (utf16str)  				{  					dst = utf16str_to_wstring(utf16str); -					LLWStringUtil::removeCRLF(dst); +					LLWStringUtil::removeWindowsCR(dst);  					GlobalUnlock(h_data);  					success = TRUE;  				} diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 097a9ac7b9..f0a91fd407 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1619,6 +1619,17 @@        <key>Value</key>        <string>default</string>      </map> +    <key>ChatAutocompleteGestures</key> +    <map> +      <key>Comment</key> +      <string>Auto-complete gestures in nearby chat</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>ChatBarStealsFocus</key>      <map>        <key>Comment</key> @@ -10168,6 +10179,17 @@      <key>Value</key>      <integer>10</integer>    </map> +  <key>MaxAttachmentComplexity</key> +  <map> +    <key>Comment</key> +    <string>Attachment's render weight limit</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>F32</string> +    <key>Value</key> +    <real>1.0E6</real> +  </map>    <key>ComplexityChangesPopUpDelay</key>    <map>      <key>Comment</key> @@ -10734,6 +10756,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>ScriptDialogLimitations</key> +    <map> +      <key>Comment</key> +      <string>Limits amount of dialogs per script (0 - per object, 1 - per channel, 2 - per channel for attachments, 3 - per channel for HUDs, 4 -unconstrained for HUDs)</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>SecondLifeEnterprise</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index feb981217d..c928cf0601 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2917,11 +2917,32 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar()  	removeItemsFromAvatar(ids_to_remove);  } -void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb) +class LLUpdateOnCOFLinkRemove : public LLInventoryCallback  { -	gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); +public: +	LLUpdateOnCOFLinkRemove(const LLUUID& remove_item_id, LLPointer<LLInventoryCallback> cb = NULL): +		mItemID(remove_item_id), +		mCB(cb) +	{ +	} -	LLInventoryModel::cat_array_t cat_array; +	/* virtual */ void fire(const LLUUID& item_id) +	{ +		// just removed cof link, "(wear)" suffix depends on presence of link, so update label +		gInventory.addChangedMask(LLInventoryObserver::LABEL, mItemID); +		if (mCB.notNull()) +		{ +			mCB->fire(item_id); +		} +	} + +private: +	LLUUID mItemID; +	LLPointer<LLInventoryCallback> mCB; +}; + +void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb) +{	LLInventoryModel::cat_array_t cat_array;  	LLInventoryModel::item_array_t item_array;  	gInventory.collectDescendents(LLAppearanceMgr::getCOF(),  								  cat_array, @@ -2932,12 +2953,20 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInve  		const LLInventoryItem* item = item_array.at(i).get();  		if (item->getIsLinkType() && item->getLinkedUUID() == item_id)  		{ -			bool immediate_delete = false;  			if (item->getType() == LLAssetType::AT_OBJECT)  			{ -				immediate_delete = true; +				// Immediate delete +				remove_inventory_item(item->getUUID(), cb, true); +				gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); +			} +			else +			{ +				// Delayed delete +				// Pointless to update item_id label here since link still exists and first notifyObservers +				// call will restore (wear) suffix, mark for update after deletion +				LLPointer<LLUpdateOnCOFLinkRemove> cb_label = new LLUpdateOnCOFLinkRemove(item_id, cb); +				remove_inventory_item(item->getUUID(), cb_label, false);  			} -			remove_inventory_item(item->getUUID(), cb, immediate_delete);  		}  	}  } diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 314b859cea..711a87dc99 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -44,7 +44,7 @@ public:  		mExpanderLabel(more_text)  	{} -	/*virtual*/ bool	getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const  +	/*virtual*/ bool	getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const   	{  		// more label always spans width of text box  		if (num_chars == 0) diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 40ae22bb4e..7895a5ff48 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -485,7 +485,8 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()  	KEY key = gKeyboard->currentKey();  	// Ignore "special" keys, like backspace, arrows, etc. -	if (length > 1  +	if (gSavedSettings.getBOOL("ChatAutocompleteGestures") +		&& length > 1  		&& raw_text[0] == '/'  		&& key < KEY_SPECIAL)  	{ diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index c654817849..b3885bf36c 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1262,6 +1262,10 @@ LLModelPreview::~LLModelPreview()  	// glod.dll!glodShutdown()  + 0x77 bytes	  	//  	//glodShutdown(); +	if(mModelLoader) +	{ +		mModelLoader->shutdown(); +	}  }  U32 LLModelPreview::calcResourceCost() diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ff8b8b0403..bcda9baa9a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2677,49 +2677,57 @@ void LLIMMgr::addMessage(  		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg);  		LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id); -		skip_message &= !session->isGroupSessionType();			// Do not skip group chats... -		if(skip_message) +		if (session)  		{ -			gIMMgr->leaveSession(new_session_id); -		} -		// When we get a new IM, and if you are a god, display a bit -		// of information about the source. This is to help liaisons -		// when answering questions. -		if(gAgent.isGodlike()) -		{ -			// *TODO:translate (low priority, god ability) -			std::ostringstream bonus_info; -			bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " " -				<< parent_estate_id -				<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "") -				<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : ""); - -			// once we have web-services (or something) which returns -			// information about a region id, we can print this out -			// and even have it link to map-teleport or something. -			//<< "*** region_id: " << region_id << std::endl -			//<< "*** position: " << position << std::endl; +			skip_message &= !session->isGroupSessionType();			// Do not skip group chats... +			if (skip_message) +			{ +				gIMMgr->leaveSession(new_session_id); +			} +			// When we get a new IM, and if you are a god, display a bit +			// of information about the source. This is to help liaisons +			// when answering questions. +			if (gAgent.isGodlike()) +			{ +				// *TODO:translate (low priority, god ability) +				std::ostringstream bonus_info; +				bonus_info << LLTrans::getString("***") + " " + LLTrans::getString("IMParentEstate") + ":" + " " +					<< parent_estate_id +					<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "") +					<< ((parent_estate_id == 5) ? "," + LLTrans::getString("IMTeen") : ""); + +				// once we have web-services (or something) which returns +				// information about a region id, we can print this out +				// and even have it link to map-teleport or something. +				//<< "*** region_id: " << region_id << std::endl +				//<< "*** position: " << position << std::endl; + +				LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str()); +			} -			LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str()); -		} +			// Logically it would make more sense to reject the session sooner, in another area of the +			// code, but the session has to be established inside the server before it can be left. +			if (LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !from_linden) +			{ +				LL_WARNS() << "Leaving IM session from initiating muted resident " << from << LL_ENDL; +				if (!gIMMgr->leaveSession(new_session_id)) +				{ +					LL_INFOS() << "Session " << new_session_id << " does not exist." << LL_ENDL; +				} +				return; +			} -		// Logically it would make more sense to reject the session sooner, in another area of the -		// code, but the session has to be established inside the server before it can be left. -		if (LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !from_linden) -		{ -			LL_WARNS() << "Leaving IM session from initiating muted resident " << from << LL_ENDL; -			if(!gIMMgr->leaveSession(new_session_id)) +			//Play sound for new conversations +			if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE))  			{ -				LL_INFOS() << "Session " << new_session_id << " does not exist." << LL_ENDL; +				make_ui_sound("UISndNewIncomingIMSession");  			} -			return;  		} - -        //Play sound for new conversations -		if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE)) -        { -            make_ui_sound("UISndNewIncomingIMSession"); -        } +		else +		{ +			// Failed to create a session, most likely due to empty name (name cache failed?) +			LL_WARNS() << "Failed to create IM session " << fixed_session_name << LL_ENDL; +		}  	}  	if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message) @@ -3022,7 +3030,7 @@ void LLIMMgr::inviteToSession(  			LLIncomingCallDialog::processCallResponse(1, payload);  			return;  		} -		else if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagAll & ~LLMute::flagVoiceChat)) +		else if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagAll & ~LLMute::flagVoiceChat) && !voice_invite)  		{  			LL_INFOS() << "Rejecting session invite from initiating muted resident " << caller_name << LL_ENDL;  			return; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index a8919db828..406c8b89d0 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -76,13 +76,6 @@  // * Review the download rate throttling.  Slow then fast?  //   Detect bandwidth usage and speed up when it drops?  // -// * A lot of calls to notifyObservers().  It looks like -//   these could be collapsed by maintaining a 'dirty' -//   bit and there appears to be an attempt to do this. -//   But it isn't used or is used in a limited fashion. -//   Are there semanic issues requiring a call after certain -//   updateItem() calls? -//  // * An error on a fetch could be due to one item in the batch.  //   If the batch were broken up, perhaps more of the inventory  //   would download.  (Handwave here, not certain this is an @@ -393,6 +386,12 @@ void LLInventoryModelBackgroundFetch::bulkFetch()  	{  		// Process completed background HTTP requests  		gInventory.handleResponses(false); +		// Just processed a bunch of items. +		// Note: do we really need notifyObservers() here? +		// OnIdle it will be called anyway due to Add flag for processed item. +		// It seems like in some cases we are updaiting on fail (no flag), +		// but is there anything to update? +		gInventory.notifyObservers();  	}  	if ((mFetchCount > max_concurrent_fetches) || @@ -711,7 +710,6 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res                          titem->setParent(lost_uuid);                          titem->updateParentOnServer(FALSE);                          gInventory.updateItem(titem); -                        gInventory.notifyObservers();                      }                  }              } @@ -784,8 +782,6 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res  	{  		fetcher->setAllFoldersFetched();  	} -	 -	gInventory.notifyObservers();  } @@ -828,7 +824,6 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http  			fetcher->setAllFoldersFetched();  		}  	} -	gInventory.notifyObservers();  } @@ -866,7 +861,6 @@ void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::Http  			fetcher->setAllFoldersFetched();  		}  	} -	gInventory.notifyObservers();  } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index b9194c6c67..5abd99d36f 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -67,7 +67,8 @@ const std::string LL_IM_FROM("from");  const std::string LL_IM_FROM_ID("from_id");  const std::string LL_TRANSCRIPT_FILE_EXTENSION("txt"); -const static std::string IM_SEPARATOR(": "); +const static char IM_SYMBOL_SEPARATOR(':'); +const static std::string IM_SEPARATOR(std::string() + IM_SYMBOL_SEPARATOR + " ");  const static std::string NEW_LINE("\n");  const static std::string NEW_LINE_SPACE_PREFIX("\n ");  const static std::string TWO_SPACES("  "); @@ -838,7 +839,7 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const  	}  	if (im[LL_IM_TIME].isDefined()) -{ +	{  		std::string timestamp = im[LL_IM_TIME].asString();  		boost::trim(timestamp);  		ostr << '[' << timestamp << ']' << TWO_SPACES; @@ -851,9 +852,29 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const  	{  		std::string from = im[LL_IM_FROM].asString();  		boost::trim(from); -		if (from.size()) + +		std::size_t found = from.find(IM_SYMBOL_SEPARATOR); +		std::size_t len = from.size(); +		std::size_t start = 0; +		while (found != std::string::npos)  		{ -			ostr << from << IM_SEPARATOR; +			std::size_t sub_len = found - start; +			if (sub_len > 0) +			{ +				ostr << from.substr(start, sub_len); +			} +			LLURI::encodeCharacter(ostr, IM_SYMBOL_SEPARATOR); +			start = found + 1; +			found = from.find(IM_SYMBOL_SEPARATOR, start); +		} +		if (start < len) +		{ +			std::string str_end = from.substr(start, len - start); +			ostr << str_end; +		} +		if (len > 0) +		{ +			ostr << IM_SEPARATOR;  		}  	} @@ -865,7 +886,7 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const  		boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX);  		ostr << im_text;  	} -	} +}  bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params)  { @@ -912,7 +933,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params  	if (!boost::regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false;  	bool has_name = name_and_text[IDX_NAME].matched; -	std::string name = name_and_text[IDX_NAME]; +	std::string name = LLURI::unescape(name_and_text[IDX_NAME]);  	//we don't need a name/text separator  	if (has_name && name.length() && name[name.length()-1] == ':') @@ -933,7 +954,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params  		U32 divider_pos = stuff.find(NAME_TEXT_DIVIDER);  		if (divider_pos != std::string::npos && divider_pos < (stuff.length() - NAME_TEXT_DIVIDER.length()))  		{ -			im[LL_IM_FROM] = stuff.substr(0, divider_pos); +			im[LL_IM_FROM] = LLURI::unescape(stuff.substr(0, divider_pos));  			im[LL_IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length());  			return true;  		} diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1a533dace7..f7e0e32256 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3626,7 +3626,15 @@ void LLMeshRepository::notifyLoadedMeshes()  		//popup queued error messages from background threads  		while (!mUploadErrorQ.empty())  		{ -			LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front()); +			LLSD substitutions(mUploadErrorQ.front()); +			if (substitutions.has("DETAILS")) +			{ +				LLNotificationsUtil::add("MeshUploadErrorDetails", substitutions); +			} +			else +			{ +				LLNotificationsUtil::add("MeshUploadError", substitutions); +			}  			mUploadErrorQ.pop();  		} diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 203c57b732..cf38090798 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -56,15 +56,20 @@  #include "llfloatergroups.h"  #include "llfloaterreg.h"  #include "llavataractions.h" +#include "llavatariconctrl.h"  #include "llnamebox.h"  #include "llviewercontrol.h"  #include "lluictrlfactory.h"  #include "llspinctrl.h"  #include "roles_constants.h"  #include "llgroupactions.h" +#include "llgroupiconctrl.h"  #include "lltrans.h"  #include "llinventorymodel.h" +#include "llavatarnamecache.h" +#include "llcachename.h" +  U8 string_value_to_click_action(std::string p_value);  std::string click_action_to_string_value( U8 action); @@ -186,10 +191,13 @@ void LLPanelPermissions::disableAll()  	getChild<LLUICtrl>("pathfinding_attributes_value")->setValue(LLStringUtil::null);  	getChildView("Creator:")->setEnabled(FALSE); +	getChild<LLUICtrl>("Creator Icon")->setVisible(FALSE);  	getChild<LLUICtrl>("Creator Name")->setValue(LLStringUtil::null);  	getChildView("Creator Name")->setEnabled(FALSE);  	getChildView("Owner:")->setEnabled(FALSE); +	getChild<LLUICtrl>("Owner Icon")->setVisible(FALSE); +	getChild<LLUICtrl>("Owner Group Icon")->setVisible(FALSE);  	getChild<LLUICtrl>("Owner Name")->setValue(LLStringUtil::null);  	getChildView("Owner Name")->setEnabled(FALSE); @@ -366,39 +374,84 @@ void LLPanelPermissions::refresh()  	// Update creator text field  	getChildView("Creator:")->setEnabled(TRUE); -	std::string creator_name; -	LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); - -	getChild<LLUICtrl>("Creator Name")->setValue(creator_name); +	std::string creator_app_link; +	LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_app_link); + +	// Style for creator and owner links (both group and agent) +	LLStyle::Params style_params; +	LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); +	style_params.color = link_color; +	style_params.readonly_color = link_color; +	style_params.is_link = true; // link will be added later +	style_params.font.style = "UNDERLINE"; + +	LLAvatarName av_name; +	if (LLAvatarNameCache::get(mCreatorID, &av_name)) +	{ +		// If name isn't present, this will 'request' it and trigger refresh() again +		LLTextBox* text_box = getChild<LLTextBox>("Creator Name"); +		style_params.link_href = creator_app_link; +		text_box->setText(av_name.getCompleteName(), style_params); +	} +	getChild<LLAvatarIconCtrl>("Creator Icon")->setValue(mCreatorID); +	getChild<LLAvatarIconCtrl>("Creator Icon")->setVisible(TRUE);  	getChildView("Creator Name")->setEnabled(TRUE);  	// Update owner text field  	getChildView("Owner:")->setEnabled(TRUE); -	std::string owner_name; -	const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name); -	if (mOwnerID.isNull()) +	std::string owner_app_link; +	const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_app_link); + + +	if (LLSelectMgr::getInstance()->selectIsGroupOwned())  	{ -		if (LLSelectMgr::getInstance()->selectIsGroupOwned()) +		// Group owned already displayed by selectGetOwner +		LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mOwnerID); +		if (group_data && group_data->isGroupPropertiesDataComplete())  		{ -			// Group owned already displayed by selectGetOwner +			LLTextBox* text_box = getChild<LLTextBox>("Owner Name"); +			style_params.link_href = owner_app_link; +			text_box->setText(group_data->mName, style_params); +			getChild<LLGroupIconCtrl>("Owner Group Icon")->setIconId(group_data->mInsigniaID); +			getChild<LLGroupIconCtrl>("Owner Group Icon")->setVisible(TRUE); +			getChild<LLUICtrl>("Owner Icon")->setVisible(FALSE);  		}  		else  		{ +			// Triggers refresh +			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mOwnerID); +		} +	} +	else +	{ +		LLUUID owner_id = mOwnerID; +		if (owner_id.isNull()) +		{  			// Display last owner if public -			std::string last_owner_name; -			LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name); +			std::string last_owner_app_link; +			LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_app_link);  			// It should never happen that the last owner is null and the owner  			// is null, but it seems to be a bug in the simulator right now. JC -			if (!mLastOwnerID.isNull() && !last_owner_name.empty()) +			if (!mLastOwnerID.isNull() && !last_owner_app_link.empty())  			{ -				owner_name.append(", last "); -				owner_name.append(last_owner_name); +				owner_app_link.append(", last "); +				owner_app_link.append(last_owner_app_link);  			} +			owner_id = mLastOwnerID; +		} +		if (LLAvatarNameCache::get(owner_id, &av_name)) +		{ +			// If name isn't present, this will 'request' it and trigger refresh() again +			LLTextBox* text_box = getChild<LLTextBox>("Owner Name"); +			style_params.link_href = owner_app_link; +			text_box->setText(av_name.getCompleteName(), style_params);  		} +		getChild<LLAvatarIconCtrl>("Owner Icon")->setValue(owner_id); +		getChild<LLAvatarIconCtrl>("Owner Icon")->setVisible(TRUE); +		getChild<LLUICtrl>("Owner Group Icon")->setVisible(FALSE);  	} -	getChild<LLUICtrl>("Owner Name")->setValue(owner_name);  	getChildView("Owner Name")->setEnabled(TRUE);  	// update group text field diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 1d021ec28f..b2c450aa0c 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -40,6 +40,7 @@  #include "lltoastnotifypanel.h"  #include "lltoastscripttextbox.h"  #include "lltrans.h" +#include "llviewerobjectlist.h"  #include "llviewerwindow.h"  #include "llfloaterimsession.h" @@ -61,6 +62,7 @@ LLUUID notification_id_to_object_id(const LLUUID& notification_id)  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// +  LLScriptFloater::LLScriptFloater(const LLSD& key)  : LLDockableFloater(NULL, true, key)  , mScriptForm(NULL) @@ -346,6 +348,11 @@ void LLScriptFloater::hideToastsIfNeeded()  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// +LLScriptFloaterManager::LLScriptFloaterManager() +{ +	gSavedSettings.getControl("ScriptDialogLimitations")->getCommitSignal()->connect(boost::bind(&clearScriptNotifications)); +} +  void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  {  	if(notification_id.isNull()) @@ -365,16 +372,86 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  	// LLDialog can spawn only one instance, LLLoadURL and LLGiveInventory can spawn unlimited number of instances  	if(OBJ_SCRIPT == obj_type)  	{ -		// If an Object spawns more-than-one floater, only the newest one is shown.  -		// The previous is automatically closed. -		script_notification_map_t::const_iterator it = findUsingObjectId(object_id); +		static LLCachedControl<U32> script_dialog_limitations(gSavedSettings, "ScriptDialogLimitations", 0); +		script_notification_map_t::const_iterator it = mNotifications.end(); +		switch (script_dialog_limitations) +		{ +			case SCRIPT_PER_CHANNEL: +			{ +				// If an Object spawns more-than-one floater per channel, only the newest one is shown. +				// The previous is automatically closed. +				LLNotificationPtr notification = LLNotifications::instance().find(notification_id); +				if (notification) +				{ +					it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); +				} +				break; +			} +			case SCRIPT_ATTACHMENT_PER_CHANNEL: +			{ +				LLViewerObject* objectp = gObjectList.findObject(object_id); +				if (objectp && objectp->getAttachmentItemID().notNull()) //in user inventory +				{ +					LLNotificationPtr notification = LLNotifications::instance().find(notification_id); +					if (notification) +					{ +						it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); +					} +				} +				else +				{ +					it = findUsingObjectId(object_id); +				} +				break; +			} +			case SCRIPT_HUD_PER_CHANNEL: +			{ +				LLViewerObject* objectp = gObjectList.findObject(object_id); +				if (objectp && objectp->isHUDAttachment()) +				{ +					LLNotificationPtr notification = LLNotifications::instance().find(notification_id); +					if (notification) +					{ +						it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger()); +					} +				} +				else +				{ +					it = findUsingObjectId(object_id); +				} +				break; +			} +			case SCRIPT_HUD_UNCONSTRAINED: +			{ +				LLViewerObject* objectp = gObjectList.findObject(object_id); +				if (objectp && objectp->isHUDAttachment()) +				{ +					// don't remove existing floaters +					break; +				} +				else +				{ +					it = findUsingObjectId(object_id); +				} +				break; +			} +			case SCRIPT_PER_OBJECT: +			default: +			{ +				// If an Object spawns more-than-one floater, only the newest one is shown. +				// The previous is automatically closed. +				it = findUsingObjectId(object_id); +				break; +			} +		} +  		if(it != mNotifications.end())  		{  			LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel();  			if (NULL != chiclet_panelp)  			{  				LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(it->first); -				if(NULL != chicletp) +				if (NULL != chicletp)  				{  					// Pass the new_message icon state further.  					set_new_message = chicletp->getShowNewMessagesIcon(); @@ -383,7 +460,7 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  			}  			LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first); -			if(floater) +			if (floater)  			{  				// Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142.  				set_new_message |= !floater->hasFocus(); @@ -579,6 +656,23 @@ LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloate  	return mNotifications.end();  } +LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloaterManager::findUsingObjectIdAndChannel(const LLUUID& object_id, S32 im_channel) +{ +	script_notification_map_t::const_iterator it = mNotifications.begin(); +	for (; mNotifications.end() != it; ++it) +	{ +		if (object_id == it->second) +		{ +			LLNotificationPtr notification = LLNotifications::instance().find(it->first); +			if (notification && (im_channel == notification->getPayload()["chat_channel"].asInteger())) +			{ +				return it; +			} +		} +	} +	return mNotifications.end(); +} +  void LLScriptFloaterManager::saveFloaterPosition(const LLUUID& object_id, const FloaterPositionInfo& fpi)  {  	if(object_id.notNull()) @@ -612,6 +706,33 @@ void LLScriptFloaterManager::setFloaterVisible(const LLUUID& notification_id, bo  	}  } +//static +void LLScriptFloaterManager::clearScriptNotifications() +{ +	LLScriptFloaterManager* inst = LLScriptFloaterManager::getInstance(); +	static const object_type_map TYPE_MAP = initObjectTypeMap(); + +	script_notification_map_t::const_iterator ntf_it = inst->mNotifications.begin(); +	while (inst->mNotifications.end() != ntf_it) +	{ +		LLUUID notification_id = ntf_it->first; +		ntf_it++; // onRemoveNotification() erases notification +		LLNotificationPtr notification = LLNotifications::instance().find(notification_id); +		if (notification) +		{ +			object_type_map::const_iterator map_it = TYPE_MAP.find(notification->getName()); +			if (map_it != TYPE_MAP.end() && map_it->second == OBJ_SCRIPT) +			{ +				if (notification != NULL && !notification->isCancelled()) +				{ +					LLNotificationsUtil::cancel(notification); +				} +				inst->onRemoveNotification(notification_id); +			} +		} +	} +} +  //////////////////////////////////////////////////////////////////  bool LLScriptFloater::isScriptTextbox(LLNotificationPtr notification) diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index c0b84abdcb..0192a8893e 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -41,7 +41,7 @@ class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager>  	// *TODO  	// LLScriptFloaterManager and LLScriptFloater will need some refactoring after we   	// know how script notifications should look like. -	LLSINGLETON_EMPTY_CTOR(LLScriptFloaterManager); +	LLSINGLETON(LLScriptFloaterManager);  public:  	typedef enum e_object_type @@ -53,6 +53,15 @@ public:  		OBJ_UNKNOWN  	}EObjectType; +	typedef enum e_limitation_type +	{ +		SCRIPT_PER_OBJECT = 0, +		SCRIPT_PER_CHANNEL = 1, +		SCRIPT_ATTACHMENT_PER_CHANNEL, +		SCRIPT_HUD_PER_CHANNEL, +		SCRIPT_HUD_UNCONSTRAINED +	}ELimitationType; +  	/**  	 * Handles new notifications.  	 * Saves notification and object ids, removes old notification if needed, creates script chiclet @@ -104,6 +113,11 @@ public:  protected: +	/** +	 * Removes all script-dialog notifications +	 */ +	static void clearScriptNotifications(); +  	typedef std::map<std::string, EObjectType> object_type_map;  	static object_type_map initObjectTypeMap(); @@ -112,6 +126,7 @@ protected:  	typedef std::map<LLUUID, LLUUID> script_notification_map_t;  	script_notification_map_t::const_iterator findUsingObjectId(const LLUUID& object_id); +	script_notification_map_t::const_iterator findUsingObjectIdAndChannel(const LLUUID& object_id, S32 im_channel);  private: diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 45dbd95bea..1d6daed9cc 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -6274,6 +6274,24 @@ BOOL	LLViewerObject::isTempAttachment() const  	return (mID.notNull() && (mID == mAttachmentItemID));  } +BOOL LLViewerObject::isHiglightedOrBeacon() const +{ +	if (LLFloaterReg::instanceVisible("beacons") && (gPipeline.getRenderBeacons(NULL) || gPipeline.getRenderHighlights(NULL))) +	{ +		BOOL has_media = (getMediaType() == LLViewerObject::MEDIA_SET); +		BOOL is_scripted = !isAvatar() && !getParent() && flagScripted(); +		BOOL is_physical = !isAvatar() && flagUsePhysics(); + +		return (isParticleSource() && gPipeline.getRenderParticleBeacons(NULL)) +				|| (isAudioSource() && gPipeline.getRenderSoundBeacons(NULL)) +				|| (has_media && gPipeline.getRenderMOAPBeacons(NULL)) +				|| (is_scripted && gPipeline.getRenderScriptedBeacons(NULL)) +				|| (is_scripted && flagHandleTouch() && gPipeline.getRenderScriptedTouchBeacons(NULL)) +				|| (is_physical && gPipeline.getRenderPhysicalBeacons(NULL)); +	} +	return FALSE; +} +  const LLUUID &LLViewerObject::getAttachmentItemID() const  { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 1e8f3f4ec2..24fcf0517e 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -178,6 +178,8 @@ public:  	virtual BOOL	isHUDAttachment() const { return FALSE; }  	virtual BOOL	isTempAttachment() const; +	virtual BOOL isHiglightedOrBeacon() const; +  	virtual void 	updateRadius() {};  	virtual F32 	getVObjRadius() const; // default implemenation is mDrawable->getRadius() @@ -388,7 +390,7 @@ public:  	 // Create if necessary  	LLAudioSource *getAudioSource(const LLUUID& owner_id); -	bool isAudioSource() {return mAudioSourcep != NULL;} +	BOOL isAudioSource() const {return mAudioSourcep != NULL;}  	U8 getMediaType() const;  	void setMediaType(U8 media_type); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 9e09971ced..7d2d6e25c7 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -176,7 +176,7 @@ public:  		mToolTip = inv_item->getName() + '\n' + inv_item->getDescription();  	} -	/*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +	/*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const  	{  		if (num_chars == 0)  		{ @@ -185,7 +185,7 @@ public:  		}  		else  		{ -			width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str()); +			width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidthF32(mLabel.c_str());  			height = llmax(mImage->getHeight(), mStyle->getFont()->getLineHeight());  		}  		return false; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f6a16f7da1..3968266c27 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -119,7 +119,7 @@ const F32 MAX_HOVER_Z = 2.0;  const F32 MIN_HOVER_Z = -2.0;  const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f; -const F32 MAX_ATTACHMENT_COMPLEXITY = 1.0e6f; +const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f;  using namespace LLAvatarAppearanceDefines; @@ -9018,6 +9018,9 @@ void LLVOAvatar::calculateUpdateRenderComplexity()       * the official viewer for consideration.       *****************************************************************/  	static const U32 COMPLEXITY_BODY_PART_COST = 200; +	static LLCachedControl<F32> max_complexity_setting(gSavedSettings,"MaxAttachmentComplexity"); +	F32 max_attachment_complexity = max_complexity_setting; +	max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY);  	// Diagnostic list of all textures on our avatar  	static std::set<LLUUID> all_textures; @@ -9099,7 +9102,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()                                                     << " children: " << attachment_children_cost                                                     << LL_ENDL;                              // Limit attachment complexity to avoid signed integer flipping of the wearer's ACI -                            cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, MAX_ATTACHMENT_COMPLEXITY); +                            cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity);  						}  					}  				} diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 657babd92c..90ba814a15 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3977,7 +3977,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  			start_face = face;  			end_face = face+1;  		} - +		pick_transparent |= isHiglightedOrBeacon();  		bool special_cursor = specialHoverCursor();  		for (S32 i = start_face; i < end_face; ++i)  		{ diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 91e4c1b603..c3a5a0dce8 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -946,18 +946,28 @@               width="90">                  Creator:              </text> +            <avatar_icon +             default_icon_name="Generic_Person" +             height="18" +             follows="left|top" +             layout="topleft" +             left_pad="1" +             name="Creator Icon" +             visible="false" +             top_delta="0" +             width="18" />              <!-- *NOTE: Intentionally wide for long names -->              <text               type="string"               length="1"               follows="left|top" -             left_pad="0" +             left_pad="1"               height="29"               layout="topleft"               name="Creator Name" -             top_delta="0" +             top_delta="-1"               translate="false" -             width="190" +             width="170"               word_wrap="true"               use_ellipses="true">                  TestString PleaseIgnore (please.ignore) @@ -974,6 +984,26 @@               width="90">                  Owner:              </text> +            <avatar_icon +             default_icon_name="Generic_Person" +             height="18" +             follows="left|top" +             layout="topleft" +             left_pad="1" +             name="Owner Icon" +             visible="false" +             top_delta="0" +             width="18" /> +            <group_icon +             default_icon_name="Generic_Group" +             height="18" +             follows="left|top" +             layout="topleft" +             left_pad="-18" +             name="Owner Group Icon" +             visible="false" +             top_delta="0" +             width="18" />              <!-- *NOTE: Intentionally wide for long names -->              <text               type="string" @@ -982,10 +1012,10 @@               height="29"               layout="topleft"               name="Owner Name" -             left_pad="0" -             top_delta="0" +             left_pad="1" +             top_delta="-1"               translate="false" -             width="190" +             width="170"               word_wrap="true"               use_ellipses="true">                  TestString PleaseIgnore (please.ignore) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4f5f0ac02c..ebe1fdc4c7 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -909,6 +909,108 @@ Please invite members within 48 hours.    <notification     icon="alertmodal.tga" +   name="JoinGroupInaccessible" +   type="alertmodal"> +This group is not accessible to you. +    <tag>group_id</tag> +    <tag>success</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="JoinGroupError" +   type="alertmodal"> +Error processing your group membership request. +    <tag>group_id</tag> +    <tag>success</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="JoinGroupError" +   type="alertmodal"> +Unable to join group: [reason] +    <tag>group_id</tag> +    <tag>success</tag> +    <tag>reason</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="JoinGroupTrialUser" +   type="alertmodal"> +Sorry, trial users can't join groups. +    <tag>group_id</tag> +    <tag>success</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="JoinGroupMaxGroups" +   type="alertmodal"> +You cannot join '[group_name]': +You are already a member of [group_count] groups, the maximum number allowed is [max_groups] +    <tag>success</tag> +    <tag>group_id</tag> +    <tag>group_name</tag> +    <tag>group_count</tag> +    <tag>max_groups</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="JoinGroupClosedEnrollment" +   type="alertmodal"> +You cannot join '[group_name]': +The group no longer has open enrollment. +    <tag>group_id</tag> +    <tag>success</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="JoinGroupSuccess" +   type="alertmodal"> +You have been added to the group +    <tag>group_id</tag> +    <tag>success</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> +   +  <notification +   icon="alertmodal.tga" +   name="JoinGroupInsufficientFunds" +   type="alertmodal"> +Unable to transfer the required L$ [membership_fee] membership fee. +    <tag>group_id</tag> +    <tag>success</tag> +    <usetemplate +       name="okbutton" +       yestext="OK"/> +  </notification> +   +  <notification +   icon="alertmodal.tga"     name="LandBuyPass"     type="alertmodal">     <tag>fail</tag> @@ -8501,12 +8603,22 @@ Select residents to share with.    </notification>    <notification -    name="MeshUploadError" +    name="MeshUploadErrorDetails"      icon="alert.tga"      type="alert">        [LABEL] failed to upload: [MESSAGE] [IDENTIFIER]  [DETAILS]See SecondLife.log for details    </notification> + +  <notification +    name="MeshUploadError" +    icon="alert.tga" +    type="alert"> +      [LABEL] failed to upload: [MESSAGE] +[IDENTIFIER] + +See SecondLife.log for details +  </notification>    <notification      name="MeshUploadPermError" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 440c6613d5..78f771cd51 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -9,6 +9,18 @@      name="chat"      top="1"      width="517"> +     +  <check_box +      control_name="ChatAutocompleteGestures" +      height="16" +      initial_value="true" +      label="Auto-complete gestures in nearby chat" +      layout="topleft" +      top="17" +      left="13" +      name="auto_complete_gestures" +      width="330"> +  </check_box>    <panel        border="false" diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 2dae1025ec..b7b67147eb 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -586,7 +586,7 @@  			 label_width="205"               left="10"               max_val="100" -             min_val="0.1" +             min_val="-100"               name="rptctrl"               width="265" />             <spinner | 
