diff options
172 files changed, 2243 insertions, 980 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index 211d4fcf08..7493e96c39 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -185,6 +185,7 @@ Ansariel Hiller  	BUG-3764  	STORM-1984  	STORM-1979 +	MAINT-5533  Aralara Rajal  Arare Chantilly  	CHUIBUG-191 diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index ae11988df8..3a8eabac09 100755 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -2176,8 +2176,7 @@ void* ll_aligned_malloc_fallback( size_t size, int align )  	SYSTEM_INFO sysinfo;  	GetSystemInfo(&sysinfo); -	unsigned int for_alloc = sysinfo.dwPageSize; -	while(for_alloc < size) for_alloc += sysinfo.dwPageSize; +	unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize;  	void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);  	if(NULL == p) { diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index d3a9bbc4ae..0fb257aab1 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -98,7 +98,7 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  //------------------------------------------------------------------------------------------------  //------------------------------------------------------------------------------------------------  	// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library -	// change preprocessro code to: #if 1 && defined(LL_WINDOWS) +	// change preprocessor code to: #if 1 && defined(LL_WINDOWS)  #if 0 && defined(LL_WINDOWS)  	void* ll_aligned_malloc_fallback( size_t size, int align ); diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp index d98bc297e5..82d0dc8b4b 100644 --- a/indra/llcommon/lluriparser.cpp +++ b/indra/llcommon/lluriparser.cpp @@ -238,12 +238,12 @@ void LLUriParser::glueSecond(std::string& uri) const  	{  		uri += '?';  		uri += mQuery; +	} -		if (mFragment.size()) -		{ -			uri += '#'; -			uri += mFragment; -		} +	if (mFragment.size()) +	{ +		uri += '#'; +		uri += mFragment;  	}  } diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp index 8573fe0d91..a2ce2fee86 100755 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -443,6 +443,10 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )  		mBitfieldMask[2] = 0x000000FF;  	} +	if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset) +	{ //here we have situation when data size in src less than actually needed +		return FALSE; +	}  	S32 src_row_span = getWidth() * 4;  	S32 alignment_bytes = (3 * src_row_span) % 4;  // round up to nearest multiple of 4 @@ -476,6 +480,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )  	S32 src_row_span = getWidth() * 1;  	S32 alignment_bytes = (3 * src_row_span) % 4;  // round up to nearest multiple of 4 +	if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset) +	{ //here we have situation when data size in src less than actually needed +		return FALSE; +	} +  	for( S32 row = 0; row < getHeight(); row++ )  	{  		for( S32 col = 0; col < getWidth(); col++ ) @@ -501,6 +510,11 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )  	S32 src_row_span = getWidth() * 3;  	S32 alignment_bytes = (3 * src_row_span) % 4;  // round up to nearest multiple of 4 +	if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset) +	{ //here we have situation when data size in src less than actually needed +		return FALSE; +	} +  	for( S32 row = 0; row < getHeight(); row++ )  	{  		for( S32 col = 0; col < getWidth(); col++ ) diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index 4eb8dc7440..d0ae105ba7 100755 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -437,7 +437,13 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu  	// Origin is the bottom left  	U8* dst = raw_image->getData();  	U8* src = getData() + mDataOffset; +  	S32 pixels = getWidth() * getHeight(); +	 +	if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - mDataOffset) +	{ //here we have situation when data size in src less than actually needed +		return FALSE; +	}  	if (getComponents() == 4)  	{ diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 4703e6cf1a..8608e45a91 100755 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2536,6 +2536,8 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  					U32 cur_influence = 0;  					LLVector4 wght(0,0,0,0); +                    U32 joints[4] = {0,0,0,0}; +					LLVector4 joints_with_weights(0,0,0,0);  					while (joint != END_INFLUENCES && idx < weights.size())  					{ @@ -2543,7 +2545,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  						influence |= ((U16) weights[idx++] << 8);  						F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); -						wght.mV[cur_influence++] = (F32) joint + w; +						wght.mV[cur_influence] = w; +						joints[cur_influence] = joint; +						cur_influence++;  						if (cur_influence >= 4)  						{ @@ -2554,8 +2558,16 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)  							joint = weights[idx++];  						}  					} - -					face.mWeights[cur_vertex].loadua(wght.mV); +                    F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; +                    if (wsum <= 0.f) +                    { +                        wght = LLVector4(0.99999f,0.f,0.f,0.f); +                    } +                    for (U32 k=0; k<4; k++) +                    { +                        joints_with_weights[k] = (F32) joints[k] + wght[k]; +                    } +					face.mWeights[cur_vertex].loadua(joints_with_weights.mV);  					cur_vertex++;  				} @@ -5584,7 +5596,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	{  		resizeVertices(num_vertices+1); -		if (!partial_build) +		//if (!partial_build)  		{  			resizeIndices(num_indices+3);  		} @@ -5592,7 +5604,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	else  	{  		resizeVertices(num_vertices); -		if (!partial_build) +		//if (!partial_build)  		{  			resizeIndices(num_indices);  		} @@ -5714,10 +5726,10 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	LL_CHECK_MEMORY -	if (partial_build) -	{ -		return TRUE; -	} +	//if (partial_build) +	//{ +	//	return TRUE; +	//}  	if (mTypeMask & HOLLOW_MASK)  	{ diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 625f7cff02..1da2d0c6b1 100755 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -190,8 +190,12 @@ const U8 LL_SCULPT_TYPE_MESH      = 5;  const U8 LL_SCULPT_TYPE_MASK      = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |  	LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; +// for value checks, assign new value after adding new types +const U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH; +  const U8 LL_SCULPT_FLAG_INVERT    = 64;  const U8 LL_SCULPT_FLAG_MIRROR    = 128; +const U8 LL_SCULPT_FLAG_MASK = LL_SCULPT_FLAG_INVERT | LL_SCULPT_FLAG_MIRROR;  const S32 LL_SCULPT_MESH_MAX_FACES = 8; diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 52626b0302..4bfd0de81e 100755 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -146,6 +146,8 @@ void LLPluginClassMedia::reset()  	mClickTarget.clear();  	mClickUUID.clear();  	mStatusCode = 0; + +	mClickEnforceTarget = false;  	// media_time class  	mCurrentTime = 0.0f; @@ -1358,6 +1360,12 @@ void LLPluginClassMedia::addCertificateFilePath(const std::string& path)  	sendMessage(message);  } +void LLPluginClassMedia::setOverrideClickTarget(const std::string &target) +{ +	mClickEnforceTarget = true; +	mOverrideClickTarget = target; +} +  void LLPluginClassMedia::crashPlugin()  {  	LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 5fe8254331..96d577f43c 100755 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -249,6 +249,13 @@ public:  	// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE  	std::string getClickUUID() const { return mClickUUID; }; +	// mClickTarget is received from message and governs how link will be opened +	// use this to enforce your own way of opening links inside plugins +	void setOverrideClickTarget(const std::string &target); +	void resetOverrideClickTarget() { mClickEnforceTarget = false; }; +	bool isOverrideClickTarget() const { return mClickEnforceTarget; } +	std::string getOverrideClickTarget() const { return mOverrideClickTarget; }; +  	// These are valid during MEDIA_EVENT_DEBUG_MESSAGE  	std::string getDebugMessageText() const { return mDebugMessageText; };  	std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; @@ -404,6 +411,8 @@ protected:  	std::string		mClickNavType;  	std::string		mClickTarget;  	std::string		mClickUUID; +	bool			mClickEnforceTarget; +	std::string		mOverrideClickTarget;  	std::string		mDebugMessageText;  	std::string		mDebugMessageLevel;  	S32				mGeometryX; diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 29747cb09c..9eff74f1e8 100755 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -317,9 +317,9 @@ S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID  	return mTextureList.setMaterialID(index, pMaterialID);  } -S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) +S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer)  { -	return mTextureList.setMaterialParams(index, pMaterialParams); +	return mTextureList.setMaterialParams(index, pMaterialParams, isInitFromServer);  }  LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index) @@ -1869,9 +1869,12 @@ BOOL LLSculptParams::pack(LLDataPacker &dp) const  BOOL LLSculptParams::unpack(LLDataPacker &dp)  { -	dp.unpackUUID(mSculptTexture, "texture"); -	dp.unpackU8(mSculptType, "type"); -	 +	U8 type; +	LLUUID id; +	dp.unpackUUID(id, "texture"); +	dp.unpackU8(type, "type"); + +	setSculptTexture(id, type);  	return TRUE;  } @@ -1896,8 +1899,7 @@ bool LLSculptParams::operator==(const LLNetworkData& data) const  void LLSculptParams::copy(const LLNetworkData& data)  {  	const LLSculptParams *param = (LLSculptParams*)&data; -	mSculptTexture = param->mSculptTexture; -	mSculptType = param->mSculptType; +	setSculptTexture(param->mSculptTexture, param->mSculptType);  } @@ -1915,20 +1917,38 @@ LLSD LLSculptParams::asLLSD() const  bool LLSculptParams::fromLLSD(LLSD& sd)  {  	const char *w; -	w = "texture"; +	U8 type; +	w = "type";  	if (sd.has(w))  	{ -		setSculptTexture( sd[w] ); -	} else goto fail; -	w = "type"; +		type = sd[w].asInteger(); +	} +	else return false; + +	w = "texture";  	if (sd.has(w))  	{ -		setSculptType( (U8)sd[w].asInteger() ); -	} else goto fail; -	 +		setSculptTexture(sd[w], type); +	} +	else return false; +  	return true; - fail: -	return false; +} + +void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type) +{ +	U8 type = sculpt_type & LL_SCULPT_TYPE_MASK; +	U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; +	if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) +	{ +		mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); +		mSculptType = LL_SCULPT_TYPE_SPHERE; +	} +	else +	{ +		mSculptTexture = texture_id; +		mSculptType = sculpt_type; +	}  }  //============================================================================ diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 1bf83e36b4..54870fbb10 100755 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -259,9 +259,8 @@ public:  	operator LLSD() const { return asLLSD(); }  	bool fromLLSD(LLSD& sd); -	void setSculptTexture(const LLUUID& id) { mSculptTexture = id; } +	void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type);  	LLUUID getSculptTexture() const         { return mSculptTexture; } -	void setSculptType(U8 type)             { mSculptType = type; }  	U8 getSculptType() const                { return mSculptType; }  }; @@ -385,7 +384,7 @@ public:  	virtual S32 setTEMediaFlags(const U8 te, const U8 flags);  	virtual S32 setTEGlow(const U8 te, const F32 glow);  	virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); -	virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); +	virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer);  	virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed  	virtual void setTESelected(const U8 te, bool sel); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index f4f08248b8..6aae2f97c6 100755 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -368,11 +368,18 @@ S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMateri  	return TEM_CHANGE_NONE;  } -S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) +S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer)  {  	if (index < mEntryList.size())  	{ -		return mEntryList[index]->setMaterialParams(pMaterialParams); +		if (!isInitFromServer && mEntryList[index]->isMatParamsInitFromServer()) +		{ +			return TEM_CHANGE_NONE; +		} +		else +		{ +			return mEntryList[index]->setMaterialParams(pMaterialParams); +		}  	}  	return TEM_CHANGE_NONE;  } diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 49c636e40f..63e6372405 100755 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -105,7 +105,7 @@ public:  	S32 setMediaFlags(const U8 index, const U8 media_flags);  	S32 setGlow(const U8 index, const F32 glow);  	S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); -	S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); +	S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer);  	LLMaterialPtr getMaterialParams(const U8 index); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 284dfc15f4..6020031099 100755 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -63,6 +63,7 @@ LLTextureEntry::LLTextureEntry()    : mMediaEntry(NULL)    , mSelected(false)    , mMaterialUpdatePending(false) +  , mInitMatParamsFromServer(false)  {  	init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);  } @@ -71,6 +72,7 @@ LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)    : mMediaEntry(NULL)    , mSelected(false)    , mMaterialUpdatePending(false) +  , mInitMatParamsFromServer(false)  {  	init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);  } @@ -79,6 +81,7 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)    : mMediaEntry(NULL)    , mSelected(false)    , mMaterialUpdatePending(false) +  , mInitMatParamsFromServer(false)  {  	mID = rhs.mID;  	mScaleS = rhs.mScaleS; @@ -562,6 +565,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)  		mMaterialUpdatePending = true;  	}  	mMaterial = pMaterialParams; +	this->mInitMatParamsFromServer = TRUE;  	return TEM_CHANGE_TEXTURE;  } diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index a40c3988f2..81e2e8a5a2 100755 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -160,6 +160,8 @@ public:  	const LLMaterialID& getMaterialID() const { return mMaterialID; };  	const LLMaterialPtr getMaterialParams() const { return mMaterial; }; +	bool isMatParamsInitFromServer() const { return mInitMatParamsFromServer; }; +      // *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.      // CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()      // to NOT return NULL.   @@ -217,6 +219,8 @@ protected:  	bool                mMaterialUpdatePending;  	LLMaterialID        mMaterialID;  	LLMaterialPtr		mMaterial; +	bool                mInitMatParamsFromServer; // Flag to identification when material paramas initialized from  +  	// Note the media data is not sent via the same message structure as the rest of the TE  	LLMediaEntry*		mMediaEntry;			// The media data for the face diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 3396213f1c..c937d190c6 100755 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -153,7 +153,7 @@ void LLDockableFloater::setVisible(BOOL visible)  		mDockControl.get()->repositionDockable();  	} -	if (visible) +	if (visible && !isMinimized())  	{  		LLFloater::setFrontmost(getAutoFocus());  	} diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 81a0204bc5..3def0386e1 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -129,6 +129,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)  	mSelectPending(FALSE),  	mLabelStyle( LLFontGL::NORMAL ),  	mHasVisibleChildren(FALSE), +	mIsFolderComplete(true),      mLocalIndentation(p.folder_indentation),  	mIndentation(0),  	mItemHeight(p.item_height), @@ -674,7 +675,7 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L  	//  	const S32 TOP_PAD = default_params.item_top_pad; -	if (hasVisibleChildren()) +	if (hasVisibleChildren() || !isFolderComplete())  	{  		LLUIImage* arrow_image = default_params.folder_arrow_image;  		gl_draw_scaled_rotated_image( @@ -934,6 +935,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):  	mLastArrangeGeneration( -1 ),  	mLastCalculatedWidth(0)  { +	// folder might have children that are not loaded yet. Mark it as incomplete until chance to check it. +	mIsFolderComplete = false;  }  void LLFolderViewFolder::updateLabelRotation() @@ -1016,6 +1019,12 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )  		mHasVisibleChildren = found;  	} +	if (!mIsFolderComplete) +	{ +		mIsFolderComplete = getFolderViewModel()->isFolderComplete(this); +	} + +  	// calculate height as a single item (without any children), and reshapes rectangle to match  	LLFolderViewItem::arrange( width, height ); @@ -1463,31 +1472,37 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)  	LLFolderView* root = getRoot(); -	for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end(); +	BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected + +	// array always go from 'will be selected' to ' will be unselected', iterate +	// in opposite direction to simplify identification of 'point of origin' in +	// case it is in the list we are working with +	for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend();  		it != end_it;  		++it)  	{  		LLFolderViewItem* item = *it; -		if (item->isSelected()) +		BOOL selected = item->isSelected(); +		if (!selection_reverse && selected)  		{ -			root->removeFromSelectionList(item); +			// it is our 'point of origin' where we shift/expand from +			// don't deselect it +			selection_reverse = TRUE;  		}  		else  		{ -			item->selectItem(); +			root->changeSelection(item, !selected);  		} -		root->addToSelectionList(item);  	} -	if (new_selection->isSelected()) +	if (selection_reverse)  	{ -		root->removeFromSelectionList(new_selection); +		// at some point we reversed selection, first element should be deselected +		root->changeSelection(last_selected_item_from_cur, FALSE);  	} -	else -	{ -		new_selection->selectItem(); -	} -	root->addToSelectionList(new_selection); + +	// element we expand to should always be selected +	root->changeSelection(new_selection, TRUE);  } @@ -1677,7 +1692,9 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r  	mIsOpen = openitem;  		if(!was_open && openitem)  		{ -		getViewModelItem()->openItem(); +			getViewModelItem()->openItem(); +			// openItem() will request content, it won't be incomplete +			mIsFolderComplete = true;  		}  		else if(was_open && !openitem)  		{ diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index ed4496cfaa..0322c8836d 100755 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -115,6 +115,7 @@ protected:  	F32							mControlLabelRotation;  	LLFolderView*				mRoot;  	bool						mHasVisibleChildren, +								mIsFolderComplete, // indicates that some children were not loaded/added yet  								mIsCurSelection,  								mDragAndDropTarget,  								mIsMouseOverTitle, @@ -212,6 +213,9 @@ public:  	BOOL hasVisibleChildren() { return mHasVisibleChildren; } +	// true if object can't have children +	BOOL isFolderComplete() { return mIsFolderComplete; } +  	// Call through to the viewed object and return true if it can be  	// removed. Returns true if it's removed.  	//virtual BOOL removeRecursively(BOOL single_item); diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index d60e36183b..a395af537a 100755 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -122,6 +122,7 @@ public:  	virtual void filter() = 0;  	virtual bool contentsReady() = 0; +	virtual bool isFolderComplete(class LLFolderViewFolder*) = 0;  	virtual void setFolderView(LLFolderView* folder_view) = 0;  	virtual LLFolderViewFilter& getFilter() = 0;  	virtual const LLFolderViewFilter& getFilter() const = 0; @@ -444,6 +445,7 @@ public:  	// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,  	// this method needs to be overloaded and return the relevant fetch status.  	virtual bool contentsReady()					{ return true; } +	virtual bool isFolderComplete(LLFolderViewFolder* folder)					{ return true; }  	struct ViewModelCompare  	{ diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7cdbcb0621..848367f8a8 100755 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -225,7 +225,6 @@ BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)  BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask)  { -	setHover(TRUE);  	getWindow()->setCursor(UI_CURSOR_ARROW);  	return TRUE;  } @@ -236,6 +235,18 @@ BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask)  	return LLUICtrl::handleRightMouseDown(x,y,mask);  } +void LLMenuItemGL::onMouseEnter(S32 x, S32 y, MASK mask) +{ +	setHover(TRUE); +	LLUICtrl::onMouseEnter(x,y,mask); +} + +void LLMenuItemGL::onMouseLeave(S32 x, S32 y, MASK mask) +{ +	setHover(FALSE); +	LLUICtrl::onMouseLeave(x,y,mask); +} +  //virtual  BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)  { @@ -533,9 +544,6 @@ void LLMenuItemGL::draw( void )  			gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1);  		}  	} - -	// clear got hover every frame -	setHover(FALSE);  }  BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& text ) @@ -1043,7 +1051,7 @@ void LLMenuItemBranchGL::onCommit( void )  	// keyboard navigation automatically propagates highlight to sub-menu  	// to facilitate fast menu control via jump keys -	if (LLMenuGL::getKeyboardMode() && getBranch()&& !getBranch()->getHighlightedItem()) +	if (LLMenuGL::getKeyboardMode() && getBranch() && !getBranch()->getHighlightedItem())  	{  		getBranch()->highlightNextItem(NULL);  	} @@ -1456,7 +1464,16 @@ BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask )  {  	// switch to mouse control mode  	LLMenuGL::setKeyboardMode(FALSE); -	onCommit(); + +	if (getVisible() && isOpen()) +	{ +		LLMenuGL::sMenuContainer->hideMenus(); +	} +	else +	{ +		onCommit(); +	} +  	make_ui_sound("UISndClick");  	return TRUE;  } @@ -1588,10 +1605,6 @@ void LLMenuItemBranchDownGL::draw( void )  			gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS);  		}  	} - -	// reset every frame so that we only show highlight  -	// when we get hover events on that frame -	setHover(FALSE);  } @@ -3381,6 +3394,11 @@ BOOL LLMenuBarGL::handleMouseDown(S32 x, S32 y, MASK mask)  	return LLMenuGL::handleMouseDown(x, y, mask);  } +BOOL LLMenuBarGL::handleDoubleClick(S32 x, S32 y, MASK mask) +{ +	return LLMenuGL::handleMouseDown(x, y, mask); +} +  void LLMenuBarGL::draw()  {  	LLMenuItemGL* itemp = getHighlightedItem(); @@ -3625,8 +3643,24 @@ BOOL LLMenuHolderGL::handleMouseDown( S32 x, S32 y, MASK mask )  	BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;  	if (!handled)  	{ -		// clicked off of menu, hide them all -		hideMenus(); +		LLMenuGL* visible_menu = (LLMenuGL*)getVisibleMenu(); +		LLMenuItemGL* parent_menu = visible_menu ? visible_menu->getParentMenuItem() : NULL; +		if (parent_menu && parent_menu->getVisible()) +		{ +			// don't hide menu if parent was hit +			LLRect parent_rect; +			parent_menu->localRectToOtherView(parent_menu->getLocalRect(), &parent_rect, this); +			if (!parent_rect.pointInRect(x, y)) +			{ +				// clicked off of menu and parent, hide them all +				hideMenus(); +			} +		} +		else +		{ +			// no visible parent, clicked off of menu, hide them all +			hideMenus(); +		}  	}  	return handled;  } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index ae9b169691..628dedb906 100755 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -158,6 +158,10 @@ public:  	virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );  	virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );  	virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + +	virtual void	onMouseEnter(S32 x, S32 y, MASK mask); +	virtual void	onMouseLeave(S32 x, S32 y, MASK mask); +  	virtual void draw( void );  	BOOL getHover() const { return mGotHover; } @@ -753,6 +757,7 @@ public:  	/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);  	/*virtual*/ BOOL handleJumpKey(KEY key);  	/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); +	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);  	/*virtual*/ void draw();  	/*virtual*/ BOOL jumpKeysActive(); diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index ea96fc573d..1fdd05a11c 100755 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -29,6 +29,7 @@  #include "linden_common.h"  #include "llsearcheditor.h" +#include "llkeyboard.h"  LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)  :	LLUICtrl(p), @@ -166,4 +167,16 @@ void LLSearchEditor::handleKeystroke()  	{  		mKeystrokeCallback(this, getValue());  	} + +	KEY key = gKeyboard->currentKey(); +	if (key == KEY_LEFT || +		key == KEY_RIGHT) +	{ +			return; +	} + +	if (mTextChangedCallback) +	{ +		mTextChangedCallback(this, getValue()); +	}  } diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index c2d7916938..3b12868225 100755 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -82,12 +82,14 @@ public:  	virtual void	setFocus( BOOL b );  	void			setKeystrokeCallback( commit_callback_t cb ) { mKeystrokeCallback = cb; } +	void			setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; }  protected:  	void onClearButtonClick(const LLSD& data);  	virtual void handleKeystroke();  	commit_callback_t mKeystrokeCallback; +	commit_callback_t mTextChangedCallback;  	LLLineEditor* mSearchEditor;  	LLButton* mSearchButton;  	LLButton* mClearButton; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 602a703450..bf660849c4 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -37,6 +37,7 @@  #include "lltextparser.h"  #include "lltextutil.h"  #include "lltooltip.h" +#include "lltrans.h"  #include "lluictrl.h"  #include "llurlaction.h"  #include "llurlregistry.h" @@ -2060,27 +2061,33 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  			// add icon before url if need  			LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted()); +			if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() ) +			{ +				setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon")); +			}  			// output the styled Url  			appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly()); +			bool tooltip_required =  !match.getTooltip().empty(); + +			// set the tooltip for the Url label +			if (tooltip_required) +			{ +				setLastSegmentToolTip(match.getTooltip()); +			} -			// show query part of url with gray color only for LLUrlEntryHTTP and LLUrlEntryHTTPNoProtocol url entries +			// show query part of url with gray color only for LLUrlEntryHTTP url entries  			std::string label = match.getQuery();  			if (label.size())  			{  				link_params.color = LLColor4::grey;  				link_params.readonly_color = LLColor4::grey;  				appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly()); -			} -			 -			// set the tooltip for the Url label -			if (! match.getTooltip().empty()) -			{ -				segment_set_t::iterator it = getSegIterContaining(getLength()-1); -				if (it != mSegments.end()) + +				// set the tooltip for the query part of url +				if (tooltip_required)  				{ -					LLTextSegmentPtr segment = *it; -					segment->setToolTip(match.getTooltip()); +					setLastSegmentToolTip(match.getTooltip());  				}  			} @@ -2107,6 +2114,16 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para  	}  } +void LLTextBase::setLastSegmentToolTip(const std::string &tooltip) +{ +	segment_set_t::iterator it = getSegIterContaining(getLength()-1); +	if (it != mSegments.end()) +	{ +		LLTextSegmentPtr segment = *it; +		segment->setToolTip(tooltip); +	} +} +  static LLTrace::BlockTimerStatHandle FTM_APPEND_TEXT("Append Text");  void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params) @@ -3557,6 +3574,22 @@ S32	 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin  	return 0;  } +BOOL LLImageTextSegment::handleToolTip(S32 x, S32 y, MASK mask) +{ +	if (!mTooltip.empty()) +	{ +		LLToolTipMgr::instance().show(mTooltip); +		return TRUE; +	} + +	return FALSE; +} + +void LLImageTextSegment::setToolTip(const std::string& tooltip) +{ +	mTooltip = tooltip; +} +  F32	LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)  {  	if ( (start >= 0) && (end <= mEnd - mStart)) diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index dfc10923f3..87809aa8fb 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -241,9 +241,15 @@ public:  	S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;  	F32			draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect); +	/*virtual*/ BOOL	handleToolTip(S32 x, S32 y, MASK mask); +	/*virtual*/ void	setToolTip(const std::string& tooltip); +  private:  	class LLTextBase&	mEditor;  	LLStyleConstSP	mStyle; + +protected: +	std::string		mTooltip;  };  typedef LLPointer<LLTextSegment> LLTextSegmentPtr; @@ -392,6 +398,8 @@ public:  	const	std::string& 	getLabel()	{ return mLabel.getString(); }  	const	LLWString&		getWlabel() { return mLabel.getWString();} +	void					setLastSegmentToolTip(const std::string &tooltip); +  	/**  	 * If label is set, draws text label (which is LLLabelTextSegment)  	 * that is visible when no user text provided diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 6db0d88998..7f6cc22e90 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -203,10 +203,10 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const  {  	LLUriParser up(unescapeUrl(url)); -	std::string query; +	std::string label;  	up.extractParts(); -	up.glueSecond(query); - +	up.glueFirst(label); +	std::string query = url.substr(label.size());  	return query;  } @@ -229,7 +229,7 @@ static std::string getStringAfterToken(const std::string str, const std::string  LLUrlEntryHTTP::LLUrlEntryHTTP()  	: LLUrlEntryBase()  { -	mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*", +	mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?\\.[a-z](:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",  							boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_http.xml";  	mTooltip = LLTrans::getString("TooltipHttpUrl"); @@ -287,46 +287,6 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const  	return getUrlFromWikiLink(string);  } -// -// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com -// -LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol() -	: LLUrlEntryBase() -{ -	mPattern = boost::regex("(" -				"\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR -				"|" // or -				"(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net -				")", -				boost::regex::perl|boost::regex::icase); -	mMenuName = "menu_url_http.xml"; -	mTooltip = LLTrans::getString("TooltipHttpUrl"); -} - -std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb) -{ -	return urlToLabelWithGreyQuery(url); -} - -std::string LLUrlEntryHTTPNoProtocol::getQuery(const std::string &url) const -{ -	return urlToGreyQuery(url); -} - -std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const -{ -	if (string.find("://") == std::string::npos) -	{ -		return "http://" + escapeUrl(string); -	} -	return escapeUrl(string); -} - -std::string LLUrlEntryHTTPNoProtocol::getTooltip(const std::string &url) const -{ -	return unescapeUrl(url); -} -  LLUrlEntryInvalidSLURL::LLUrlEntryInvalidSLURL()  	: LLUrlEntryBase()  { @@ -489,7 +449,7 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const  //  LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()  {                               -	mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*", +	mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*",  		boost::regex::perl|boost::regex::icase);  	mIcon = "Hand"; @@ -527,7 +487,7 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const  //  LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()    { -	mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)", +	mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)",  		boost::regex::perl|boost::regex::icase);  	mIcon = "Hand"; @@ -1401,9 +1361,43 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)  	return mIcon;  } +// +// LLUrlEntryEmail Describes a generic mailto: Urls +// +LLUrlEntryEmail::LLUrlEntryEmail() +	: LLUrlEntryBase() +{ +	mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,6}", +							boost::regex::perl | boost::regex::icase); +	mMenuName = "menu_url_email.xml"; +	mTooltip = LLTrans::getString("TooltipEmail"); +} + +std::string LLUrlEntryEmail::getLabel(const std::string &url, const LLUrlLabelCallback &cb) +{ +	int pos = url.find("mailto:"); + +	if (pos == std::string::npos) +	{ +		return escapeUrl(url); +	} + +	std::string ret = escapeUrl(url.substr(pos + 7, url.length() - pos + 8)); +	return ret; +} + +std::string LLUrlEntryEmail::getUrl(const std::string &string) const +{ +	if (string.find("mailto:") == std::string::npos) +	{ +		return "mailto:" + escapeUrl(string); +	} +	return escapeUrl(string); +} +  LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile()  { -    mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*", +    mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/profile",          boost::regex::perl|boost::regex::icase);      mIcon = "Generic_Experience";  	mMenuName = "menu_url_experience.xml"; diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index dd1f257a3d..413c20a657 100755 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -157,19 +157,6 @@ public:  	/*virtual*/ std::string getUrl(const std::string &string) const;  }; -/// -/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com -/// -class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase -{ -public: -	LLUrlEntryHTTPNoProtocol(); -	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); -	/*virtual*/ std::string getQuery(const std::string &url) const; -	/*virtual*/ std::string getUrl(const std::string &string) const; -	/*virtual*/ std::string getTooltip(const std::string &url) const; -}; -  class LLUrlEntryInvalidSLURL : public LLUrlEntryBase  {  public: @@ -506,5 +493,16 @@ public:  	/*virtual*/ std::string getIcon(const std::string &url);  }; +/// +/// LLUrlEntryEmail Describes a generic mailto: Urls +/// +class LLUrlEntryEmail : public LLUrlEntryBase +{ +public: +	LLUrlEntryEmail(); +	/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); +	/*virtual*/ std::string getUrl(const std::string &string) const; +}; +  #endif diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 2085505947..69eefa736c 100755 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -76,9 +76,7 @@ LLUrlRegistry::LLUrlRegistry()  	registerUrl(new LLUrlEntrySL());  	mUrlEntrySLLabel = new LLUrlEntrySLLabel();  	registerUrl(mUrlEntrySLLabel); -	// most common pattern is a URL without any protocol, -	// e.g., "secondlife.com" -	registerUrl(new LLUrlEntryHTTPNoProtocol());	 +	registerUrl(new LLUrlEntryEmail());  }  LLUrlRegistry::~LLUrlRegistry() @@ -155,11 +153,9 @@ static bool stringHasUrl(const std::string &text)  	return (text.find("://") != std::string::npos ||  			text.find("www.") != std::string::npos ||  			text.find(".com") != std::string::npos || -			text.find(".net") != std::string::npos || -			text.find(".edu") != std::string::npos || -			text.find(".org") != std::string::npos ||  			text.find("<nolink>") != std::string::npos || -			text.find("<icon") != std::string::npos); +			text.find("<icon") != std::string::npos || +			text.find("@") != std::string::npos);  }  bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted) @@ -218,9 +214,40 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL  	// did we find a match? if so, return its details in the match object  	if (match_entry)  	{ + +		// Skip if link is an email with an empty username (starting with @). See MAINT-5371. +		if (match_start > 0 && text.substr(match_start - 1, 1) == "@") +			return false; +  		// fill in the LLUrlMatch object and return it  		std::string url = text.substr(match_start, match_end - match_start + 1); +		LLUrlEntryBase *stripped_entry = NULL; +		if(LLStringUtil::containsNonprintable(url)) +		{ +			LLStringUtil::stripNonprintable(url); + +			std::vector<LLUrlEntryBase *>::iterator iter; +			for (iter = mUrlEntry.begin(); iter != mUrlEntry.end(); ++iter) +			{ +				LLUrlEntryBase *url_entry = *iter; +				U32 start = 0, end = 0; +				if (matchRegex(url.c_str(), url_entry->getPattern(), start, end)) +				{ +					if (mLLUrlEntryInvalidSLURL == *iter) +					{ +						if(url_entry && url_entry->isSLURLvalid(url)) +						{ +							continue; +						} +					} +					stripped_entry = url_entry; +					break; +				} +			} +		} + +  		if (match_entry == mUrlEntryTrusted)  		{  			LLUriParser up(url); @@ -228,10 +255,12 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL  			url = up.normalizedUri();  		} +		std::string url_label = stripped_entry? stripped_entry->getLabel(url, cb) : match_entry->getLabel(url, cb); +		std::string url_query = stripped_entry? stripped_entry->getQuery(url) : match_entry->getQuery(url);  		match.setValues(match_start, match_end,  						match_entry->getUrl(url), -						match_entry->getLabel(url, cb), -						match_entry->getQuery(url), +						url_label, +						url_query,  						match_entry->getTooltip(url),  						match_entry->getIcon(url),  						match_entry->getStyle(), diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 15f2354552..96e94c0f80 100755 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -653,79 +653,6 @@ namespace tut  	void object::test<11>()  	{  		// -		// test LLUrlEntryHTTPNoProtocol - general URLs without a protocol -		// -		LLUrlEntryHTTPNoProtocol url; - -		testRegex("naked .com URL", url, -				  "see google.com", -				  "http://google.com"); - -		testRegex("naked .org URL", url, -				  "see en.wikipedia.org for details", -				  "http://en.wikipedia.org"); - -		testRegex("naked .net URL", url, -				  "example.net", -				  "http://example.net"); - -		testRegex("naked .edu URL (2 instances)", url, -				  "MIT web site is at web.mit.edu and also www.mit.edu", -				  "http://web.mit.edu"); - -		testRegex("don't match e-mail addresses", url, -				  "test@lindenlab.com", -				  ""); - -		testRegex(".com URL with path", url, -				  "see secondlife.com/status for grid status", -				  "http://secondlife.com/status"); - -		testRegex(".com URL with port", url, -				  "secondlife.com:80", -				  "http://secondlife.com:80"); - -		testRegex(".com URL with port and path", url, -				  "see secondlife.com:80/status", -				  "http://secondlife.com:80/status"); - -		testRegex("www.*.com URL with port and path", url, -				  "see www.secondlife.com:80/status", -				  "http://www.secondlife.com:80/status"); - -		testRegex("invalid .com URL [1]", url, -				  "..com", -				  ""); - -		testRegex("invalid .com URL [2]", url, -				  "you.come", -				  ""); - -		testRegex("invalid .com URL [3]", url, -				  "recommended", -				  ""); - -		testRegex("invalid .edu URL", url, -				  "hi there scheduled maitenance has begun", -				  ""); - -		testRegex("invalid .net URL", url, -				  "foo.netty", -				  ""); - -		testRegex("XML tags around URL [1]", url, -				  "<foo>secondlife.com</foo>", -				  "http://secondlife.com"); - -		testRegex("XML tags around URL [2]", url, -				  "<foo>secondlife.com/status?bar=1</foo>", -				  "http://secondlife.com/status?bar=1"); -	} - -	template<> template<> -	void object::test<12>() -	{ -		//  		// test LLUrlEntryNoLink - turn off hyperlinking  		//  		LLUrlEntryNoLink url; @@ -752,7 +679,7 @@ namespace tut  	}  	template<> template<> -	void object::test<13>() +	void object::test<12>()  	{  		//  		// test LLUrlEntryRegion - secondlife:///app/region/<location> URLs @@ -860,4 +787,101 @@ namespace tut  			"secondlife:///app/region/Product%20Engine",  			"Product Engine");  	} + +	template<> template<> +	void object::test<13>() +	{ +		// +		// test LLUrlEntryemail - general emails +		// +		LLUrlEntryEmail url; + +		// Regex tests. +		testRegex("match e-mail addresses", url, +				  "test@lindenlab.com", +				  "mailto:test@lindenlab.com"); + +		testRegex("match e-mail addresses with mailto: prefix", url, +				  "mailto:test@lindenlab.com", +				  "mailto:test@lindenlab.com"); + +		testRegex("match e-mail addresses with different domains", url, +				  "test@foo.org.us", +				  "mailto:test@foo.org.us"); + +		testRegex("match e-mail addresses with different domains", url, +				  "test@foo.bar", +				  "mailto:test@foo.bar"); + +		testRegex("don't match incorrect e-mail addresses", url, +				  "test @foo.com", +				  ""); + +		testRegex("don't match incorrect e-mail addresses", url, +				  "test@ foo.com", +				  ""); +	} + +	template<> template<> +	void object::test<14>() +	{ +		// +		// test LLUrlEntrySimpleSecondlifeURL - http://*.secondlife.com/* and http://*lindenlab.com/* urls +		// +		LLUrlEntrySecondlifeURL url; + +		testRegex("match urls with protocol", url, +				  "this url should match http://lindenlab.com/products/second-life", +				  "http://lindenlab.com/products/second-life"); + +		testRegex("match urls with protocol", url, +				  "search something https://marketplace.secondlife.com/products/search on marketplace and test the https", +				  "https://marketplace.secondlife.com/products/search"); + +		testRegex("match urls with port", url, +				  "let's specify some port http://secondlife.com:888/status", +				  "http://secondlife.com:888/status"); + +		testRegex("don't match urls w/o protocol", url, +				  "looks like an url something www.marketplace.secondlife.com/products but no https prefix", +				  ""); + +		testRegex("but with a protocol www is fine", url, +				  "so let's add a protocol http://www.marketplace.secondlife.com:8888/products", +				  "http://www.marketplace.secondlife.com:8888/products"); + +		testRegex("don't match urls w/o protocol", url, +				  "and even no www something secondlife.com/status", +				  ""); +	} + +	template<> template<> +	void object::test<15>() +	{ +		// +		// test LLUrlEntrySimpleSecondlifeURL - http://*.secondlife.com and http://*lindenlab.com urls +		// + +		LLUrlEntrySimpleSecondlifeURL url; + +		testRegex("match urls with a protocol", url, +				  "this url should match http://lindenlab.com", +				  "http://lindenlab.com"); + +		testRegex("match urls with a protocol", url, +				  "search something https://marketplace.secondlife.com on marketplace and test the https", +				  "https://marketplace.secondlife.com"); + +		testRegex("don't match urls w/o protocol", url, +				  "looks like an url something www.marketplace.secondlife.com but no https prefix", +				  ""); + +		testRegex("but with a protocol www is fine", url, +				  "so let's add a protocol http://www.marketplace.secondlife.com", +				  "http://www.marketplace.secondlife.com"); + +		testRegex("don't match urls w/o protocol", url, +				  "and even no www something lindenlab.com", +				  ""); +	}  } diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 5720660034..1b24250618 100755 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -49,8 +49,8 @@ LLSplashScreen *gSplashScreenp = NULL;  BOOL gDebugClicks = FALSE;  BOOL gDebugWindowProc = FALSE; -const S32 gURLProtocolWhitelistCount = 4; -const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:" }; +const S32 gURLProtocolWhitelistCount = 5; +const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" };  // CP: added a handler list - this is what's used to open the protocol and is based on registry entry  //	   only meaningful difference currently is that file: protocols are opened using http: diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index f02052ca6a..e6e8f27f53 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -53,6 +53,7 @@ bool runMainLoop();  void initMainLoop();  void cleanupViewer();  void handleUrl(const char* url); +void dispatchUrl(std::string url);  /* Defined in llwindowmacosx-objc.mm: */  int createNSApp(int argc, const char **argv); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 98d0ba53f6..5f378c64e8 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14211,7 +14211,7 @@      <key>MaxFPS</key>      <map>        <key>Comment</key> -      <string>Yield some time to the local host if we reach a threshold framerate.</string> +      <string>OBSOLETE UNUSED setting.</string>        <key>Persist</key>        <integer>1</integer>        <key>Type</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl index 6cd38d8ef5..3060307b21 100755 --- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -37,8 +37,7 @@ mat4 getObjectSkinnedTransform()  		 index = min(index, vec4(51.0));  		 index = max(index, vec4( 0.0)); -	float scale = 1.0/(w.x+w.y+w.z+w.w); -	w *= scale; +    w *= 1.0/(w.x+w.y+w.z+w.w);  	int i1 = int(index.x);  	int i2 = int(index.y); diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 595c11fae2..58fb01d200 100755 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -29,6 +29,7 @@ out vec4 frag_data[3];  #define frag_data gl_FragData  #endif +uniform float minimum_alpha;  uniform sampler2D diffuseMap;  uniform sampler2D bumpMap; @@ -47,16 +48,23 @@ vec2 encode_normal(vec3 n)  void main()   { -	vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb; -	vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; +	vec4 col = texture2D(diffuseMap, vary_texcoord0.xy); +	 +	if(col.a < minimum_alpha) +	{ +		discard; +    }		 +		col *= vertex_color; +		 +		vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; -	vec3 tnorm = vec3(dot(norm,vary_mat0), +		vec3 tnorm = vec3(dot(norm,vary_mat0),  			  dot(norm,vary_mat1),  			  dot(norm,vary_mat2)); -	frag_data[0] = vec4(col, 0.0); -	frag_data[1] = vertex_color.aaaa; // spec -	//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested -	vec3 nvn = normalize(tnorm); -	frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0); +		frag_data[0] = vec4(col.rgb, 0.0); +		frag_data[1] = vertex_color.aaaa; // spec +		//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested +		vec3 nvn = normalize(tnorm); +		frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0);	  } diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 95cdf90e99..b8677fd9e4 100755 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -165,7 +165,9 @@ lbl_configure_default_lang:  	StrCpy $LANGUAGE $0
  # For silent installs, no language prompt, use default
 -    IfSilent lbl_return
 +    IfSilent 0 +3
 +    StrCpy $SKIP_AUTORUN "true"
 +    Goto lbl_return
      StrCmp $SKIP_DIALOGS "true" lbl_return
  lbl_build_menu:
 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 092d868bb9..297bd9a05b 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2843,7 +2843,7 @@ BOOL LLAgent::isInGroup(const LLUUID& group_id, BOOL ignore_god_mode /* FALSE */  // This implementation should mirror LLAgentInfo::hasPowerInGroup  BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const  { -	if (isGodlike()) +	if (isGodlikeWithoutAdminMenuFakery())  		return true;  	// GP_NO_POWERS can also mean no power is enough to grant an ability. diff --git a/indra/newview/llagentdata.cpp b/indra/newview/llagentdata.cpp index 5f6a082d75..d2c644a06f 100755 --- a/indra/newview/llagentdata.cpp +++ b/indra/newview/llagentdata.cpp @@ -31,3 +31,4 @@  LLUUID gAgentID;  LLUUID gAgentSessionID; +std::string gAgentUsername; diff --git a/indra/newview/llagentdata.h b/indra/newview/llagentdata.h index 83d6a53d5e..efdd97f6c4 100755 --- a/indra/newview/llagentdata.h +++ b/indra/newview/llagentdata.h @@ -30,5 +30,6 @@  extern LLUUID gAgentID;  extern LLUUID gAgentSessionID; +extern std::string gAgentUsername;  #endif diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 35593dd4ff..142a3250c8 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1869,6 +1869,10 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)  		{  			++n_clothes;  		} +		else if (item->getType() == LLAssetType::AT_BODYPART) +		{ +			return isAgentAvatarValid(); +		}  		else  		{  			LL_WARNS() << "Unexpected wearable type" << LL_ENDL; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9b9b591cd1..fbf2a04bcc 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2784,10 +2784,12 @@ bool LLAppViewer::initConfiguration()  	//  	gWindowTitle = LLTrans::getString("APP_NAME");  #if LL_DEBUG -	gWindowTitle += std::string(" [DEBUG] ") + gArgs; -#else -	gWindowTitle += std::string(" ") + gArgs; +	gWindowTitle += std::string(" [DEBUG]")  #endif +	if (!gArgs.empty()) +	{ +		gWindowTitle += std::string(" ") + gArgs; +	}  	LLStringUtil::truncate(gWindowTitle, 255);  	//RN: if we received a URL, hand it off to the existing instance. @@ -4948,6 +4950,7 @@ void LLAppViewer::idle()  		gIdleCallbacks.callFunctions();  		gInventory.idleNotifyObservers(); +		LLAvatarTracker::instance().idleNotifyObservers();  	}  	// Metrics logging (LLViewerAssetStats, etc.) diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 56154a2de3..09227806fd 100755 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -62,9 +62,10 @@ namespace  	// They are not used immediately by the app.  	int gArgC;  	char** gArgV; -	LLAppViewerMacOSX* gViewerAppPtr; +	LLAppViewerMacOSX* gViewerAppPtr = NULL;      void (*gOldTerminateHandler)() = NULL; +    std::string gHandleSLURL;  }  static void exceptionTerminateHandler() @@ -107,7 +108,11 @@ bool initViewer()  	{  		LL_WARNS() << "Application init failed." << LL_ENDL;  	} - +    else if (!gHandleSLURL.empty()) +    { +        dispatchUrl(gHandleSLURL); +        gHandleSLURL = ""; +    }  	return ok;  } @@ -393,22 +398,31 @@ bool LLAppViewerMacOSX::getMasterSystemAudioMute()  void handleUrl(const char* url_utf8)  { -    if (url_utf8) +    if (url_utf8 && gViewerAppPtr)      { -        std::string url = url_utf8; -	    // Safari 3.2 silently mangles secondlife:///app/ URLs into -	    // secondlife:/app/ (only one leading slash). -	    // Fix them up to meet the URL specification. JC -	    const std::string prefix = "secondlife:/app/"; -	    std::string test_prefix = url.substr(0, prefix.length()); -	    LLStringUtil::toLower(test_prefix); -	    if (test_prefix == prefix) -	    { -		    url.replace(0, prefix.length(), "secondlife:///app/"); -	    } -		 -	    LLMediaCtrl* web = NULL; -    	const bool trusted_browser = false; -	    LLURLDispatcher::dispatch(url, "", web, trusted_browser); +        gHandleSLURL = ""; +        dispatchUrl(url_utf8);      } +    else if (url_utf8) +    { +        gHandleSLURL = url_utf8; +    } +} + +void dispatchUrl(std::string url) +{ +    // Safari 3.2 silently mangles secondlife:///app/ URLs into +    // secondlife:/app/ (only one leading slash). +    // Fix them up to meet the URL specification. JC +    const std::string prefix = "secondlife:/app/"; +    std::string test_prefix = url.substr(0, prefix.length()); +    LLStringUtil::toLower(test_prefix); +    if (test_prefix == prefix) +    { +        url.replace(0, prefix.length(), "secondlife:///app/"); +    } +     +    LLMediaCtrl* web = NULL; +    const bool trusted_browser = false; +    LLURLDispatcher::dispatch(url, "", web, trusted_browser);  } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index b6c5496c17..f79d1aa609 100755 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -97,7 +97,8 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  LLAvatarTracker::LLAvatarTracker() :  	mTrackingData(NULL),  	mTrackedAgentValid(false), -	mModifyMask(0x0)	 +	mModifyMask(0x0), +	mIsNotifyObservers(FALSE)  {  } @@ -272,7 +273,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)  					<< "]" << LL_ENDL;  		}  	} -	notifyObservers(); +	// do not notify observers here - list can be large so let it be done on idle.  	return new_buddy_count;  } @@ -473,8 +474,25 @@ void LLAvatarTracker::removeObserver(LLFriendObserver* observer)  		mObservers.end());  } +void LLAvatarTracker::idleNotifyObservers() +{ +	if (mModifyMask == LLFriendObserver::NONE && mChangedBuddyIDs.size() == 0) +	{ +		return; +	} +	notifyObservers(); +} +  void LLAvatarTracker::notifyObservers()  { +	if (mIsNotifyObservers) +	{ +		// Don't allow multiple calls. +		// new masks and ids will be processed later from idle. +		return; +	} +	mIsNotifyObservers = TRUE; +  	observer_list_t observers(mObservers);  	observer_list_t::iterator it = observers.begin();  	observer_list_t::iterator end = observers.end(); @@ -490,6 +508,7 @@ void LLAvatarTracker::notifyObservers()  	mModifyMask = LLFriendObserver::NONE;  	mChangedBuddyIDs.clear(); +	mIsNotifyObservers = FALSE;  }  void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer) @@ -531,7 +550,7 @@ void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)  // store flag for change  // and id of object change applies to  void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent) -{  +{  	mModifyMask |= mask;   	if (referent.notNull())  	{ diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h index 6e5fc01cd8..1f819a42fd 100755 --- a/indra/newview/llcallingcard.h +++ b/indra/newview/llcallingcard.h @@ -143,6 +143,7 @@ public:  	// observers left behind.  	void addObserver(LLFriendObserver* observer);  	void removeObserver(LLFriendObserver* observer); +	void idleNotifyObservers();  	void notifyObservers();  	// Observers interested in updates of a particular avatar. @@ -209,6 +210,8 @@ private:  	LLAvatarTracker(const LLAvatarTracker&);  	bool operator==(const LLAvatarTracker&); +	BOOL mIsNotifyObservers; +  public:  	// don't you dare create or delete this object  	LLAvatarTracker(); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index b81b95462e..dc0835eb1c 100755 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -376,6 +376,10 @@ public:  			|| mSourceType == CHAT_SOURCE_SYSTEM)  		{  			mFrom = LLTrans::getString("SECOND_LIFE"); +			if(!chat.mFromName.empty() && (mFrom != chat.mFromName)) +			{ +				mFrom += " (" + chat.mFromName + ")"; +			}  			user_name->setValue(mFrom);  			updateMinUserNameWidth();  		} diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index b38d472156..62f08144b9 100755 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -153,6 +153,7 @@ public:  	 * file name is conversation.log  	 */  	std::string getFileName(); +	LLConversation* findConversation(const LLIMModel::LLIMSession* session);  private: @@ -184,7 +185,7 @@ private:  	void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name);  	void updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages); -	LLConversation* findConversation(const LLIMModel::LLIMSession* session); +  	typedef std::vector<LLConversation> conversations_vec_t;  	std::vector<LLConversation>				mConversations; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 6e32ce60ec..328a638f2f 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -136,7 +136,24 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32  		items.push_back(std::string("im"));  		items.push_back(std::string("offer_teleport"));  		items.push_back(std::string("request_teleport")); -		items.push_back(std::string("voice_call")); + +		if (getType() != CONV_SESSION_1_ON_1) +		{ +			items.push_back(std::string("voice_call")); +		} +		else +		{ +			LLVoiceChannel* voice_channel = LLIMModel::getInstance() ? LLIMModel::getInstance()->getVoiceChannel(this->getUUID()) : NULL; +			if(voice_channel != LLVoiceChannel::getCurrentVoiceChannel()) +			{ +				items.push_back(std::string("voice_call")); +			} +			else +			{ +				items.push_back(std::string("disconnect_from_voice")); +			} +		} +  		items.push_back(std::string("chat_history"));  		items.push_back(std::string("separator_chat_history"));  		items.push_back(std::string("add_friend")); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index f828b56f7f..8bbc529244 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1553,7 +1553,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  		(drawable && drawable->isState(LLDrawable::REBUILD_ALL)))  	{  		if (drawable && drawable->isState(LLDrawable::REBUILD_ALL)) -		{ //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues +		{ +            //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues  			for (S32 i = 0; i < drawable->getNumFaces(); ++i)  			{  				LLFace* facep = drawable->getFace(i); @@ -1570,13 +1571,15 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  			buffer = face->getVertexBuffer();  		}  		else -		{ //just rebuild this face +		{ +			//just rebuild this face  			getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face);  		}  	}  	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) -	{ //perform software vertex skinning for this face +	{ +		//perform software vertex skinning for this face  		LLStrider<LLVector3> position;  		LLStrider<LLVector3> normal; @@ -1604,10 +1607,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  			{  				joint = avatar->getJoint("mPelvis");  			} -			if (!joint) -			{ -				LL_DEBUGS("Avatar") << "Failed to find " << skin->mJointNames[j] << LL_ENDL; -			}  			if (joint)  			{  				mat[j] = skin->mInvBindMatrix[j]; @@ -1632,12 +1631,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*  			{  				F32 w = weight[j][k]; -				idx[k] = llclamp((S32) floorf(w), 0, JOINT_COUNT-1); +				idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)JOINT_COUNT-1);  				wght[k] = w - floorf(w);  				scale += wght[k];  			} - +            // This is enforced  in unpackVolumeFaces() +            llassert(scale>0.f);  			wght *= 1.f/scale;  			for (U32 k = 0; k < 4; k++) @@ -1737,6 +1737,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)  				for (U32 i = 0; i < count; ++i)  				{  					LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); +                    if (!joint) +                    { +                        joint = avatar->getJoint("mPelvis"); +                    }  					if (joint)  					{  						mat[i] = skin->mInvBindMatrix[i]; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 33f7bc305c..7b9fd5c6c6 100755 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -864,6 +864,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)  	{  		LLDrawInfo& params = **i; +		gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff);  		LLDrawPoolBump::bindBumpMap(params, bump_channel);  		pushBatch(params, mask, TRUE);  	} diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp index b50c81eedc..7f2363aadc 100644 --- a/indra/newview/llexperienceassociationresponder.cpp +++ b/indra/newview/llexperienceassociationresponder.cpp @@ -29,6 +29,7 @@  #include "llviewerprecompiledheaders.h"  #include "llexperienceassociationresponder.h"  #include "llexperiencecache.h" +#include "llviewerobjectlist.h"  #include "llviewerregion.h"  #include "llagent.h" @@ -47,7 +48,13 @@ void ExperienceAssociationResponder::fetchAssociatedExperience( const LLUUID& ob  void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, callback_t callback)  { -    LLViewerRegion* region = gAgent.getRegion(); +    LLViewerObject* object = gObjectList.findObject(request["object-id"]); +    if (!object) +    { +        LL_WARNS() << "Failed to find object with ID " << request["object-id"] << " in fetchAssociatedExperience" << LL_ENDL; +        return; +    } +    LLViewerRegion* region = object->getRegion();      if (region)      {          std::string lookup_url=region->getCapability("GetMetadata");  diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index f2b369a9ad..8f3eaaa207 100755 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -380,9 +380,11 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)  	mShowDragMarker(FALSE),  	mLandingTab(NULL),  	mLastTab(NULL), -	mTabsHighlightEnabled(TRUE) -  , mUpdateDropDownItems(true) -,	mRestoreOverflowMenu(false) +	mTabsHighlightEnabled(TRUE), +	mUpdateDropDownItems(true), +	mRestoreOverflowMenu(false), +	mGetPrevItems(true), +	mItemsChangedTimer()  {  	// Register callback for menus with current registrar (will be parent panel's registrar)  	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected", @@ -659,6 +661,15 @@ void LLFavoritesBarCtrl::changed(U32 mask)  			LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());  		}  		updateButtons(); +		if (!mItemsChangedTimer.getStarted()) +		{ +			mItemsChangedTimer.start(); +		} +		else +		{ +			mItemsChangedTimer.reset(); +		} +  	}  } @@ -693,6 +704,21 @@ void LLFavoritesBarCtrl::draw()  		// Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again)  		mShowDragMarker = FALSE;  	} +	if (mItemsChangedTimer.getStarted()) +	{ +		if (mItemsChangedTimer.getElapsedTimeF32() > 1.f) +		{ +			LLFavoritesOrderStorage::instance().saveFavoritesRecord(); +			mItemsChangedTimer.stop(); +		} +	} + +	if(!mItemsChangedTimer.getStarted() && LLFavoritesOrderStorage::instance().mUpdateRequired) +	{ +		LLFavoritesOrderStorage::instance().mUpdateRequired = false; +		mItemsChangedTimer.start(); +	} +  }  const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() @@ -723,6 +749,12 @@ void LLFavoritesBarCtrl::updateButtons()  		return;  	} +	if(mGetPrevItems) +	{ +		LLFavoritesOrderStorage::instance().mPrevFavorites = mItems; +		mGetPrevItems = false; +	} +  	const LLButton::Params& button_params = getButtonParams();  	if(mItems.empty()) @@ -844,6 +876,7 @@ void LLFavoritesBarCtrl::updateButtons()  	{  		mUpdateDropDownItems = false;  	} +  }  LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset) @@ -912,9 +945,11 @@ BOOL LLFavoritesBarCtrl::postBuild()  BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &items)  { +  	if (mFavoriteFolderId.isNull())  		return FALSE; +  	LLInventoryModel::cat_array_t cats;  	LLIsType is_type(LLAssetType::AT_LANDMARK); @@ -1411,6 +1446,7 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const  const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml";  const S32 LLFavoritesOrderStorage::NO_INDEX = -1; +bool LLFavoritesOrderStorage::mSaveOnExit = false;  void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index)  { @@ -1447,6 +1483,7 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)          LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " already loaded" << LL_ENDL;  		onLandmarkLoaded(asset_id, lm);  	} +	return;  }  // static @@ -1482,13 +1519,16 @@ void LLFavoritesOrderStorage::destroyClass()  		LLFile::remove(old_filename);  	} -	if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) -	{ -		LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); -	} -	else +	std::string filename = getSavedOrderFileName(); +	file.open(filename.c_str()); +	if (file.is_open())  	{ -		LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser(); +		file.close(); +		LLFile::remove(filename); +		if(mSaveOnExit) +		{ +			LLFavoritesOrderStorage::instance().saveFavoritesRecord(true); +		}  	}  } @@ -1503,108 +1543,57 @@ std::string LLFavoritesOrderStorage::getSavedOrderFileName()  void LLFavoritesOrderStorage::load()  { -	// load per-resident sorting information  	std::string filename = getSavedOrderFileName(); -  	LLSD settings_llsd;  	llifstream file;  	file.open(filename.c_str());  	if (file.is_open())  	{  		LLSDSerialize::fromXML(settings_llsd, file); -        LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' " -                                 << (settings_llsd.isMap() ? "" : "un") << "successfully" -                                 << LL_ENDL; -        file.close(); -	} -    else -    { -        LL_WARNS("FavoritesBar") << "unable to open favorites order file at '" << filename << "'" << LL_ENDL; -    } - -	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); -		iter != settings_llsd.endMap(); ++iter) -	{ -		mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); +		LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' " +	                                 << (settings_llsd.isMap() ? "" : "un") << "successfully" +	                                 << LL_ENDL; +		file.close(); +		mSaveOnExit = true; + +		for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); +			iter != settings_llsd.endMap(); ++iter) +		{ +			mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); +		}  	} -} - -void LLFavoritesOrderStorage::saveFavoritesSLURLs() -{ -	// Do not change the file if we are not logged in yet. -	if (!LLLoginInstance::getInstance()->authSuccess()) +	else  	{ -		LL_WARNS("FavoritesBar") << "Cannot save favorites: not logged in" << LL_ENDL; -		return; +		filename = getStoredFavoritesFilename(); +		if (!filename.empty()) +		{ +			llifstream in_file; +			in_file.open(filename.c_str()); +			LLSD fav_llsd; +			LLSD user_llsd; +			if (in_file.is_open()) +			{ +				LLSDSerialize::fromXML(fav_llsd, in_file); +				LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' " +												<< (fav_llsd.isMap() ? "" : "un") << "successfully" +												<< LL_ENDL; +				in_file.close(); +				user_llsd = fav_llsd[gAgentUsername]; + +				S32 index = 0; +				for (LLSD::array_iterator iter = user_llsd.beginArray(); +						iter != user_llsd.endArray(); ++iter) +				{ +					mSortIndexes.insert(std::make_pair(iter->get("id").asUUID(), index)); +					index++; +				} +			} +			else +			{ +				LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; +			} +		}  	} - -	std::string filename = getStoredFavoritesFilename(); -    if (!filename.empty()) -    { -        llifstream in_file; -        in_file.open(filename.c_str()); -        LLSD fav_llsd; -        if (in_file.is_open()) -        { -            LLSDSerialize::fromXML(fav_llsd, in_file); -            LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' " -                                     << (fav_llsd.isMap() ? "" : "un") << "successfully" -                                     << LL_ENDL; -            in_file.close(); -        } -        else -        { -            LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; -        } - -        const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); -        LLInventoryModel::cat_array_t cats; -        LLInventoryModel::item_array_t items; -        gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); - -        LLSD user_llsd; -        for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) -        { -            LLSD value; -            value["name"] = (*it)->getName(); -            value["asset_id"] = (*it)->getAssetUUID(); - -            slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); -            if (slurl_iter != mSLURLs.end()) -            { -                LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" <<  slurl_iter->second << ", value=" << value << LL_ENDL; -                value["slurl"] = slurl_iter->second; -                user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value; -            } -            else -            { -                LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL; -            } -        } - -        LLAvatarName av_name; -        LLAvatarNameCache::get( gAgentID, &av_name ); -        // Note : use the "John Doe" and not the "john.doe" version of the name  -        // as we'll compare it with the stored credentials in the login panel. -        fav_llsd[av_name.getUserName()] = user_llsd; - -        llofstream file; -        file.open(filename.c_str()); -        if ( file.is_open() ) -        { -            LLSDSerialize::toPrettyXML(fav_llsd, file); -            LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName() -                                     << "' to '" << filename << "' " -                                     << LL_ENDL; -            file.close(); -        } -        else -        { -            LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName() -                                     << "' at '" << filename << "' " -                                     << LL_ENDL; -        } -    }  }  void LLFavoritesOrderStorage::removeFavoritesRecordOfUser() @@ -1626,8 +1615,30 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()              // See saveFavoritesSLURLs() here above for the reason why.              if (fav_llsd.has(av_name.getUserName()))              { -                LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL; -                fav_llsd.erase(av_name.getUserName()); +            	LLSD user_llsd = fav_llsd[av_name.getUserName()]; + +            	if (user_llsd.beginArray()->has("id")) +            	{ +            		for (LLSD::array_iterator iter = user_llsd.beginArray();iter != user_llsd.endArray(); ++iter) +            		{ +            			LLSD value; +            			value["id"]= iter->get("id").asUUID(); +            			iter->assign(value); +            		} +            		fav_llsd[av_name.getUserName()] = user_llsd; +            		llofstream file; +            		file.open(filename.c_str()); +            		if ( file.is_open() ) +            		{ +            				LLSDSerialize::toPrettyXML(fav_llsd, file); +            				file.close(); +            		} +            	} +            	else +            	{ +            		LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL; +            		fav_llsd.erase(av_name.getUserName()); +            	}              }              llofstream out_file; @@ -1648,20 +1659,20 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar  	if (landmark)      {          LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " loaded" << LL_ENDL; -	LLVector3d pos_global; -	if (!landmark->getGlobalPos(pos_global)) -	{ -		// If global position was unknown on first getGlobalPos() call -		// it should be set for the subsequent calls. -		landmark->getGlobalPos(pos_global); -	} +        LLVector3d pos_global; +        if (!landmark->getGlobalPos(pos_global)) +        { +        	// If global position was unknown on first getGlobalPos() call +        	// it should be set for the subsequent calls. +        	landmark->getGlobalPos(pos_global); +        } -	if (!pos_global.isExactlyZero()) -	{ -        LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL; -		LLLandmarkActions::getSLURLfromPosGlobal(pos_global, +        if (!pos_global.isExactlyZero()) +        { +        	LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL; +        	LLLandmarkActions::getSLURLfromPosGlobal(pos_global,  			boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); -	} +        }      }  } @@ -1671,41 +1682,6 @@ void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::st  	mSLURLs[asset_id] = slurl;  } -void LLFavoritesOrderStorage::save() -{ -	if (mIsDirty) -    { -        // something changed, so save it -        std::string filename = LLFavoritesOrderStorage::getInstance()->getSavedOrderFileName(); -        if (!filename.empty()) -        { -            LLSD settings_llsd; - -            for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter) -            { -                settings_llsd[iter->first.asString()] = iter->second; -            } - -            llofstream file; -            file.open(filename.c_str()); -            if ( file.is_open() ) -            { -                LLSDSerialize::toPrettyXML(settings_llsd, file); -                LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL; -            } -            else -            { -                LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL; -            } -        } -        else -        { -            LL_DEBUGS("FavoritesBar") << "no user directory available to store favorites order file" << LL_ENDL; -        } -    } -} - -  void LLFavoritesOrderStorage::cleanup()  {  	// nothing to clean @@ -1720,7 +1696,7 @@ void LLFavoritesOrderStorage::cleanup()  	sort_index_map_t  aTempMap;  	//copy unremoved values from mSortIndexes to aTempMap -	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  +	std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),  		inserter(aTempMap, aTempMap.begin()),  		is_not_in_fav); @@ -1752,8 +1728,8 @@ void LLFavoritesOrderStorage::saveOrder()  void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items )  { -	int sortField = 0; +	int sortField = 0;  	// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field  	for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)  	{ @@ -1793,6 +1769,110 @@ void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_it  	saveItemsOrder(items);  } +BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed) +{ + +	LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); +	if (favorite_folder.isNull()) +			return FALSE; + +	LLInventoryModel::item_array_t items; +	LLInventoryModel::cat_array_t cats; + +	LLIsType is_type(LLAssetType::AT_LANDMARK); +	gInventory.collectDescendentsIf(favorite_folder, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + +	std::sort(items.begin(), items.end(), LLFavoritesSort()); + +	if((items != mPrevFavorites) || pref_changed) +	{ +		std::string filename = getStoredFavoritesFilename(); +		if (!filename.empty()) +		{ +			llifstream in_file; +			in_file.open(filename.c_str()); +			LLSD fav_llsd; +			if (in_file.is_open()) +			{ +				LLSDSerialize::fromXML(fav_llsd, in_file); +				in_file.close(); +			} +			else +			{ +				LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL; +			} + +			LLSD user_llsd; +			S32 fav_iter = 0; +			for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) +			{ +				LLSD value; +				if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) +				{ +					value["name"] = (*it)->getName(); +					value["asset_id"] = (*it)->getAssetUUID(); +					value["id"] = (*it)->getUUID(); +					slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); +					if (slurl_iter != mSLURLs.end()) +					{ +						value["slurl"] = slurl_iter->second; +						user_llsd[fav_iter] = value; +					} +					else +					{ +						getSLURL((*it)->getAssetUUID()); +						mUpdateRequired = true; +						return FALSE; +					} +				} +				else +				{ +					value["id"] = (*it)->getUUID(); +					user_llsd[fav_iter] = value; +				} + +				fav_iter ++; +			} + +			LLAvatarName av_name; +			LLAvatarNameCache::get( gAgentID, &av_name ); +			// Note : use the "John Doe" and not the "john.doe" version of the name +			// as we'll compare it with the stored credentials in the login panel. +			fav_llsd[av_name.getUserName()] = user_llsd; +			llofstream file; +			file.open(filename.c_str()); +			if ( file.is_open() ) +			{ +				LLSDSerialize::toPrettyXML(fav_llsd, file); +				file.close(); +				mSaveOnExit = false; +			} +			else +			{ +				LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName() +												<< "' at '" << filename << "' " << LL_ENDL; +			} +		} + +		mPrevFavorites = items; +	} + +	return TRUE; + +} + +void LLFavoritesOrderStorage::showFavoritesOnLoginChanged(BOOL show) +{ +	if (show) +	{ +		saveFavoritesRecord(true); +	} +	else +	{ +		removeFavoritesRecordOfUser(); +	} +} +  void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)  {  	if (mTargetLandmarkId.isNull()) return; diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index a370724947..66fc8b2ae7 100755 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -105,8 +105,10 @@ protected:  	bool mUpdateDropDownItems;  	bool mRestoreOverflowMenu; -	LLUUID mSelectedItemID; +	bool mGetPrevItems; +	LLUUID mSelectedItemID; +	LLFrameTimer mItemsChangedTimer;  	LLUIImage* mImageDragIndication;  private: @@ -204,12 +206,23 @@ public:  	 * @see cleanup()  	 */  	static void destroyClass(); +	static std::string getStoredFavoritesFilename(); +	static std::string getSavedOrderFileName(); + +	BOOL saveFavoritesRecord(bool pref_changed = false); +	void showFavoritesOnLoginChanged(BOOL show); + +	LLInventoryModel::item_array_t mPrevFavorites; +  	const static S32 NO_INDEX; +	static bool mSaveOnExit; +	bool mUpdateRequired; +  private:  	friend class LLSingleton<LLFavoritesOrderStorage>; -	LLFavoritesOrderStorage() : mIsDirty(false) { load(); } -	~LLFavoritesOrderStorage() { save(); } +	LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); } +	~LLFavoritesOrderStorage() {}  	/**  	 * Removes sort indexes for items which are not in Favorites bar for now. @@ -217,13 +230,8 @@ private:  	void cleanup();  	const static std::string SORTING_DATA_FILE_NAME; -    std::string getSavedOrderFileName(); -    static std::string getStoredFavoritesFilename(); -     -	void load(); -	void save(); -	void saveFavoritesSLURLs(); +	void load();  	// Remove record of current user's favorites from file on disk.  	void removeFavoritesRecordOfUser(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index e71daa6067..c5d637d1fc 100755 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -34,10 +34,12 @@  // Viewer includes  #include "llagent.h"  #include "llagentui.h" -#include "llappviewer.h"  +#include "llappviewer.h" +#include "llnotificationsutil.h"  #include "llslurl.h"  #include "llvoiceclient.h"  #include "lluictrlfactory.h" +#include "llupdaterservice.h"  #include "llviewertexteditor.h"  #include "llviewercontrol.h"  #include "llviewerstats.h" @@ -99,9 +101,23 @@ public:  	/// separated so that we can programmatically access the same info.  	static LLSD getInfo();  	void onClickCopyToClipboard(); +	void onClickUpdateCheck(); + +	// checks state of updater service and starts a check outside of schedule. +	// subscribes callback for closest state update +	static void setUpdateListener();  private:  	void setSupportText(const std::string& server_release_notes_url); + +	// notifications for user requested checks +	static void showCheckUpdateNotification(S32 state); + +	// callback method for manual checks +	static bool callbackCheckUpdate(LLSD const & event); + +	// listener name for update checks +	static const std::string sCheckUpdateListenerName;  }; @@ -132,6 +148,9 @@ BOOL LLFloaterAbout::postBuild()  	getChild<LLUICtrl>("copy_btn")->setCommitCallback(  		boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this)); +	getChild<LLUICtrl>("update_btn")->setCommitCallback( +		boost::bind(&LLFloaterAbout::onClickUpdateCheck, this)); +  	static const LLUIColor about_color = LLUIColorTable::instance().getColor("TextFgReadOnlyColor");  	if (gAgent.getRegion()) @@ -235,6 +254,11 @@ void LLFloaterAbout::onClickCopyToClipboard()  	support_widget->deselect();  } +void LLFloaterAbout::onClickUpdateCheck() +{ +	setUpdateListener(); +} +  void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)  {  #if LL_WINDOWS @@ -256,6 +280,68 @@ void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)  }  ///---------------------------------------------------------------------------- +/// Floater About Update-check related functions +///---------------------------------------------------------------------------- + +const std::string LLFloaterAbout::sCheckUpdateListenerName = "LLUpdateNotificationListener"; + +void LLFloaterAbout::showCheckUpdateNotification(S32 state) +{ +	switch (state) +	{ +	case LLUpdaterService::UP_TO_DATE: +		LLNotificationsUtil::add("UpdateViewerUpToDate"); +		break; +	case LLUpdaterService::DOWNLOADING: +	case LLUpdaterService::INSTALLING: +		LLNotificationsUtil::add("UpdateDownloadInProgress"); +		break; +	case LLUpdaterService::TERMINAL: +		// download complete, user triggered check after download pop-up appeared +		LLNotificationsUtil::add("UpdateDownloadComplete"); +		break; +	default: +		LLNotificationsUtil::add("UpdateCheckError"); +		break; +	} +} + +bool LLFloaterAbout::callbackCheckUpdate(LLSD const & event) +{ +	if (!event.has("payload")) +	{ +		return false; +	} + +	LLSD payload = event["payload"]; +	if (payload.has("type") && payload["type"].asInteger() == LLUpdaterService::STATE_CHANGE) +	{ +		LLEventPumps::instance().obtain("mainlooprepeater").stopListening(sCheckUpdateListenerName); +		showCheckUpdateNotification(payload["state"].asInteger()); +	} +	return false; +} + +void LLFloaterAbout::setUpdateListener() +{ +	LLUpdaterService update_service; +	S32 service_state = update_service.getState(); +	// Note: Do not set state listener before forceCheck() since it set's new state +	if (update_service.forceCheck() || service_state == LLUpdaterService::CHECKING_FOR_UPDATE) +	{ +		LLEventPump& mainloop(LLEventPumps::instance().obtain("mainlooprepeater")); +		if (mainloop.getListener(sCheckUpdateListenerName) == LLBoundListener()) // dummy listener +		{ +			mainloop.listen(sCheckUpdateListenerName, boost::bind(&callbackCheckUpdate, _1)); +		} +	} +	else +	{ +		showCheckUpdateNotification(service_state); +	} +} + +///----------------------------------------------------------------------------  /// LLFloaterAboutUtil  ///----------------------------------------------------------------------------  void LLFloaterAboutUtil::registerFloater() @@ -265,6 +351,11 @@ void LLFloaterAboutUtil::registerFloater()  } +void LLFloaterAboutUtil::checkUpdatesAndNotify() +{ +	LLFloaterAbout::setUpdateListener(); +} +  ///----------------------------------------------------------------------------  /// Class LLServerReleaseNotesURLFetcher implementation  ///---------------------------------------------------------------------------- diff --git a/indra/newview/llfloaterabout.h b/indra/newview/llfloaterabout.h index 8fc1aa4f29..be34b631cc 100755 --- a/indra/newview/llfloaterabout.h +++ b/indra/newview/llfloaterabout.h @@ -30,6 +30,9 @@  namespace LLFloaterAboutUtil  {  	void registerFloater(); + +	// Support for user initialized update/state checks +	void checkUpdatesAndNotify();  }  #endif // LL_LLFLOATERABOUT_H diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 34904cf7ed..957c91b226 100755 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -32,6 +32,7 @@  #include "llavataractions.h"  #include "llfloaterbump.h" +#include "llfloaterreg.h"  #include "llfloaterreporter.h"  #include "llmutelist.h"  #include "llpanelblockedlist.h" @@ -87,11 +88,11 @@ BOOL LLFloaterBump::postBuild()  // virtual  void LLFloaterBump::onOpen(const LLSD& key)  { -	mNames.clear(); -	mList->deleteAllItems(); -  	if (gMeanCollisionList.empty())  	{ +		mNames.clear(); +		mList->deleteAllItems(); +  		std::string none_detected = getString("none_detected");  		LLSD row;  		row["columns"][0]["value"] = none_detected; @@ -100,12 +101,20 @@ void LLFloaterBump::onOpen(const LLSD& key)  	}  	else  	{ -		for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); -			 iter != gMeanCollisionList.end(); ++iter) -		{ -			LLMeanCollisionData *mcd = *iter; -			add(mList, mcd); -		} +		populateCollisionList(); +	} +} + +void LLFloaterBump::populateCollisionList() +{ +	mNames.clear(); +	mList->deleteAllItems(); + +	for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); +				 iter != gMeanCollisionList.end(); ++iter) +	{ +		LLMeanCollisionData *mcd = *iter; +		add(mList, mcd);  	}  } @@ -247,3 +256,8 @@ void LLFloaterBump::inviteToGroup()  {  	LLAvatarActions::inviteToGroup(mItemUUID);  } + +LLFloaterBump* LLFloaterBump::getInstance() +{ +	return LLFloaterReg::getTypedInstance<LLFloaterBump>("bumps"); +} diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index 11b7db9fee..ce52c75255 100755 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -46,6 +46,10 @@ public:  	/*virtual*/	BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key); +	static LLFloaterBump* getInstance(); + +	void populateCollisionList(); +  	void startIM();  	void startCall();  	void reportAbuse(); diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index 3a2047cfef..da85d378b2 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -64,9 +64,9 @@ const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazo  const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";  const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare"; -const S32 MAX_QUALITY = 100;        // Max quality value for jpeg images -const S32 MIN_QUALITY = 0;          // Min quality value for jpeg images -const S32 TARGET_DATA_SIZE = 95000; // Size of the image (compressed) we're trying to send to Facebook +const S32 MAX_QUALITY = 100;         // Max quality value for jpeg images +const S32 MIN_QUALITY = 0;           // Min quality value for jpeg images +const S32 TARGET_DATA_SIZE = 950000; // Size of the image (compressed) we're trying to send to Facebook  std::string get_map_url()  { diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ab57e8c170..f1a6ef78a6 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -261,6 +261,8 @@ BOOL LLFloaterIMContainer::postBuild()  	mInitialized = true; +	mIsFirstOpen = true; +  	// Add callbacks:  	// We'll take care of view updates on idle  	gIdleCallbacks.addFunction(idle, this); @@ -636,14 +638,16 @@ void LLFloaterIMContainer::setVisible(BOOL visible)  	{  		// Make sure we have the Nearby Chat present when showing the conversation container  		nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); -		if (nearby_chat == NULL) +		if ((nearby_chat == NULL) || mIsFirstOpen)  		{ +			 mIsFirstOpen = false;  			// If not found, force the creation of the nearby chat conversation panel  			// *TODO: find a way to move this to XML as a default panel or something like that  			LLSD name("nearby_chat");  			LLFloaterReg::toggleInstanceOrBringToFront(name);              selectConversationPair(LLUUID(NULL), false, false);  		} +  		flashConversationItemWidget(mSelectedSession,false);  		LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); @@ -1216,7 +1220,22 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,          {  			if (selectedIDS.size() > 0)  			{ -				LLAvatarActions::viewChatHistory(selectedIDS.front()); +				if(conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) +				{ +					LLFloaterReg::showInstance("preview_conversation", conversationItem->getUUID(), true); +				} +				else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC) +				{ +					LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(conversationItem->getUUID())); +					if(conv) +					{ +						LLFloaterReg::showInstance("preview_conversation", conv->getSessionID(), true); +					} +				} +				else +				{ +					LLAvatarActions::viewChatHistory(selectedIDS.front()); +				}  			}          }          else @@ -1316,6 +1335,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)  			{  				return LLLogChat::isNearbyTranscriptExist();  			} +			else if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_AD_HOC) +			{ +				const LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(uuids.front())); +				if(conv) +				{ +					return LLLogChat::isAdHocTranscriptExist(conv->getHistoryFileName()); +				} +				return false; +			}  			else  			{  				bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP); @@ -1881,22 +1909,28 @@ bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid)  		return false;  	} -	if (!gdatap->mMembers.size()) +	if (gdatap->mPendingBanRequest)  	{  		return false;  	} -	LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid)); -	if (mi == gdatap->mMembers.end()) +	if (gdatap->isRoleMemberDataComplete())  	{ -		return false; -	} +		if (!gdatap->mMembers.size()) +		{ +			return false; +		} -	LLGroupMemberData* member_data = (*mi).second; -	// Is the member an owner? -	if ( member_data && member_data->isInRole(gdatap->mOwnerRole) ) -	{ -		return false; +		LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid)); +		if (mi != gdatap->mMembers.end()) +		{ +			LLGroupMemberData* member_data = (*mi).second; +			// Is the member an owner? +			if (member_data && member_data->isInRole(gdatap->mOwnerRole)) +			{ +				return false; +			} +		}  	}  	if(	gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) && @@ -1924,20 +1958,8 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)  		LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;  		return;  	} -	std::vector<LLUUID> ids; -	ids.push_back(participant_uuid); - -	LLGroupBanData ban_data; -	gdatap->createBanEntry(participant_uuid, ban_data); -	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids); -	LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids); -	LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid); -	LLSD args; -	std::string name; -	gCacheName->getFullName(participant_uuid, name); -	args["AVATAR_NAME"] = name; -	args["GROUP_NAME"] = gdatap->mName; -	LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args)); + +	gdatap->banMemberById(participant_uuid);  } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index f21c0b9947..60cef83d9a 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -193,6 +193,8 @@ private:  	bool mInitialized;  	bool mIsFirstLaunch; +	bool mIsFirstOpen; +  	LLUUID mSelectedSession;  	std::string mGeneralTitle; diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index b7fff6cae3..ee3d633dd0 100755 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -326,7 +326,21 @@ void LLFloaterJoystick::onClickOK(void *joy_panel)  	}  } +void LLFloaterJoystick::onClickCloseBtn(bool app_quitting) +{ +	cancel(); +	closeFloater(app_quitting); +} +  void LLFloaterJoystick::setSNDefaults()  {  	LLViewerJoystick::getInstance()->setSNDefaults();  } + +void LLFloaterJoystick::onClose(bool app_quitting) +{ +	if (app_quitting) +	{ +		cancel(); +	} +} diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index 9c3752540d..a1b5951389 100755 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -45,6 +45,11 @@ public:  	virtual void draw();  	static  void setSNDefaults(); +protected: + +	void onClose(bool app_quitting); +	void onClickCloseBtn(bool app_quitting); +  private:  	LLFloaterJoystick(const LLSD& data); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index ce32aeda94..f9fd5069af 100755 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2439,6 +2439,8 @@ void LLPanelLandAccess::refresh()  			mListAccess->clearSortOrder();  			mListAccess->deleteAllItems();  			S32 count = parcel->mAccessList.size(); +			getChild<LLUICtrl>("AllowedText")->setTextArg("[COUNT]", llformat("%d",count)); +  			getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));  			getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); @@ -2484,6 +2486,7 @@ void LLPanelLandAccess::refresh()  			mListBanned->clearSortOrder();  			mListBanned->deleteAllItems();  			S32 count = parcel->mBanList.size(); +			getChild<LLUICtrl>("BanCheck")->setTextArg("[COUNT]", llformat("%d",count));  			getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));  			getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST)); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 918dc98a3a..41005144a7 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -3683,7 +3683,7 @@ BOOL LLModelPreview::render()  			}  			else  			{ -				LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; +				LL_INFOS(" ") << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;  				regen = TRUE;  			}  		} @@ -3691,6 +3691,10 @@ BOOL LLModelPreview::render()  		if (regen)  		{  			genBuffers(mPreviewLOD, skin_weight); +			{ +				LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; +				regen = TRUE; +			}  		}  		if (!skin_weight) diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 042cf47070..04a818c2c0 100755 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -166,15 +166,59 @@ void LLFloaterPermsDefault::onCommitCopy(const LLSD& user_data)  	xfer->setEnabled(copyable);  } -class LLFloaterPermsResponder : public LLHTTPClient::Responder +const int MAX_HTTP_RETRIES = 5; +LLFloaterPermsRequester* LLFloaterPermsRequester::sPermsRequester = NULL; + +LLFloaterPermsRequester::LLFloaterPermsRequester(const std::string url, const LLSD report,  +	int maxRetries) +	: mRetriesCount(0), mMaxRetries(maxRetries), mUrl(url), mReport(report) +{} + +//static  +void LLFloaterPermsRequester::init(const std::string url, const LLSD report, int maxRetries) +{ +	if (sPermsRequester == NULL) { +		sPermsRequester = new LLFloaterPermsRequester(url, report, maxRetries); +	} +} +     +//static +void LLFloaterPermsRequester::finalize() +{ +	if (sPermsRequester != NULL) +	{ +		delete sPermsRequester; +		sPermsRequester = NULL; +	} +} + +//static +LLFloaterPermsRequester* LLFloaterPermsRequester::instance() +{ +	return sPermsRequester; +} + +void LLFloaterPermsRequester::start()  { -public: -	LLFloaterPermsResponder(): LLHTTPClient::Responder() {} -private: -	static	std::string sPreviousReason; +	++mRetriesCount; +	LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder()); +} +     +bool LLFloaterPermsRequester::retry() +{ +	if (++mRetriesCount < mMaxRetries) +	{ +		LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder()); +		return true; +	} +	return false; +} -	void httpFailure() +void LLFloaterPermsResponder::httpFailure() +{ +	if (!LLFloaterPermsRequester::instance() || !LLFloaterPermsRequester::instance()->retry())  	{ +		LLFloaterPermsRequester::finalize();  		const std::string& reason = getReason();  		// Do not display the same error more than once in a row  		if (reason != sPreviousReason) @@ -185,27 +229,27 @@ private:  			LLNotificationsUtil::add("DefaultObjectPermissions", args);  		}  	} +} -	void httpSuccess() -	{ -		//const LLSD& content = getContent(); -		//dump_sequential_xml("perms_responder_result.xml", content); - -		// Since we have had a successful POST call be sure to display the next error message -		// even if it is the same as a previous one. -		sPreviousReason = ""; -		LLFloaterPermsDefault::setCapSent(true); -		LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL; -	} -}; +void LLFloaterPermsResponder::httpSuccess() +{ +	//const LLSD& content = getContent(); +	//dump_sequential_xml("perms_responder_result.xml", content); -	std::string	LLFloaterPermsResponder::sPreviousReason; +	// Since we have had a successful POST call be sure to display the next error message +	// even if it is the same as a previous one. +	sPreviousReason = ""; +	LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL; +} + +std::string	LLFloaterPermsResponder::sPreviousReason;  void LLFloaterPermsDefault::sendInitialPerms()  {  	if(!mCapSent)  	{  		updateCap(); +		setCapSent(true);  	}  } @@ -230,8 +274,8 @@ void LLFloaterPermsDefault::updateCap()              LLSDSerialize::toPrettyXML(report, sent_perms_log);              LL_CONT << sent_perms_log.str() << LL_ENDL;          } -     -		LLHTTPClient::post(object_url, report, new LLFloaterPermsResponder()); +        LLFloaterPermsRequester::init(object_url, report, MAX_HTTP_RETRIES); +        LLFloaterPermsRequester::instance()->start();  	}      else      { diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h index 2bb0a19dc1..d3b52c1fe5 100755 --- a/indra/newview/llfloaterperms.h +++ b/indra/newview/llfloaterperms.h @@ -29,6 +29,7 @@  #define LL_LLFLOATERPERMPREFS_H  #include "llfloater.h" +#include "llhttpclient.h"  class LLFloaterPerms : public LLFloater  { @@ -89,4 +90,36 @@ private:  	bool mNextOwnerTransfer[CAT_LAST];  }; +class LLFloaterPermsRequester +{ +public: +	LLFloaterPermsRequester(const std::string url, const LLSD report, int maxRetries); + +	static void init(const std::string url, const LLSD report, int maxRetries); +	static void finalize(); +	static LLFloaterPermsRequester* instance(); + +	void start(); +	bool retry(); + +private: +	int mRetriesCount; +	int mMaxRetries; +	const std::string mUrl; +	const LLSD mReport; +public: +	static LLFloaterPermsRequester* sPermsRequester; +}; + +class LLFloaterPermsResponder : public LLHTTPClient::Responder +{ +public: +	LLFloaterPermsResponder() : LLHTTPClient::Responder() {} +private: +	static	std::string sPreviousReason; + +	void httpFailure(); +	void httpSuccess(); +}; +  #endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ee4396758e..dac610eda1 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -49,6 +49,7 @@  //#include "llfirstuse.h"  #include "llfloaterreg.h"  #include "llfloaterabout.h" +#include "llfavoritesbar.h"  #include "llfloaterhardwaresettings.h"  #include "llfloatersidepanelcontainer.h"  #include "llfloaterimsession.h" @@ -1919,7 +1920,7 @@ BOOL LLPanelPreference::postBuild()  	}  	if (hasChild("favorites_on_login_check", TRUE))  	{ -		getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); +		getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&handleFavoritesOnLoginChanged, _1, _2));  		bool show_favorites_at_login = LLPanelLogin::getShowFavorites();  		getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setValue(show_favorites_at_login);  	} @@ -2004,11 +2005,15 @@ void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& v  	}  } -void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value) +void LLPanelPreference::handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value)  { -	if (checkbox && checkbox->getValue()) +	if (checkbox)  	{ -		LLNotificationsUtil::add("FavoritesOnLogin"); +		LLFavoritesOrderStorage::instance().showFavoritesOnLoginChanged(checkbox->getValue().asBoolean()); +		if(checkbox->getValue()) +		{ +			LLNotificationsUtil::add("FavoritesOnLogin"); +		}  	}  } @@ -2235,6 +2240,11 @@ void LLFloaterPreferenceProxy::onOpen(const LLSD& key)  void LLFloaterPreferenceProxy::onClose(bool app_quitting)  { +	if(app_quitting) +	{ +		cancel(); +	} +  	if (mSocksSettingsDirty)  	{ @@ -2334,6 +2344,11 @@ void LLFloaterPreferenceProxy::onBtnCancel()  	cancel();  } +void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting) +{ +	cancel(); +} +  void LLFloaterPreferenceProxy::cancel()  { @@ -2344,7 +2359,7 @@ void LLFloaterPreferenceProxy::cancel()  		LLSD ctrl_value = iter->second;  		control->set(ctrl_value);  	} - +	mSocksSettingsDirty = false;  	closeFloater();  } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 7bf6ae7d79..04e5e37731 100755 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -229,7 +229,7 @@ private:  	//for "Only friends and groups can call or IM me"  	static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&);  	//for "Show my Favorite Landmarks at Login" -	static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value); +	static void handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value);  	typedef std::map<std::string, LLColor4> string_color_map_t;  	string_color_map_t mSavedColors; @@ -269,6 +269,7 @@ protected:  	void saveSettings();  	void onBtnOk();  	void onBtnCancel(); +	void onClickCloseBtn(bool app_quitting = false);  	void onChangeSocksSettings(); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 2f4d2a93b2..99a5cf8002 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -35,6 +35,7 @@  #include "llassetstorage.h"  #include "llavatarnamecache.h"  #include "llcachename.h" +#include "llcheckboxctrl.h"  #include "llfontgl.h"  #include "llimagej2c.h"  #include "llinventory.h" @@ -137,6 +138,7 @@ BOOL LLFloaterReporter::postBuild()  	mOwnerName = LLStringUtil::null;  	getChild<LLUICtrl>("summary_edit")->setFocus(TRUE); +	getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE);  	mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString(); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 16fa4684ab..afec981d56 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -663,14 +663,20 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)  {  	LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;  	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; +	LLSnapshotLivePreview* previewp = getPreviewView(view); -	if (!view || !check_box) +	if (!view || !check_box || !previewp)  	{  		return;  	}  	gSavedSettings.setBOOL("UseFreezeFrame", check_box->get()); +	if (check_box->get()) +	{ +		previewp->prepareFreezeFrame(); +	} +  	updateLayout(view);  } diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index c1c21c593e..ae33acb842 100755 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -141,6 +141,12 @@ BOOL LLFloaterTOS::postBuild()  		// Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer.  		// Store the URL separately and navigate here instead.  		web_browser->navigateTo( getString( "loading_url" ) ); +		LLPluginClassMedia* media_plugin = web_browser->getMediaPlugin(); +		if (media_plugin) +		{ +			// All links from tos_html should be opened in external browser +			media_plugin->setOverrideClickTarget("_external"); +		}  	}  	return TRUE; diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 1b1c24b19a..ece3e10faa 100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -284,12 +284,12 @@ BOOL LLFloaterWorldMap::postBuild()  	LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");  	avatar_combo->selectFirstItem();  	avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) ); -	avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); +	avatar_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );  	mListFriendCombo = dynamic_cast<LLCtrlListInterface *>(avatar_combo);  	LLSearchEditor *location_editor = getChild<LLSearchEditor>("location");  	location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1)); -	location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this)); +	location_editor->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));  	getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));  	mListSearchResults = childGetListInterface("search_results"); @@ -297,7 +297,7 @@ BOOL LLFloaterWorldMap::postBuild()  	LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");  	landmark_combo->selectFirstItem();  	landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) ); -	landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); +	landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );  	mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo);  	mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f); diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp index 44eda4d6c0..e9f80b795a 100755 --- a/indra/newview/llfolderviewmodelinventory.cpp +++ b/indra/newview/llfolderviewmodelinventory.cpp @@ -109,6 +109,29 @@ bool LLFolderViewModelInventory::contentsReady()  	return !LLInventoryModelBackgroundFetch::instance().folderFetchActive();  } +bool LLFolderViewModelInventory::isFolderComplete(LLFolderViewFolder* folder) +{ +	LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); +	LLUUID cat_id = modelp->getUUID(); +	if (cat_id.isNull()) +	{ +		return false; +	} +	LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); +	if (cat) +	{ +		// don't need to check version - descendents_server == -1 if we have no data +		S32 descendents_server = cat->getDescendentCount(); +		S32 descendents_actual = cat->getViewerDescendentCount(); +		if (descendents_server == descendents_actual +			|| (descendents_actual > 0 && descendents_server == -1)) // content was loaded in previous session +		{ +			return true; +		} +	} +	return false; +} +  void LLFolderViewModelItemInventory::requestSort()  {  	LLFolderViewModelItemCommon::requestSort(); diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 0516fc3b4b..dea54cbe57 100755 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -115,6 +115,7 @@ public:  	void sort(LLFolderViewFolder* folder);  	bool contentsReady(); +	bool isFolderComplete(LLFolderViewFolder* folder);  	bool startDrag(std::vector<LLFolderViewModelItem*>& items);  private: diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 86f9da6318..4d92fee04f 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -239,7 +239,8 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :  	mRoleMemberDataComplete(false),  	mGroupPropertiesDataComplete(false),  	mPendingRoleMemberRequest(false), -	mAccessTime(0.0f) +	mAccessTime(0.0f), +	mPendingBanRequest(false)  {  	mMemberVersion.generate();  } @@ -761,8 +762,69 @@ void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)  	mBanList.erase(ban_id);  } +void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid) +{ +	if (!mMemberDataComplete || +		!mRoleDataComplete || +		!(mRoleMemberDataComplete && mMembers.size())) +	{ +		LL_WARNS() << "No Role-Member data yet, setting ban request to pending." << LL_ENDL; +		mPendingBanRequest = true; +		mPendingBanMemberID = participant_uuid; + +		if (!mMemberDataComplete) +		{ +			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); +		} + +		if (!mRoleDataComplete) +		{ +			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mID); +		} + +		return; +	} +	 +	LLGroupMgrGroupData::member_list_t::iterator mi = mMembers.find((participant_uuid)); +	if (mi == mMembers.end()) +	{ +		if (!mPendingBanRequest) +		{ +			mPendingBanRequest = true; +			mPendingBanMemberID = participant_uuid; +			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); // member isn't in members list, request reloading +		} +		else +		{ +			mPendingBanRequest = false; +		} +		return; +	} +	mPendingBanRequest = false; + +	LLGroupMemberData* member_data = (*mi).second; +	if (member_data && member_data->isInRole(mOwnerRole)) +	{ +		return; // can't ban group owner +	} + +	std::vector<LLUUID> ids; +	ids.push_back(participant_uuid); + +	LLGroupBanData ban_data; +	createBanEntry(participant_uuid, ban_data); +	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mID, LLGroupMgr::BAN_CREATE, ids); +	LLGroupMgr::getInstance()->sendGroupMemberEjects(mID, ids); +	LLGroupMgr::getInstance()->sendGroupMembersRequest(mID); +	LLSD args; +	std::string name; +	gCacheName->getFullName(participant_uuid, name); +	args["AVATAR_NAME"] = name; +	args["GROUP_NAME"] = mName; +	LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args)); +}  //  // LLGroupMgr @@ -1245,6 +1307,11 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)  	group_datap->mChanged = TRUE;  	LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA); + +	if (group_datap->mPendingBanRequest) +	{ +		group_datap->banMemberById(group_datap->mPendingBanMemberID); +	}  }  // static @@ -1993,8 +2060,6 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content)  	LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST);  } - -  // Responder class for capability group management  class GroupMemberDataResponder : public LLHTTPClient::Responder  { @@ -2083,11 +2148,6 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)  		return;  	} -	// If we have no members, there's no reason to do anything else -	S32	num_members	= content["member_count"]; -	if(num_members < 1) -		return; -	  	LLUUID group_id = content["group_id"].asUUID();  	LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id); @@ -2097,6 +2157,18 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)  		return;  	} +	// If we have no members, there's no reason to do anything else +	S32	num_members	= content["member_count"]; +	if (num_members < 1) +	{ +		LL_INFOS("GrpMgr") << "Received empty group members list for group id: " << group_id.asString() << LL_ENDL; +		// Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237 +		group_datap->mMemberDataComplete = true; +		group_datap->mChanged = TRUE; +		LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA); +		return; +	} +	  	group_datap->mMemberCount = num_members;  	LLSD	member_list	= content["members"]; diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 2e94e8d9a0..5307c4de92 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -149,7 +149,7 @@ public:  	const uuid_vec_t& getRoleMembers() const { return mMemberIDs; }  	S32 getMembersInRole(uuid_vec_t members, BOOL needs_sort = TRUE); -	S32 getTotalMembersInRole() { return mMemberIDs.size(); } +	S32 getTotalMembersInRole() { return mMemberCount ? mMemberCount : mMemberIDs.size(); } //FIXME: Returns 0 for Everyone role when Member list isn't yet loaded, see MAINT-5225  	LLRoleData getRoleData() const { return mRoleData; }  	void setRoleData(LLRoleData data) { mRoleData = data; } @@ -269,8 +269,8 @@ public:  	void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData());  	void removeBanEntry(const LLUUID& ban_id); +	void banMemberById(const LLUUID& participant_uuid); -  public:  	typedef	std::map<LLUUID,LLGroupMemberData*> member_list_t;  	typedef	std::map<LLUUID,LLGroupRoleData*> role_list_t; @@ -302,6 +302,9 @@ public:  	S32					mMemberCount;  	S32					mRoleCount; +	bool				mPendingBanRequest; +	LLUUID				mPendingBanMemberID; +  protected:  	void sendRoleChanges();  	void cancelRoleChanges(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 605f71f412..c990eda074 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -121,7 +121,7 @@ bool isAddAction(const std::string& action)  bool isRemoveAction(const std::string& action)  { -	return ("take_off" == action || "detach" == action || "deactivate" == action); +	return ("take_off" == action || "detach" == action);  }  bool isMarketplaceCopyAction(const std::string& action) @@ -777,14 +777,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,  			{  				items.push_back(std::string("Marketplace Separator")); -                if (gMenuHolder->getChild<LLView>("MerchantOutbox")->getVisible()) -                { -                    items.push_back(std::string("Merchant Copy")); -                    if (!canListOnOutboxNow()) -                    { -                        disabled_items.push_back(std::string("Merchant Copy")); -                    } -                }                  if (gMenuHolder->getChild<LLView>("MarketplaceListings")->getVisible())                  {                      items.push_back(std::string("Marketplace Copy")); @@ -915,15 +907,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,  		return;  	} -	// "Remove link" and "Delete" are the same operation. -	if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID)) -	{ -		items.push_back(std::string("Remove Link")); -	} -	else -	{ -		items.push_back(std::string("Delete")); -	} +	items.push_back(std::string("Delete"));  	if (!isItemRemovable())  	{ @@ -1714,16 +1698,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)  		folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();  		return;  	} -	else if (isMarketplaceCopyAction(action)) -	{ -		LL_INFOS() << "Copy item to marketplace action!" << LL_ENDL; - -		LLInventoryItem* itemp = model->getItem(mUUID); -		if (!itemp) return; - -		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); -		copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId()); -	}  	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))  	{  		LLInventoryItem* itemp = model->getItem(mUUID); @@ -1810,7 +1784,9 @@ void LLItemBridge::restoreItem()  	if(item)  	{  		LLInventoryModel* model = getInventoryModel(); -		const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); +		bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT); + +		const LLUUID new_parent = model->findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType()));  		// do not restamp on restore.  		LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);  	} @@ -2437,7 +2413,8 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const  BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  											BOOL drop,  											std::string& tooltip_msg, -                                            BOOL user_confirm) +											BOOL is_link, +											BOOL user_confirm)  {  	LLInventoryModel* model = getInventoryModel(); @@ -2483,6 +2460,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  		const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);  		const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);  		const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); +		const BOOL move_is_into_current_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_CURRENT_OUTFIT);  		const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);  		//-------------------------------------------------------------------------------- @@ -2520,8 +2498,18 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  		}  		if (is_movable && move_is_into_outfit)  		{ +			if((mUUID == my_outifts_id) || (getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_NONE)) +			{ +				is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)); +			} +			else +			{ +				is_movable = false; +			} +		} +		if(is_movable && move_is_into_current_outfit && is_link) +		{  			is_movable = FALSE; -			// tooltip?  		}  		if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE)))  		{ @@ -2705,9 +2693,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  					}  				}  			} +  			// if target is current outfit folder we use link  			if (move_is_into_current_outfit && -				inv_cat->getPreferredType() == LLFolderType::FT_NONE) +				(inv_cat->getPreferredType() == LLFolderType::FT_NONE || +				inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT))  			{  				// traverse category and add all contents to currently worn.  				BOOL append = true; @@ -3296,16 +3286,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  		removeSystemFolder();  	}  #endif -	else if (isMarketplaceCopyAction(action)) -	{ -		LL_INFOS() << "Copy folder to marketplace action!" << LL_ENDL; - -		LLInventoryCategory * cat = gInventory.getCategory(mUUID); -		if (!cat) return; - -		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); -		copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId()); -	}  	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))  	{  		LLInventoryCategory * cat = gInventory.getCategory(mUUID); @@ -4141,7 +4121,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,  				LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID());  				if (linked_category)  				{ -					accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg); +					accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg, TRUE);  				}  			}  			else @@ -4561,7 +4541,7 @@ void LLFolderBridge::callback_dropCategoryIntoFolder(const LLSD& notification, c      if (option == 0) // YES      {          std::string tooltip_msg; -        dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE); +		dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE, FALSE);      }  } @@ -5760,7 +5740,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action)  		gInventory.updateItem(item);  		gInventory.notifyObservers();  	} -	else if (isRemoveAction(action)) +	else if ("deactivate" == action || isRemoveAction(action))  	{  		LLGestureMgr::instance().deactivateGesture(mUUID); @@ -6382,12 +6362,8 @@ void LLWearableBridge::performAction(LLInventoryModel* model, std::string action  void LLWearableBridge::openItem()  { -	LLViewerInventoryItem* item = getItem(); - -	if (item) -	{ -		LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); -	} +	performAction(getInventoryModel(), +			      get_is_item_worn(mUUID) ? "take_off" : "wear");  }  void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 7e7cf9c7dd..03e19cc4da 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -274,7 +274,7 @@ public:  	{}  	BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE); -	BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE); +	BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE);      void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item);      void callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 990343c205..6aaf45c35d 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2473,7 +2473,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root  	{  		LLSD args;  		args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" :  "DeleteItem"); -		LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&onItemsRemovalConfirmation, _1, _2, root->getHandle())); +		LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));          // Note: marketplace listings will be updated in the callback if delete confirmed  		return;  	} diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 6ae8fd0f13..b93bf9a163 100755 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -465,9 +465,9 @@ struct LLInventoryAction  	static void removeItemFromDND(LLFolderView* root);  private: -    static void buildMarketplaceFolders(LLFolderView* root); -    static void updateMarketplaceFolders(); -    static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed +	static void buildMarketplaceFolders(LLFolderView* root); +	static void updateMarketplaceFolders(); +	static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed  }; diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 4e9947fca0..46c1ffa789 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -515,7 +515,7 @@ void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id)  			{  				LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);  				LLSculptParams new_params(*old_params); -				new_params.setSculptTexture(new_id); +				new_params.setSculptTexture(new_id, (*old_params).getSculptType());  				object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, TRUE);  			}  		} diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index cf04c5f7a5..8d21fda8f9 100755 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -862,14 +862,11 @@ void LLLocationInputCtrl::refreshParcelIcons()  		bool see_avs        = current_parcel->getSeeAVs();  		bool pathfinding_dynamic_enabled = agent_region->dynamicPathfindingEnabled(); -		bool is_parcel_owner = (gAgent.getID() == current_parcel->getOwnerID()); -		bool allow_group_modify = (gAgent.isInGroup(current_parcel->getGroupID()) && current_parcel->getAllowGroupModify()); -  		// Most icons are "block this ability"  		mParcelIcon[VOICE_ICON]->setVisible(   !allow_voice );  		mParcelIcon[FLY_ICON]->setVisible(     !allow_fly );  		mParcelIcon[PUSH_ICON]->setVisible(    !allow_push ); -		mParcelIcon[BUILD_ICON]->setVisible(   !allow_build && !is_parcel_owner && !allow_group_modify ); +		mParcelIcon[BUILD_ICON]->setVisible(   !allow_build );  		mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );  		mParcelIcon[DAMAGE_ICON]->setVisible(  allow_damage );  		mParcelIcon[PATHFINDING_DIRTY_ICON]->setVisible(mIsNavMeshDirty); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 7ddacf3033..4116e38f11 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -804,6 +804,22 @@ bool LLLogChat::isNearbyTranscriptExist()  	return false;  } +bool LLLogChat::isAdHocTranscriptExist(std::string file_name) +{ +	std::vector<std::string> list_of_transcriptions; +	LLLogChat::getListOfTranscriptFiles(list_of_transcriptions); + +	file_name = makeLogFileName(file_name); +	BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions) +	{ +	   	if (transcript_file_name == file_name) +	   	{ +	   		return true; +		} +	} +	return false; +} +  //*TODO mark object's names in a special way so that they will be distinguishable form avatar name   //which are more strict by its nature (only firstname and secondname)  //Example, an object's name can be written like "Object <actual_object's_name>" diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index ca597599dd..6022e539a9 100755 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -120,6 +120,7 @@ public:  	static void deleteTranscripts();  	static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);  	static bool isNearbyTranscriptExist(); +	static bool isAdHocTranscriptExist(std::string file_name);  	static bool historyThreadsFinished(LLUUID session_id);  	static LLLoadHistoryThread* getLoadHistoryThread(LLUUID session_id); diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 407613d32c..85faa70552 100755 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -1677,12 +1677,12 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)  				F32 alpha = (1.f - (1.f *  ((F32)llabs(i) / (F32)num_ticks_per_side1)));  				LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple1 + i) * smallest_subdivision1); -				F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); - -				if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) +				//No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) +				//F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); +				/*if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)  				{  					continue; -				} +				}*/  				F32 tick_scale = 1.f;  				for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) @@ -1710,12 +1710,12 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)  				F32 alpha = (1.f - (1.f *  ((F32)llabs(i) / (F32)num_ticks_per_side2)));  				LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple2 + i) * smallest_subdivision2); -				F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); - -				if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f) +				//No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) +				//F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel); +				/*if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)  				{  					continue; -				} +				}*/  				F32 tick_scale = 1.f;  				for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 394db71fb9..b4259a456c 100755 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1285,12 +1285,12 @@ void LLManipTranslate::renderSnapGuides()  				{  					tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit)); -					F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); - -					if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) +					//No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) +					//F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); +					/*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f)  					{  						continue; -					} +					}*/  					// add in off-axis offset  					tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index b96bdd73ff..73faed7ef5 100755 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -95,6 +95,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :  	mStretchToFill( true ),  	mMaintainAspectRatio ( true ),  	mDecoupleTextureSize ( false ), +	mUpdateScrolls( false ),  	mTextureWidth ( 1024 ),  	mTextureHeight ( 1024 ),  	mClearCache(false), @@ -682,7 +683,13 @@ bool LLMediaCtrl::ensureMediaSourceExists()  			mMediaSource->addObserver( this );  			mMediaSource->setBackgroundColor( getBackgroundColor() );  			mMediaSource->setTrustedBrowser(mTrusted); -			mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + +			F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; +			if (scale_factor != mMediaSource->getPageZoomFactor()) +			{ +				mMediaSource->setPageZoomFactor( scale_factor ); +				mUpdateScrolls = true; +			}  			if(mClearCache)  			{ @@ -720,10 +727,11 @@ void LLMediaCtrl::draw()  {  	F32 alpha = getDrawContext().mAlpha; -	if ( gRestoreGL == 1 ) +	if ( gRestoreGL == 1 || mUpdateScrolls)  	{  		LLRect r = getRect();  		reshape( r.getWidth(), r.getHeight(), FALSE ); +		mUpdateScrolls = false;  		return;  	} @@ -765,7 +773,12 @@ void LLMediaCtrl::draw()  	{  		gGL.pushUIMatrix();  		{ -			mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); +			F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; +			if (scale_factor != mMediaSource->getPageZoomFactor()) +			{ +				mMediaSource->setPageZoomFactor( scale_factor ); +				mUpdateScrolls = true; +			}  			// scale texture to fit the space using texture coords  			gGL.getTexUnit(0)->bind(media_texture); @@ -970,11 +983,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)  		case MEDIA_EVENT_CLICK_LINK_HREF:  		{ -			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;  			// retrieve the event parameters  			std::string url = self->getClickURL(); -			std::string target = self->getClickTarget(); +			std::string target = self->isOverrideClickTarget() ? self->getOverrideClickTarget() : self->getClickTarget();  			std::string uuid = self->getClickUUID(); +			LL_DEBUGS("Media") << "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;  			LLNotification::Params notify_params;  			notify_params.name = "PopupAttempt"; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 785c57b78a..988733b85a 100755 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -192,7 +192,8 @@ public:  				mHidingInitialLoad,  				mClearCache,  				mHoverTextChanged, -				mDecoupleTextureSize; +				mDecoupleTextureSize, +				mUpdateScrolls;  		std::string mHomePageUrl,  					mHomePageMimeType, diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index fe562baf96..70035bcc74 100755 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -303,7 +303,15 @@ void LLFloaterMove::onFlyButtonClick()  void LLFloaterMove::setMovementMode(const EMovementMode mode)  {  	mCurrentMode = mode; -	gAgent.setFlying(MM_FLY == mode); + +	if(MM_FLY == mode) +	{ +		LLAgent::toggleFlying(); +	} +	else +	{ +		gAgent.setFlying(FALSE); +	}  	// attempts to set avatar flying can not set it real flying in some cases.  	// For ex. when avatar fell down & is standing up. diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 79988a0800..5510598ae7 100755 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -130,8 +130,14 @@ BOOL LLNameListCtrl::handleDragAndDrop(  	return handled;  } -void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group) +void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience)  { +	if(is_experience) +	{ +		LLFloaterReg::showInstance("experience_profile", avatar_id, true); +		return; +	} +  	if (is_group)  		LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id));  	else @@ -230,10 +236,11 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)  				// Should we show a group or an avatar inspector?  				bool is_group = hit_item->isGroup(); +				bool is_experience = hit_item->isExperience();  				LLToolTip::Params params;  				params.background_visible( false ); -				params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) ); +				params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience) );  				params.delay_time(0.0f);		// spawn instantly on hover  				params.image( icon );  				params.message(""); @@ -295,7 +302,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(  	const std::string& prefix)  {  	LLUUID id = name_item.value().asUUID(); -	LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP); +	LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP, name_item.target() == EXPERIENCE);  	if (!item) return NULL; @@ -353,6 +360,8 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(  			}  			break;  		} +	case EXPERIENCE: +		// just use supplied name  	default:  		break;  	} diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 515962df7d..19ce3c7aed 100755 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -44,22 +44,30 @@ class LLNameListItem : public LLScrollListItem, public LLHandleProvider<LLNameLi  public:  	bool isGroup() const { return mIsGroup; }  	void setIsGroup(bool is_group) { mIsGroup = is_group; } +	bool isExperience() const { return mIsExperience; } +	void setIsExperience(bool is_experience) { mIsExperience = is_experience; }  protected:  	friend class LLNameListCtrl;  	LLNameListItem( const LLScrollListItem::Params& p ) -	:	LLScrollListItem(p), mIsGroup(false) +	:	LLScrollListItem(p), mIsGroup(false), mIsExperience(false)  	{  	}  	LLNameListItem( const LLScrollListItem::Params& p, bool is_group ) -	:	LLScrollListItem(p), mIsGroup(is_group) +	:	LLScrollListItem(p), mIsGroup(is_group), mIsExperience(false) +	{ +	} + +	LLNameListItem( const LLScrollListItem::Params& p, bool is_group, bool is_experience ) +	:	LLScrollListItem(p), mIsGroup(is_group), mIsExperience(is_experience)  	{  	}  private:  	bool mIsGroup; +	bool mIsExperience;  }; @@ -73,7 +81,8 @@ public:  	{  		INDIVIDUAL,  		GROUP, -		SPECIAL +		SPECIAL, +		EXPERIENCE  	} ENameType;  	// provide names for enums @@ -160,7 +169,7 @@ public:  	/*virtual*/ void mouseOverHighlightNthItem( S32 index );  private: -	void showInspector(const LLUUID& avatar_id, bool is_group); +	void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false);  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item);  private: diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 9bd6007772..b7e1b2d3a4 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1168,6 +1168,8 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO          targetPanel->setVisible(show);          toggleTypeSpecificControls(type); +		// Update type controls here +		updateTypeSpecificControls(type);          if (show)          { @@ -1179,7 +1181,6 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO                  mNameEditor->setText(mWearableItem->getName());                  updatePanelPickerControls(type); -                updateTypeSpecificControls(type);                  // clear and rebuild visual param list                  U8 num_subparts = wearable_entry->mSubparts.size(); diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index fc4ee9862e..7c07301762 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -33,6 +33,7 @@  #include "llfloaterexperiencepicker.h"  #include "llfloaterreg.h"  #include "llhandle.h" +#include "llnamelistctrl.h"  #include "llscrolllistctrl.h"  #include "llviewerregion.h"  #include "llagent.h" @@ -54,7 +55,7 @@ LLPanelExperienceListEditor::LLPanelExperienceListEditor()  BOOL LLPanelExperienceListEditor::postBuild()  { -	mItems = getChild<LLScrollListCtrl>("experience_list"); +	mItems = getChild<LLNameListCtrl>("experience_list");  	mAdd = getChild<LLButton>("btn_add");  	mRemove = getChild<LLButton>("btn_remove");  	mProfile = getChild<LLButton>("btn_profile"); @@ -178,12 +179,13 @@ void LLPanelExperienceListEditor::onItems()  	{  		const LLUUID& experience = *it;  		item["id"]=experience; +		item["target"] = LLNameListCtrl::EXPERIENCE;  		LLSD& columns = item["columns"];  		columns[0]["column"] = "experience_name";  		columns[0]["value"] = getString("loading");  		mItems->addElement(item); -		LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,  +		LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,  			getDerivedHandle<LLPanelExperienceListEditor>(), _1));  	} diff --git a/indra/newview/llpanelexperiencelisteditor.h b/indra/newview/llpanelexperiencelisteditor.h index f69f0509be..bc9867752d 100644 --- a/indra/newview/llpanelexperiencelisteditor.h +++ b/indra/newview/llpanelexperiencelisteditor.h @@ -31,6 +31,7 @@  #include "lluuid.h"  #include <set> +class LLNameListCtrl;  class LLScrollListCtrl;  class LLButton;  class LLFloaterExperiencePicker; @@ -82,7 +83,7 @@ private:  	uuid_list_t mExperienceIds; -	LLScrollListCtrl*			mItems; +	LLNameListCtrl*				mItems;  	filter_list					mFilters;  	LLButton*					mAdd;  	LLButton*					mRemove; diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index 70d826a407..43dc7569a4 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -42,6 +42,7 @@  #include "llviewercontrol.h"  #include "llfloater.h"  #include "lltrans.h" +#include <boost/regex.hpp>  #define BTN_FIND		"find"  #define BTN_OK			"ok_btn" @@ -147,6 +148,46 @@ void LLPanelExperiencePicker::editKeystroke( class LLLineEditor* caller, void* u  void LLPanelExperiencePicker::onBtnFind()  {  	mCurrentPage=1; +	boost::cmatch what; +	std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString(); +	const boost::regex expression("secondlife:///app/experience/[\\da-f-]+/profile"); +	if (boost::regex_match(text.c_str(), what, expression)) +	{ +		LLURI uri(text); +		LLSD path_array = uri.pathArray(); +		if (path_array.size() == 4) +		{ +			std::string exp_id = path_array.get(2).asString(); +			LLUUID experience_id(exp_id); +			if (!experience_id.isNull()) +			{ +				const LLSD& experience_details = LLExperienceCache::get(experience_id); +				if(!experience_details.isUndefined()) +				{ +					std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); +					if(!experience_name_string.empty()) +					{ +						getChild<LLUICtrl>(TEXT_EDIT)->setValue(experience_name_string); +					} +				} +				else +				{ +					getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems(); +					getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching")); + +					getChildView(BTN_OK)->setEnabled(FALSE); +					getChildView(BTN_PROFILE)->setEnabled(FALSE); + +					getChildView(BTN_RIGHT)->setEnabled(FALSE); +					getChildView(BTN_LEFT)->setEnabled(FALSE); +					LLExperienceCache::get(experience_id, boost::bind(&LLPanelExperiencePicker::onBtnFind, this)); +					return; +				} +			} +		} +	} + +  	find();  } @@ -183,7 +224,6 @@ void LLPanelExperiencePicker::find()  	getChildView(BTN_LEFT)->setEnabled(FALSE);  } -  bool LLPanelExperiencePicker::isSelectButtonEnabled()  {  	LLScrollListCtrl* list=getChild<LLScrollListCtrl>(LIST_RESULTS); diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 9823e84cd9..d7e89b4832 100755 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -307,7 +307,7 @@ private:  						LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material);  					} -					object->setTEMaterialParams(face, new_material); +					object->setTEMaterialParams(face, new_material, TRUE);  					return new_material;  				}  				return NULL; diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index f67a90fd01..342b57ba4a 100755 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -338,7 +338,7 @@ void LLPanelGroup::update(LLGroupChange gc)  		group_name_ctrl->setToolTip(group_name);  		LLGroupData agent_gdatap; -		bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike(); +		bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery();  		bool join_btn_visible = !is_member && gdatap->mOpenEnrollment;  		mButtonJoin->setVisible(join_btn_visible); @@ -470,7 +470,7 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)  		}  		LLGroupData agent_gdatap; -		bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike(); +		bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery();  		tab_roles->setVisible(is_member);  		tab_notices->setVisible(is_member); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 7ffaa05919..b2164c1f21 100755 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -287,11 +287,6 @@ void LLPanelGroupGeneral::activate()  	{  		LLGroupMgr::getInstance()->sendGroupTitlesRequest(mGroupID);  		LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID); -		 -		if (!gdatap || !gdatap->isMemberDataComplete() ) -		{ -			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); -		}  		mFirstUse = FALSE;  	} diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index e662a05dfc..866cb8dbef 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -243,56 +243,59 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)  	LLGroupMgrGroupData::member_list_t::iterator agent_iter =  		gdatap->mMembers.find(gAgent.getID()); +	//loop over the agent's roles in the group +	//then add those roles to the list of roles that the agent +	//can invite people to be. +	//if the user is the owner then we add +	//all of the roles in the group, +	//else if they have the add to roles power +	//we add every role but owner, +	//else if they have the limited add to roles power +	//we add every role the user is in, +	//else we just add to everyone +	bool is_owner = FALSE; +	bool can_assign_any = gAgent.hasPowerInGroup(mGroupID, +												 GP_ROLE_ASSIGN_MEMBER); +	bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID, +													 GP_ROLE_ASSIGN_MEMBER_LIMITED); +	LLGroupMemberData* member_data = NULL;  	//get the member data for the agent if it exists -	if ( agent_iter != gdatap->mMembers.end() ) +	if (agent_iter != gdatap->mMembers.end())  	{ -		LLGroupMemberData* member_data = (*agent_iter).second; - -		//loop over the agent's roles in the group -		//then add those roles to the list of roles that the agent -		//can invite people to be -		if ( member_data && mRoleNames) +		member_data = (*agent_iter).second; +		if (member_data && mRoleNames)  		{ -			//if the user is the owner then we add -			//all of the roles in the group -			//else if they have the add to roles power -			//we add every role but owner, -			//else if they have the limited add to roles power -			//we add every role the user is in -			//else we just add to everyone -			bool is_owner   = member_data->isOwner(); -			bool can_assign_any = gAgent.hasPowerInGroup(mGroupID, -												 GP_ROLE_ASSIGN_MEMBER); -			bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID, -												 GP_ROLE_ASSIGN_MEMBER_LIMITED); +			is_owner = member_data->isOwner(); +		}//end if member data is not null +	}//end if agent is in the group + -			LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin(); -			LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); -			//populate the role list -			for ( ; rit != end; ++rit) +	LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin(); +	LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); + +	//populate the role list: +	for ( ; rit != end; ++rit) +	{ +		LLUUID role_id = (*rit).first; +		LLRoleData rd; +		if ( gdatap->getRoleData(role_id,rd) ) +		{ +			// Owners can add any role. +			if ( is_owner  +				// Even 'can_assign_any' can't add owner role. +				|| (can_assign_any && role_id != gdatap->mOwnerRole) +				// Add all roles user is in +				|| (can_assign_limited && member_data && member_data->isInRole(role_id)) +				// Everyone role. +				|| role_id == LLUUID::null )  			{ -				LLUUID role_id = (*rit).first; -				LLRoleData rd; -				if ( gdatap->getRoleData(role_id,rd) ) -				{ -					// Owners can add any role. -					if ( is_owner  -						// Even 'can_assign_any' can't add owner role. -						 || (can_assign_any && role_id != gdatap->mOwnerRole) -						// Add all roles user is in -						 || (can_assign_limited && member_data->isInRole(role_id)) -						// Everyone role. -						 || role_id == LLUUID::null ) -					{ -							mRoleNames->add(rd.mRoleName, -											role_id, -											ADD_BOTTOM); -					} -				} +				mRoleNames->add(rd.mRoleName, +								role_id, +								ADD_BOTTOM);  			} -		}//end if member data is not null -	}//end if agent is in the group +		} +	}  }  //static @@ -579,7 +582,8 @@ void LLPanelGroupInvite::updateLists()  		{  			waiting = true;  		} -		if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete())  +		if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() +			&& (gdatap->isRoleMemberDataComplete() || !gdatap->mMembers.size())) // MAINT-5270: large groups receives an empty members list without some powers, so RoleMemberData wouldn't be complete for them  		{  			if ( mImplementation->mRoleNames )  			{ diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index c3a10b3fa0..00c204e702 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -350,12 +350,10 @@ void LLPanelGroupRoles::update(LLGroupChange gc)  void LLPanelGroupRoles::activate()  { +	if (!gAgent.isInGroup(mGroupID)) return; +  	// Start requesting member and role data if needed.  	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); -	if (!gdatap || !gdatap->isMemberDataComplete() ) -	{ -		LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); -	}  	if (!gdatap || !gdatap->isRoleDataComplete() )  	{ @@ -364,13 +362,7 @@ void LLPanelGroupRoles::activate()  		LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);  	} - -	// Check role-member mapping data. -	if (!gdatap || !gdatap->isRoleMemberDataComplete() ) -	{ -		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); -	} - +	  	// Need this to get base group member powers  	if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )  	{ @@ -1163,7 +1155,37 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)  	if ( selfp )  	{ -		selfp->handleEjectMembers(); +		selfp->confirmEjectMembers(); +	} +} + +void LLPanelGroupMembersSubTab::confirmEjectMembers() +{ +	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); +	if (selection.empty()) return; + +	S32 selection_count = selection.size(); +	if (selection_count == 1) +	{ +		LLSD args; +		std::string fullname; +		gCacheName->getFullName(mMembersList->getValue(), fullname); +		args["AVATAR_NAME"] = fullname; +		LLSD payload; +		LLNotificationsUtil::add("EjectGroupMemberWarning", +				 	 	 	 	 args, +								 payload, +								 boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); +	} +	else +	{ +		LLSD args; +		args["COUNT"] = llformat("%d", selection_count); +		LLSD payload; +		LLNotificationsUtil::add("EjectGroupMembersWarning", +				 	 	 	 	 args, +								 payload, +								 boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));  	}  } @@ -1190,6 +1212,16 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()  	LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);  } +bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (0 == option) // Eject button +	{ +		handleEjectMembers(); +	} +	return false; +} +  void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)  {  	LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id); @@ -1327,15 +1359,26 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()  void LLPanelGroupMembersSubTab::activate()  { +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); +  	LLPanelGroupSubTab::activate();  	if(!mActivated)  	{ +		if (!gdatap || !gdatap->isMemberDataComplete()) +		{ +			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); +		} + +		if (!gdatap || !gdatap->isRoleMemberDataComplete()) +		{ +			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); +		} +  		update(GC_ALL);  		mActivated = true;  	}  	else  	{ -		LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);  		// Members can be removed outside of this tab, checking changes  		if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount()))  		{ @@ -1636,7 +1679,13 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)  	{  		// Build a string with info on retrieval progress.  		std::ostringstream retrieved; -		if ( !gdatap->isMemberDataComplete() ) + +		if ( gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && !gdatap->mMembers.size() ) +		{ +			// MAINT-5237 +			retrieved << "Member list not available."; +		} +		else if ( !gdatap->isMemberDataComplete() )  		{  			// Still busy retreiving member list.  			retrieved << "Retrieving member list (" << gdatap->mMembers.size() @@ -1783,7 +1832,7 @@ void LLPanelGroupMembersSubTab::updateMembers()  		{  			mMembersList->setEnabled(TRUE);  		} -		else +		else if (gdatap->mMembers.size())   		{  			mMembersList->setEnabled(FALSE);  			mMembersList->setCommentText(std::string("No match.")); @@ -1801,7 +1850,47 @@ void LLPanelGroupMembersSubTab::updateMembers()  void LLPanelGroupMembersSubTab::onBanMember(void* user_data)  {  	LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data); -	self->handleBanMember(); +	self->confirmBanMembers(); +} + +void LLPanelGroupMembersSubTab::confirmBanMembers() +{ +	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); +	if (selection.empty()) return; + +	S32 selection_count = selection.size(); +	if (selection_count == 1) +	{ +		LLSD args; +		std::string fullname; +		gCacheName->getFullName(mMembersList->getValue(), fullname); +		args["AVATAR_NAME"] = fullname; +		LLSD payload; +		LLNotificationsUtil::add("BanGroupMemberWarning", +				 	 	 	 	 args, +								 payload, +								 boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2)); +	} +	else +	{ +		LLSD args; +		args["COUNT"] = llformat("%d", selection_count); +		LLSD payload; +		LLNotificationsUtil::add("BanGroupMembersWarning", +				 	 	 	 	 args, +								 payload, +								 boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2)); +	} +} + +bool LLPanelGroupMembersSubTab::handleBanCallback(const LLSD& notification, const LLSD& response) +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (0 == option) // Eject button +	{ +		handleBanMember(); +	} +	return false;  }  void LLPanelGroupMembersSubTab::handleBanMember() @@ -2111,20 +2200,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)  			mDeleteRoleButton->setEnabled(FALSE);  		}  	} - -	if(!mFirstOpen) -	{ -		if (!gdatap || !gdatap->isMemberDataComplete()) -		{ -			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); -		} - -		if (!gdatap || !gdatap->isRoleMemberDataComplete()) -		{ -			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); -		} -	} - +	  	if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)  	    && gdatap  	    && gdatap->isMemberDataComplete() diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 540b24ada6..9a696124a8 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -171,6 +171,7 @@ public:  	void handleEjectMembers();  	void sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members);  	bool handleEjectCallback(const LLSD& notification, const LLSD& response); +	void confirmEjectMembers();  	static void onRoleCheck(LLUICtrl* check, void* user_data);  	void handleRoleCheck(const LLUUID& role_id, @@ -178,6 +179,8 @@ public:  	static void onBanMember(void* user_data);  	void handleBanMember(); +	bool handleBanCallback(const LLSD& notification, const LLSD& response); +	void confirmBanMembers();  	void applyMemberChanges(); diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index d4894d4a42..06bb886ae8 100755 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -147,6 +147,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)  				}  				else  				{ +					LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos);  					region_name = desc;  				} diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 7aaf9510eb..4229419fce 100755 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -604,7 +604,7 @@ void LLPanelMainInventory::updateItemcountText()  	}  	else  	{ -		text = getString("ItemcountUnknown"); +		text = getString("ItemcountUnknown", string_args);  	}      mCounterCtrl->setValue(text); diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index 2856ea9db1..d7c43c224c 100755 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -319,6 +319,10 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& _media  // Helper to set media control to media URL as required  void LLPanelMediaSettingsGeneral::updateMediaPreview()  { +	if(LLTrans::getString("Multiple Media") == mHomeURL->getValue().asString()) +	{ +		return; +	}  	if ( mHomeURL->getValue().asString().length() > 0 )  	{  		if(mPreviewMedia->getCurrentNavUrl() != mHomeURL->getValue().asString()) diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index dcd0aab3ab..5dd44b4444 100755 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -1739,9 +1739,10 @@ void LLPanelObject::sendSculpt()  		return;  	LLSculptParams sculpt_params; +	LLUUID sculpt_id = LLUUID::null;  	if (mCtrlSculptTexture) -		sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID()); +		sculpt_id = mCtrlSculptTexture->getImageAssetID();  	U8 sculpt_type = 0; @@ -1765,7 +1766,7 @@ void LLPanelObject::sendSculpt()  	if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get()))  		sculpt_type |= LL_SCULPT_FLAG_INVERT; -	sculpt_params.setSculptType(sculpt_type); +	sculpt_params.setSculptTexture(sculpt_id, sculpt_type);  	mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);  } @@ -2000,7 +2001,11 @@ void LLPanelObject::onCancelSculpt(const LLSD& data)  	LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");  	if(!mTextureCtrl)  		return; -	 + +	if(mSculptTextureRevert == LLUUID::null) +	{ +		mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE); +	}  	mTextureCtrl->setImageAssetID(mSculptTextureRevert);  	sendSculpt(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 5977d558d3..de4efc8612 100755 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -85,6 +85,8 @@ static const std::string RECENT_TAB_NAME	= "recent_panel";  static const std::string BLOCKED_TAB_NAME	= "blocked_panel"; // blocked avatars  static const std::string COLLAPSED_BY_USER  = "collapsed_by_user"; +const S32 BASE_MAX_AGENT_GROUPS = 42; +const S32 PREMIUM_MAX_AGENT_GROUPS = 60;  extern S32 gMaxAgentGroups; @@ -585,6 +587,7 @@ BOOL LLPanelPeople::postBuild()  	getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	getChild<LLFilterEditor>("fbc_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLTextBox>("groupcount")->setURLClickedCallback(boost::bind(&LLPanelPeople::onGroupLimitInfo, this));  	mTabContainer = getChild<LLTabContainer>("tabs");  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); @@ -902,8 +905,11 @@ void LLPanelPeople::updateButtons()  		LLPanel* groups_panel = mTabContainer->getCurrentPanel();  		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected -		groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.size())); -		groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.size()))); + +		U32 groups_count = gAgent.mGroups.size(); +		U32 groups_ramaining = gMaxAgentGroups > groups_count ? gMaxAgentGroups - groups_count : 0; +		groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d", groups_count)); +		groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d", groups_ramaining));  	}  	else  	{ @@ -1114,6 +1120,14 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)  	}  } +void LLPanelPeople::onGroupLimitInfo() +{ +	LLSD args; +	args["MAX_BASIC"] = BASE_MAX_AGENT_GROUPS; +	args["MAX_PREMIUM"] = PREMIUM_MAX_AGENT_GROUPS; +	LLNotificationsUtil::add("GroupLimitInfo", args); +} +  void LLPanelPeople::onTabSelected(const LLSD& param)  {  	std::string tab_name = getChild<LLPanel>(param.asString())->getName(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index c1d7a134fa..eb7e76a772 100755 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -93,6 +93,7 @@ private:  	// UI callbacks  	void					onFilterEdit(const std::string& search_string); +	void					onGroupLimitInfo();  	void					onTabSelected(const LLSD& param);  	void					onAddFriendButtonClicked();  	void					onAddFriendWizButtonClicked(); diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index d73a5b402e..55c09d85ea 100755 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -432,7 +432,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)  		mNoPicks = !mPicksList->size();  	} -	else if(APT_CLASSIFIEDS == type) +	else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type))  	{  		LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data);  		if(c_info && getAvatarId() == c_info->target_id) diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 4bcd932d4b..a9a0c30e26 100755 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -921,7 +921,12 @@ void LLPanelPlaces::onBackButtonClicked()  void LLPanelPlaces::togglePickPanel(BOOL visible)  {  	if (mPickPanel) +	{  		mPickPanel->setVisible(visible); +		mPlaceProfile->setVisible(!visible); +		updateVerbs(); +	} +  }  void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) @@ -1141,16 +1146,21 @@ void LLPanelPlaces::updateVerbs()  	bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;  	bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; +	bool is_pick_panel_visible = false; +	if(mPickPanel) +	{ +		is_pick_panel_visible = mPickPanel->isInVisibleChain(); +	}  	bool have_3d_pos = ! mPosGlobal.isExactlyZero(); -	mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); -	mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn); +	mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); +	mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);  	mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);  	mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);  	mSaveBtn->setVisible(isLandmarkEditModeOn);  	mCancelBtn->setVisible(isLandmarkEditModeOn);  	mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); -	mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn); +	mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);  	mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos); diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index ac9a31ce4e..109013498e 100755 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -313,14 +313,11 @@ void LLPanelTopInfoBar::updateParcelIcons()  		bool allow_damage	= vpm->allowAgentDamage(agent_region, current_parcel);  		bool see_avs        = current_parcel->getSeeAVs(); -		bool is_parcel_owner = (gAgent.getID() == current_parcel->getOwnerID()); -		bool allow_group_modify = (gAgent.isInGroup(current_parcel->getGroupID()) && current_parcel->getAllowGroupModify()); -  		// Most icons are "block this ability"  		mParcelIcon[VOICE_ICON]->setVisible(   !allow_voice );  		mParcelIcon[FLY_ICON]->setVisible(     !allow_fly );  		mParcelIcon[PUSH_ICON]->setVisible(    !allow_push ); -		mParcelIcon[BUILD_ICON]->setVisible(   !allow_build && !is_parcel_owner && !allow_group_modify ); +		mParcelIcon[BUILD_ICON]->setVisible(   !allow_build );  		mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );  		mParcelIcon[DAMAGE_ICON]->setVisible(  allow_damage );  		mDamageText->setVisible(allow_damage); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 1bbb22416d..67832c5994 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1391,6 +1391,8 @@ void LLLiveLSLEditor::buildExperienceList()  	else  	{  		mExperiences->setEnabled(TRUE); +		mExperiences->sortByName(TRUE); +		mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex());  		getChild<LLButton>("view_profile")->setVisible(TRUE);  	}  } @@ -2621,8 +2623,12 @@ void LLLiveLSLEditor::onLoad(void* userdata)  void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)  {  	LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata; -	self->mCloseAfterSave = close_after_save; -	self->saveIfNeeded(); +	if(self) +	{ +		self->mCloseAfterSave = close_after_save; +		self->mScriptEd->mErrorList->setCommentText(""); +		self->saveIfNeeded(); +	}  } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index f91a18d8d3..c8cf0faa15 100755 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -618,4 +618,5 @@ void LLPreviewTexture::setObjectID(const LLUUID& object_id)  		mAssetStatus = PREVIEW_ASSET_UNLOADED;  		loadAsset();  	} +	refreshFromItem();  } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 4fafbf917b..55bcb3dc65 100755 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2127,7 +2127,7 @@ void LLSelectMgr::selectionRemoveMaterial()  			{  			        LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL;  				LLMaterialMgr::getInstance()->remove(object->getID(),face); -				object->setTEMaterialParams(face, NULL); +				object->setTEMaterialParams(face, NULL, FALSE);  			}  			return true;  		} @@ -4950,6 +4950,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,  									ESendType send_type)  {  	LLSelectNode* node; +	LLSelectNode* linkset_root = NULL;  	LLViewerRegion*	last_region;  	LLViewerRegion*	current_region; @@ -4957,6 +4958,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,  	S32 packets_sent = 0;  	S32 objects_in_this_packet = 0; +	bool link_operation = message_name == "ObjectLink"; +  	//clear update override data (allow next update through)  	struct f : public LLSelectedNodeFunctor  	{ @@ -5065,6 +5068,12 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,  			&& (! gMessageSystem->isSendFull(NULL))  			&& (objects_in_this_packet < MAX_OBJECTS_PER_PACKET))  		{ +			if (link_operation && linkset_root == NULL) +			{ +				// linksets over 254 will be split into multiple messages, +				// but we need to provide same root for all messages or we will get separate linksets +				linkset_root = node; +			}  			// add another instance of the body of the data  			(*pack_body)(node, user_data);              // do any related logging @@ -5093,6 +5102,22 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,  			gMessageSystem->newMessage(message_name.c_str());  			(*pack_header)(user_data); +			if (linkset_root != NULL) +			{ +				if (current_region != last_region) +				{ +					// root should be in one region with the child, reset it +					linkset_root = NULL; +				} +				else +				{ +					// add root instance into new message +					(*pack_body)(linkset_root, user_data); +					++objects_sent; +					++objects_in_this_packet; +				} +			} +  			// don't move to the next object, we still need to add the  			// body data.   		} diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 17ecfab4fb..2548d730f0 100755 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -370,18 +370,25 @@ void LLSidepanelTaskInfo::refresh()  	// Update creator text field  	getChildView("Creator:")->setEnabled(TRUE); +  	std::string creator_name; -	LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name); +	LLUUID creator_id; +	LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_name); -	getChild<LLUICtrl>("Creator Name")->setValue(creator_name); -	getChildView("Creator Name")->setEnabled(TRUE); +	if(creator_id != mCreatorID ) +	{ +		mDACreatorName->setValue(creator_name); +		mCreatorID = creator_id; +	} +	mDACreatorName->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()) +	LLUUID owner_id; +	const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); +	if (owner_id.isNull())  	{  		if (LLSelectMgr::getInstance()->selectIsGroupOwned())  		{ @@ -402,7 +409,12 @@ void LLSidepanelTaskInfo::refresh()  			}  		}  	} -	getChild<LLUICtrl>("Owner Name")->setValue(owner_name); + +	if(owner_id.isNull() || (owner_id != mOwnerID)) +	{ +		mDAOwnerName->setValue(owner_name); +		mOwnerID = owner_id; +	}  	getChildView("Owner Name")->setEnabled(TRUE);  	// update group text field diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp index 728fc69723..a8e012bfa1 100755 --- a/indra/newview/llslurl.cpp +++ b/indra/newview/llslurl.cpp @@ -271,7 +271,14 @@ LLSLURL::LLSLURL(const std::string& slurl)  			// at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z   			// are collectively optional  			// are optional +  			mRegion = LLURI::unescape(path_array[0].asString()); + +			if(LLStringUtil::containsNonprintable(mRegion)) +			{ +				LLStringUtil::stripNonprintable(mRegion); +			} +  			path_array.erase(0);  			// parse the x, y, and optionally z diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 0ae8a338e0..6af9d61a54 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -195,7 +195,8 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail          // Stop shining animation.          mShineAnimTimer.stop();  		mSnapshotDelayTimer.start(); -		mSnapshotDelayTimer.setTimerExpirySec(delay); +		mSnapshotDelayTimer.resetWithExpiry(delay); +  		mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal(); @@ -670,10 +671,27 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  		return FALSE;  	} -	// If we're in freeze-frame mode and camera has moved, update snapshot. +	if (previewp->mSnapshotDelayTimer.getStarted()) // Wait for a snapshot delay timer +	{ +		if (!previewp->mSnapshotDelayTimer.hasExpired()) +		{ +			return FALSE; +		} +		previewp->mSnapshotDelayTimer.stop(); +	} + +	if (LLToolCamera::getInstance()->hasMouseCapture()) // Hide full-screen preview while camming, either don't take snapshots while ALT-zoom active +	{ +		previewp->setVisible(FALSE); +		return FALSE; +	} + +	// If we're in freeze-frame and/or auto update mode and camera has moved, update snapshot.  	LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();  	LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); -	if (previewp->mForceUpdateSnapshot || (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview && +	if (previewp->mForceUpdateSnapshot || +		(((gSavedSettings.getBOOL("AutoSnapshot") && LLView::isAvailable(previewp->mViewContainer)) || +		(gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview)) &&  		(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f)))  	{  		previewp->mCameraPos = new_camera_pos; @@ -688,11 +706,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  		previewp->mForceUpdateSnapshot = FALSE;  	} -	// see if it's time yet to snap the shot and bomb out otherwise. -	previewp->mSnapshotActive =  -		(previewp->mSnapshotDelayTimer.getStarted() &&	previewp->mSnapshotDelayTimer.hasExpired()) -		&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active -	if (!previewp->mSnapshotActive && previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate()) +	if (previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate())  	{  		return FALSE;  	} @@ -706,6 +720,8 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )              previewp->mPreviewImage = new LLImageRaw;          } +        previewp->mSnapshotActive = TRUE; +          previewp->setVisible(FALSE);          previewp->setEnabled(FALSE); @@ -734,40 +750,9 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )              // Full size preview is set: get the decoded image result and save it for animation              if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview)              { -                // Get the decoded version of the formatted image -                previewp->getEncodedImage(); -             -                // We need to scale that a bit for display... -                LLPointer<LLImageRaw> scaled = new LLImageRaw( -                    previewp->mPreviewImageEncoded->getData(), -                    previewp->mPreviewImageEncoded->getWidth(), -                    previewp->mPreviewImageEncoded->getHeight(), -                    previewp->mPreviewImageEncoded->getComponents()); - -                if (!scaled->isBufferInvalid()) -                { -                    // leave original image dimensions, just scale up texture buffer -                    if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024) -                    { -                        // go ahead and shrink image to appropriate power of 2 for display -                        scaled->biasedScaleToPowerOfTwo(1024); -                        previewp->setImageScaled(TRUE); -                    } -                    else -                    { -                        // expand image but keep original image data intact -                        scaled->expandToPowerOfTwo(1024, FALSE); -                    } - -                    previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); -                    LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; -                    gGL.getTexUnit(0)->bind(curr_preview_image); -                    curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); -                    curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); - -                    previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame -                } +                previewp->prepareFreezeFrame();              } +              // The snapshot is updated now...              previewp->mSnapshotUpToDate = TRUE; @@ -777,7 +762,6 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )          }          previewp->getWindow()->decBusyCount();          previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode -        previewp->mSnapshotDelayTimer.stop();          previewp->mSnapshotActive = FALSE;          LL_DEBUGS() << "done creating snapshot" << LL_ENDL;      } @@ -796,6 +780,47 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )  	return TRUE;  } +void LLSnapshotLivePreview::prepareFreezeFrame() +{ +    // Get the decoded version of the formatted image +    getEncodedImage(); + +    // We need to scale that a bit for display... +    LLPointer<LLImageRaw> scaled = new LLImageRaw( +        mPreviewImageEncoded->getData(), +        mPreviewImageEncoded->getWidth(), +        mPreviewImageEncoded->getHeight(), +        mPreviewImageEncoded->getComponents()); + +    if (!scaled->isBufferInvalid()) +    { +        // leave original image dimensions, just scale up texture buffer +        if (mPreviewImageEncoded->getWidth() > 1024 || mPreviewImageEncoded->getHeight() > 1024) +        { +            // go ahead and shrink image to appropriate power of 2 for display +            scaled->biasedScaleToPowerOfTwo(1024); +            setImageScaled(TRUE); +        } +        else +        { +            // expand image but keep original image data intact +            scaled->expandToPowerOfTwo(1024, FALSE); +        } + +        mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE); +        LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex]; +        gGL.getTexUnit(0)->bind(curr_preview_image); +        curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); +        curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); + + +        if (gSavedSettings.getBOOL("UseFreezeFrame") && mAllowFullScreenPreview) +        { +            mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame +        } +    } +} +  S32 LLSnapshotLivePreview::getEncodedImageWidth() const  {      S32 width = getWidth(); diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index fed33bf37c..57e5d83f8e 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -119,7 +119,7 @@ public:  	void generateThumbnailImage(BOOL force_update = FALSE) ;  	void resetThumbnailImage() { mThumbnailImage = NULL ; }  	void drawPreviewRect(S32 offset_x, S32 offset_y) ; - +	void prepareFreezeFrame();  	LLViewerTexture* getBigThumbnailImage();  	S32  getBigThumbnailWidth() const { return mBigThumbnailWidth ; } diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 7867e1573c..44c980c96f 100755 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -547,21 +547,8 @@ void LLSpeakerMgr::updateSpeakerList()  				// For groups, we need to hit the group manager.  				// Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail.  				LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id); -                F32 large_group_delay = 0.f; -                if (gdatap) -                { -                    //This is a viewer-side bandaid for maint-4414 it does not fix the core issue. -                    large_group_delay = (F32)(gdatap->mMemberCount / 5000); -                } -                 -                const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout") + large_group_delay; - -				if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout)) -				{ -					// Request the data the first time around -					LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id); -				} -				else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) + +				if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())  				{  					// Add group members when we get the complete list (note: can take a while before we get that list)  					LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d2050aec3e..965aad517d 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -421,9 +421,7 @@ bool idle_startup()  		gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());  		gSavedSettings.setString("LastGPUString", thisGPU); -		// load dynamic GPU/feature tables from website (S3) -		LLFeatureManager::getInstance()->fetchHTTPTables(); -		 +  		std::string xml_file = LLUI::locateSkin("xui_version.xml");  		LLXMLNodePtr root;  		bool xml_ok = false; @@ -3238,6 +3236,23 @@ bool process_login_success_response()  			LLStringUtil::trim(gDisplayName);  		}  	} +	std::string first_name; +	if(response.has("first_name")) +	{ +		first_name = response["first_name"].asString(); +		LLStringUtil::replaceChar(first_name, '"', ' '); +		LLStringUtil::trim(first_name); +		gAgentUsername = first_name; +	} + +	if(response.has("last_name") && !gAgentUsername.empty() && (gAgentUsername != "Resident")) +	{ +		std::string last_name = response["last_name"].asString(); +		LLStringUtil::replaceChar(last_name, '"', ' '); +		LLStringUtil::trim(last_name); +		gAgentUsername = gAgentUsername + " " + last_name; +	} +  	if(gDisplayName.empty())  	{  		if(response.has("first_name")) @@ -3258,6 +3273,7 @@ bool process_login_success_response()  			gDisplayName += text;  		}  	} +  	if(gDisplayName.empty())  	{  		gDisplayName.assign(gUserCredential->asString()); diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index ef852bc905..bcdf8360ed 100755 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1544,17 +1544,20 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)  		{  			std::string dirname = mTexturesDirName + delem + subdirs[i];  			LL_INFOS() << "Deleting files in directory: " << dirname << LL_ENDL; -			gDirUtilp->deleteFilesInDir(dirname, mask);  			if (purge_directories)  			{ -				LLFile::rmdir(dirname); +				gDirUtilp->deleteDirAndContents(dirname); +			} +			else +			{ +				gDirUtilp->deleteFilesInDir(dirname, mask);  			}  		}  		if (purge_directories)  		{  			gDirUtilp->deleteFilesInDir(mTexturesDirName, mask);  			LLFile::rmdir(mTexturesDirName); -		}		 +		}  	}  	mHeaderIDMap.clear();  	mTexturesSizeMap.clear(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 81fbc471b3..5c9aedcf8f 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1155,8 +1155,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,  	}  	LLSculptParams sculpt_params; -	sculpt_params.setSculptTexture(asset_id); -	sculpt_params.setSculptType(LL_SCULPT_TYPE_MESH); +	sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH);  	hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);  	dialog_refresh_all(); diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp index cad5769042..8a61114852 100755 --- a/indra/newview/llurllineeditorctrl.cpp +++ b/indra/newview/llurllineeditorctrl.cpp @@ -84,7 +84,7 @@ void LLURLLineEditor::copyEscapedURLToClipboard()  	const std::string unescaped_text = wstring_to_utf8str(mText.getWString().substr(left_pos, length));  	LLWString text_to_copy;  	// *HACK: Because LLSLURL is currently broken we cannot use it to check if unescaped_text is a valid SLURL (see EXT-8335). -	if (LLStringUtil::startsWith(unescaped_text, "http://")) // SLURL +	if (LLStringUtil::startsWith(unescaped_text, "http://") || LLStringUtil::startsWith(unescaped_text, "secondlife://")) // SLURL  		text_to_copy = utf8str_to_wstring(LLWeb::escapeURL(unescaped_text));  	else // human-readable location  		text_to_copy = utf8str_to_wstring(unescaped_text); diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 6803adfaa2..1ce42e97b8 100755 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -248,6 +248,7 @@ public:  	void setHomeURL(const std::string& home_url, const std::string& mime_type = LLStringUtil::null) { mHomeURL = home_url; mHomeMimeType = mime_type;};  	void clearCache();  	void setPageZoomFactor( double factor ); +	double getPageZoomFactor() {return mZoomFactor;}  	std::string getMimeType() { return mMimeType; }  	void scaleMouse(S32 *mouse_x, S32 *mouse_y);  	void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2505ae6a9c..38d62dee5e 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -57,6 +57,7 @@  #include "llfacebookconnect.h"  #include "llfilepicker.h"  #include "llfirstuse.h" +#include "llfloaterabout.h"  #include "llfloaterbuy.h"  #include "llfloaterbuycontents.h"  #include "llbuycurrencyhtml.h" @@ -2139,6 +2140,22 @@ class LLAdvancedCheckShowObjectUpdates : public view_listener_t +/////////////////////// +// CHECK FOR UPDATES // +/////////////////////// + + + +class LLAdvancedCheckViewerUpdates : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		LLFloaterAboutUtil::checkUpdatesAndNotify(); +		return true; +	} +}; + +  ////////////////////  // COMPRESS IMAGE //  //////////////////// @@ -7140,11 +7157,10 @@ void handle_selected_texture_info(void*)     			{     				msg.append( llformat("%d ", (S32)(it->second[i])));     			} - -			LLSD args; -			args["MESSAGE"] = msg; -			LLNotificationsUtil::add("SystemMessage", args);     		} +   		LLSD args; +   		args["MESSAGE"] = msg; +   		LLNotificationsUtil::add("SystemMessage", args);  	}  } @@ -8920,6 +8936,7 @@ void initialize_menus()  	// Advanced (toplevel)  	view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");  	view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates"); +	view_listener_t::addMenu(new LLAdvancedCheckViewerUpdates(), "Advanced.CheckViewerUpdates");  	view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");  	view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");  	view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 886725be79..e570657cf9 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -57,6 +57,7 @@  #include "llcallingcard.h"  #include "llbuycurrencyhtml.h"  #include "llfirstuse.h" +#include "llfloaterbump.h"  #include "llfloaterbuyland.h"  #include "llfloaterland.h"  #include "llfloaterregioninfo.h" @@ -2349,7 +2350,8 @@ static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::s  	LLNotificationsUtil::add("GodMessage", args);  	// Treat like a system message and put in chat history. -	chat.mText = av_name.getCompleteName() + ": " + message; +	chat.mSourceType = CHAT_SOURCE_SYSTEM; +	chat.mText = message;  	LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");  	if (nearby_chat) @@ -2860,6 +2862,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  	case IM_FROM_TASK:  		{ +  			if (is_do_not_disturb && !is_owned_by_me)  			{  				return; @@ -2943,17 +2946,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			payload["from_id"] = from_id;  			payload["slurl"] = location;  			payload["name"] = name; -			std::string session_name; +  			if (from_group)  			{  				payload["group_owned"] = "true";  			} -			LLNotification::Params params("ServerObjectMessage"); -			params.substitutions = substitutions; -			params.payload = payload; - -			LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group); +			LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload);  		}  		break; @@ -3789,11 +3788,15 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)  			}  		} -		LLSD msg_notify = LLSD(LLSD::emptyMap()); -		msg_notify["session_id"] = LLUUID(); -        msg_notify["from_id"] = chat.mFromID; -		msg_notify["source_type"] = chat.mSourceType; -        on_new_message(msg_notify); +		if (mesg != "") +		{ +			LLSD msg_notify = LLSD(LLSD::emptyMap()); +			msg_notify["session_id"] = LLUUID(); +			msg_notify["from_id"] = chat.mFromID; +			msg_notify["source_type"] = chat.mSourceType; +			on_new_message(msg_notify); +		} +  	}  } @@ -6263,6 +6266,11 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use  			gCacheName->get(perp, false, boost::bind(&mean_name_callback, _1, _2, _3));  		}  	} +	LLFloaterBump* bumps_floater = LLFloaterBump::getInstance(); +	if(bumps_floater && bumps_floater->isInVisibleChain()) +	{ +		bumps_floater->populateCollisionList(); +	}  }  void process_frozen_message(LLMessageSystem *msgsystem, void **user_data) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index ac3f07fcd8..05d116704e 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2885,6 +2885,9 @@ struct LLFilenameAndTask  {  	LLUUID mTaskID;  	std::string mFilename; + +	// for sequencing in case of multiple updates +	S16 mSerial;  #ifdef _DEBUG  	static S32 sCount;  	LLFilenameAndTask() @@ -2920,9 +2923,17 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)  		return;  	} -	msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum);  	LLFilenameAndTask* ft = new LLFilenameAndTask;  	ft->mTaskID = task_id; +	// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update +	msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial); + +	if (ft->mSerial < object->mInventorySerialNum) +	{ +		// viewer did some changes to inventory that were not saved yet. +		LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL; +		object->mInventorySerialNum = ft->mSerial; +	}  	std::string unclean_filename;  	msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename); @@ -2962,9 +2973,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS  {  	LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data;  	LLViewerObject* object = NULL; -	if(ft && (0 == error_code) && -	   (object = gObjectList.findObject(ft->mTaskID))) + +	if (ft +		&& (0 == error_code) +		&& (object = gObjectList.findObject(ft->mTaskID)) +		&& ft->mSerial >= object->mInventorySerialNum)  	{ +		object->mInventorySerialNum = ft->mSerial;  		if (object->loadTaskInvFile(ft->mFilename))  		{ @@ -2995,7 +3010,7 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS  	}  	else  	{ -		// This Occurs When to requests were made, and the first one +		// This Occurs When two requests were made, and the first one  		// has already handled it.  		LL_DEBUGS() << "Problem loading task inventory. Return code: "  				 << error_code << LL_ENDL; @@ -4637,7 +4652,7 @@ S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID  	return retval;  } -S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer)  {  	S32 retval = 0;  	const LLTextureEntry *tep = getTE(te); @@ -4647,13 +4662,14 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri  		return 0;  	} -	retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); +	setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); +	setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); + +	retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams, isInitFromServer);  	LL_DEBUGS("Material") << "Changing material params for te " << (S32)te  							<< ", object " << mID  			               << " (" << retval << ")"  							<< LL_ENDL; -	setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); -	setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null);  	refreshMaterials();  	return retval; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 05c87c153b..db2749f413 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -330,7 +330,7 @@ public:  	/*virtual*/	S32		setTEMediaFlags(const U8 te, const U8 media_flags );  	/*virtual*/ S32     setTEGlow(const U8 te, const F32 glow);  	/*virtual*/ S32     setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); -	/*virtual*/ S32		setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); +	/*virtual*/ S32		setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer);  	// Used by Materials update functions to properly kick off rebuilds  	// of VBs etc when materials updates require changes. diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index f60829e9e8..24a6758312 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -60,6 +60,7 @@  #include "llfeaturemanager.h"  #include "llviewernetwork.h"  #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived +#include "llsdserialize.h"  namespace LLStatViewer  { @@ -616,8 +617,10 @@ void send_stats()  	body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames");  	body["MinimalSkin"] = false; -	 +  	LLViewerStats::getInstance()->addToMessage(body); + +	LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL;  	LLHTTPClient::post(url, body, new ViewerStatsResponder());  	LLViewerStats::instance().getRecording().resume(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f753448770..b97a1bde99 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -160,6 +160,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;  const S32 MORPH_MASK_REQUESTED_DISCARD = 0; +const F32 MAX_STANDOFF_FROM_ORIGIN = 3; +const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32; +  // Discard level at which to switch to baked textures  // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB  const S32 SWITCH_TO_BAKED_DISCARD = 5; @@ -2132,7 +2135,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)  	// animate the character  	// store off last frame's root position to be consistent with camera position -	LLVector3 root_pos_last = mRoot->getWorldPosition(); +	mLastRootPos = mRoot->getWorldPosition();  	BOOL detailed_update = updateCharacter(agent);  	static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false); @@ -2150,7 +2153,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)  		idleUpdateWindEffect();  	} -	idleUpdateNameTag( root_pos_last ); +	idleUpdateNameTag( mLastRootPos );  	idleUpdateRenderCost();  } @@ -6080,10 +6083,10 @@ void LLVOAvatar::getOffObject()  	{  		return;  	} -	 +  	LLViewerObject* sit_object = (LLViewerObject*)getParent(); -	if (sit_object)  +	if (sit_object)  	{  		stopMotionFromSource(sit_object->getID());  		LLFollowCamMgr::setCameraActive(sit_object->getID(), FALSE); @@ -6100,9 +6103,19 @@ void LLVOAvatar::getOffObject()  	}  	// assumes that transform will not be updated with drawable still having a parent +	// or that drawable had no parent from the start  	LLVector3 cur_position_world = mDrawable->getWorldPosition();  	LLQuaternion cur_rotation_world = mDrawable->getWorldRotation(); +	if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN +		&& (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN +			|| dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE)) +	{ +		// Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent +		// restore coordinates from cache +		cur_position_world = mLastRootPos; +	} +  	// set *local* position based on last *world* position, since we're unparenting the avatar  	mDrawable->mXform.setPosition(cur_position_world);  	mDrawable->mXform.setRotation(cur_rotation_world);	 @@ -6278,6 +6291,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)  BOOL LLVOAvatar::isVisible() const  {  	return mDrawable.notNull() +		&& (!mOrphaned || isSelf())  		&& (mDrawable->isVisible() || mIsDummy);  } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 1c3f4f2aa7..5b4379165a 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -869,6 +869,8 @@ public:  private:  	// set this property only with LLVOAvatar::sitDown method  	BOOL 			mIsSitting; +	// position backup in case of missing data +	LLVector3		mLastRootPos;  /**                    Hierarchy   **                                                                            ** diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 267061b83d..19d61f6e33 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1624,6 +1624,66 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies");  static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives");  static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled) +{ +	bool regen_faces = false; + +	LLVolume *old_volumep, *new_volumep; +	F32 old_lod, new_lod; +	S32 old_num_faces, new_num_faces; + +	old_volumep = getVolume(); +	old_lod = old_volumep->getDetail(); +	old_num_faces = old_volumep->getNumFaces(); +	old_volumep = NULL; + +	{ +		LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); +		const LLVolumeParams &volume_params = getVolume()->getParams(); +		setVolume(volume_params, 0); +	} + +	new_volumep = getVolume(); +	new_lod = new_volumep->getDetail(); +	new_num_faces = new_volumep->getNumFaces(); +	new_volumep = NULL; + +	if ((new_lod != old_lod) || mSculptChanged) +	{ +		compiled = TRUE; +		sNumLODChanges += new_num_faces; + +		if ((S32)getNumTEs() != getVolume()->getNumFaces()) +		{ +			setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. +		} + +		drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + +		{ +			LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); +			regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); +			if (regen_faces) +			{ +				regenFaces(); +			} + +			if (mSculptChanged) +			{ //changes in sculpt maps can thrash an object bounding box without  +				//triggering a spatial group bounding box update -- force spatial group +				//to update bounding boxes +				LLSpatialGroup* group = mDrawable->getSpatialGroup(); +				if (group) +				{ +					group->unbound(); +				} +			} +		} +	} + +	return regen_faces; +} +  BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  {  	LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES); @@ -1664,83 +1724,35 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  		return TRUE; // No update to complete  	} -	if (mVolumeChanged || mFaceMappingChanged ) +	if (mVolumeChanged || mFaceMappingChanged)  	{  		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); -		compiled = TRUE; +		bool was_regen_faces = false;  		if (mVolumeChanged)  		{ -			LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); -			LLVolumeParams volume_params = getVolume()->getParams(); -			setVolume(volume_params, 0); +			was_regen_faces = lodOrSculptChanged(drawable, compiled);  			drawable->setState(LLDrawable::REBUILD_VOLUME);  		} - +		else if (mSculptChanged || mLODChanged)  		{ +			compiled = TRUE; +			was_regen_faces = lodOrSculptChanged(drawable, compiled); +		} + +		if (!was_regen_faces) {  			LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES);  			regenFaces(); -			genBBoxes(FALSE);  		} + +		genBBoxes(FALSE);  	} -	else if ((mLODChanged) || (mSculptChanged)) +	else if (mLODChanged || mSculptChanged)  	{  		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - -		LLVolume *old_volumep, *new_volumep; -		F32 old_lod, new_lod; -		S32 old_num_faces, new_num_faces ; - -		old_volumep = getVolume(); -		old_lod = old_volumep->getDetail(); -		old_num_faces = old_volumep->getNumFaces() ; -		old_volumep = NULL ; - -		{ -			LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME); -			LLVolumeParams volume_params = getVolume()->getParams(); -			setVolume(volume_params, 0); -		} - -		new_volumep = getVolume(); -		new_lod = new_volumep->getDetail(); -		new_num_faces = new_volumep->getNumFaces() ; -		new_volumep = NULL ; - -		if ((new_lod != old_lod) || mSculptChanged) -		{ -			compiled = TRUE; -			sNumLODChanges += new_num_faces ; -	 -			if((S32)getNumTEs() != getVolume()->getNumFaces()) -			{ -				setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. -			} - -			drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - -			{ -				LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES); -				if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs()) -				{ -					regenFaces(); -				} -				genBBoxes(FALSE); - -				if (mSculptChanged) -				{ //changes in sculpt maps can thrash an object bounding box without  -				  //triggering a spatial group bounding box update -- force spatial group -				  //to update bounding boxes -					LLSpatialGroup* group = mDrawable->getSpatialGroup(); -					if (group) -					{ -						group->unbound(); -					} -				} -			} -		} - +		compiled = TRUE; +		lodOrSculptChanged(drawable, compiled);  		genBBoxes(FALSE);  	}  	// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local @@ -2010,7 +2022,7 @@ void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLM  		LLTextureEntry* texture_entry = pVol->getTE(te);  		if (texture_entry && (texture_entry->getMaterialID() == pMaterialID))  		{ -			pVol->setTEMaterialParams(te, pMaterialParams); +			pVol->setTEMaterialParams(te, pMaterialParams, FALSE);  		}  	}  } @@ -2081,7 +2093,7 @@ bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)  	for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)  	{  		LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); -		LLViewerObject::setTEMaterialParams(it->first, it->second); +		LLViewerObject::setTEMaterialParams(it->first, it->second, FALSE);  	}  	//clear wait-list @@ -2158,7 +2170,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)  	for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)  	{  		LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); -		LLViewerObject::setTEMaterialParams(it->first, it->second); +		LLViewerObject::setTEMaterialParams(it->first, it->second, FALSE);  	}  	//clear wait-list @@ -2167,7 +2179,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)  	return 0 != new_material.size();  } -S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer)  {  	LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams); @@ -2264,7 +2276,7 @@ S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialPa  		}  	} -	S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); +	S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial, isInitFromServer);  	LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res  							 << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" ) @@ -4163,7 +4175,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  	}  	//build matrix palette -	static const size_t kMaxJoints = 64; +	static const size_t kMaxJoints = 52;  	LLMatrix4a mp[kMaxJoints];  	LLMatrix4* mat = (LLMatrix4*) mp; @@ -4174,6 +4186,8 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  		LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);          if (!joint)          { +            // Fall back to a point inside the avatar if mesh is +            // rigged to an unknown joint.              joint = avatar->getJoint("mPelvis");          }  		if (joint) @@ -4220,8 +4234,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  						wght[k] = w - floorf(w);  						scale += wght[k];  					} - -					wght *= 1.f/scale; +                    // This is enforced  in unpackVolumeFaces() +                    llassert(scale>0.f); +                    wght *= 1.f / scale;  					for (U32 k = 0; k < 4; k++)  					{ @@ -4229,9 +4244,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  						LLMatrix4a src;  						// Insure ref'd bone is in our clamped array of mats -						llassert(idx[k] < kMaxJoints); -						// clamp k to kMaxJoints to avoid reading garbage off stack in release -						src.setMul(mp[idx[(k < kMaxJoints) ? k : 0]], w); +						// clamp idx to maxJoints to avoid reading garbage off stack in release +                        S32 index = llclamp((S32)idx[k],(S32)0,(S32)kMaxJoints-1); +						src.setMul(mp[index], w);  						final_mat.add(src);  					} diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index bbaca316b0..ff7438ac09 100755 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -192,7 +192,7 @@ public:  	static void	setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te); -	/*virtual*/ S32		setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); +	/*virtual*/ S32		setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer);  	/*virtual*/ S32		setTEScale(const U8 te, const F32 s, const F32 t);  	/*virtual*/ S32		setTEScaleS(const U8 te, const F32 s);  	/*virtual*/ S32		setTEScaleT(const U8 te, const F32 t); @@ -339,6 +339,10 @@ protected:  	void cleanUpMediaImpls();  	void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;  	void removeMediaImpl(S32 texture_index) ; + +private: +	bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled); +  public:  	static S32 getRenderComplexityMax() {return mRenderComplexity_last;} diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index bfae142812..837b30586b 100755 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -383,6 +383,7 @@ void LLWorldMap::reloadItems(bool force)  		LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_MATURE_EVENT);  		LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_ADULT_EVENT);  		LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE); +		LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT);  	}  } diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml index aa6bc53672..299322001b 100755 --- a/indra/newview/skins/default/xui/da/menu_viewer.xml +++ b/indra/newview/skins/default/xui/da/menu_viewer.xml @@ -37,7 +37,7 @@  		<menu_item_separator/>  		<menu_item_call label="Profil for sted" name="Place Profile"/>  		<menu_item_call label="Om land" name="About Land"/> -		<menu_item_call label="Region/Estate" name="Region/Estate"/> +		<menu_item_call label="Region/Estate" name="RegionEstate"/>  		<menu_item_call label="Køb dette land" name="Buy Land"/>  		<menu_item_call label="Mit land" name="My Land"/>  		<menu label="Vis" name="LandShow"> diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 33b876bdb9..aad3b9d062 100755 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1311,9 +1311,6 @@ Prøv igen om lidt.  	<notification name="NoValidCircuit">  		Ingen gyldig kode for kredsløb.  	</notification> -	<notification name="NoValidTimestamp"> -		Ikke et gyldigt klokkeslæt. -	</notification>  	<notification name="NoPendingConnection">  		Kunne ikke skabe fast forbindelse.  	</notification> diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml index 1924ff4ec3..956530c990 100755 --- a/indra/newview/skins/default/xui/de/menu_viewer.xml +++ b/indra/newview/skins/default/xui/de/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Fliegen" name="Fly"/>  			<menu_item_check label="Immer rennen" name="Always Run"/>  			<menu_item_call label="Animation meines Avatars stoppen" name="Stop Animating My Avatar"/> -			<menu_item_call label="Gehen/Rennen/Fliegen..." name="Walk / run / fly"/> +			<menu_item_call label="Gehen/Rennen/Fliegen..." name="WalkRunFly"/>  		</menu>  		<menu label="Status" name="Status">  			<menu_item_check label="Abwesend" name="Away"/> @@ -64,7 +64,7 @@  		<menu_item_call label="Foto" name="Take Snapshot"/>  		<menu_item_call label="Ortsprofil" name="Place Profile"/>  		<menu_item_call label="Landinformationen" name="About Land"/> -		<menu_item_call label="Region/Grundbesitz" name="Region/Estate"/> +		<menu_item_call label="Region/Grundbesitz" name="RegionEstate"/>  		<menu_item_call label="Mein Landbesitz..." name="My Land"/>  		<menu_item_call label="Dieses Land kaufen" name="Buy Land"/>  		<menu label="Anzeigen" name="LandShow"> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 0b1c18cd51..fa7db0a8a3 100755 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2802,9 +2802,6 @@ Versuchen Sie es in einigen Minuten erneut.  	<notification name="NoValidCircuit">  		Kein gültiger Verbindungscode.  	</notification> -	<notification name="NoValidTimestamp"> -		Kein gültiger Zeitstempel. -	</notification>  	<notification name="NoPendingConnection">  		Verbindung kann nicht hergestellt werden.  	</notification> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 60f36770bb..ec87b3684e 100755 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -43,6 +43,14 @@          top_pad="5"          height="25"          width="180" /> +      <button +        follows="left|top" +        label="Check for updates" +        name="update_btn" +        left_pad="70" +        top_delta="0" +        height="25" +        width="180" />      </panel>      <panel        border="true"  diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 90d45d5ebc..edf028bf60 100755 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -2013,7 +2013,7 @@ Only large parcels can be listed in search.               name="AllowedText"               top="0"               width="230"> -                Allowed Residents +                Allowed Residents ([COUNT])              </text>              <name_list               column_padding="0" @@ -2062,7 +2062,7 @@ Only large parcels can be listed in search.               name="BanCheck"               top="0"               width="200"> -                Banned Residents +                Banned Residents ([COUNT])              </text>              <name_list               column_padding="0" diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml index 1f2fe62b3c..126e3aac48 100755 --- a/indra/newview/skins/default/xui/en/floater_bumps.xml +++ b/indra/newview/skins/default/xui/en/floater_bumps.xml @@ -7,7 +7,7 @@   help_topic="floater_bumps"   save_rect="true"   title="BUMPS, PUSHES & HITS" - width="400"> + width="420">      <floater.string       name="none_detected">          None detected @@ -34,7 +34,7 @@      </floater.string>      <floater.string       name="timeStr"> -        [[hour,datetime,slt]:[min,datetime,slt]] +        [[hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt]]      </floater.string>      <scroll_list       draw_border="false" @@ -45,5 +45,5 @@       multi_select="true"       name="bump_list"       top="20" -     width="388" /> +     width="408" />  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_experiences.xml b/indra/newview/skins/default/xui/en/floater_experiences.xml index 70e7507907..442da887c5 100644 --- a/indra/newview/skins/default/xui/en/floater_experiences.xml +++ b/indra/newview/skins/default/xui/en/floater_experiences.xml @@ -12,7 +12,7 @@    name="floater_experiences"    save_rect="true"    single_instance="true" -  reuse_instance="false" +     bg_opaque_color="0 0.5 0 0.3"    title="EXPERIENCES">    <tab_container diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 91adec0789..61002bf1b5 100755 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -565,14 +565,6 @@      <menu_item_call       label="Delete"       layout="topleft" -     name="Remove Link"> -        <menu_item_call.on_click -         function="Inventory.DoToSelected" -         parameter="delete" /> -    </menu_item_call> -    <menu_item_call -     label="Delete" -     layout="topleft"       name="Delete">          <menu_item_call.on_click           function="Inventory.DoToSelected" @@ -785,14 +777,6 @@  	 layout="topleft"  	 name="Marketplace Separator" />  	<menu_item_call -	 label="Copy to Merchant Outbox" -	 layout="topleft" -	 name="Merchant Copy"> -		<menu_item_call.on_click -		 function="Inventory.DoToSelected" -		 parameter="copy_to_outbox" /> -	</menu_item_call> -	<menu_item_call          label="Copy to Marketplace Listings"          layout="topleft"          name="Marketplace Copy"> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index e91eea04d1..73ca7c529d 100755 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -108,6 +108,12 @@               function="Floater.Show"               parameter="sl_about" />          </menu_item_call> +        <menu_item_call +         label="Check for Updates" +         name="Check for Updates"> +            <menu_item_call.on_click +             function="Advanced.CheckViewerUpdates"/> +        </menu_item_call>      </menu>      <menu_item_check        label="Show Debug Menu" diff --git a/indra/newview/skins/default/xui/en/menu_url_email.xml b/indra/newview/skins/default/xui/en/menu_url_email.xml new file mode 100644 index 0000000000..6467fe5c90 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_url_email.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Email Popup"> +    <menu_item_call +     label="Compose Email in an External client" +     layout="topleft" +     name="email_open_external"> +        <menu_item_call.on_click +         function="Url.OpenExternal" /> +    </menu_item_call> +    <menu_item_separator +     layout="topleft" /> +    <menu_item_call +     label="Copy Email to clipboard" +     layout="topleft" +     name="email_copy"> +        <menu_item_call.on_click +         function="Url.CopyLabel" /> +    </menu_item_call> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 2463c5f43b..3f557d0d0f 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -134,7 +134,7 @@          </menu_item_call>          <menu_item_call           label="Walk / run / fly..." -         name="Walk / run / fly"> +         name="WalkRunFly">            <menu_item_call.on_click             function="Floater.ToggleOrBringToFront"             parameter="moveview" /> @@ -509,7 +509,7 @@          </menu_item_call>          <menu_item_call           label="Region / Estate" -         name="Region/Estate"> +         name="RegionEstate">              <menu_item_call.on_click               function="Floater.Show"               parameter="region_info" /> @@ -1438,7 +1438,7 @@                   function="Floater.Show"                   parameter="bumps" />          </menu_item_call> -        <menu_item_separator/>     +        <menu_item_separator/>          <menu_item_call           label="About [APP_NAME]"           name="About Second Life"> @@ -1446,6 +1446,12 @@               function="Floater.Show"               parameter="sl_about" />          </menu_item_call> +        <menu_item_call +         label="Check for Updates" +         name="Check for Updates"> +          <menu_item_call.on_click +           function="Advanced.CheckViewerUpdates"/> +        </menu_item_call>      </menu>      <menu       create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f847c73287..70ba4d5077 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -819,6 +819,33 @@ If you no longer wish to have these abilities granted to this role, disable them        notext="Cancel"        yestext="Eject"/>    </notification> +   +  <notification +    icon="alertmodal.tga" +    name="BanGroupMemberWarning" +    type="alertmodal"> +     You are about to ban [AVATAR_NAME] from the group. +     <tag>group</tag> +     <tag>confirm</tag> +     <usetemplate +      ignoretext="Confirm banning a participant from group" +      name="okcancelignore" +      notext="Cancel" +      yestext="Ban"/> +  </notification> +  <notification +    icon="alertmodal.tga" +    name="BanGroupMembersWarning" +    type="alertmodal"> +     You are about to ban [COUNT] members from group. +     <tag>group</tag> +     <tag>confirm</tag> +     <usetemplate +      ignoretext="Confirm banning multiple members from group" +      name="okcancelignore" +      notext="Cancel" +      yestext="Ban"/> +  </notification>    <notification     icon="alertmodal.tga" @@ -3892,6 +3919,53 @@ see [[INFO_URL] Information about this update]       name="okbutton"       yestext="OK"/>    </notification> +   +  <notification + icon="alertmodal.tga" + name="UpdateDownloadInProgress" + type="alertmodal"> +An update is available! +It's downloading in the background and we will prompt you to restart your viewer to finish installing it as soon as it's ready. +    <tag>confirm</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> +   +  <notification + icon="alertmodal.tga" + name="UpdateDownloadComplete" + type="alertmodal"> +An update was downloaded. It will be installed during restart. +    <tag>confirm</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification + icon="alertmodal.tga" + name="UpdateCheckError" + type="alertmodal"> +An error occured while checking for update. +Please try again later. +    <tag>confirm</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification + icon="alertmodal.tga" + name="UpdateViewerUpToDate" + type="alertmodal"> +Your viewer is up to date! +If you can't wait to try out the latest features and fixes, check out the Alternate Viewers page. http://wiki.secondlife.com/wiki/Linden_Lab_Official:Alternate_Viewers. +    <tag>confirm</tag> +    <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification>    <notification     icon="alertmodal.tga" @@ -4217,6 +4291,21 @@ You have reached your maximum number of groups. Please leave some group before j    <notification     icon="alert.tga" +   name="GroupLimitInfo" +   type="alert"> +The group limit for base accounts is [MAX_BASIC], and for [https://secondlife.com/premium/ premium] +accounts is [MAX_PREMIUM]. +If you downgraded your account, you will need to get below [MAX_BASIC] group limit before you can join more. + +[https://secondlife.com/my/account/membership.php Upgrade today!] +    <tag>group</tag> +    <usetemplate +     name="okbutton" +     yestext="Close"/> +  </notification> + +  <notification +   icon="alert.tga"     name="KickUser"     type="alert">     <tag>win</tag> @@ -7029,15 +7118,6 @@ No valid circuit code.    <notification  	icon="notify.tga" -	name="NoValidTimestamp" -   persist="true" -	type="notify"> -   <tag>fail</tag> -No valid timestamp. -  </notification> - -  <notification -	icon="notify.tga"  	name="NoPendingConnection"     persist="true"  	type="notify"> diff --git a/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml b/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml index c76b958eda..c357f9e7d5 100644 --- a/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml +++ b/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml @@ -47,19 +47,19 @@        height="12"        follows="top|left">     </text> -  <scroll_list +  <name_list      draw_heading="false"      left="3"      width="225"      height="75"      follows="all"      name="experience_list"> -    <columns +    <name_list.columns        width="225"        user_resize="false"        name="experience_name"        label="Name"/> -  </scroll_list> +  </name_list>    <button      layout="topleft"      follows="top|right" 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 0518688f45..0a85477bf4 100755 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -21,7 +21,7 @@    </panel.string>    <panel.string     name="ItemcountUnknown"> - +    Fetched [ITEM_COUNT] Items [FILTER]    </panel.string>    <text  		     type="string" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 2d4665c128..4fb8b9a67f 100755 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -506,7 +506,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                  left="3"                  use_ellipses="true"                  name="groupcount"> -              You belong to [COUNT] groups, and can join [REMAINING] more. +              You belong to [COUNT] groups, and can join [REMAINING] more.  [secondlife:/// Want more?]              </text>              <group_list               allow_select="true"  diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 2e778014c5..3e96160834 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -216,7 +216,7 @@       control_name="QAMode"       follows="top|left"       height="15" -     label="Show Developer Menu" +     label="Show Develop Menu"       layout="topleft"       left="30"       name="show_develop_menu_check" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 1e9a1aa27c..b201e071ef 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -270,7 +270,7 @@           value="1" />        -->          <combo_box.item -         label="Download and install updates manually" +         label="I will download and install updates manually"           name="Install_manual"           value="0" />    </combo_box> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b7e0cff146..4eb6e2462d 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -238,6 +238,7 @@ Please try logging in again in a minute.</string>  	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>  	<string name="TooltipTooManyWearables">You can't wear a folder containing more than [AMOUNT] items.  You can change this limit in Advanced > Show Debug Settings > WearFolderLimit.</string>  	<string name="TooltipPrice" value="L$[AMOUNT]: "/> +	<string name="TooltipSLIcon">This links to a page on the official SecondLife.com or LindenLab.com domain.</string>      <string name="TooltipOutboxDragToWorld">You can't rez items from the Marketplace Listings folder</string>      <string name="TooltipOutboxWorn">You can't put items you are wearing in the Marketplace Listings folder</string> @@ -277,6 +278,7 @@ Please try logging in again in a minute.</string>  	<string name="TooltipMapUrl">Click to view this location on a map</string>  	<string name="TooltipSLAPP">Click to run the secondlife:// command</string>  	<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" /> +	<string name="TooltipEmail">Click to compose an email</string>  	<!-- text for SLURL labels -->  	<string name="SLurlLabelTeleport">Teleport to</string> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index 5118171d80..f6ebb498ec 100755 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Volar" name="Fly"/>  			<menu_item_check label="Correr siempre" name="Always Run"/>  			<menu_item_call label="Parar mis animaciones" name="Stop Animating My Avatar"/> -			<menu_item_call label="Caminar / Correr / Volar..." name="Walk / run / fly"/> +			<menu_item_call label="Caminar / Correr / Volar..." name="WalkRunFly"/>  		</menu>  		<menu label="Estado" name="Status">  			<menu_item_check label="Ausente" name="Away"/> @@ -63,7 +63,7 @@  		<menu_item_call label="Foto" name="Take Snapshot"/>  		<menu_item_call label="Perfil del lugar" name="Place Profile"/>  		<menu_item_call label="Acerca del terreno" name="About Land"/> -		<menu_item_call label="Región/Estado" name="Region/Estate"/> +		<menu_item_call label="Región/Estado" name="RegionEstate"/>  		<menu_item_call label="Mis terrenos..." name="My Land"/>  		<menu_item_call label="Comprar este terreno" name="Buy Land"/>  		<menu label="Mostrar" name="LandShow"> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 9578e1b863..1e367b33fc 100755 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2796,9 +2796,6 @@ Por favor, vuelve a intentarlo en unos momentos.  	<notification name="NoValidCircuit">  		Circuito de código inválido.  	</notification> -	<notification name="NoValidTimestamp"> -		Fecha inválida. -	</notification>  	<notification name="NoPendingConnection">  		No se puede crear la conexión.  	</notification> diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index 33b2ba6982..788cdbf856 100755 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Voler" name="Fly"/>  			<menu_item_check label="Toujours courir" name="Always Run"/>  			<menu_item_call label="Arrêter mon animation" name="Stop Animating My Avatar"/> -			<menu_item_call label="Marcher / Courir / Voler..." name="Walk / run / fly"/> +			<menu_item_call label="Marcher / Courir / Voler..." name="WalkRunFly"/>  		</menu>  		<menu label="Statut" name="Status">  			<menu_item_check label="Absent" name="Away"/> @@ -64,7 +64,7 @@  		<menu_item_call label="Photo" name="Take Snapshot"/>  		<menu_item_call label="Profil du lieu" name="Place Profile"/>  		<menu_item_call label="À propos du terrain" name="About Land"/> -		<menu_item_call label="Région/Domaine" name="Region/Estate"/> +		<menu_item_call label="Région/Domaine" name="RegionEstate"/>  		<menu_item_call label="Mes terrains..." name="My Land"/>  		<menu_item_call label="Acheter ce terrain" name="Buy Land"/>  		<menu label="Afficher" name="LandShow"> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index f13a80fe61..29e6fe1979 100755 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2788,9 +2788,6 @@ Veuillez réessayer dans quelques minutes.  	<notification name="NoValidCircuit">  		Aucun code de circuit valide.  	</notification> -	<notification name="NoValidTimestamp"> -		Timestamp non valide. -	</notification>  	<notification name="NoPendingConnection">  		Impossible de créer la connexion en attente.  	</notification> diff --git a/indra/newview/skins/default/xui/fr/panel_login.xml b/indra/newview/skins/default/xui/fr/panel_login.xml index 40082cb265..2b8249c8a9 100755 --- a/indra/newview/skins/default/xui/fr/panel_login.xml +++ b/indra/newview/skins/default/xui/fr/panel_login.xml @@ -1,9 +1,6 @@  <?xml version="1.0" encoding="utf-8"?>  <panel name="panel_login">  	<panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=fr</panel.string> -	<panel.string name="forgot_password_url"> -		http://secondlife.com/account/request.php?lang=fr -	</panel.string>  	<layout_stack name="ui_stack">  		<layout_panel name="ui_container">  			<combo_box label="Nom d'utilisateur" name="username_combo" tool_tip="Nom d'utilisateur que vous avez choisi lors de votre inscription (par exemple, bobsmith12 ou Steller Sunshine)."/> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index 3f4c370ccd..18ddad5ee8 100755 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Vola" name="Fly"/>  			<menu_item_check label="Corri sempre" name="Always Run"/>  			<menu_item_call label="Ferma animazione" name="Stop Animating My Avatar"/> -			<menu_item_call label="Cammina / corri / vola..." name="Walk / run / fly"/> +			<menu_item_call label="Cammina / corri / vola..." name="WalkRunFly"/>  		</menu>  		<menu label="Stato" name="Status">  			<menu_item_check label="Assente" name="Away"/> @@ -64,7 +64,7 @@  		<menu_item_call label="Istantanea" name="Take Snapshot"/>  		<menu_item_call label="Profilo del luogo" name="Place Profile"/>  		<menu_item_call label="Informazioni sul terreno" name="About Land"/> -		<menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/> +		<menu_item_call label="Regione/proprietà immobiliare" name="RegionEstate"/>  		<menu_item_call label="Terreni posseduti..." name="My Land"/>  		<menu_item_call label="Acquista questo terreno" name="Buy Land"/>  		<menu label="Mostra" name="LandShow"> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 06f2b70dcf..61131b09c3 100755 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2793,9 +2793,6 @@ Riprova tra qualche istante.  	<notification name="NoValidCircuit">  		Nessun codice circuito valido.  	</notification> -	<notification name="NoValidTimestamp"> -		Nessuna data/timestamp valido. -	</notification>  	<notification name="NoPendingConnection">  		Impossibile creare la connessione in sospeso.  	</notification> diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml index 3f756c5f94..0384dc1efc 100755 --- a/indra/newview/skins/default/xui/ja/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="飛ぶ" name="Fly"/>  			<menu_item_check label="常に走る" name="Always Run"/>  			<menu_item_call label="私のアニメーションを停止する" name="Stop Animating My Avatar"/> -			<menu_item_call label="歩行/走行/飛行..." name="Walk / run / fly"/> +			<menu_item_call label="歩行/走行/飛行..." name="WalkRunFly"/>  		</menu>  		<menu label="ログイン" name="Status">  			<menu_item_check label="一時退席中" name="Away"/> @@ -64,7 +64,7 @@  		<menu_item_call label="スナップショット" name="Take Snapshot"/>  		<menu_item_call label="場所のプロフィール" name="Place Profile"/>  		<menu_item_call label="土地情報" name="About Land"/> -		<menu_item_call label="地域 / 不動産" name="Region/Estate"/> +		<menu_item_call label="地域 / 不動産" name="RegionEstate"/>  		<menu_item_call label="保有地..." name="My Land"/>  		<menu_item_call label="この土地を購入" name="Buy Land"/>  		<menu label="表示" name="LandShow"> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 694f38467e..5f0ce7a73b 100755 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2836,9 +2836,6 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ  	<notification name="NoValidCircuit">  		回路コードが無効です。  	</notification> -	<notification name="NoValidTimestamp"> -		タイムスタンプが無効です。 -	</notification>  	<notification name="NoPendingConnection">  		接続を生成できません。  	</notification> diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml index ef3fe71945..6fd498eea8 100755 --- a/indra/newview/skins/default/xui/pl/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml @@ -33,7 +33,7 @@  		<menu_item_call label="Zrób zdjęcie" name="Take Snapshot"/>  		<menu_item_call label="Profil miejsca" name="Place Profile"/>  		<menu_item_call label="O posiadłości" name="About Land"/> -		<menu_item_call label="Region/Majątek" name="Region/Estate"/> +		<menu_item_call label="Region/Majątek" name="RegionEstate"/>  		<menu_item_call label="Moje posiadłości" name="My Land"/>  		<menu_item_call label="Kup posiadłość" name="Buy Land"/>  		<menu label="Pokaż" name="LandShow"> diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 62fda0d601..c4a65d92b4 100755 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -2368,9 +2368,6 @@ Spróbuj ponowanie za kilka minut.  	<notification name="NoValidCircuit">  		Nieważny obwód kodowania.  	</notification> -	<notification name="NoValidTimestamp"> -		Niewłaściwy czas zapisu. -	</notification>  	<notification name="NoPendingConnection">  		Brak możliwości wykonania połączenia.  	</notification> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index 9b3b6077ed..3d5d9eccc6 100755 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Voar" name="Fly"/>  			<menu_item_check label="Correr sempre" name="Always Run"/>  			<menu_item_call label="Parar minha animação" name="Stop Animating My Avatar"/> -			<menu_item_call label="Andar/correr/voar..." name="Walk / run / fly"/> +			<menu_item_call label="Andar/correr/voar..." name="WalkRunFly"/>  		</menu>  		<menu label="Status" name="Status">  			<menu_item_check label="Ausente" name="Away"/> @@ -64,7 +64,7 @@  		<menu_item_call label="Foto" name="Take Snapshot"/>  		<menu_item_call label="Perfil da região" name="Place Profile"/>  		<menu_item_call label="Sobre terrenos" name="About Land"/> -		<menu_item_call label="Região/Propriedade" name="Region/Estate"/> +		<menu_item_call label="Região/Propriedade" name="RegionEstate"/>  		<menu_item_call label="Meus terrenos..." name="My Land"/>  		<menu_item_call label="Comprar este terreno" name="Buy Land"/>  		<menu label="Mostrar" name="LandShow"> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 29b85d9e97..a264495404 100755 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -2777,9 +2777,6 @@ Por favor, tente novamente em alguns instantes.  	<notification name="NoValidCircuit">  		Código de circuito inválido.  	</notification> -	<notification name="NoValidTimestamp"> -		Hora inválida. -	</notification>  	<notification name="NoPendingConnection">  		Impossível criar a conexão pendente.  	</notification> diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml index 958105a70f..d22ca845f9 100755 --- a/indra/newview/skins/default/xui/ru/menu_viewer.xml +++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Полет" name="Fly"/>  			<menu_item_check label="Всегда бегать" name="Always Run"/>  			<menu_item_call label="Остановить анимацию" name="Stop Animating My Avatar"/> -			<menu_item_call label="Ходьба / бег / полет..." name="Walk / run / fly"/> +			<menu_item_call label="Ходьба / бег / полет..." name="WalkRunFly"/>  		</menu>  		<menu label="Статус" name="Status">  			<menu_item_check label="Нет на месте" name="Away"/> @@ -62,7 +62,7 @@  		<menu_item_call label="Снимок" name="Take Snapshot"/>  		<menu_item_call label="Профиль места" name="Place Profile"/>  		<menu_item_call label="О земле" name="About Land"/> -		<menu_item_call label="Регион/землевладение" name="Region/Estate"/> +		<menu_item_call label="Регион/землевладение" name="RegionEstate"/>  		<menu_item_call label="Мои владения..." name="My Land"/>  		<menu_item_call label="Купить эту землю" name="Buy Land"/>  		<menu label="Показать" name="LandShow"> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index acf3ce608f..70b9a25590 100755 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -2788,9 +2788,6 @@ http://secondlife.com/download.  	<notification name="NoValidCircuit">  		Нет подходящего кода канала.  	</notification> -	<notification name="NoValidTimestamp"> -		Нет подходящей метки времени. -	</notification>  	<notification name="NoPendingConnection">  		Невозможно создать отложенное соединение.  	</notification> diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml index cc8d8c895b..cea57011dd 100755 --- a/indra/newview/skins/default/xui/tr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="Uç" name="Fly"/>  			<menu_item_check label="Daima Koş" name="Always Run"/>  			<menu_item_call label="Beni Anime Etmeyi Durdur" name="Stop Animating My Avatar"/> -			<menu_item_call label="Yürü / koş / uç..." name="Walk / run / fly"/> +			<menu_item_call label="Yürü / koş / uç..." name="WalkRunFly"/>  		</menu>  		<menu label="Durum" name="Status">  			<menu_item_check label="Uzakta" name="Away"/> @@ -62,7 +62,7 @@  		<menu_item_call label="Anlık Görüntü" name="Take Snapshot"/>  		<menu_item_call label="Profili yerleştir" name="Place Profile"/>  		<menu_item_call label="Arazi hakkında" name="About Land"/> -		<menu_item_call label="Bölge / Gayrimenkul" name="Region/Estate"/> +		<menu_item_call label="Bölge / Gayrimenkul" name="RegionEstate"/>  		<menu_item_call label="Sahip olduğum arazi parçaları..." name="My Land"/>  		<menu_item_call label="Bu araziyi satın al" name="Buy Land"/>  		<menu label="Göster" name="LandShow"> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index a6c69c7ab2..df22251b3d 100755 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -2788,9 +2788,6 @@ Lütfen biraz sonra tekrar deneyin.  	<notification name="NoValidCircuit">  		Geçerli bir devre kodu yok.  	</notification> -	<notification name="NoValidTimestamp"> -		Geçerli bir zaman damgası yok. -	</notification>  	<notification name="NoPendingConnection">  		Beklemedeki bağlantı oluşturulamıyor.  	</notification> diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml index e94f52a401..9572ad49d3 100755 --- a/indra/newview/skins/default/xui/zh/menu_viewer.xml +++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml @@ -15,7 +15,7 @@  			<menu_item_check label="飛行" name="Fly"/>  			<menu_item_check label="以跑代步" name="Always Run"/>  			<menu_item_call label="停止我身上的動作" name="Stop Animating My Avatar"/> -			<menu_item_call label="行走 / 跑步 / 飛行…" name="Walk / run / fly"/> +			<menu_item_call label="行走 / 跑步 / 飛行…" name="WalkRunFly"/>  		</menu>  		<menu label="狀態" name="Status">  			<menu_item_check label="離開" name="Away"/> @@ -62,7 +62,7 @@  		<menu_item_call label="快照" name="Take Snapshot"/>  		<menu_item_call label="地點小檔案" name="Place Profile"/>  		<menu_item_call label="土地資料" name="About Land"/> -		<menu_item_call label="地區/領地" name="Region/Estate"/> +		<menu_item_call label="地區/領地" name="RegionEstate"/>  		<menu_item_call label="我所擁有的土地…" name="My Land"/>  		<menu_item_call label="購買這塊土地" name="Buy Land"/>  		<menu label="顯示" name="LandShow"> diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index 179f01e90d..0a98101b60 100755 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -2778,9 +2778,6 @@ SHA1 指紋:[MD5_DIGEST]  	<notification name="NoValidCircuit">  		沒有有效的線路碼。  	</notification> -	<notification name="NoValidTimestamp"> -		沒有有效的時間戳記。 -	</notification>  	<notification name="NoPendingConnection">  		無法建立待通的連線。  	</notification> diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index c152493a51..788955a1b2 100755 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -132,6 +132,7 @@ public:  	void startChecking(bool install_if_ready);  	void stopChecking(); +	bool forceCheck();  	bool isChecking();  	LLUpdaterService::eUpdaterState getState(); @@ -266,6 +267,46 @@ void LLUpdaterServiceImpl::stopChecking()  	setState(LLUpdaterService::TERMINAL);  } +bool LLUpdaterServiceImpl::forceCheck() +{ +	if (!mIsDownloading && getState() != LLUpdaterService::CHECKING_FOR_UPDATE) +	{ +		if (mIsChecking) +		{ +			// Service is running, just reset the timer +			if (mTimer.getStarted()) +			{ +				mTimer.setTimerExpirySec(0); +				setState(LLUpdaterService::CHECKING_FOR_UPDATE); +				return true; +			} +		} +		else if (!mChannel.empty() && !mVersion.empty()) +		{ +			// one time check +			bool has_install = checkForInstall(false); +			if (!has_install) +			{ +				std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL(); +				if (!query_url.empty()) +				{ +					setState(LLUpdaterService::CHECKING_FOR_UPDATE); +					mUpdateChecker.checkVersion(query_url, mChannel, mVersion, +						mPlatform, mPlatformVersion, mUniqueId, +						mWillingToTest); +					return true; +				} +				else +				{ +					LL_WARNS("UpdaterService") +						<< "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid() << LL_ENDL; +				} +			} +		} +	} +	return false; +} +  bool LLUpdaterServiceImpl::isChecking()  {  	return mIsChecking; @@ -402,9 +443,9 @@ bool LLUpdaterServiceImpl::checkForResume()  void LLUpdaterServiceImpl::error(std::string const & message)  { +	setState(LLUpdaterService::TEMPORARY_ERROR);  	if(mIsChecking)  	{ -		setState(LLUpdaterService::TEMPORARY_ERROR);  		restartTimer(mCheckPeriod);  	}  } @@ -449,8 +490,12 @@ void LLUpdaterServiceImpl::response(LLSD const & content)  	else  	{  		LL_WARNS("UpdaterService") << "Invalid update query response ignored; retry in " -								   << mCheckPeriod << " seconds" << LL_ENDL; -		restartTimer(mCheckPeriod); +			<< mCheckPeriod << " seconds" << LL_ENDL; +		setState(LLUpdaterService::TEMPORARY_ERROR); +		if (mIsChecking) +		{ +			restartTimer(mCheckPeriod); +		}  	}  } @@ -672,6 +717,11 @@ void LLUpdaterService::stopChecking()  	mImpl->stopChecking();  } +bool LLUpdaterService::forceCheck() +{ +	return mImpl->forceCheck(); +} +  bool LLUpdaterService::isChecking()  {  	return mImpl->isChecking(); diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 0ddf24935b..95bbe1695c 100755 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -84,6 +84,7 @@ public:  	void startChecking(bool install_if_ready = false);  	void stopChecking(); +	bool forceCheck();  	bool isChecking();  	eUpdaterState getState(); | 
