diff options
Diffstat (limited to 'indra')
178 files changed, 4244 insertions, 1161 deletions
| diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index b92ccd1d77..9f4c108dff 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -548,12 +548,11 @@ void LLAudioEngine::enableWind(bool enable)  {  	if (enable && (!mEnableWind))  	{ -		initWind(); -		mEnableWind = enable; +		mEnableWind = initWind();  	}  	else if (mEnableWind && (!enable))  	{ -		mEnableWind = enable; +		mEnableWind = false;  		cleanupWind();  	}  } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index d287104204..5876cef4ea 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -195,7 +195,7 @@ protected:  	virtual LLAudioBuffer *createBuffer() = 0;  	virtual LLAudioChannel *createChannel() = 0; -	virtual void initWind() = 0; +	virtual bool initWind() = 0;  	virtual void cleanupWind() = 0;  	virtual void setInternalGain(F32 gain) = 0; diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp index d7f58defca..7a8a04afa1 100644 --- a/indra/llaudio/llaudioengine_fmod.cpp +++ b/indra/llaudio/llaudioengine_fmod.cpp @@ -54,13 +54,12 @@ extern "C" {  	void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);  } -FSOUND_DSPUNIT *gWindDSP = NULL; -  LLAudioEngine_FMOD::LLAudioEngine_FMOD()  {  	mInited = false;  	mWindGen = NULL; +	mWindDSP = NULL;  } @@ -258,10 +257,10 @@ void LLAudioEngine_FMOD::allocateListener(void)  void LLAudioEngine_FMOD::shutdown()  { -	if (gWindDSP) +	if (mWindDSP)  	{ -		FSOUND_DSP_SetActive(gWindDSP,false); -		FSOUND_DSP_Free(gWindDSP); +		FSOUND_DSP_SetActive(mWindDSP,false); +		FSOUND_DSP_Free(mWindDSP);  	}  	stopInternetStream(); @@ -289,29 +288,66 @@ LLAudioChannel * LLAudioEngine_FMOD::createChannel()  } -void LLAudioEngine_FMOD::initWind() +bool LLAudioEngine_FMOD::initWind()  { -	mWindGen = new LLWindGen<MIXBUFFERFORMAT>; +	if (!mWindGen) +	{ +		bool enable; +		 +		switch (FSOUND_GetMixer()) +		{ +			case FSOUND_MIXER_MMXP5: +			case FSOUND_MIXER_MMXP6: +			case FSOUND_MIXER_QUALITY_MMXP5: +			case FSOUND_MIXER_QUALITY_MMXP6: +				enable = (typeid(MIXBUFFERFORMAT) == typeid(S16)); +				break; +			case FSOUND_MIXER_BLENDMODE: +				enable = (typeid(MIXBUFFERFORMAT) == typeid(S32)); +				break; +			case FSOUND_MIXER_QUALITY_FPU: +				enable = (typeid(MIXBUFFERFORMAT) == typeid(F32)); +				break; +			default: +				// FSOUND_GetMixer() does not return a valid mixer type on Darwin +				LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL; +				enable = true; +				break; +		} +		 +		if (enable) +		{ +			mWindGen = new LLWindGen<MIXBUFFERFORMAT>(FSOUND_GetOutputRate()); +		} +		else +		{ +			LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL; +		} +	} + +	mNextWindUpdate = 0.0; -	if (!gWindDSP) +	if (mWindGen && !mWindDSP)  	{ -		gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); +		mWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen);  	} -	if (gWindDSP) +	if (mWindDSP)  	{ -		FSOUND_DSP_SetActive(gWindDSP, true); +		FSOUND_DSP_SetActive(mWindDSP, true); +		return true;  	} -	mNextWindUpdate = 0.0; +	 +	return false;  }  void LLAudioEngine_FMOD::cleanupWind()  { -	if (gWindDSP) +	if (mWindDSP)  	{ -		FSOUND_DSP_SetActive(gWindDSP, false); -		FSOUND_DSP_Free(gWindDSP); -		gWindDSP = NULL; +		FSOUND_DSP_SetActive(mWindDSP, false); +		FSOUND_DSP_Free(mWindDSP); +		mWindDSP = NULL;  	}  	delete mWindGen; @@ -740,30 +776,12 @@ void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int len  	// originalbuffer = fmod's original mixbuffer.  	// newbuffer = the buffer passed from the previous DSP unit.  	// length = length in samples at this mix time. -	// param = user parameter passed through in FSOUND_DSP_Create. -	// -	// modify the buffer in some fashion +	// userdata = user parameter passed through in FSOUND_DSP_Create.  	LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen =  		(LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata; -	U8 stride; - -#if LL_DARWIN -	stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT); -#else -	int mixertype = FSOUND_GetMixer(); -	if (mixertype == FSOUND_MIXER_BLENDMODE || -	    mixertype == FSOUND_MIXER_QUALITY_FPU) -	{ -		stride = 4; -	} -	else -	{ -		stride = 2; -	} -#endif - -	newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride); +	 +	newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length);  	return newbuffer;  } diff --git a/indra/llaudio/llaudioengine_fmod.h b/indra/llaudio/llaudioengine_fmod.h index 3968657cba..0e386a3884 100644 --- a/indra/llaudio/llaudioengine_fmod.h +++ b/indra/llaudio/llaudioengine_fmod.h @@ -55,15 +55,15 @@ public:  	virtual void shutdown(); -	/*virtual*/ void initWind(); +	/*virtual*/ bool initWind();  	/*virtual*/ void cleanupWind();  	/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);  #if LL_DARWIN -        typedef S32 MIXBUFFERFORMAT; +	typedef S32 MIXBUFFERFORMAT;  #else -        typedef S16 MIXBUFFERFORMAT; +	typedef S16 MIXBUFFERFORMAT;  #endif  protected: @@ -83,6 +83,7 @@ protected:  	void* mUserData;  	LLWindGen<MIXBUFFERFORMAT> *mWindGen; +	FSOUND_DSPUNIT *mWindDSP;  }; diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index a5982ccbd6..887c791790 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -370,7 +370,7 @@ U32 LLAudioBufferOpenAL::getLength()  // ------------ -void LLAudioEngine_OpenAL::initWind() +bool LLAudioEngine_OpenAL::initWind()  {  	ALenum error;  	llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; @@ -397,10 +397,12 @@ void LLAudioEngine_OpenAL::initWind()  	if(mWindBuf==NULL)  	{  		llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; -		mEnableWind=false; +		return false;  	}  	llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; + +	return true;  }  void LLAudioEngine_OpenAL::cleanupWind() @@ -508,14 +510,14 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)  		alGenBuffers(1,&buffer);  		if((error=alGetError()) != AL_NO_ERROR)  		{ -			llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; +			llwarns << "LLAudioEngine_OpenAL::updateWind() Error creating wind buffer: " << error << llendl;  			break;  		}  		alBufferData(buffer,  			     AL_FORMAT_STEREO16,  			     mWindGen->windGenerate(mWindBuf, -						    mWindBufSamples, 2), +						    mWindBufSamples),  			     mWindBufBytes,  			     mWindBufFreq);  		error = alGetError(); diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h index 5aca03e195..16125b2476 100644 --- a/indra/llaudio/llaudioengine_openal.h +++ b/indra/llaudio/llaudioengine_openal.h @@ -57,23 +57,23 @@ class LLAudioEngine_OpenAL : public LLAudioEngine  		LLAudioBuffer* createBuffer();  		LLAudioChannel* createChannel(); -		/*virtual*/ void initWind(); +		/*virtual*/ bool initWind();  		/*virtual*/ void cleanupWind();  		/*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude);  	private:  		void * windDSP(void *newbuffer, int length); -	        typedef S16 WIND_SAMPLE_T; -        	LLWindGen<WIND_SAMPLE_T> *mWindGen; -        	S16 *mWindBuf; -        	U32 mWindBufFreq; -        	U32 mWindBufSamples; -        	U32 mWindBufBytes; -        	ALuint mWindSource; -	        int mNumEmptyWindALBuffers; - -        	static const int MAX_NUM_WIND_BUFFERS = 80; -        	static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec +        typedef S16 WIND_SAMPLE_T; +    	LLWindGen<WIND_SAMPLE_T> *mWindGen; +    	S16 *mWindBuf; +    	U32 mWindBufFreq; +    	U32 mWindBufSamples; +    	U32 mWindBufBytes; +    	ALuint mWindSource; +        int mNumEmptyWindALBuffers; + +    	static const int MAX_NUM_WIND_BUFFERS = 80; +    	static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec  };  class LLAudioChannelOpenAL : public LLAudioChannel diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h index 847bfa6e9d..1908b2545f 100644 --- a/indra/llaudio/llwindgen.h +++ b/indra/llaudio/llwindgen.h @@ -33,104 +33,149 @@  #define WINDGEN_H  #include "llcommon.h" -#include "llrand.h"  template <class MIXBUFFERFORMAT_T>  class LLWindGen  {  public: -	LLWindGen() : +	LLWindGen(const U32 sample_rate = 44100) :  		mTargetGain(0.f),  		mTargetFreq(100.f),  		mTargetPanGainR(0.5f), -		mbuf0(0.0), -		mbuf1(0.0), -		mbuf2(0.0), -		mbuf3(0.0), -		mbuf4(0.0), -		mbuf5(0.0), -		mY0(0.0), -		mY1(0.0), +		mInputSamplingRate(sample_rate), +		mSubSamples(2), +		mFilterBandWidth(50.f), +		mBuf0(0.0f), +		mBuf1(0.0f), +		mBuf2(0.0f), +		mY0(0.0f), +		mY1(0.0f),  		mCurrentGain(0.f),  		mCurrentFreq(100.f), -		mCurrentPanGainR(0.5f) {}; - -	static const U32 getInputSamplingRate() {return mInputSamplingRate;} +		mCurrentPanGainR(0.5f) +	{ +		mSamplePeriod = (F32)mSubSamples / (F32)mInputSamplingRate; +		mB2 = expf(-F_TWO_PI * mFilterBandWidth * mSamplePeriod); +	} +	const U32 getInputSamplingRate() { return mInputSamplingRate; } +	  	// newbuffer = the buffer passed from the previous DSP unit.  	// numsamples = length in samples-per-channel at this mix time. -	// stride = number of bytes between start of each sample.  	// NOTE: generates L/R interleaved stereo -	MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride) +	MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples)  	{ -		U8 *cursamplep = (U8*)newbuffer; +		MIXBUFFERFORMAT_T *cursamplep = newbuffer; +		 +		// Filter coefficients +		F32 a0 = 0.0f, b1 = 0.0f; -		double bandwidth = 50.0F; -		double a0,b1,b2; +		// No need to clip at normal volumes +		bool clip = mCurrentGain > 2.0f; -		// calculate resonant filter coeffs -		b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate)); +		bool interp_freq = false;  -		while (numsamples--) +		//if the frequency isn't changing much, we don't need to interpolate in the inner loop +		if (llabs(mTargetFreq - mCurrentFreq) < (mCurrentFreq * 0.112))  		{ -			mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq)); -			mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain)); -			mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR)); -			b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate)); -			a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); -			double nextSample; +			// calculate resonant filter coefficients +			mCurrentFreq = mTargetFreq; +			b1 = (-4.0f * mB2) / (1.0f + mB2) * cosf(F_TWO_PI * (mCurrentFreq * mSamplePeriod)); +			a0 = (1.0f - mB2) * sqrtf(1.0f - (b1 * b1) / (4.0f * mB2)); +		} +		else +		{ +			interp_freq = true; +		} +		 +		while (numsamples) +		{ +			F32 next_sample; +			 +			// Start with white noise +			// This expression is fragile, rearrange it and it will break! +			next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); -			// start with white noise -			nextSample = ll_frand(2.0f) - 1.0f; +			// Apply a pinking filter +			// Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ +			mBuf0 = mBuf0 * 0.99765f + next_sample * 0.0990460f; +			mBuf1 = mBuf1 * 0.96300f + next_sample * 0.2965164f; +			mBuf2 = mBuf2 * 0.57000f + next_sample * 1.0526913f; -			// apply pinking filter -			mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample;  -			mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample; -			mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample; -			mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample; -			mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample; -			mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample; +			next_sample = mBuf0 + mBuf1 + mBuf2 + next_sample * 0.1848f; -			nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5; +			if (interp_freq) +			{ +				// calculate and interpolate resonant filter coefficients +				mCurrentFreq = (0.999f * mCurrentFreq) + (0.001f * mTargetFreq); +				b1 = (-4.0f * mB2) / (1.0f + mB2) * cosf(F_TWO_PI * (mCurrentFreq * mSamplePeriod)); +				a0 = (1.0f - mB2) * sqrtf(1.0f - (b1 * b1) / (4.0f * mB2)); +			} -			// do a resonant filter on the noise -			nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 ); +			// Apply a resonant low-pass filter on the pink noise +	        next_sample = a0 * next_sample - b1 * mY0 - mB2 * mY1;  			mY1 = mY0; -			mY0 = nextSample; +			mY0 = next_sample; -			nextSample *= mCurrentGain; +			mCurrentGain = (0.999f * mCurrentGain) + (0.001f * mTargetGain); +			mCurrentPanGainR = (0.999f * mCurrentPanGainR) + (0.001f * mTargetPanGainR); -			MIXBUFFERFORMAT_T	sample; +			// For a 3dB pan law use: +			// next_sample *= mCurrentGain * ((mCurrentPanGainR*(mCurrentPanGainR-1)*1.652+1.413); +		    next_sample *= mCurrentGain; -			sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f); -			*(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); -			cursamplep += stride; - -			sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f); -			*(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); -			cursamplep += stride; +			// delta is used to interpolate between synthesized samples +			F32 delta = (next_sample - mLastSample) / (F32)mSubSamples; +			 +			// Fill the audio buffer, clipping if necessary +			for (U8 i=mSubSamples; i && numsamples; --i, --numsamples)  +			{ +				mLastSample = mLastSample + delta; +				S32	sample_right = (S32)(mLastSample * mCurrentPanGainR); +				S32	sample_left = (S32)mLastSample - sample_right; +				 +				if (!clip) +				{ +					*cursamplep = (MIXBUFFERFORMAT_T)sample_left; +					++cursamplep; +					*cursamplep = (MIXBUFFERFORMAT_T)sample_right; +					++cursamplep; +				} +				else +				{ +					*cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_left, (S32)S16_MIN, (S32)S16_MAX); +					++cursamplep; +					*cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_right, (S32)S16_MIN, (S32)S16_MAX); +					++cursamplep; +				} +			}  		}  		return newbuffer;  	} - +	 +public:  	F32 mTargetGain;  	F32 mTargetFreq;  	F32 mTargetPanGainR; - +	  private: -	static const U32 mInputSamplingRate = 44100; -	F64 mbuf0; -	F64 mbuf1; -	F64 mbuf2; -	F64 mbuf3; -	F64 mbuf4; -	F64 mbuf5; -	F64 mY0; -	F64 mY1; +	U32 mInputSamplingRate; +	U8  mSubSamples; +	F32 mSamplePeriod; +	F32 mFilterBandWidth; +	F32 mB2; +	 +	F32 mBuf0; +	F32 mBuf1; +	F32 mBuf2; +	F32 mY0; +	F32 mY1; +	  	F32 mCurrentGain;  	F32 mCurrentFreq;  	F32 mCurrentPanGainR; +	F32 mLastSample;  };  #endif diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index e19f8b0454..476a23ec64 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -99,8 +99,9 @@ LLAssetDictionary::LLAssetDictionary()  	addEntry(LLAssetType::AT_LINK, 				new AssetEntry("LINK",				"link",		"sym link",			false,		false,		true));  	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", 	"sym folder link",	false,		false,		true)); - +#if LL_MESH_ENABLED  	addEntry(LLAssetType::AT_MESH,              new AssetEntry("MESH",              "mesh",     "mesh",             false, false, false)); +#endif  	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE,		FALSE,		FALSE)); diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 90cd03c433..ebc43134cb 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -114,9 +114,10 @@ public:  		AT_LINK_FOLDER = 25,  			// Inventory folder link - +#if LL_MESH_ENABLED  		AT_MESH = 49,  		    // Mesh data in our proprietary SLM format +#endif  		AT_COUNT = 50, diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 2d4ee604b0..82cd22a832 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -89,7 +89,9 @@ LLInventoryDictionary::LLInventoryDictionary()  	addEntry(LLInventoryType::IT_WEARABLE,            new InventoryEntry("wearable",  "wearable",      2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART));  	addEntry(LLInventoryType::IT_ANIMATION,           new InventoryEntry("animation", "animation",     1, LLAssetType::AT_ANIMATION));    	addEntry(LLInventoryType::IT_GESTURE,             new InventoryEntry("gesture",   "gesture",       1, LLAssetType::AT_GESTURE));  +#if LL_MESH_ENABLED  	addEntry(LLInventoryType::IT_MESH,                new InventoryEntry("mesh",      "mesh",          1, LLAssetType::AT_MESH)); +#endif  } @@ -150,8 +152,9 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =  	LLInventoryType::IT_NONE,			// AT_NONE  	LLInventoryType::IT_NONE,			// AT_NONE  	LLInventoryType::IT_NONE,			// AT_NONE -	 +#if LL_MESH_ENABLED  	LLInventoryType::IT_MESH            // AT_MESH +#endif  };  // static diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index 37829f5eae..d2fc67ef64 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -68,7 +68,9 @@ public:  		IT_ANIMATION = 19,  		IT_GESTURE = 20, +#if LL_MESH_ENABLED  		IT_MESH = 22, +#endif  		IT_COUNT = 23,  		IT_NONE = -1 diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 209b506c30..c3c15e1374 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -61,11 +61,11 @@  #endif  // Single Precision Floating Point Routines -#ifndef fsqrtf -#define fsqrtf(x)		((F32)sqrt((F64)(x))) -#endif  #ifndef sqrtf -#define sqrtf(x)		((F32)sqrt((F64)(x))) +#define sqrtf(x)	((F32)sqrt((F64)(x))) +#endif +#ifndef fsqrtf +#define fsqrtf(x)	sqrtf(x)  #endif  #ifndef cosf @@ -78,11 +78,14 @@  #define tanf(x)		((F32)tan((F64)(x)))  #endif  #ifndef acosf -#define acosf(x)		((F32)acos((F64)(x))) +#define acosf(x)	((F32)acos((F64)(x)))  #endif  #ifndef powf -#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) +#define powf(x,y)	((F32)pow((F64)(x),(F64)(y))) +#endif +#ifndef expf +#define expf(x)		((F32)exp((F64)(x)))  #endif  const F32	GRAVITY			= -9.8f; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index cafa1e5c44..10cef533b0 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2546,10 +2546,12 @@ S32	LLVolume::getNumFaces() const  {  	U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK); +#if LL_MESH_ENABLED  	if (sculpt_type == LL_SCULPT_TYPE_MESH)  	{  		return LL_SCULPT_MESH_MAX_FACES;  	} +#endif  	return (S32)mProfilep->mFaces.size();  } @@ -2922,11 +2924,6 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,  	LLMemType m1(LLMemType::MTYPE_VOLUME);      U8 sculpt_type = mParams.getSculptType(); -	if (sculpt_type & LL_SCULPT_TYPE_MASK == LL_SCULPT_TYPE_MESH) -	{ -		llerrs << "WTF?" << llendl; -	} -  	BOOL data_is_empty = FALSE;  	if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) @@ -4135,10 +4132,12 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,  	normals.clear();  	segments.clear(); +#if LL_MESH_ENABLED  	if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)  	{  		return;  	} +#endif  	S32 cur_index = 0;  	//for each face @@ -5567,6 +5566,8 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		corners[0].getPosition(), corners[0].mTexCoord,  		corners[1].getPosition(), corners[1].mTexCoord,  		corners[2].getPosition(), corners[2].mTexCoord); +	 +	binormal.normalize3fast();  	S32 size = (grid_size+1)*(grid_size+1);  	resizeVertices(size); @@ -6335,10 +6336,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		resizeVertices(num_vertices);  		resizeIndices(num_indices); +#if LL_MESH_ENABLED  		if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)  		{  			mEdge.resize(num_indices);  		} +#else +		mEdge.resize(num_indices); +#endif  	}  	LLVector4a* pos = (LLVector4a*) mPositions; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c49d1c650d..0782944079 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -41,6 +41,8 @@ class LLVolumeParams;  class LLProfile;  class LLPath; +#define LL_MESH_ENABLED 0 +  template <class T> class LLOctreeNode;  class LLVector4a; @@ -190,10 +192,15 @@ const U8 LL_SCULPT_TYPE_SPHERE    = 1;  const U8 LL_SCULPT_TYPE_TORUS     = 2;  const U8 LL_SCULPT_TYPE_PLANE     = 3;  const U8 LL_SCULPT_TYPE_CYLINDER  = 4; +#if LL_MESH_ENABLED  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; +#else +const U8 LL_SCULPT_TYPE_MASK      = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | +	LL_SCULPT_TYPE_CYLINDER; +#endif  const U8 LL_SCULPT_FLAG_INVERT    = 64;  const U8 LL_SCULPT_FLAG_MIRROR    = 128; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 48c20b09a8..514ca25aa0 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1318,7 +1318,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  	{		  		if (mGLBuffer)  		{ -			if (useVBOs() && sVBOActive) +			if (sVBOActive)  			{  				glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);  				sBindCount++; @@ -1330,7 +1330,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  				setup = TRUE; // ... or a client memory pointer changed  			}  		} -		if (useVBOs() && mGLIndices && sIBOActive) +		if (mGLIndices && sIBOActive)  		{  			/*if (sMapped)  			{ diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 8e0245c451..6bf1347514 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -66,8 +66,12 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)   , mAutoScrolling( false )   , mAutoScrollRate( 0.f )   , mSelectedTab( NULL ) + , mTabComparator( NULL ) + , mNoVisibleTabsHelpText(NULL)  { -  mSingleExpansion = params.single_expansion; +	initNoTabsWidget(params.empty_accordion_text); + +	mSingleExpansion = params.single_expansion;  	if(mFitParent && !mSingleExpansion)  	{  		llinfos << "fit_parent works best when combined with single_expansion" << llendl; @@ -78,7 +82,10 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel()   , mAutoScrolling( false )   , mAutoScrollRate( 0.f )   , mSelectedTab( NULL ) + , mNoVisibleTabsHelpText(NULL)  { +	initNoTabsWidget(LLTextBox::Params()); +  	mSingleExpansion = false;  	mFitParent = false;  	LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");	 @@ -168,6 +175,8 @@ BOOL LLAccordionCtrl::postBuild()  		}  	} +	updateNoTabsHelpTextVisibility(); +  	return TRUE;  } @@ -187,8 +196,15 @@ void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)  	rcLocal.mRight = rcLocal.mLeft + width;  	rcLocal.mTop = rcLocal.mBottom + height; +	// get textbox a chance to reshape its content +	mNoVisibleTabsHelpText->reshape(width, height, called_from_parent); +  	setRect(rcLocal); +	// assume that help text is always fit accordion. +	// necessary text paddings can be set via h_pad and v_pad +	mNoVisibleTabsHelpText->setRect(getLocalRect()); +  	arrange();  } @@ -359,6 +375,31 @@ void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view)  	}  } +void	LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params) +{ +	LLTextBox::Params tp = tb_params; +	tp.rect(getLocalRect()); +	mNoVisibleTabsOrigString = tp.initial_value().asString(); +	mNoVisibleTabsHelpText = LLUICtrlFactory::create<LLTextBox>(tp, this); +} + +void	LLAccordionCtrl::updateNoTabsHelpTextVisibility() +{ +	bool visible_exists = false; +	std::vector<LLAccordionCtrlTab*>::const_iterator it = mAccordionTabs.begin(); +	const std::vector<LLAccordionCtrlTab*>::const_iterator it_end = mAccordionTabs.end(); +	for (; it != it_end; ++it) +	{ +		if ((*it)->getVisible()) +		{ +			visible_exists = true; +			break; +		} +	} + +	mNoVisibleTabsHelpText->setVisible(!visible_exists); +} +  void	LLAccordionCtrl::arrangeSinge()  {  	S32 panel_left = BORDER_MARGIN;	  // Margin from left side of Splitter @@ -737,6 +778,20 @@ S32	LLAccordionCtrl::notifyParent(const LLSD& info)  		}  		return 1;  	} +	else if (info.has("child_visibility_change")) +	{ +		BOOL new_visibility = info["child_visibility_change"]; +		if (new_visibility) +		{ +			// there is at least one visible tab +			mNoVisibleTabsHelpText->setVisible(FALSE); +		} +		else +		{ +			// it could be the latest visible tab, check all of them +			updateNoTabsHelpTextVisibility(); +		} +	}  	return LLPanel::notifyParent(info);  }  void	LLAccordionCtrl::reset		() @@ -745,6 +800,28 @@ void	LLAccordionCtrl::reset		()  		mScrollbar->setDocPos(0);  } +void LLAccordionCtrl::sort() +{ +	if (!mTabComparator) +	{ +		llwarns << "No comparator specified for sorting accordion tabs." << llendl; +		return; +	} + +	std::sort(mAccordionTabs.begin(), mAccordionTabs.end(), LLComparatorAdaptor(*mTabComparator)); +	arrange(); +} + +void	LLAccordionCtrl::setFilterSubString(const std::string& filter_string) +{ +	LLStringUtil::format_map_t args; +	args["[SEARCH_TERM]"] = LLURI::escape(filter_string); +	std::string text = mNoVisibleTabsOrigString; +	LLStringUtil::format(text, args); + +	mNoVisibleTabsHelpText->setValue(text); +} +  S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)  {  	if(tab_index < 0) diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index a029201c90..fc6f2d896c 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -34,6 +34,7 @@  #define LL_ACCORDIONCTRL_H  #include "llpanel.h" +#include "lltextbox.h"  #include "llscrollbar.h"  #include <vector> @@ -56,6 +57,19 @@ private:  public: +	/** +	 * Abstract comparator for accordion tabs. +	 */ +	class LLTabComparator +	{ +	public: +		LLTabComparator() {}; +		virtual ~LLTabComparator() {}; + +		/** Returns true if tab1 < tab2, false otherwise */ +		virtual bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const = 0; +	}; +  	struct Params   		: public LLInitParam::Block<Params, LLPanel::Params>  	{ @@ -64,10 +78,12 @@ public:  								accordion tabs are responsible for scrolling their content.  								*NOTE fit_parent works best when combined with single_expansion.  								Accordion view should implement getRequiredRect() and provide valid height*/ +		Optional<LLTextBox::Params>	empty_accordion_text;  		Params()  			: single_expansion("single_expansion",false)  			, fit_parent("fit_parent", false) +			, empty_accordion_text("empty_accordion_text")  		{};  	}; @@ -105,7 +121,18 @@ public:  	void	reset		(); +	void	setComparator(const LLTabComparator* comp) { mTabComparator = comp; } +	void	sort(); + +	/** +	 * Sets filter substring as a search_term for help text when there are no any visible tabs. +	 */ +	void	setFilterSubString(const std::string& filter_string); +  private: +	void	initNoTabsWidget(const LLTextBox::Params& tb_params); +	void	updateNoTabsHelpTextVisibility(); +  	void	arrangeSinge();  	void	arrangeMultiple(); @@ -123,6 +150,21 @@ private:  	BOOL	autoScroll				(S32 x, S32 y); +	/** +	 * An adaptor for LLTabComparator +	 */ +	struct LLComparatorAdaptor +	{ +		LLComparatorAdaptor(const LLTabComparator& comparator) : mComparator(comparator) {}; + +		bool operator()(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) +		{ +			return mComparator.compare(tab1, tab2); +		} + +		const LLTabComparator& mComparator; +	}; +  private:  	LLRect			mInnerRect;  	LLScrollbar*	mScrollbar; @@ -130,7 +172,11 @@ private:  	bool			mFitParent;  	bool			mAutoScrolling;  	F32				mAutoScrollRate; -	LLAccordionCtrlTab* mSelectedTab; +	LLTextBox*		mNoVisibleTabsHelpText; +	std::string		mNoVisibleTabsOrigString; + +	LLAccordionCtrlTab*		mSelectedTab; +	const LLTabComparator*	mTabComparator;  }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 83e67980a3..1bc8086a27 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -409,6 +409,13 @@ void LLAccordionCtrlTab::changeOpenClose(bool is_open)  	}  } +void LLAccordionCtrlTab::handleVisibilityChange(BOOL new_visibility) +{ +	LLUICtrl::handleVisibilityChange(new_visibility); + +	notifyParent(LLSD().with("child_visibility_change", new_visibility)); +} +  BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)  {  	if(mCollapsible && mHeaderVisible && mCanOpenClose) @@ -466,7 +473,7 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel)  	addChild(panel,0);  } -std::string LLAccordionCtrlTab::getTitle() +std::string LLAccordionCtrlTab::getTitle() const  {  	LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);  	if (header) diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 83a9024a74..82e0234bfc 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -115,7 +115,7 @@ public:  	void		setAccordionView(LLView* panel);  	LLView*		getAccordionView() { return mContainerPanel; }; -	std::string getTitle(); +	std::string getTitle() const;  	// Set text and highlight substring in LLAccordionCtrlTabHeader  	void setTitle(const std::string& title, const std::string& hl = LLStringUtil::null); @@ -154,6 +154,11 @@ public:  	// Call reshape after changing size  	virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); +	/** +	 * Raises notifyParent event with "child_visibility_change" = new_visibility +	 */ +	void handleVisibilityChange(BOOL new_visibility); +  	// Changes expand/collapse state and triggers expand/collapse callbacks  	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index fad98e553f..341debc9a8 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -810,6 +810,11 @@ void LLFloater::applyTitle()  	{  		mDragHandle->setTitle ( mTitle );  	} + +	if (getHost()) +	{ +		getHost()->updateFloaterTitle(this);	 +	}  }  std::string LLFloater::getCurrentTitle() const diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 75342afbe2..e9614ea660 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -339,6 +339,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  		{  			if( *cur == '\n' )  			{ +				LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(cur-base); +				text_segment->setToken( 0 ); +				insertSegment( *seg_list, text_segment, text_len, defaultColor, editor);  				cur++;  				if( !*cur || *cur == '\n' )  				{ @@ -378,9 +381,8 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  						}  						S32 seg_end = cur - base; -						LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); -						text_segment->setToken( cur_token ); -						insertSegment( seg_list, text_segment, text_len, defaultColor, editor); +						//create segments from seg_start to seg_end +						insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor);  						line_done = TRUE; // to break out of second loop.  						break;  					} @@ -486,11 +488,12 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  						seg_end = seg_start + between_delimiters + cur_delimiter->getLength();  					} - +					insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor); +					/*  					LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor );  					text_segment->setToken( cur_delimiter );  					insertSegment( seg_list, text_segment, text_len, defaultColor, editor); - +					*/  					// Note: we don't increment cur, since the end of one delimited seg may be immediately  					// followed by the start of another one.  					continue; @@ -519,10 +522,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  						// llinfos << "Seg: [" << word.c_str() << "]" << llendl; - -						LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); -						text_segment->setToken( cur_token ); -						insertSegment( seg_list, text_segment, text_len, defaultColor, editor); +						insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor);  					}  					cur += seg_len;   					continue; @@ -537,24 +537,50 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  	}  } -void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>* seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) +void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor ) +{ +	std::string::size_type pos = wtext.find('\n',seg_start); +	 +	while (pos!=-1 && pos < (std::string::size_type)seg_end) +	{ +		if (pos!=seg_start) +		{ +			LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, pos, editor ); +			text_segment->setToken( cur_token ); +			insertSegment( seg_list, text_segment, text_len, defaultColor, editor); +		} + +		LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(pos); +		text_segment->setToken( cur_token ); +		insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + +		seg_start = pos+1; +		pos = wtext.find('\n',seg_start); +	} + +	LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); +	text_segment->setToken( cur_token ); +	insertSegment( seg_list, text_segment, text_len, defaultColor, editor); +} + +void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor )  { -	LLTextSegmentPtr last = seg_list->back(); +	LLTextSegmentPtr last = seg_list.back();  	S32 new_seg_end = new_segment->getEnd();  	if( new_segment->getStart() == last->getStart() )  	{ -		seg_list->pop_back(); +		seg_list.pop_back();  	}  	else  	{  		last->setEnd( new_segment->getStart() );  	} -	seg_list->push_back( new_segment ); +	seg_list.push_back( new_segment );  	if( new_seg_end < text_len )  	{ -		seg_list->push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) ); +		seg_list.push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) );  	}  } diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index e5b66dfa56..09378e408b 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -129,7 +129,8 @@ public:  private:  	LLColor3	readColor(const std::string& s); -	void		insertSegment(std::vector<LLTextSegmentPtr> *seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor); +	void		insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor); +	void		insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor);  	BOOL		mLoaded;  	word_token_map_t mWordTokenMap; diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 3aea648562..b1dbce0000 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -238,6 +238,16 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,  	moveResizeHandlesToFront();  } +void LLMultiFloater::updateFloaterTitle(LLFloater* floaterp) +{ +	S32 index = mTabContainer->getIndexForPanel(floaterp); +	if (index != -1) +	{ +		mTabContainer->setPanelTitle(index, floaterp->getShortTitle()); +	} +} + +  /**  	BOOL selectFloater(LLFloater* floaterp) diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index bbf2c56fe7..24a841f64e 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -80,6 +80,7 @@ public:  	void onTabSelected();  	virtual void updateResizeLimits(); +	virtual void updateFloaterTitle(LLFloater* floaterp);  protected:  	struct LLFloaterData diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index d86709c448..72f3a14822 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2743,6 +2743,12 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor)  	editor->addDocumentChild(mView);  } +LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1) +{ +	LLStyleSP s( new LLStyle(LLStyle::Params().visible(true))); + +	mFontHeight = llceil(s->getFont()->getLineHeight()); +}  LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1)  {  	mFontHeight = llceil(style->getFont()->getLineHeight()); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 176308c61a..89ce5cdc8e 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -519,6 +519,7 @@ class LLLineBreakTextSegment : public LLTextSegment  public:  	LLLineBreakTextSegment(LLStyleConstSP style,S32 pos); +	LLLineBreakTextSegment(S32 pos);  	~LLLineBreakTextSegment();  	bool		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;  	S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const; diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index ddb76fb2ba..2b01288fd7 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -2041,9 +2041,11 @@ std::string get_extension(LLAssetType::EType type)  	case LLAssetType::AT_ANIMATION:  		extension = ".lla";  		break; +#if LL_MESH_ENABLED  	case LLAssetType::AT_MESH:  		extension = ".slm";  		break; +#endif  	default:  		// Just use the asset server filename extension in most cases  		extension += "."; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 186e539ce0..d2ae81180b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -221,6 +221,7 @@ set(viewer_SOURCE_FILES      llfloaterurldisplay.cpp      llfloaterurlentry.cpp      llfloatervoicedevicesettings.cpp +    llfloatervoiceeffect.cpp      llfloaterwater.cpp      llfloaterwhitelistentry.cpp      llfloaterwindlight.cpp @@ -314,6 +315,7 @@ set(viewer_SOURCE_FILES      llnotificationstorage.cpp      llnotificationtiphandler.cpp      lloutfitslist.cpp +    lloutfitobserver.cpp      lloutputmonitorctrl.cpp      llpanelavatar.cpp      llpanelavatartag.cpp @@ -364,6 +366,7 @@ set(viewer_SOURCE_FILES      llpanelprofileview.cpp      llpanelteleporthistory.cpp      llpaneltiptoast.cpp +    llpanelvoiceeffect.cpp      llpaneltopinfobar.cpp      llpanelvolume.cpp      llpanelvolumepulldown.cpp @@ -746,6 +749,7 @@ set(viewer_HEADER_FILES      llfloaterurldisplay.h      llfloaterurlentry.h      llfloatervoicedevicesettings.h +    llfloatervoiceeffect.h      llfloaterwater.h      llfloaterwhitelistentry.h      llfloaterwindlight.h @@ -834,6 +838,7 @@ set(viewer_HEADER_FILES      llnotificationmanager.h      llnotificationstorage.h      lloutfitslist.h +    lloutfitobserver.h      lloutputmonitorctrl.h      llpanelavatar.h      llpanelavatartag.h @@ -884,6 +889,7 @@ set(viewer_HEADER_FILES      llpanelprofileview.h      llpanelteleporthistory.h      llpaneltiptoast.h +    llpanelvoiceeffect.h      llpaneltopinfobar.h      llpanelvolume.h      llpanelvolumepulldown.h diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 16e39fc1c4..937c4e4c6a 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -41,6 +41,8 @@  						</array>  					<key>tags</key>  						<array> +							<!-- sample entry for debugging a specific item	--> +<!--						<string>Voice</string>							-->  						</array>  				</map>  			</array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1482bed415..df9393c316 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -583,7 +583,7 @@        <key>Type</key>        <string>U32</string>        <key>Value</key> -      <integer>180</integer> +      <integer>120</integer>      </map>      <key>AvatarSex</key>      <map> @@ -4908,7 +4908,7 @@      <key>Type</key>      <string>Boolean</string>      <key>Value</key> -    <real>1</real> +    <real>0</real>    </map>    <key>MigrateCacheDirectory</key>      <map> @@ -6818,7 +6818,7 @@      <key>Type</key>      <string>F32</string>      <key>Value</key> -    <real>0.0</real> +    <real>-0.001</real>    </map>    <key>RenderSpotShadowOffset</key>    <map> @@ -10919,6 +10919,28 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>VoiceEffectExpiryWarningTime</key> +    <map> +      <key>Comment</key> +      <string>How much notice to give of Voice Morph subscriptions expiry, in seconds.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>259200</integer> +    </map> +    <key>VoiceMorphingEnabled</key> +    <map> +      <key>Comment</key> +      <string>Whether or not to enable Voice Morphs and show the UI.</string> +      <key>Persist</key> +      <integer>0</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>      <key>AutoDisengageMic</key>      <map>        <key>Comment</key> @@ -11555,5 +11577,16 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>OutfitOperationsTimeout</key> +    <map> +      <key>Comment</key> +      <string>Timeout for outfit related operations.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>180</integer> +    </map>  </map>  </llsd> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 3ce32a05b0..d4000e9253 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -99,6 +99,17 @@          <key>Value</key>              <integer>1</integer>          </map> +    <key>VoiceEffectDefault</key> +    <map> +        <key>Comment</key> +            <string>Selected Voice Morph</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string>00000000-0000-0000-0000-000000000000</string> +    </map>      <!-- Settings below are for back compatibility only.      They are not used in current viewer anymore. But they can't be removed to avoid diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d2e55f88a0..03efcadc98 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3589,10 +3589,10 @@ void LLAgent::sendAgentSetAppearance()  			if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index))  			{  				generate_valid_hash = FALSE; +				llinfos << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << llendl;  			} -			LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash); - +			const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);  			if (hash.notNull())  			{  				ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index d79a1e80ed..acf43dda1e 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -64,6 +64,25 @@ BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE;  using namespace LLVOAvatarDefines; +/////////////////////////////////////////////////////////////////////////////// + +// Callback to wear and start editing an item that has just been created. +class LLWearAndEditCallback : public LLInventoryCallback +{ +	void fire(const LLUUID& inv_item) +	{ +		if (inv_item.isNull()) return; + +		// Request editing the item after it gets worn. +		gAgentWearables.requestEditingWearable(inv_item); + +		// Wear it. +		LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); +	} +}; + +/////////////////////////////////////////////////////////////////////////////// +  // HACK: For EXT-3923: Pants item shows in inventory with skin icon and messes with "current look"  // Some db items are corrupted, have inventory flags = 0, implying wearable type = shape, even though  // wearable type stored in asset is some other value. @@ -1990,7 +2009,7 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con  	LLWearable* wearable = LLWearableList::instance().createNewWearable(type);  	LLAssetType::EType asset_type = wearable->getAssetType();  	LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; -	LLPointer<LLInventoryCallback> cb = wear ? new WearOnAvatarCallback : NULL; +	LLPointer<LLInventoryCallback> cb = wear ? new LLWearAndEditCallback : NULL;  	LLUUID folder_id;  	if (parent_id.notNull()) @@ -2013,17 +2032,44 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con  // static  void LLAgentWearables::editWearable(const LLUUID& item_id)  { -	LLViewerInventoryItem* item; -	LLWearable* wearable; +	LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); +	if (!item) +	{ +		llwarns << "Failed to get linked item" << llendl; +		return; +	} + +	LLWearable* wearable = gAgentWearables.getWearableFromItemID(item_id); +	if (!wearable) +	{ +		llwarns << "Cannot get wearable" << llendl; +		return; +	} + +	if (!gAgentWearables.isWearableModifiable(item->getUUID())) +	{ +		llwarns << "Cannot modify wearable" << llendl; +		return; +	} + +	LLPanel* panel = LLSideTray::getInstance()->getPanel("sidepanel_appearance"); +	LLSidepanelAppearance::editWearable(wearable, panel); +} + +// Request editing the item after it gets worn. +void LLAgentWearables::requestEditingWearable(const LLUUID& item_id) +{ +	mItemToEdit = gInventory.getLinkedItemID(item_id); +} -	if ((item = gInventory.getLinkedItem(item_id)) && -		(wearable = gAgentWearables.getWearableFromAssetID(item->getAssetUUID())) && -		gAgentWearables.isWearableModifiable(item->getUUID()) && -		item->isFinished()) +// Start editing the item if previously requested. +void LLAgentWearables::editWearableIfRequested(const LLUUID& item_id) +{ +	if (mItemToEdit.notNull() && +		mItemToEdit == gInventory.getLinkedItemID(item_id))  	{ -		LLPanel* panel = LLSideTray::getInstance()->showPanel("panel_outfit_edit", LLSD()); -		// copied from LLPanelOutfitEdit::onEditWearableClicked() -		LLSidepanelAppearance::editWearable(wearable, panel->getParent()); +		LLAgentWearables::editWearable(item_id); +		mItemToEdit.setNull();  	}  } diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 679ecefa6f..a41b949be6 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -148,6 +148,12 @@ public:  	static void		editWearable(const LLUUID& item_id);  	bool			moveWearable(const LLViewerInventoryItem* item, bool closer_to_body); +	void			requestEditingWearable(const LLUUID& item_id); +	void			editWearableIfRequested(const LLUUID& item_id); + +private: +	LLUUID			mItemToEdit; +  	//--------------------------------------------------------------------  	// Removing wearables  	//-------------------------------------------------------------------- diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 1032da4990..12d2752180 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -38,11 +38,13 @@  #include "llagentwearables.h"  #include "llappearancemgr.h"  #include "llcommandhandler.h" +#include "lleventtimer.h"  #include "llgesturemgr.h"  #include "llinventorybridge.h"  #include "llinventoryfunctions.h"  #include "llinventoryobserver.h"  #include "llnotificationsutil.h" +#include "lloutfitobserver.h"  #include "llpaneloutfitsinventory.h"  #include "llselectmgr.h"  #include "llsidepanelappearance.h" @@ -55,6 +57,34 @@  char ORDER_NUMBER_SEPARATOR('@'); +class LLOutfitUnLockTimer: public LLEventTimer +{ +public: +	LLOutfitUnLockTimer(F32 period) : LLEventTimer(period) +	{ +		// restart timer on BOF changed event +		LLOutfitObserver::instance().addBOFChangedCallback(boost::bind( +				&LLOutfitUnLockTimer::reset, this)); +		stop(); +	} + +	/*virtual*/ +	BOOL tick() +	{ +		if(mEventTimer.hasExpired()) +		{ +			LLAppearanceMgr::instance().setOutfitLocked(false); +		} +		return FALSE; +	} +	void stop() { mEventTimer.stop(); } +	void start() { mEventTimer.start(); } +	void reset() { mEventTimer.reset(); } +	BOOL getStarted() { return mEventTimer.getStarted(); } + +	LLTimer&  getEventTimer() { return mEventTimer;} +}; +  // support for secondlife:///app/appearance SLapps  class LLAppearanceHandler : public LLCommandHandler  { @@ -762,6 +792,27 @@ void LLAppearanceMgr::onOutfitRename(const LLSD& notification, const LLSD& respo  	}  } +void LLAppearanceMgr::setOutfitLocked(bool locked) +{ +	if (mOutfitLocked == locked) +	{ +		return; +	} + +	mOutfitLocked = locked; +	if (locked) +	{ +		mUnlockOutfitTimer->reset(); +		mUnlockOutfitTimer->start(); +	} +	else +	{ +		mUnlockOutfitTimer->stop(); +	} + +	LLOutfitObserver::instance().notifyOutfitLockChanged(); +} +  void LLAppearanceMgr::addCategoryToCurrentOutfit(const LLUUID& cat_id)  {  	LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); @@ -1810,6 +1861,14 @@ void LLAppearanceMgr::onFirstFullyVisible()  bool LLAppearanceMgr::updateBaseOutfit()  { +	if (isOutfitLocked()) +	{ +		// don't allow modify locked outfit +		llassert(!isOutfitLocked()); +		return false; +	} +	setOutfitLocked(true); +  	const LLUUID base_outfit_id = getBaseOutfitUUID();  	if (base_outfit_id.isNull()) return false; @@ -2138,6 +2197,14 @@ LLAppearanceMgr::LLAppearanceMgr():  	mAttachmentInvLinkEnabled(false),  	mOutfitIsDirty(false)  { +	LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); + +	// unlock outfit on save operation completed +	outfit_observer.addCOFSavedCallback(boost::bind( +			&LLAppearanceMgr::setOutfitLocked, this, false)); + +	mUnlockOutfitTimer.reset(new LLOutfitUnLockTimer(gSavedSettings.getS32( +			"OutfitOperationsTimeout")));  }  LLAppearanceMgr::~LLAppearanceMgr() diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f1beef5857..2227a43cd8 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -42,10 +42,12 @@  class LLWearable;  class LLWearableHoldingPattern;  class LLInventoryCallback; +class LLOutfitUnLockTimer;  class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>  {  	friend class LLSingleton<LLAppearanceMgr>; +	friend class LLOutfitUnLockTimer;  public:  	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t; @@ -162,6 +164,8 @@ public:  	// COF is processed if cat_id is not specified  	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null); +	bool isOutfitLocked() { return mOutfitLocked; } +  protected:  	LLAppearanceMgr();  	~LLAppearanceMgr(); @@ -186,10 +190,20 @@ private:  	static void onOutfitRename(const LLSD& notification, const LLSD& response); +	void setOutfitLocked(bool locked); +  	std::set<LLUUID> mRegisteredAttachments;  	bool mAttachmentInvLinkEnabled;  	bool mOutfitIsDirty; +	/** +	 * Lock for blocking operations on outfit until server reply or timeout exceed +	 * to avoid unsynchronized outfit state or performing duplicate operations. +	 */ +	bool mOutfitLocked; + +	std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; +  	//////////////////////////////////////////////////////////////////////////////////  	// Item-specific convenience functions   public: diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 512b1dde7f..6978cdf672 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1302,8 +1302,10 @@ bool LLAppViewer::cleanup()  	llinfos << "Cleaning Up" << llendflush; +#if LL_MESH_ENABLED  	// shut down mesh streamer  	gMeshRepo.shutdown(); +#endif  	// Must clean up texture references before viewer window is destroyed.  	LLHUDManager::getInstance()->updateEffects(); @@ -1728,8 +1730,10 @@ bool LLAppViewer::initThreads()  		mFastTimerLogThread->start();  	} +#if LL_MESH_ENABLED  	// Mesh streaming and caching  	gMeshRepo.init(); +#endif  	LLFilePickerThread::initClass(); diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index c48dcdb061..afb76735ec 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -305,6 +305,7 @@ void LLAssetUploadResponder::uploadComplete(const LLSD& content)  {  } +#if LL_MESH_ENABLED  LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(  	const LLSD& post_data,  	const LLUUID& vfile_id, @@ -426,6 +427,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)  	LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE);  } +#endif  LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,  												 const LLUUID& vfile_id, @@ -675,6 +677,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)  } +#if LL_MESH_ENABLED  /////////////////////////////////////////////////////  // LLNewAgentInventoryVariablePriceResponder::Impl //  ///////////////////////////////////////////////////// @@ -1142,3 +1145,5 @@ void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog(  				boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder>(this)));  	}  } +#endif + diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index af3b3daf46..9abaccfde0 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -61,7 +61,7 @@ protected:  	std::string mFileName;  }; - +#if LL_MESH_ENABLED  // TODO*: Remove this once deprecated  class LLNewAgentInventoryResponder : public LLAssetUploadResponder  { @@ -116,6 +116,7 @@ private:  	class Impl;  	Impl* mImpl;  }; +#endif  struct LLBakedUploadData;  class LLSendTexLayerResponder : public LLAssetUploadResponder diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 7a3eddf7a6..41f5fe64a1 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -203,7 +203,9 @@ LLBottomTray::~LLBottomTray()  	// override effect of save_visibility=true.  	// this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly:  	//		i.g when floater changes its visibility - button changes its toggle state. +	getChild<LLUICtrl>("build_btn")->setControlValue(false);  	getChild<LLUICtrl>("search_btn")->setControlValue(false); +	getChild<LLUICtrl>("world_map_btn")->setControlValue(false);  }  // *TODO Vadim: why void* ? diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index dd99c6564c..60a2392d87 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -95,7 +95,7 @@ static void* create_non_avatar_caller(void*)  	return new LLNonAvatarCaller;  } -LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL; +LLVoiceChannel* LLCallFloater::sCurrentVoiceChannel = NULL;  LLCallFloater::LLCallFloater(const LLSD& key)  : LLTransientDockableFloater(NULL, false, key) @@ -113,7 +113,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)  	mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);  	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL); -	LLVoiceClient::getInstance()->addObserver(this); +	LLVoiceClient::instance().addObserver(this);  	LLTransientFloaterMgr::getInstance()->addControlView(this);  	// force docked state since this floater doesn't save it between recreations @@ -158,7 +158,6 @@ BOOL LLCallFloater::postBuild()  	initAgentData(); -  	connectToChannel(LLVoiceChannel::getCurrentVoiceChannel());  	setIsChrome(true); @@ -204,7 +203,7 @@ void LLCallFloater::draw()  }  // virtual -void LLCallFloater::onChange() +void LLCallFloater::onParticipantsChanged()  {  	if (NULL == mParticipants) return;  	updateParticipantsVoiceState(); @@ -287,22 +286,22 @@ void LLCallFloater::updateSession()  	if (NULL == mSpeakerManager)  	{ -		// by default let show nearby chat participants +		// By default show nearby chat participants  		mSpeakerManager = LLLocalSpeakerMgr::getInstance();  		LL_DEBUGS("Voice") << "Set DEFAULT speaker manager" << LL_ENDL;  		mVoiceType = VC_LOCAL_CHAT;  	}  	updateTitle(); -	 -	//hide "Leave Call" button for nearby chat + +	// Hide "Leave Call" button for nearby chat  	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;  	childSetVisible("leave_call_btn_panel", !is_local_chat);  	refreshParticipantList();  	updateAgentModeratorState(); -	//show floater for voice calls & only in CONNECTED to voice channel state +	// Show floater for voice calls & only in CONNECTED to voice channel state  	if (!is_local_chat &&  	    voice_channel &&  	    LLVoiceChannel::STATE_CONNECTED == voice_channel->getState()) @@ -368,7 +367,7 @@ void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)  	// *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO  	// it sill be sent for the same channel again (when state is changed).  	// So, lets ignore this call. -	if (channel == sCurrentVoiceCanel) return; +	if (channel == sCurrentVoiceChannel) return;  	LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls"); @@ -715,9 +714,9 @@ void LLCallFloater::connectToChannel(LLVoiceChannel* channel)  {  	mVoiceChannelStateChangeConnection.disconnect(); -	sCurrentVoiceCanel = channel; +	sCurrentVoiceChannel = channel; -	mVoiceChannelStateChangeConnection = sCurrentVoiceCanel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2)); +	mVoiceChannelStateChangeConnection = sCurrentVoiceChannel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2));  	updateState(channel->getState());  } @@ -737,7 +736,7 @@ void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old  void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)  { -	LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceCanel->getSessionName() << LL_ENDL; +	LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceChannel->getSessionName() << LL_ENDL;  	if (LLVoiceChannel::STATE_CONNECTED == new_state)  	{  		updateSession(); diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index 0a8ea7de39..e4341175e2 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -47,15 +47,15 @@ class LLSpeakerMgr;  class LLSpeakersDelayActionsStorage;  /** - * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button. - * It can be torn-off and freely positioned onscreen. + * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron + * on the Speak button. It can be torn-off and freely positioned onscreen.   * - * When the Resident is engaged in Nearby Voice Chat, the Voice Control Panel provides control over  - * the Resident's own microphone input volume, the audible volume of each of the other participants, - * the Resident's own Voice Morphing settings (if she has subscribed to enable the feature), and Voice Recording. + * When the Resident is engaged in Voice Chat, the Voice Control Panel provides control + * over the audible volume of each of the other participants, the Resident's own Voice + * Morphing settings (if she has subscribed to enable the feature), and Voice Recording.   * - * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an  - * 'Leave Call' button to allow the Resident to leave that voice channel. + * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel + * also provides a 'Leave Call' button to allow the Resident to leave that voice channel.   */  class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver  { @@ -75,7 +75,7 @@ public:  	 *  	 * Refreshes list to display participants not in voice as disabled.  	 */ -	/*virtual*/ void onChange(); +	/*virtual*/ void onParticipantsChanged();  	static void sOnCurrentChannelChanged(const LLUUID& session_id); @@ -259,7 +259,7 @@ private:  	 *  	 * @see sOnCurrentChannelChanged()  	 */ -	static LLVoiceChannel* sCurrentVoiceCanel; +	static LLVoiceChannel* sCurrentVoiceChannel;  	/* virtual */  	LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 7ac3d14c72..916d53da3c 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -387,13 +387,7 @@ LLPanelClothingListItem* LLCOFWearables::buildClothingListItem(LLViewerInventory  	item_panel->childSetAction("btn_edit", mCOFCallbacks.mEditWearable);  	//turning on gray separator line for the last item in the items group of the same wearable type -	if (last) -	{ -		LLRect rect = item_panel->getRect(); -		item_panel->reshape(rect.getWidth(), rect.getHeight() + -		item_panel->getChild<LLView>("wearable_type_separator_icon")->getRect().getHeight()); -		item_panel->childSetVisible("wearable_type_separator_icon", true); -	} +	item_panel->childSetVisible("wearable_type_separator_icon", last);  	return item_panel;  } @@ -427,7 +421,7 @@ LLPanelDeletableWearableListItem* LLCOFWearables::buildAttachemntListItem(LLView  	llassert(item);  	if (!item) return NULL; -	LLPanelDeletableWearableListItem* item_panel = LLPanelDeletableWearableListItem::create(item); +	LLPanelAttachmentListItem* item_panel = LLPanelAttachmentListItem::create(item);  	if (!item_panel) return NULL;  	//setting callbacks diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9268cb1d47..63ca17d62d 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -103,6 +103,7 @@ S32 normal_channel = -1;  S32 specular_channel = -1;  S32 cube_channel = -1; +#if LL_MESH_ENABLED  static const U32 rigged_data_mask[] = {  	LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,  	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK, @@ -114,6 +115,7 @@ static const U32 rigged_data_mask[] = {  	LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK,						   	LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK,  }; +#endif  static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); @@ -194,12 +196,14 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)  	case 2:  		beginDeferredSkinned();  		break; +#if LL_MESH_ENABLED  	case 3:  		beginDeferredRiggedSimple();  		break;  	case 4:  		beginDeferredRiggedBump();  		break; +#endif  	}  } @@ -226,12 +230,14 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)  	case 2:  		endDeferredSkinned();  		break; +#if LL_MESH_ENABLED  	case 3:  		endDeferredRiggedSimple();  		break;  	case 4:  		endDeferredRiggedBump();  		break; +#endif  	}  } @@ -242,7 +248,11 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass)  S32 LLDrawPoolAvatar::getNumPostDeferredPasses()  { +#if LL_MESH_ENABLED  	return 6; +#else +	return 1; +#endif  }  void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) @@ -252,6 +262,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)  	case 0:  		beginPostDeferredAlpha();  		break; +#if LL_MESH_ENABLED  	case 1:  		beginRiggedFullbright();  		break; @@ -267,6 +278,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)  	case 5:  		beginRiggedGlow();  		break; +#endif  	}  } @@ -284,6 +296,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha()  	enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);  } +#if LL_MESH_ENABLED  void LLDrawPoolAvatar::beginDeferredRiggedAlpha()  {  	sVertexProgram = &gDeferredSkinnedAlphaProgram; @@ -301,6 +314,7 @@ void LLDrawPoolAvatar::endDeferredRiggedAlpha()  	LLVertexBuffer::sWeight4Loc = -1;  	sVertexProgram = NULL;  } +#endif  void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)  { @@ -309,6 +323,7 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)  	case 0:  		endPostDeferredAlpha();  		break; +#if LL_MESH_ENABLED  	case 1:  		endRiggedFullbright();  		break; @@ -324,6 +339,7 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)  	case 5:  		endRiggedGlow();  		break; +#endif  	}  } @@ -357,7 +373,11 @@ void LLDrawPoolAvatar::renderPostDeferred(S32 pass)  S32 LLDrawPoolAvatar::getNumShadowPasses()  { +#if LL_MESH_ENABLED  	return 2; +#else +	return 1; +#endif  }  void LLDrawPoolAvatar::beginShadowPass(S32 pass) @@ -448,6 +468,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)  		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);  	} +#if LL_MESH_ENABLED  	else  	{  		renderRigged(avatarp, RIGGED_SIMPLE); @@ -457,10 +478,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)  		renderRigged(avatarp, RIGGED_SHINY);  		renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA);  	} +#endif  }  S32 LLDrawPoolAvatar::getNumPasses()  { +#if LL_MESH_ENABLED  	if (LLPipeline::sImpostorRender)  	{  		return 8; @@ -473,8 +496,19 @@ S32 LLDrawPoolAvatar::getNumPasses()  	{  		return 3;  	} +#else +	if (LLPipeline::sImpostorRender) +	{ +		return 1; +	} +	else  +	{ +		return 3; +	} +#endif  } +  S32 LLDrawPoolAvatar::getNumDeferredPasses()  {  	if (LLPipeline::sImpostorRender) @@ -522,6 +556,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)  	case 2:  		beginSkinned();  		break; +#if LL_MESH_ENABLED  	case 3:  		beginRiggedSimple();  		break; @@ -543,6 +578,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)  	case 9:  		beginRiggedGlow();  		break; +#endif  	}  } @@ -566,6 +602,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)  	case 2:  		endSkinned();  		break; +#if LL_MESH_ENABLED  	case 3:  		endRiggedSimple();  		break; @@ -587,6 +624,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)  	case 9:  		endRiggedGlow();  		break; +#endif  	}  } @@ -772,6 +810,7 @@ void LLDrawPoolAvatar::endSkinned()  	gGL.getTexUnit(0)->activate();  } +#if LL_MESH_ENABLED  void LLDrawPoolAvatar::beginRiggedSimple()  {  	sVertexProgram = &gSkinnedObjectSimpleProgram; @@ -924,6 +963,7 @@ void LLDrawPoolAvatar::endDeferredRiggedBump()  	sDiffuseChannel = 0;  	sVertexProgram = NULL;  } +#endif  void LLDrawPoolAvatar::beginDeferredSkinned()  { @@ -1069,6 +1109,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  		return;  	} +#if LL_MESH_ENABLED  	if (pass == 3)  	{  		if (is_deferred_render) @@ -1150,7 +1191,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  		gGL.setSceneBlendType(LLRender::BT_ALPHA);  		return;  	} - +#endif  	if (sShaderLevel > 0)  	{ @@ -1188,6 +1229,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  	}  } +#if LL_MESH_ENABLED  void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)  {  	U32 data_mask = 0; @@ -1377,7 +1419,7 @@ void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar)  {  	renderRigged(avatar, RIGGED_GLOW, true);  } - +#endif @@ -1479,6 +1521,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const  	return LLColor3(0.f, 1.f, 0.f);  } +#if LL_MESH_ENABLED  void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)  {  	if (facep->mRiggedIndex.empty()) @@ -1533,6 +1576,7 @@ void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)  		}  	}  } +#endif  LLVertexBufferAvatar::LLVertexBufferAvatar()  : LLVertexBuffer(sDataMask,  diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 4a5b009412..46ffc42f04 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -96,6 +96,23 @@ public:  	void beginRigid();  	void beginImpostor();  	void beginSkinned(); +	 +	void endRigid(); +	void endImpostor(); +	void endSkinned(); + +	void beginDeferredImpostor(); +	void beginDeferredRigid(); +	void beginDeferredSkinned(); +	 +	void endDeferredImpostor(); +	void endDeferredRigid(); +	void endDeferredSkinned(); +	 +	void beginPostDeferredAlpha(); +	void endPostDeferredAlpha(); + +#if LL_MESH_ENABLED  	void beginRiggedSimple();  	void beginRiggedFullbright();  	void beginRiggedFullbrightShiny(); @@ -103,12 +120,8 @@ public:  	void beginRiggedAlpha();  	void beginRiggedFullbrightAlpha();  	void beginRiggedGlow(); -	void beginPostDeferredAlpha();  	void beginDeferredRiggedAlpha(); -	void endRigid(); -	void endImpostor(); -	void endSkinned();  	void endRiggedSimple();  	void endRiggedFullbright();  	void endRiggedFullbrightShiny(); @@ -116,18 +129,11 @@ public:  	void endRiggedAlpha();  	void endRiggedFullbrightAlpha();  	void endRiggedGlow(); -	void endPostDeferredAlpha();  	void endDeferredRiggedAlpha(); -	void beginDeferredImpostor(); -	void beginDeferredRigid(); -	void beginDeferredSkinned();  	void beginDeferredRiggedSimple();  	void beginDeferredRiggedBump(); -	void endDeferredImpostor(); -	void endDeferredRigid(); -	void endDeferredSkinned();  	void endDeferredRiggedSimple();  	void endDeferredRiggedBump(); @@ -147,11 +153,6 @@ public:  	void renderDeferredRiggedSimple(LLVOAvatar* avatar);  	void renderDeferredRiggedBump(LLVOAvatar* avatar); -	/*virtual*/ LLViewerTexture *getDebugTexture(); -	/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - -	void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. -  	typedef enum  	{  		RIGGED_SIMPLE = 0, @@ -202,6 +203,13 @@ public:  	void removeRiggedFace(LLFace* facep);   	std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES]; +#endif + +	/*virtual*/ LLViewerTexture *getDebugTexture(); +	/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display + +	void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. +  	static BOOL sSkipOpaque;  	static BOOL sSkipTransparent; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index e4f9e28c77..c48106863e 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -224,11 +224,13 @@ void LLFace::destroy()  	{  		LLFastTimer t(FTM_DESTROY_DRAWPOOL); +#if LL_MESH_ENABLED  		if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR)  		{  			((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this);  		}  		else +#endif  		{  			mDrawPoolp->removeFace(this);  		} diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 3c2ee6a0b1..3d833c24cc 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -91,10 +91,6 @@  ///----------------------------------------------------------------------------  /// Local function declarations, constants, enums, and typedefs  ///---------------------------------------------------------------------------- -S32 LLFloaterSnapshot::sUIWinHeightLong = 526 ; -S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 230 ; -S32 LLFloaterSnapshot::sUIWinWidth = 215 ; -  LLSnapshotFloaterView* gSnapshotFloaterView = NULL;  const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -1174,9 +1170,6 @@ public:  	}  	static void onClickNewSnapshot(void* data);  	static void onClickAutoSnap(LLUICtrl *ctrl, void* data); -	//static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); -	static void onClickLess(void* data) ; -	static void onClickMore(void* data) ;  	static void onClickUICheck(LLUICtrl *ctrl, void* data);  	static void onClickHUDCheck(LLUICtrl *ctrl, void* data);  	static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); @@ -1190,7 +1183,7 @@ public:  	static void onCommitCustomResolution(LLUICtrl *ctrl, void* data);  	static void onCommitSnapshot(LLFloaterSnapshot* view, LLSnapshotLivePreview::ESnapshotType type);  	static void onCommitProfilePic(LLFloaterSnapshot* view); -	static void onToggleAdvanced(LLUICtrl *ctrl, void* data); +	static void showAdvanced(LLFloaterSnapshot* view, const BOOL visible);  	static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ;  	static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); @@ -1401,41 +1394,6 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)  	}  } -void LLFloaterSnapshot::Impl::onClickMore(void* data) -{ -	gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE ); -	 -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		 -	if (view) -	{ -		view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() ); -		view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong()); -		updateControls(view) ; -		updateLayout(view) ; -		if(getPreviewView(view)) -		{ -			getPreviewView(view)->setThumbnailImageSize() ; -		} -	} -} -void LLFloaterSnapshot::Impl::onClickLess(void* data) -{ -	gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE ); -	 -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;		 -	if (view) -	{ -		view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() ); -		view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort()); -		updateControls(view) ; -		updateLayout(view) ; -		if(getPreviewView(view)) -		{ -			getPreviewView(view)->setThumbnailImageSize() ; -		} -	} -} -  // static  void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data)  { @@ -1693,30 +1651,28 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data)  }  //static  -void LLFloaterSnapshot::Impl::onToggleAdvanced(LLUICtrl* ctrl, void* data) +void LLFloaterSnapshot::Impl::showAdvanced(LLFloaterSnapshot* view, const BOOL visible)  { -	LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; -  	LLPanel* advanced_panel = view->getChild<LLPanel>("snapshot_advanced"); -	if (advanced_panel->getVisible()) +	if (advanced_panel->getVisible() != visible)  	{ -		advanced_panel->setVisible(false); +		gSavedSettings.setBOOL("AdvanceSnapshot", visible); -		// shrink floater back to original size -		view->reshape(view->getRect().getWidth() - advanced_panel->getRect().getWidth(), view->getRect().getHeight()); +		advanced_panel->setVisible(visible); +		view->getChild<LLButton>("hide_advanced")->setVisible(visible); +		view->getChild<LLButton>("show_advanced")->setVisible(!visible); -		view->getChild<LLButton>("hide_advanced")->setVisible(false); -		view->getChild<LLButton>("show_advanced")->setVisible(true); -	} -	else -	{ -		advanced_panel->setVisible(true); -		// stretch the floater so it can accommodate the advanced panel -		view->reshape(view->getRect().getWidth() + advanced_panel->getRect().getWidth(), view->getRect().getHeight()); - -		view->getChild<LLButton>("hide_advanced")->setVisible(true); -		view->getChild<LLButton>("show_advanced")->setVisible(false); +		if (visible) +		{ +			// stretch the floater so it can accommodate the advanced panel +			view->reshape(view->getRect().getWidth() + advanced_panel->getRect().getWidth(), view->getRect().getHeight()); +		} +		else +		{ +			// shrink floater back to original size +			view->reshape(view->getRect().getWidth() - advanced_panel->getRect().getWidth(), view->getRect().getHeight()); +		}  	}  } @@ -2004,6 +1960,11 @@ LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)  	  impl (*(new Impl))  {  	//Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_snapshot.xml", FALSE); + +	mCommitCallbackRegistrar.add("Snapshot.ShowButtons",  boost::bind(&LLFloaterSnapshot::updateButtons, this, _2)); +	mCommitCallbackRegistrar.add("Snapshot.ShowAdvanced", boost::bind(&Impl::showAdvanced, this, true)); +	mCommitCallbackRegistrar.add("Snapshot.HideAdvanced", boost::bind(&Impl::showAdvanced, this, false)); +	mCommitCallbackRegistrar.add("Snapshot.Refresh", boost::bind(&Impl::onClickNewSnapshot, this));  }  // Destroys the object @@ -2025,27 +1986,14 @@ LLFloaterSnapshot::~LLFloaterSnapshot()  BOOL LLFloaterSnapshot::postBuild()  { - -	getChild<LLButton>("share")->setCommitCallback(boost::bind(&LLFloaterSnapshot::updateButtons, this, SNAPSHOT_SHARE)); -	getChild<LLButton>("save")->setCommitCallback(boost::bind(&LLFloaterSnapshot::updateButtons, this, SNAPSHOT_SAVE)); -	getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterSnapshot::updateButtons, this, SNAPSHOT_MAIN)); -  	getChild<LLButton>("share_to_web")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_WEB));  	getChild<LLButton>("share_to_email")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_POSTCARD));  	getChild<LLButton>("save_to_inventory")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_TEXTURE));  	getChild<LLButton>("save_to_computer")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_LOCAL));  	getChild<LLButton>("set_profile_pic")->setCommitCallback(boost::bind(&Impl::onCommitProfilePic, this)); -	childSetCommitCallback("show_advanced", Impl::onToggleAdvanced, this); -	childSetCommitCallback("hide_advanced", Impl::onToggleAdvanced, this); -  	childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); -	childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); - -	childSetAction("more_btn", Impl::onClickMore, this); -	childSetAction("less_btn", Impl::onClickLess, this); -  	childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this);  	childSetValue("image_quality_slider", gSavedSettings.getS32("SnapshotQuality")); @@ -2097,12 +2045,13 @@ BOOL LLFloaterSnapshot::postBuild()  	impl.mPreviewHandle = previewp->getHandle();  	impl.updateControls(this);  	impl.updateLayout(this); +	impl.showAdvanced(this, gSavedSettings.getBOOL("AdvanceSnapshot"));  	//save off the refresh button's rectangle so we can apply offsets with thumbnail resize   	mRefreshBtnRect = getChild<LLButton>("new_snapshot_btn")->getRect();  	// make sure we share/hide the general buttons  -	updateButtons(SNAPSHOT_MAIN); +	updateButtons(LLSD("main"));  	return LLDockableFloater::postBuild();  } @@ -2192,19 +2141,20 @@ void LLFloaterSnapshot::update()  	}  } -bool LLFloaterSnapshot::updateButtons(ESnapshotMode mode) +bool LLFloaterSnapshot::updateButtons(const LLSD& mode)  { -	childSetVisible("share", mode == SNAPSHOT_MAIN); -	childSetVisible("save", mode == SNAPSHOT_MAIN); -	childSetVisible("set_profile_pic", mode == SNAPSHOT_MAIN); +	std::string button_mode = mode.asString(); -//	childSetVisible("share_to_web", mode == SNAPSHOT_SHARE); -	childSetVisible("share_to_email", mode == SNAPSHOT_SHARE); +	bool mode_main("main" == button_mode); +	bool mode_share("share" == button_mode); +	bool mode_save("save" == button_mode); -	childSetVisible("save_to_inventory", mode == SNAPSHOT_SAVE); -	childSetVisible("save_to_computer", mode == SNAPSHOT_SAVE); +	// Default to a known state if mode is invalid. +	if (!mode_main && !mode_share && !mode_save) mode_main = true; -	childSetVisible("cancel", mode != SNAPSHOT_MAIN);	 +	childSetVisible("panel_snapshot_main", mode_main); +	childSetVisible("panel_snapshot_share", mode_share); +	childSetVisible("panel_snapshot_save", mode_save);  	return true;  } diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 931d355748..8c4373c35c 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -47,13 +47,6 @@ public:  		SNAPSHOT_FORMAT_BMP  	} ESnapshotFormat; -	enum ESnapshotMode -	{ -		SNAPSHOT_SHARE, -		SNAPSHOT_SAVE, -		SNAPSHOT_MAIN -	}; -  	LLFloaterSnapshot(const LLSD& key);  	virtual ~LLFloaterSnapshot(); @@ -66,7 +59,7 @@ public:  	void setAsProfilePic(const LLUUID& image_id); -	bool updateButtons(ESnapshotMode mode); +	bool updateButtons(const LLSD& mode);  	static S32  getUIWinHeightLong()  {return sUIWinHeightLong ;}  	static S32  getUIWinHeightShort() {return sUIWinHeightShort ;} diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp new file mode 100644 index 0000000000..ca1f142760 --- /dev/null +++ b/indra/newview/llfloatervoiceeffect.cpp @@ -0,0 +1,288 @@ +/**  + * @file llfloatervoiceeffect.cpp + * @author Aimee + * @brief Selection and preview of voice effect. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatervoiceeffect.h" + +#include "llscrolllistctrl.h" +#include "lltrans.h" +#include "llweb.h" + +LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key) +	: LLFloater(key) +{ +	mCommitCallbackRegistrar.add("VoiceEffect.Record",	boost::bind(&LLFloaterVoiceEffect::onClickRecord, this)); +	mCommitCallbackRegistrar.add("VoiceEffect.Play",	boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); +	mCommitCallbackRegistrar.add("VoiceEffect.Stop",	boost::bind(&LLFloaterVoiceEffect::onClickStop, this)); +//	mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); +} + +// virtual +LLFloaterVoiceEffect::~LLFloaterVoiceEffect() +{ +	if(LLVoiceClient::instanceExists()) +	{ +		LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +		if (effect_interface) +		{ +			effect_interface->removeObserver(this); +		} +	} +} + +// virtual +BOOL LLFloaterVoiceEffect::postBuild() +{ +	setDefaultBtn("record_btn"); +	getChild<LLButton>("record_btn")->setFocus(true); +	childSetTextArg("voice_morphing_link", "[URL]", LLTrans::getString("voice_morphing_url")); + +	mVoiceEffectList = getChild<LLScrollListCtrl>("voice_effect_list"); +	if (mVoiceEffectList) +	{ +		mVoiceEffectList->setCommitCallback(boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); +//		mVoiceEffectList->setDoubleClickCallback(boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); +	} + +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		effect_interface->addObserver(this); + +		// Disconnect from the current voice channel ready to record a voice sample for previewing +		effect_interface->enablePreviewBuffer(true); +	} + +	refreshEffectList(); +	updateControls(); + +	return TRUE; +} + +// virtual +void LLFloaterVoiceEffect::onClose(bool app_quitting) +{ +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		effect_interface->enablePreviewBuffer(false); +	} +} + +void LLFloaterVoiceEffect::refreshEffectList() +{ +	if (!mVoiceEffectList) +	{ +		return; +	} + +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (!effect_interface) +	{ +		mVoiceEffectList->setEnabled(false); +		return; +	} + +	LL_DEBUGS("Voice")<< "Rebuilding Voice Morph list."<< LL_ENDL; + +	// Preserve selected items and scroll position +	S32 scroll_pos = mVoiceEffectList->getScrollPos(); +	uuid_vec_t selected_items; +	std::vector<LLScrollListItem*> items = mVoiceEffectList->getAllSelected(); +	for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++) +	{ +		selected_items.push_back((*it)->getUUID()); +	} + +	mVoiceEffectList->deleteAllItems(); + +	{ +		// Add the "No Voice Morph" entry +		LLSD element; + +		element["id"] = LLUUID::null; +		element["columns"][NAME_COLUMN]["column"] = "name"; +		element["columns"][NAME_COLUMN]["value"] = getString("no_voice_effect"); +		element["columns"][NAME_COLUMN]["font"]["style"] = "BOLD"; + +		LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); +		// *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( +		if(sl_item) +		{ +			((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(LLFontGL::BOLD); +		} +	} + +	// Add each Voice Morph template, if there are any (template list includes all usable effects) +	const voice_effect_list_t& template_list = effect_interface->getVoiceEffectTemplateList(); +	if (!template_list.empty()) +	{ +		for (voice_effect_list_t::const_iterator it = template_list.begin(); it != template_list.end(); ++it) +		{ +			const LLUUID& effect_id = it->second; +			std::string effect_name = it->first; + +			LLSD effect_properties = effect_interface->getVoiceEffectProperties(effect_id); + +			// Tag the active effect. +			if (effect_id == LLVoiceClient::instance().getVoiceEffectDefault()) +			{ +				effect_name += " " + getString("active_voice_effect"); +			} + +			// Tag available effects that are new this session +			if (effect_properties["is_new"].asBoolean()) +			{ +				effect_name += " " + getString("new_voice_effect"); +			} + +			LLDate expiry_date = effect_properties["expiry_date"].asDate(); +			bool is_template_only = effect_properties["template_only"].asBoolean(); + +			std::string font_style = "NORMAL"; +			if (!is_template_only) +			{ +				font_style = "BOLD"; +			} + +			LLSD element; +			element["id"] = effect_id; + +			element["columns"][NAME_COLUMN]["column"] = "name"; +			element["columns"][NAME_COLUMN]["value"] = effect_name; +			element["columns"][NAME_COLUMN]["font"]["style"] = font_style; + +			element["columns"][1]["column"] = "expires"; +			if (!is_template_only) +			{ +				element["columns"][DATE_COLUMN]["value"] = expiry_date; +				element["columns"][DATE_COLUMN]["type"] = "date"; +			} +			else { +				element["columns"][DATE_COLUMN]["value"] = getString("unsubscribed_voice_effect"); +			} +//			element["columns"][DATE_COLUMN]["font"]["style"] = "NORMAL"; + +			LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); +			// *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( +			if(sl_item) +			{ +				LLFontGL::StyleFlags style = is_template_only ? LLFontGL::NORMAL : LLFontGL::BOLD; +				dynamic_cast<LLScrollListText*>(sl_item->getColumn(0))->setFontStyle(style); +			} +		} +	} + +	// Re-select items that were selected before, and restore the scroll position +	for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++) +	{ +		mVoiceEffectList->selectByID(*it); +	} +	mVoiceEffectList->setScrollPos(scroll_pos); +	mVoiceEffectList->setEnabled(true); +} + +void LLFloaterVoiceEffect::updateControls() +{ +	bool recording = false; + +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		recording = effect_interface->isPreviewRecording(); +	} + +	getChild<LLButton>("record_btn")->setVisible(!recording); +	getChild<LLButton>("record_stop_btn")->setVisible(recording); +} + +// virtual +void LLFloaterVoiceEffect::onVoiceEffectChanged(bool effect_list_updated) +{ +	if (effect_list_updated) +	{ +		refreshEffectList(); +	} +	updateControls(); +} + +void LLFloaterVoiceEffect::onClickRecord() +{ +	LL_DEBUGS("Voice") << "Record clicked" << LL_ENDL; +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		effect_interface->recordPreviewBuffer(); +	} +	updateControls(); +} + +void LLFloaterVoiceEffect::onClickPlay() +{ +	LL_DEBUGS("Voice") << "Play clicked" << LL_ENDL; +	if (!mVoiceEffectList) +	{ +		return; +	} + +	const LLUUID& effect_id = mVoiceEffectList->getCurrentID(); + +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		effect_interface->playPreviewBuffer(effect_id); +	} +	updateControls(); +} + +void LLFloaterVoiceEffect::onClickStop() +{ +	LL_DEBUGS("Voice") << "Stop clicked" << LL_ENDL; +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		effect_interface->stopPreviewBuffer(); +	} +	updateControls(); +} + +//void LLFloaterVoiceEffect::onClickActivate() +//{ +//	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +//	if (effect_interface && mVoiceEffectList) +//	{ +//		effect_interface->setVoiceEffect(mVoiceEffectList->getCurrentID()); +//	} +//} + diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h new file mode 100644 index 0000000000..fe207a05c3 --- /dev/null +++ b/indra/newview/llfloatervoiceeffect.h @@ -0,0 +1,78 @@ +/**  + * @file llfloatervoiceeffect.h + * @author Aimee + * @brief Selection and preview of voice effects. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERVOICEEFFECT_H +#define LL_LLFLOATERVOICEEFFECT_H + +#include "llfloater.h" +#include "llvoiceclient.h" + +class LLButton; +class LLScrollListCtrl; + +class LLFloaterVoiceEffect +	: public LLFloater +	, public LLVoiceEffectObserver +{ +public: +	LOG_CLASS(LLFloaterVoiceEffect); + +	LLFloaterVoiceEffect(const LLSD& key); +	virtual ~LLFloaterVoiceEffect(); + +	virtual BOOL postBuild(); +	virtual void onClose(bool app_quitting); + +private: +	enum ColumnIndex +	{ +		NAME_COLUMN = 0, +		DATE_COLUMN = 1, +	}; + +	void refreshEffectList(); +	void updateControls(); + +	/// Called by voice effect provider when voice effect list is changed. +	virtual void onVoiceEffectChanged(bool effect_list_updated); + +	void onClickRecord(); +	void onClickPlay(); +	void onClickStop(); +//	void onClickActivate(); + +	LLUUID mSelectedID; +	LLScrollListCtrl* mVoiceEffectList; +}; + +#endif diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 3aa9d75bc0..967f38bfd2 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -60,8 +60,14 @@  #include "llinventorymodel.h"  #include "llrootview.h"  #include "llspeakers.h" +#include "llsidetray.h" +static const S32 RECT_PADDING_NOT_INIT = -1; +static const S32 RECT_PADDING_NEED_RECALC = -2; + +S32 LLIMFloater::sAllowedRectRightPadding = RECT_PADDING_NOT_INIT; +  LLIMFloater::LLIMFloater(const LLUUID& session_id)    : LLTransientDockableFloater(NULL, true, session_id),  	mControlPanel(NULL), @@ -444,19 +450,44 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  	return floater;  } +//static +bool LLIMFloater::resetAllowedRectPadding(const LLSD& newvalue) +{ +	//reset allowed rect right padding if "SidebarCameraMovement" option  +	//or sidebar state changed +	sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC ; +	return true; +} +  void LLIMFloater::getAllowedRect(LLRect& rect)  { +	if (sAllowedRectRightPadding == RECT_PADDING_NOT_INIT) //wasn't initialized +	{ +		gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2)); + +		LLSideTray*	side_bar = LLSideTray::getInstance(); +		side_bar->getCollapseSignal().connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2)); +		sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC; +	} +  	rect = gViewerWindow->getWorldViewRectScaled(); -	static S32 right_padding = 0; -	if (right_padding == 0) +	if (sAllowedRectRightPadding == RECT_PADDING_NEED_RECALC) //recalc allowed rect right padding  	{  		LLPanel* side_bar_tabs =  				gViewerWindow->getRootView()->getChild<LLPanel> (  						"side_bar_tabs"); -		right_padding = side_bar_tabs->getRect().getWidth(); +		sAllowedRectRightPadding = side_bar_tabs->getRect().getWidth();  		LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs); + +		if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE) +		{ +			LLSideTray*	side_bar = LLSideTray::getInstance(); + +			if (side_bar->getVisible() && !side_bar->getCollapsed()) +				sAllowedRectRightPadding += side_bar->getRect().getWidth(); +		}  	} -	rect.mRight -= right_padding; +	rect.mRight -= sAllowedRectRightPadding;  }  void LLIMFloater::setDocked(bool docked, bool pop_on_undock) diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index fef178e3a2..f1e68a2b3d 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -155,6 +155,10 @@ private:  	static void closeHiddenIMToasts(); +	static bool resetAllowedRectPadding(const LLSD& newvalue); +	//need to keep this static for performance issues +	static S32 sAllowedRectRightPadding; +  	static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response);  	LLPanelChatControlPanel* mControlPanel; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 97d51a9d90..37d2c50493 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -917,6 +917,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  			// Only should happen for broken links.  			new_listener = new LLLinkItemBridge(inventory, root, uuid);  			break; +#if LL_MESH_ENABLED  	    case LLAssetType::AT_MESH:  			if(!(inv_type == LLInventoryType::IT_MESH))  			{ @@ -924,6 +925,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,  			}  			new_listener = new LLMeshBridge(inventory, root, uuid);  			break; +#endif  		default:  			llinfos << "Unhandled asset type (llassetstorage.h): " @@ -2765,7 +2767,9 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,  		case DAD_ANIMATION:  		case DAD_GESTURE:  		case DAD_LINK: +#if LL_MESH_ENABLED  		case DAD_MESH: +#endif  			accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,  										drop);  			break; @@ -3635,7 +3639,9 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,  			case DAD_BODYPART:  			case DAD_ANIMATION:  			case DAD_GESTURE: -		case DAD_MESH: +#if LL_MESH_ENABLED +			case DAD_MESH: +#endif  			{  				LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;  				const LLPermissions& perm = inv_item->getPermissions(); @@ -4843,6 +4849,7 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	hide_context_entries(menu, items, disabled_items);  } +#if LL_MESH_ENABLED  // +=================================================+  // |        LLMeshBridge                             |  // +=================================================+ @@ -4899,6 +4906,7 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	hide_context_entries(menu, items, disabled_items);  } +#endif  // +=================================================+  // |        LLLinkBridge                             | diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index d637fc6e36..8de7d63173 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -527,7 +527,7 @@ protected:  }; - +#if LL_MESH_ENABLED  class LLMeshBridge : public LLItemBridge  {  	friend class LLInvFVBridge; @@ -543,7 +543,7 @@ protected:  		     const LLUUID& uuid) :                         LLItemBridge(inventory, root, uuid) {}  }; - +#endif diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 33b52cfd5e..c82ebd1439 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -324,6 +324,19 @@ private:  	LLWearableType::EType mWearableType;  }; +/** Filter out wearables-links */ +class LLFindActualWearablesOfType : public LLFindWearablesOfType +{ +public: +	LLFindActualWearablesOfType(LLWearableType::EType type) : LLFindWearablesOfType(type) {} +	virtual ~LLFindActualWearablesOfType() {} +	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) +	{ +		if (item && item->getIsLinkType()) return false; +		return LLFindWearablesOfType::operator()(cat, item); +	} +}; +  // Find worn items.  class LLFindWorn : public LLInventoryCollectFunctor  { diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 0dd6f53be7..2c60d38cb5 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -177,7 +177,10 @@ protected:  	void setIconImage(const LLUIImagePtr& image);  	/** Set item title - inventory item name usually */ -	void setTitle(const std::string& title, const std::string& highlit_text); +	virtual void setTitle(const std::string& title, const std::string& highlit_text); + + +	LLViewerInventoryItem* mItem;  	// force not showing link icon on item's icon  	bool mForceNoLinksOnIcons; @@ -196,7 +199,6 @@ private:  	/** reshape remaining widgets */  	void reshapeMiddleWidgets(); -	LLViewerInventoryItem* mItem;  	LLIconCtrl*		mIconCtrl;  	LLTextBox*		mTitleCtrl; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6fc5804a48..15760bf155 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -721,8 +721,20 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)  			// Valid UUID; set the item UUID and rename it  			new_item->setCreator(id);  			std::string avatar_name; -			// Fetch the currect name -			gCacheName->get(id, FALSE, boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), _1, _2, _3)); + +			if (gCacheName->getFullName(id, avatar_name)) +			{ +				new_item->rename(avatar_name); +				mask |= LLInventoryObserver::LABEL; +			} +			else +			{ +				// Fetch the current name +				gCacheName->get(id, FALSE, +					boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), +					_1, _2, _3)); +			} +  		}  	}  	else if (new_item->getType() == LLAssetType::AT_GESTURE) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index b4f0947b2c..ce44e37017 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -33,15 +33,14 @@  #include "llviewerprecompiledheaders.h"  #include "llinventorymodelbackgroundfetch.h" -// Seraph clean this up  #include "llagent.h" +#include "llappviewer.h" +#include "llcallbacklist.h"  #include "llinventorypanel.h"  #include "llviewercontrol.h"  #include "llviewermessage.h" -#include "llviewerwindow.h" -#include "llappviewer.h"  #include "llviewerregion.h" -#include "llcallbacklist.h" +#include "llviewerwindow.h"  const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;  const S32 MAX_FETCH_RETRIES = 10; @@ -63,47 +62,47 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()  {  } -bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() +bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const  {  	return mFetchQueue.empty() && mBulkFetchCount<=0;  } -bool LLInventoryModelBackgroundFetch::libraryFetchStarted() +bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const  {  	return mRecursiveLibraryFetchStarted;  } -bool LLInventoryModelBackgroundFetch::libraryFetchCompleted() +bool LLInventoryModelBackgroundFetch::libraryFetchCompleted() const  {  	return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID());  } -bool LLInventoryModelBackgroundFetch::libraryFetchInProgress() +bool LLInventoryModelBackgroundFetch::libraryFetchInProgress() const  {  	return libraryFetchStarted() && !libraryFetchCompleted();  } -bool LLInventoryModelBackgroundFetch::inventoryFetchStarted() +bool LLInventoryModelBackgroundFetch::inventoryFetchStarted() const  {  	return mRecursiveInventoryFetchStarted;  } -bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() +bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() const  {  	return inventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID());  } -bool LLInventoryModelBackgroundFetch::inventoryFetchInProgress() +bool LLInventoryModelBackgroundFetch::inventoryFetchInProgress() const  {  	return inventoryFetchStarted() && !inventoryFetchCompleted();  } -bool LLInventoryModelBackgroundFetch::isEverythingFetched() +bool LLInventoryModelBackgroundFetch::isEverythingFetched() const  {  	return mAllFoldersFetched;  } -BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() +BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const  {  	return mBackgroundFetchActive;  } @@ -132,7 +131,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive  		}  		else  		{ -			// specific folder requests go to front of queue +			// Specific folder requests go to front of queue.  			if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)  			{  				mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive)); @@ -187,7 +186,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  {  	if (mBackgroundFetchActive && gAgent.getRegion())  	{ -		//If we'll be using the capability, we'll be sending batches and the background thing isn't as important. +		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.  		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");     		if (!url.empty())   		{ @@ -195,8 +194,12 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			return;  		} -		//DEPRECATED OLD CODE FOLLOWS. -		// no more categories to fetch, stop fetch process +#if 1 +		//-------------------------------------------------------------------------------- +		// DEPRECATED OLD CODE +		// + +		// No more categories to fetch, stop fetch process.  		if (mFetchQueue.empty())  		{  			llinfos << "Inventory fetch completed" << llendl; @@ -209,11 +212,11 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  		F32 slow_fetch_time = lerp(mMinTimeBetweenFetches, mMaxTimeBetweenFetches, 0.5f);  		if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() > slow_fetch_time)  		{ -			// double timeouts on failure +			// Double timeouts on failure.  			mMinTimeBetweenFetches = llmin(mMinTimeBetweenFetches * 2.f, 10.f);  			mMaxTimeBetweenFetches = llmin(mMaxTimeBetweenFetches * 2.f, 120.f);  			llinfos << "Inventory fetch times grown to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; -			// fetch is no longer considered "timely" although we will wait for full time-out +			// fetch is no longer considered "timely" although we will wait for full time-out.  			mTimelyFetchPending = FALSE;  		} @@ -226,14 +229,14 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			if(gDisconnected)  			{ -				// just bail if we are disconnected. +				// Just bail if we are disconnected.  				break;  			}  			const FetchQueueInfo info = mFetchQueue.front();  			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID); -			// category has been deleted, remove from queue. +			// Category has been deleted, remove from queue.  			if (!cat)  			{  				mFetchQueue.pop_front(); @@ -243,8 +246,8 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&   				LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())  			{ -				// category exists but has no children yet, fetch the descendants -				// for now, just request every time and rely on retry timer to throttle +				// Category exists but has no children yet, fetch the descendants +				// for now, just request every time and rely on retry timer to throttle.  				if (cat->fetch())  				{  					mFetchTimer.reset(); @@ -258,13 +261,13 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  					break;  				}  			} -			// do I have all my children? +			// Do I have all my children?  			else if (gInventory.isCategoryComplete(info.mCatUUID))  			{ -				// finished with this category, remove from queue +				// Finished with this category, remove from queue.  				mFetchQueue.pop_front(); -				// add all children to queue +				// Add all children to queue.  				LLInventoryModel::cat_array_t* categories;  				LLInventoryModel::item_array_t* items;  				gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); @@ -275,10 +278,10 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  					mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));  				} -				// we received a response in less than the fast time +				// We received a response in less than the fast time.  				if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)  				{ -					// shrink timeouts based on success +					// Shrink timeouts based on success.  					mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);  					mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);  					//llinfos << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; @@ -289,8 +292,8 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			}  			else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)  			{ -				// received first packet, but our num descendants does not match db's num descendants -				// so try again later +				// Received first packet, but our num descendants does not match db's num descendants +				// so try again later.  				mFetchQueue.pop_front();  				if (mNumFetchRetries++ < MAX_FETCH_RETRIES) @@ -303,9 +306,14 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  				break;  			} -			// not enough time has elapsed to do a new fetch +			// Not enough time has elapsed to do a new fetch  			break;  		} + +		// +		// DEPRECATED OLD CODE +		//-------------------------------------------------------------------------------- +#endif  	}  } @@ -333,10 +341,10 @@ protected:  	BOOL getIsRecursive(const LLUUID& cat_id) const;  private:  	LLSD mRequestSD; -	uuid_vec_t mRecursiveCatUUIDs; // Hack for storing away which cat fetches are recursive. +	uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive  }; -//If we get back a normal response, handle it here +// If we get back a normal response, handle it here.  void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  {  	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); @@ -428,7 +436,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  				gInventory.updateItem(titem);  			} -			// set version and descendentcount according to message. +			// Set version and descendentcount according to message.  			LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);  			if(cat)  			{ @@ -448,7 +456,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  		{	  			LLSD folder_sd = *folder_it; -			//These folders failed on the dataserver.  We probably don't want to retry them. +			// These folders failed on the dataserver.  We probably don't want to retry them.  			llinfos << "Folder " << folder_sd["folder_id"].asString()   					<< "Error: " << folder_sd["error"].asString() << llendl;  		} @@ -465,7 +473,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  	gInventory.notifyObservers("fetchDescendents");  } -//If we get back an error (not found, etc...), handle it here +// If we get back an error (not found, etc...), handle it here.  void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason)  {  	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance(); @@ -475,7 +483,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str  	fetcher->incrBulkFetch(-1); -	if (status==499) // Timed out. +	if (status==499) // timed out  	{  		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();  			folder_it != mRequestSD["folders"].endArray(); @@ -502,7 +510,8 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat  	return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end());  } -//static   Bundle up a bunch of requests to send all at once. +// Bundle up a bunch of requests to send all at once. +// static     void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  {  	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. @@ -521,7 +530,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  		(mBulkFetchCount > max_concurrent_fetches) ||  		(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))  	{ -		return; // just bail if we are disconnected. +		return; // just bail if we are disconnected  	}	  	U32 folder_count=0; diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index c1e37eda8f..04f96586d7 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -33,39 +33,15 @@  #ifndef LL_LLINVENTORYMODELBACKGROUNDFETCH_H  #define LL_LLINVENTORYMODELBACKGROUNDFETCH_H -// Seraph clean this up -#include "llassettype.h" -#include "llfoldertype.h" -#include "lldarray.h" -#include "llframetimer.h" -#include "llhttpclient.h" +#include "llsingleton.h"  #include "lluuid.h" -#include "llpermissionsflags.h" -#include "llstring.h" -#include <map> -#include <set> -#include <string> -#include <vector> - -// Seraph clean this up -class LLInventoryObserver; -class LLInventoryObject; -class LLInventoryItem; -class LLInventoryCategory; -class LLViewerInventoryItem; -class LLViewerInventoryCategory; -class LLViewerInventoryItem; -class LLViewerInventoryCategory; -class LLMessageSystem; -class LLInventoryCollectFunctor; -  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // Class LLInventoryModelBackgroundFetch  // -// This class handles background fetch. +// This class handles background fetches, which are fetches of +// inventory folder.  Fetches can be recursive or not.  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -  class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch>  {  	friend class LLInventoryModelFetchDescendentsResponder; @@ -75,48 +51,37 @@ public:  	~LLInventoryModelBackgroundFetch();  	// Start and stop background breadth-first fetching of inventory contents. -	// This gets triggered when performing a filter-search +	// This gets triggered when performing a filter-search.  	void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE); -	BOOL backgroundFetchActive(); -	bool isEverythingFetched(); -	void incrBulkFetch(S16 fetching); -	void stopBackgroundFetch(); // stop fetch process -	bool isBulkFetchProcessingComplete(); -	// Add categories to a list to be fetched in bulk. -	void bulkFetch(std::string url); +	BOOL backgroundFetchActive() const; +	bool isEverythingFetched() const; // completing the fetch once per session should be sufficient -	bool libraryFetchStarted(); -	bool libraryFetchCompleted(); -	bool libraryFetchInProgress(); +	bool libraryFetchStarted() const; +	bool libraryFetchCompleted() const; +	bool libraryFetchInProgress() const; -	bool inventoryFetchStarted(); -	bool inventoryFetchCompleted(); -	bool inventoryFetchInProgress(); -    void findLostItems(); +	bool inventoryFetchStarted() const; +	bool inventoryFetchCompleted() const; +	bool inventoryFetchInProgress() const; -	void setAllFoldersFetched(); +    void findLostItems();	 +protected: +	void incrBulkFetch(S16 fetching); +	bool isBulkFetchProcessingComplete() const; +	void bulkFetch(std::string url); -	static void backgroundFetchCB(void*); // background fetch idle function  	void backgroundFetch(); -	 -	struct FetchQueueInfo -	{ -		FetchQueueInfo(const LLUUID& id, BOOL recursive) : -			mCatUUID(id), mRecursive(recursive) -		{ -		} -		LLUUID mCatUUID; -		BOOL mRecursive; -	}; -protected: +	static void backgroundFetchCB(void*); // background fetch idle function +	void stopBackgroundFetch(); // stop fetch process + +	void setAllFoldersFetched();  	bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;  private:   	BOOL mRecursiveInventoryFetchStarted;  	BOOL mRecursiveLibraryFetchStarted;  	BOOL mAllFoldersFetched; -	// completing the fetch once per session should be sufficient  	BOOL mBackgroundFetchActive;  	S16 mBulkFetchCount;  	BOOL mTimelyFetchPending; @@ -126,6 +91,15 @@ private:  	F32 mMinTimeBetweenFetches;  	F32 mMaxTimeBetweenFetches; +	struct FetchQueueInfo +	{ +		FetchQueueInfo(const LLUUID& id, BOOL recursive) : +			mCatUUID(id), mRecursive(recursive) +		{ +		} +		LLUUID mCatUUID; +		BOOL mRecursive; +	};  	typedef std::deque<FetchQueueInfo> fetch_queue_t;  	fetch_queue_t mFetchQueue;  }; diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index d2b402fe14..bd35259670 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -62,13 +62,9 @@  #include "llsdutil.h"  #include <deque> -// If the viewer gets a notification, your observer assumes -// that that notification is for itself and then tries to process -// the results.  The notification could be for something else (e.g. -// you're fetching an item and a notification gets triggered because -// you renamed some other item).  This counter is to specify how many -// notification to wait for before giving up. -static const U32 MAX_NUM_NOTIFICATIONS_TO_PROCESS = 127; +const U32 LLInventoryFetchItemsObserver::MAX_NUM_ATTEMPTS_TO_PROCESS = 10; +const F32 LLInventoryFetchItemsObserver::FETCH_TIMER_EXPIRY = 10.0f; +  LLInventoryObserver::LLInventoryObserver()  { @@ -149,7 +145,7 @@ void LLInventoryCompletionObserver::watchItem(const LLUUID& id)  LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const LLUUID& item_id) :  	LLInventoryFetchObserver(item_id), -	mNumTries(MAX_NUM_NOTIFICATIONS_TO_PROCESS) +	mNumTries(MAX_NUM_ATTEMPTS_TO_PROCESS)  {  	mIDs.clear();  	mIDs.push_back(item_id); @@ -158,35 +154,47 @@ LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const LLUUID& item_  LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const uuid_vec_t& item_ids) :  	LLInventoryFetchObserver(item_ids), -	mNumTries(MAX_NUM_NOTIFICATIONS_TO_PROCESS) +	mNumTries(MAX_NUM_ATTEMPTS_TO_PROCESS)  {  }  void LLInventoryFetchItemsObserver::changed(U32 mask)  { -	BOOL any_items_missing = FALSE; -  	// scan through the incomplete items and move or erase them as  	// appropriate.  	if (!mIncomplete.empty())  	{ +		// if period of an attempt expired... +		if (mFetchingPeriod.hasExpired()) +		{ +			// ...reset timer and reduce count of attempts +			mFetchingPeriod.reset(); +			mFetchingPeriod.setTimerExpirySec(FETCH_TIMER_EXPIRY); + +			--mNumTries; + +			LL_INFOS("InventoryFetch") << "LLInventoryFetchItemsObserver: " << this << ", attempt(s) left: " << (S32)mNumTries << LL_ENDL; +		} + +		// do we still have any attempts? +		bool timeout_expired = mNumTries <= 0; +  		for (uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )  		{  			const LLUUID& item_id = (*it);  			LLViewerInventoryItem* item = gInventory.getItem(item_id);  			if (!item)  			{ -				any_items_missing = TRUE; -				if (mNumTries > 0) +				if (timeout_expired)  				{ -					// Keep trying. -					++it; +					// Just concede that this item hasn't arrived in reasonable time and continue on. +					LL_WARNS("InventoryFetch") << "Fetcher timed out when fetching inventory item UUID: " << item_id << LL_ENDL; +					it = mIncomplete.erase(it);  				}  				else  				{ -					// Just concede that this item hasn't arrived in reasonable time and continue on. -					llwarns << "Fetcher timed out when fetching inventory item assetID:" << item_id << llendl; -					it = mIncomplete.erase(it); +					// Keep trying. +					++it;  				}  				continue;  			} @@ -198,14 +206,10 @@ void LLInventoryFetchItemsObserver::changed(U32 mask)  			}  			++it;  		} -		if (any_items_missing) -		{ -			mNumTries--; -		}  		if (mIncomplete.empty())  		{ -			mNumTries = MAX_NUM_NOTIFICATIONS_TO_PROCESS; +			mNumTries = MAX_NUM_ATTEMPTS_TO_PROCESS;  			done();  		}  	} @@ -315,6 +319,10 @@ void LLInventoryFetchItemsObserver::startFetch()  		item_entry["item_id"] = (*it);  		items_llsd.append(item_entry);  	} + +	mFetchingPeriod.resetWithExpiry(FETCH_TIMER_EXPIRY); +	mNumTries = MAX_NUM_ATTEMPTS_TO_PROCESS; +  	fetch_items_from_llsd(items_llsd);  } diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 6d5a86a6fc..72c13f55c6 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -110,6 +110,22 @@ public:  	/*virtual*/ void changed(U32 mask);  private:  	S8 mNumTries; // Number of times changed() was called without success +	LLFrameTimer mFetchingPeriod; + +	/** +	 * If the viewer gets a notification, your observer assumes +	 * that that notification is for itself and then tries to process +	 * the results.  The notification could be for something else (e.g. +	 * you're fetching an item and a notification gets triggered because +	 * you renamed some other item).  This counter is to specify how many +	 * periods of time to wait for before giving up. +	 */ +	static const U32 MAX_NUM_ATTEMPTS_TO_PROCESS; + +	/** +	 * Period of waiting a notification when requested items get added into inventory. +	 */ +	static const F32 FETCH_TIMER_EXPIRY;  };  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/lloutfitobserver.cpp b/indra/newview/lloutfitobserver.cpp new file mode 100644 index 0000000000..5652a98981 --- /dev/null +++ b/indra/newview/lloutfitobserver.cpp @@ -0,0 +1,136 @@ +/** + * @file lloutfitobserver.cpp + * @brief Outfit observer facade. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llappearancemgr.h" +#include "lloutfitobserver.h" +#include "llinventorymodel.h" +#include "llviewerinventory.h" + +LLOutfitObserver::LLOutfitObserver() : +	mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) +{ +	gInventory.addObserver(this); +} + +LLOutfitObserver::~LLOutfitObserver() +{ +	if (gInventory.containsObserver(this)) +	{ +		gInventory.removeObserver(this); +	} +} + +void LLOutfitObserver::changed(U32 mask) +{ +	if (!gInventory.isInventoryUsable()) +		return; + +	bool COF_changed = checkCOF(); + +	if (!COF_changed) +	{ +		checkBaseOutfit(); +	} +} + +// static +S32 LLOutfitObserver::getCategoryVersion(const LLUUID& cat_id) +{ +	LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); +	if (!cat) +		return LLViewerInventoryCategory::VERSION_UNKNOWN; + +	return cat->getVersion(); +} + +bool LLOutfitObserver::checkCOF() +{ +	LLUUID cof = LLAppearanceMgr::getInstance()->getCOF(); +	if (cof.isNull()) +		return false; + +	S32 cof_version = getCategoryVersion(cof); + +	if (cof_version == mCOFLastVersion) +		return false; + +	mCOFLastVersion = cof_version; + +	// dirtiness state should be updated before sending signal +	LLAppearanceMgr::getInstance()->updateIsDirty(); +	mCOFChanged(); + +	return true; +} + +void LLOutfitObserver::checkBaseOutfit() +{ +	LLUUID baseoutfit_id = +			LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); + +	if (baseoutfit_id == mBaseOutfitId) +	{ +		if (baseoutfit_id.isNull()) +			return; + +		const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id); + +		if (baseoutfit_ver == mBaseOutfitLastVersion) +			return; +	} +	else +	{ +		mBaseOutfitId = baseoutfit_id; +		mBOFReplaced(); + +		if (baseoutfit_id.isNull()) +			return; + +		mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); +	} + +	LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); +	// dirtiness state should be updated before sending signal +	app_mgr.updateIsDirty(); +	mBOFChanged(); + +	if (mLastOutfitDirtiness != app_mgr.isOutfitDirty()) +	{ +		if(!app_mgr.isOutfitDirty()) +		{ +			mCOFSaved(); +		} +		mLastOutfitDirtiness = app_mgr.isOutfitDirty(); +	} +} diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h new file mode 100644 index 0000000000..a4b5fbe04a --- /dev/null +++ b/indra/newview/lloutfitobserver.h @@ -0,0 +1,96 @@ +/** + * @file lloutfitobserver.h + * @brief Outfit observer facade. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_OUTFITOBSERVER_H +#define LL_OUTFITOBSERVER_H + +#include "llsingleton.h" + +/** + * Outfit observer facade that provides simple possibility to subscribe on + * BOF(base outfit) replaced, BOF changed, COF(current outfit) changed events. + */ +class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitObserver> +{ +public: +	virtual ~LLOutfitObserver(); + +	friend class LLSingleton<LLOutfitObserver>; + +	virtual void changed(U32 mask); + +	void notifyOutfitLockChanged() { mOutfitLockChanged();  } + +	typedef boost::signals2::signal<void (void)> signal_t; + +	void addBOFReplacedCallback(const signal_t::slot_type& cb) { mBOFReplaced.connect(cb); } + +	void addBOFChangedCallback(const signal_t::slot_type& cb) { mBOFChanged.connect(cb); } + +	void addCOFChangedCallback(const signal_t::slot_type& cb) { mCOFChanged.connect(cb); } + +	void addCOFSavedCallback(const signal_t::slot_type& cb) { mCOFSaved.connect(cb); } + +	void addOutfitLockChangedCallback(const signal_t::slot_type& cb) { mOutfitLockChanged.connect(cb); } + +protected: +	LLOutfitObserver(); + +	/** Get a version of an inventory category specified by its UUID */ +	static S32 getCategoryVersion(const LLUUID& cat_id); + +	bool checkCOF(); + +	void checkBaseOutfit(); + +	//last version number of a COF category +	S32 mCOFLastVersion; + +	LLUUID mBaseOutfitId; + +	S32 mBaseOutfitLastVersion; + +	bool mLastOutfitDirtiness; + +private: +	signal_t mBOFReplaced; +	signal_t mBOFChanged; +	signal_t mCOFChanged; +	signal_t mCOFSaved; + +	/** +	 * Signal for changing state of outfit lock. +	 */ +	signal_t mOutfitLockChanged; +}; + +#endif /* LL_OUTFITOBSERVER_H */ diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 77db280487..e20b2e26be 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -53,6 +53,20 @@  static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y); +static const LLOutfitTabNameComparator OUTFIT_TAB_NAME_COMPARATOR; + +/*virtual*/ +bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const +{ +	std::string name1 = tab1->getTitle(); +	std::string name2 = tab2->getTitle(); + +	LLStringUtil::toUpper(name1); +	LLStringUtil::toUpper(name2); + +	return name1 < name2; +} +  //////////////////////////////////////////////////////////////////////////  class OutfitContextMenu : public LLListContextMenu @@ -158,6 +172,7 @@ LLOutfitsList::~LLOutfitsList()  BOOL LLOutfitsList::postBuild()  {  	mAccordion = getChild<LLAccordionCtrl>("outfits_accordion"); +	mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);  	return TRUE;  } @@ -328,7 +343,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)  		updateOutfitTab(*items_iter);  	} -	mAccordion->arrange(); +	mAccordion->sort();  }  void LLOutfitsList::onSelectionChange(LLUICtrl* ctrl) @@ -500,6 +515,8 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)  void LLOutfitsList::applyFilter(const std::string& new_filter_substring)  { +	mAccordion->setFilterSubString(new_filter_substring); +  	for (outfits_map_t::iterator  			 iter = mOutfitsMap.begin(),  			 iter_end = mOutfitsMap.end(); diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 44f6ec908b..bb516446d2 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -32,18 +32,34 @@  #ifndef LL_LLOUTFITSLIST_H  #define LL_LLOUTFITSLIST_H +#include "llaccordionctrl.h"  #include "llpanel.h"  // newview  #include "llinventorymodel.h"  #include "llinventoryobserver.h" -class LLAccordionCtrl;  class LLAccordionCtrlTab;  class LLWearableItemsList;  class LLListContextMenu;  /** + * @class LLOutfitTabNameComparator + * + * Comparator of outfit tabs. + */ +class LLOutfitTabNameComparator : public LLAccordionCtrl::LLTabComparator +{ +	LOG_CLASS(LLOutfitTabNameComparator); + +public: +	LLOutfitTabNameComparator() {}; +	virtual ~LLOutfitTabNameComparator() {}; + +	/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const; +}; + +/**   * @class LLOutfitsList   *   * A list of agents's outfits from "My Outfits" inventory category diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 7d82a10ca2..d8cfd4fc5d 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -159,7 +159,9 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  		case DAD_ANIMATION:  		case DAD_GESTURE:  		case DAD_CALLINGCARD: +#if LL_MESH_ENABLED  		case DAD_MESH: +#endif  		{  			LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;  			if(gInventory.getItem(inv_item->getUUID()) diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 898cabb03d..58df2746f3 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -819,7 +819,9 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,  		case DAD_ANIMATION:  		case DAD_GESTURE:  		case DAD_CALLINGCARD: +#if LL_MESH_ENABLED  		case DAD_MESH: +#endif  			accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);  			if(accept && drop)  			{ @@ -1240,6 +1242,7 @@ LLUIImagePtr LLTaskWearableBridge::getIcon() const  	return LLInventoryIcon::getIcon(mAssetType, mInventoryType, FALSE, mFlags, FALSE );  } +#if LL_MESH_ENABLED  ///----------------------------------------------------------------------------  /// Class LLTaskMeshBridge  ///---------------------------------------------------------------------------- @@ -1351,6 +1354,7 @@ void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  	hide_context_entries(menu, items, disabled_items);  } +#endif  ///----------------------------------------------------------------------------  /// LLTaskInvFVBridge impl @@ -1431,11 +1435,13 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*  						 object->getUUID(),  						 object->getName());  		break; +#if LL_MESH_ENABLED  	case LLAssetType::AT_MESH:  		new_bridge = new LLTaskMeshBridge(panel,  										  object->getUUID(),  										  object->getName());  		break; +#endif  	default:  		llinfos << "Unhandled inventory type (llassetstorage.h): "  				<< (S32)type << llendl; diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 4982e98f8e..e07d5c064b 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -39,6 +39,7 @@  #include "llagentcamera.h"  #include "llagentwearables.h"  #include "llappearancemgr.h" +#include "lloutfitobserver.h"  #include "llcofwearables.h"  #include "llfilteredwearablelist.h"  #include "llinventory.h" @@ -143,100 +144,6 @@ private:  	}  }; -class LLCOFObserver : public LLInventoryObserver -{ -public: -	LLCOFObserver(LLPanelOutfitEdit *panel) : mPanel(panel),  -		mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) -	{ -		gInventory.addObserver(this); -	} - -	virtual ~LLCOFObserver() -	{ -		if (gInventory.containsObserver(this)) -		{ -			gInventory.removeObserver(this); -		} -	} -	 -	virtual void changed(U32 mask) -	{ -		if (!gInventory.isInventoryUsable()) return; -	 -		bool panel_updated = checkCOF(); - -		if (!panel_updated) -		{ -			checkBaseOutfit(); -		} -	} - -protected: - -	/** Get a version of an inventory category specified by its UUID */ -	static S32 getCategoryVersion(const LLUUID& cat_id) -	{ -		LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); -		if (!cat) return LLViewerInventoryCategory::VERSION_UNKNOWN; - -		return cat->getVersion(); -	} - -	bool checkCOF() -	{ -		LLUUID cof = LLAppearanceMgr::getInstance()->getCOF(); -		if (cof.isNull()) return false; - -		S32 cof_version = getCategoryVersion(cof); - -		if (cof_version == mCOFLastVersion) return false; -		 -		mCOFLastVersion = cof_version; - -		mPanel->update(); - -		return true; -	} - -	void checkBaseOutfit() -	{ -		LLUUID baseoutfit_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); - -		if (baseoutfit_id == mBaseOutfitId) -		{ -			if (baseoutfit_id.isNull()) return; - -			const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id); - -			if (baseoutfit_ver == mBaseOutfitLastVersion) return; -		} -		else -		{ -			mBaseOutfitId = baseoutfit_id; -			mPanel->updateCurrentOutfitName(); - -			if (baseoutfit_id.isNull()) return; - -			mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); -		} - -		mPanel->updateVerbs(); -	} -	 - - - -	LLPanelOutfitEdit *mPanel; - -	//last version number of a COF category -	S32 mCOFLastVersion; - -	LLUUID  mBaseOutfitId; - -	S32 mBaseOutfitLastVersion; -}; -  class LLCOFDragAndDropObserver : public LLInventoryAddItemByAssetObserver  {  public: @@ -277,7 +184,6 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()  	mSearchFilter(NULL),  	mCOFWearables(NULL),  	mInventoryItemsPanel(NULL), -	mCOFObserver(NULL),  	mGearMenu(NULL),  	mCOFDragAndDropObserver(NULL),  	mInitialized(false), @@ -288,7 +194,12 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()  	mSavedFolderState = new LLSaveFolderState();  	mSavedFolderState->setApply(FALSE); -	mCOFObserver = new LLCOFObserver(this); + +	LLOutfitObserver& observer = LLOutfitObserver::instance(); +	observer.addBOFReplacedCallback(boost::bind(&LLPanelOutfitEdit::updateCurrentOutfitName, this)); +	observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); +	observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); +	observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::update, this));  	mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES);  	for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++) @@ -303,7 +214,6 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit()  {  	delete mSavedFolderState; -	delete mCOFObserver;  	delete mCOFDragAndDropObserver;  	delete mWearableListMaskCollector; @@ -371,7 +281,7 @@ BOOL LLPanelOutfitEdit::postBuild()  	childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));  	mWearableListMaskCollector = new LLFindNonLinksByMask(ALL_ITEMS_MASK); -	mWearableListTypeCollector = new LLFindWearablesOfType(LLWearableType::WT_NONE); +	mWearableListTypeCollector = new LLFindActualWearablesOfType(LLWearableType::WT_NONE);  	mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel");  	mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list"); @@ -585,35 +495,10 @@ void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)  void LLPanelOutfitEdit::onEditWearableClicked(void)  { -	LLUUID id_to_edit = mCOFWearables->getSelectedUUID(); -	LLViewerInventoryItem * item_to_edit = gInventory.getItem(id_to_edit); - -	if (item_to_edit) +	LLUUID selected_item_id = mCOFWearables->getSelectedUUID(); +	if (selected_item_id.notNull())  	{ -		// returns null if not a wearable (attachment, etc). -		LLWearable* wearable_to_edit = gAgentWearables.getWearableFromAssetID(item_to_edit->getAssetUUID()); -		if(wearable_to_edit) -		{ -			bool can_modify = false; -			bool is_complete = item_to_edit->isFinished(); -			// if item_to_edit is a link, its properties are not appropriate,  -			// lets get original item with actual properties -			LLViewerInventoryItem* original_item = gInventory.getItem(wearable_to_edit->getItemID()); -			if(original_item) -			{ -				can_modify = original_item->getPermissions().allowModifyBy(gAgentID); -				is_complete = original_item->isFinished(); -			} - -			if (can_modify && is_complete) -			{											  -				LLSidepanelAppearance::editWearable(wearable_to_edit, getParent()); -				if (mEditWearableBtn->getVisible()) -				{ -					mEditWearableBtn->setVisible(FALSE); -				} -			} -		} +		gAgentWearables.editWearable(selected_item_id);  	}  } @@ -756,16 +641,14 @@ void LLPanelOutfitEdit::updateCurrentOutfitName()  //private  void LLPanelOutfitEdit::updateVerbs()  { -	//*TODO implement better handling of COF dirtiness -	LLAppearanceMgr::getInstance()->updateIsDirty(); -  	bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); +	bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked();  	bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull(); -	mSaveComboBtn->setSaveBtnEnabled(outfit_is_dirty); +	mSaveComboBtn->setSaveBtnEnabled(!outfit_locked && outfit_is_dirty);  	childSetEnabled(REVERT_BTN, outfit_is_dirty && has_baseoutfit); -	mSaveComboBtn->setMenuItemEnabled("save_outfit", outfit_is_dirty); +	mSaveComboBtn->setMenuItemEnabled("save_outfit", !outfit_locked && outfit_is_dirty);  	mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing")); diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 802386c573..24ecf75c18 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -49,7 +49,7 @@ class LLButton;  class LLCOFWearables;  class LLTextBox;  class LLInventoryCategory; -class LLCOFObserver; +class LLOutfitObserver;  class LLCOFDragAndDropObserver;  class LLInventoryPanel;  class LLSaveFolderState; @@ -153,7 +153,6 @@ private:  	LLInventoryItemsList* 			mWearableItemsList;  	LLPanel*						mWearableItemsPanel; -	LLCOFObserver*	mCOFObserver;  	LLCOFDragAndDropObserver* mCOFDragAndDropObserver;  	std::vector<LLLookItemType> mLookItemTypes; diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 5f67f3d989..8b451c156c 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -50,6 +50,7 @@  #include "lllineeditor.h"  #include "llmodaldialog.h"  #include "llnotificationsutil.h" +#include "lloutfitobserver.h"  #include "lloutfitslist.h"  #include "llsaveoutfitcombobtn.h"  #include "llsidepanelappearance.h" @@ -204,6 +205,11 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :  	mSavedFolderState = new LLSaveFolderState();  	mSavedFolderState->setApply(FALSE);  	gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this)); + +	LLOutfitObserver& observer = LLOutfitObserver::instance(); +	observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); +	observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); +	observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this));  }  LLPanelOutfitsInventory::~LLPanelOutfitsInventory() @@ -517,12 +523,12 @@ void LLPanelOutfitsInventory::updateListCommands()  {  	bool trash_enabled = isActionEnabled("delete");  	bool wear_enabled = isActionEnabled("wear"); -	bool make_outfit_enabled = isActionEnabled("make_outfit"); +	bool make_outfit_enabled = isActionEnabled("save_outfit");  	mListCommands->childSetEnabled("trash_btn", trash_enabled);  	mListCommands->childSetEnabled("wear_btn", wear_enabled);  	mListCommands->childSetVisible("wear_btn", wear_enabled); -	mSaveComboBtn->setSaveBtnEnabled(make_outfit_enabled); +	mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled);  }  void LLPanelOutfitsInventory::showGearMenu() @@ -663,9 +669,12 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)  			return FALSE;  		}  	} -	if (command_name == "make_outfit") +	if (command_name == "save_outfit")  	{ -		return TRUE; +		bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked(); +		bool outfit_dirty =LLAppearanceMgr::getInstance()->isOutfitDirty(); +		// allow save only if outfit isn't locked and is dirty +		return !outfit_locked && outfit_dirty;  	}  	if (command_name == "edit" ||  @@ -789,6 +798,7 @@ void LLPanelOutfitsInventory::onWearablesLoaded()  	setWearablesLoading(false);  } +// static  LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP()  {  	static LLSidepanelAppearance* panel_appearance = diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index aff7839bcc..d58ae554b0 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -75,7 +75,7 @@ public:  	void setParent(LLSidepanelAppearance *parent);  	LLFolderView* getRootFolder(); -	LLSidepanelAppearance* getAppearanceSP(); +	static LLSidepanelAppearance* getAppearanceSP();  	static LLPanelOutfitsInventory* findInstance(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 0a4af00f78..f16d1d8fda 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1450,6 +1450,8 @@ void LLPanelPeople::showFriendsAccordionsIfNeeded()  		LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");  		accordion->arrange(); +		// *TODO: new empty_accordion_text attribute was implemented in accordion (EXT-7368). +		// this code should be refactored to use it  		// keep help text in a synchronization with accordions visibility.  		updateFriendListHelpText();  	} diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp new file mode 100644 index 0000000000..fd470798ee --- /dev/null +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -0,0 +1,169 @@ +/**  + * @file llpanelvoiceeffect.cpp + * @author Aimee + * @brief Panel to select Voice Morphs. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2010, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelvoiceeffect.h" + +#include "llcombobox.h" +#include "llfloaterreg.h" +#include "llpanel.h" +#include "lltrans.h" +#include "lltransientfloatermgr.h" +#include "llvoiceclient.h" + +static LLRegisterPanelClassWrapper<LLPanelVoiceEffect> t_panel_voice_effect("panel_voice_effect"); + +LLPanelVoiceEffect::LLPanelVoiceEffect() +	: mVoiceEffectCombo(NULL) +{ +	mCommitCallbackRegistrar.add("Voice.CommitVoiceEffect", boost::bind(&LLPanelVoiceEffect::onCommitVoiceEffect, this)); +} + +LLPanelVoiceEffect::~LLPanelVoiceEffect() +{ +	LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox"); +	LLTransientFloaterMgr::getInstance()->removeControlView(combo_list_view); + +	if(LLVoiceClient::instanceExists()) +	{ +		LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +		if (effect_interface) +		{ +			effect_interface->removeObserver(this); +		} +	} +} + +// virtual +BOOL LLPanelVoiceEffect::postBuild() +{ +	mVoiceEffectCombo = getChild<LLComboBox>("voice_effect"); + +	// Need to tell LLTransientFloaterMgr about the combo list, otherwise it can't +	// be clicked while in a docked floater as it extends outside the floater area. +	LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox"); +	LLTransientFloaterMgr::getInstance()->addControlView(combo_list_view); + +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (effect_interface) +	{ +		effect_interface->addObserver(this); +	} + +	update(true); + +	return TRUE; +} + +////////////////////////////////////////////////////////////////////////// +/// PRIVATE SECTION +////////////////////////////////////////////////////////////////////////// + +void LLPanelVoiceEffect::onCommitVoiceEffect() +{ +	LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +	if (!effect_interface) +	{ +		mVoiceEffectCombo->setEnabled(false); +		return; +	} + +	LLSD value = mVoiceEffectCombo->getValue(); +	if (value.asInteger() == PREVIEW_VOICE_EFFECTS) +	{ +		// Open the Voice Morph preview floater +		LLFloaterReg::showInstance("voice_effect"); +	} +	else if (value.asInteger() == GET_VOICE_EFFECTS) +	{ +		// Open the voice morphing info web page +		LLWeb::loadURL(LLTrans::getString("voice_morphing_url")); +	} +	else +	{ +		effect_interface->setVoiceEffect(value.asUUID()); +	} + +	mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect()); +} + +// virtual +void LLPanelVoiceEffect::onVoiceEffectChanged(bool effect_list_updated) +{ +	update(effect_list_updated); +} + +void LLPanelVoiceEffect::update(bool list_updated) +{ +	if (mVoiceEffectCombo) +	{ +		LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +		if (list_updated) +		{ +			// Add the default "No Voice Morph" entry. +			mVoiceEffectCombo->removeall(); +			mVoiceEffectCombo->add(getString("no_voice_effect"), LLUUID::null); +			mVoiceEffectCombo->addSeparator(); + +			// Add entries for each Voice Morph. +			const voice_effect_list_t& effect_list = effect_interface->getVoiceEffectList(); +			if (!effect_list.empty()) +			{ +				for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) +				{ +					mVoiceEffectCombo->add(it->first, it->second, ADD_BOTTOM); +				} + +				mVoiceEffectCombo->addSeparator(); +			} + +			// Add the fixed entries to go to the preview floater or marketing page. +			mVoiceEffectCombo->add(getString("preview_voice_effects"), PREVIEW_VOICE_EFFECTS); +			mVoiceEffectCombo->add(getString("get_voice_effects"), GET_VOICE_EFFECTS); +		} + +		if (effect_interface && LLVoiceClient::instance().isVoiceWorking()) +		{ +			// Select the current Voice Morph. +			mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect()); +			mVoiceEffectCombo->setEnabled(true); +		} +		else +		{ +			// If voice isn't working or Voice Effects are not supported disable the control. +			mVoiceEffectCombo->setValue(LLUUID::null); +			mVoiceEffectCombo->setEnabled(false); +		} +	} +} diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h new file mode 100644 index 0000000000..b5bf2f05a8 --- /dev/null +++ b/indra/newview/llpanelvoiceeffect.h @@ -0,0 +1,73 @@ +/**  + * @file llpanelvoiceeffect.h + * @author Aimee + * @brief Panel to select Voice Effects. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2010, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_PANELVOICEEFFECT_H +#define LL_PANELVOICEEFFECT_H + +#include "llpanel.h" +#include "llvoiceclient.h" + +class LLComboBox; + +class LLPanelVoiceEffect +	: public LLPanel +	, public LLVoiceEffectObserver +{ +public: +	LOG_CLASS(LLPanelVoiceEffect); + +	LLPanelVoiceEffect(); +	virtual ~LLPanelVoiceEffect(); + +	virtual BOOL postBuild(); + +private: +	void onCommitVoiceEffect(); +	void update(bool list_updated); + +	/// Called by voice effect provider when voice effect list is changed. +	virtual void onVoiceEffectChanged(bool effect_list_updated); + +	// Fixed entries in the Voice Morph list +	typedef enum e_voice_effect_combo_items +	{ +		NO_VOICE_EFFECT = 0, +		PREVIEW_VOICE_EFFECTS = 1, +		GET_VOICE_EFFECTS = 2 +	} EVoiceEffectComboItems; + +	LLComboBox* mVoiceEffectCombo; +}; + + +#endif //LL_PANELVOICEEFFECT_H diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index f020ad9bc2..a27afeab7c 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -94,7 +94,7 @@ public:  		mAvalineCallers.insert(avaline_caller_id);  	} -	void onChange() +	void onParticipantsChanged()  	{  		uuid_set_t participant_uuids;  		LLVoiceClient::getInstance()->getParticipantList(participant_uuids); diff --git a/indra/newview/llsaveoutfitcombobtn.cpp b/indra/newview/llsaveoutfitcombobtn.cpp index b9b577084b..9518b0cbb3 100644 --- a/indra/newview/llsaveoutfitcombobtn.cpp +++ b/indra/newview/llsaveoutfitcombobtn.cpp @@ -34,6 +34,7 @@  #include "llappearancemgr.h"  #include "llpaneloutfitsinventory.h" +#include "llsidepanelappearance.h"  #include "llsaveoutfitcombobtn.h"  #include "llviewermenu.h" diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index ceef03d2f8..0ce7ffb077 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6165,6 +6165,7 @@ S32 LLObjectSelection::getObjectCount(BOOL mesh_adjust)  	cleanupNodes();  	S32 count = mList.size(); +#if LL_MESH_ENABLED  	if (mesh_adjust)  	{  		for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) @@ -6185,6 +6186,7 @@ S32 LLObjectSelection::getObjectCount(BOOL mesh_adjust)  		}  	} +#endif  	return count;  } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 872939c209..e23643da0b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -42,6 +42,7 @@  #include "llfloaterreg.h"  #include "llfloaterworldmap.h"  #include "llfoldervieweventlistener.h" +#include "lloutfitobserver.h"  #include "llpaneleditwearable.h"  #include "llpaneloutfitsinventory.h"  #include "llsidetray.h" @@ -73,26 +74,6 @@ private:  	LLSidepanelAppearance *mPanel;  }; -class LLWatchForOutfitRenameObserver : public LLInventoryObserver -{ -public: -	LLWatchForOutfitRenameObserver(LLSidepanelAppearance *panel) : -		mPanel(panel) -	{} -	virtual void changed(U32 mask); -	 -private: -	LLSidepanelAppearance *mPanel; -}; - -void LLWatchForOutfitRenameObserver::changed(U32 mask) -{ -	if (mask & LABEL) -	{ -		mPanel->refreshCurrentOutfitName(); -	} -} -  LLSidepanelAppearance::LLSidepanelAppearance() :  	LLPanel(),  	mFilterSubString(LLStringUtil::null), @@ -101,12 +82,13 @@ LLSidepanelAppearance::LLSidepanelAppearance() :  	mCurrOutfitPanel(NULL),  	mOpened(false)  { +	LLOutfitObserver& outfit_observer =  LLOutfitObserver::instance(); +	outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); +	outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));  }  LLSidepanelAppearance::~LLSidepanelAppearance()  { -	gInventory.removeObserver(mOutfitRenameWatcher); -	delete mOutfitRenameWatcher;  }  // virtual @@ -160,8 +142,6 @@ BOOL LLSidepanelAppearance::postBuild()  	mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook"); -	mOutfitRenameWatcher = new LLWatchForOutfitRenameObserver(this); -	gInventory.addObserver(mOutfitRenameWatcher);  	setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 30022ae375..812d6362ef 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -40,7 +40,6 @@  class LLFilterEditor;  class LLCurrentlyWornFetchObserver; -class LLWatchForOutfitRenameObserver;  class LLPanelEditWearable;  class LLWearable;  class LLPanelOutfitsInventory; @@ -97,9 +96,6 @@ private:  	// Used to make sure the user's inventory is in memory.  	LLCurrentlyWornFetchObserver* mFetchWorn; -	// Used to update title when currently worn outfit gets renamed. -	LLWatchForOutfitRenameObserver* mOutfitRenameWatcher; -  	// Search string for filtering landmarks and teleport  	// history locations  	std::string					mFilterSubString; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 3c97f01887..9406f80b75 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -469,6 +469,9 @@ void LLSideTray::reflectCollapseChange()  	}  	gFloaterView->refresh(); +	 +	LLSD new_value = mCollapsed; +	mCollapseSignal(this,new_value);  }  void LLSideTray::arrange() diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index e8fdee9430..e176ff5aff 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -159,6 +159,8 @@ public:  	void		updateSidetrayVisibility(); +	commit_signal_t& getCollapseSignal() { return mCollapseSignal; } +  protected:  	LLSideTrayTab* getTab		(const std::string& name); @@ -187,6 +189,8 @@ private:  	child_vector_t					mTabs;  	LLSideTrayTab*					mActiveTab;	 +	commit_signal_t					mCollapseSignal; +  	LLButton*						mCollapseButton;  	bool							mCollapsed; diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 29237946d2..ea7601517d 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -107,7 +107,7 @@ private:  	 * So, method does not calculate difference between these list it only switches off already   	 * switched on indicators and switches on indicators of voice channel participants  	 */ -	void onChange(); +	void onParticipantsChanged();  	/**  	 * Changes state of indicators specified by LLUUIDs @@ -205,7 +205,7 @@ void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_  	mSwitchedIndicatorsOn.clear();  } -void SpeakingIndicatorManager::onChange() +void SpeakingIndicatorManager::onParticipantsChanged()  {  	LL_DEBUGS("SpeakingIndicator") << "Voice participant list was changed, updating indicators" << LL_ENDL; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 7b57f09e59..6088c31559 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -292,7 +292,11 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop(  {  	BOOL handled = FALSE; -	if ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) +	bool is_mesh = false; +#if LL_MESH_ENABLED +	is_mesh = cargo_type == DAD_MESH; +#endif +	if ((cargo_type == DAD_TEXTURE) || is_mesh)  	{  		LLInventoryItem *item = (LLInventoryItem *)cargo_data; @@ -1177,8 +1181,12 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,  	// returns true, then the cast was valid, and we can perform  	// the third test without problems.  	LLInventoryItem* item = (LLInventoryItem*)cargo_data;  +	bool is_mesh = false; +#if LL_MESH_ENABLED +	is_mesh = cargo_type == DAD_MESH; +#endif  	if (getEnabled() && -		((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) && +		((cargo_type == DAD_TEXTURE) || is_mesh) &&  		 allowDrop(item))  	{  		if (drop) diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 15924d67cf..d679ccd3d8 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -331,7 +331,9 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()  	addEntry(DAD_ANIMATION, 	new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,		&LLToolDragAndDrop::dad3dUpdateInventory,			&LLToolDragAndDrop::dad3dNULL));  	addEntry(DAD_GESTURE, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dActivateGesture,		&LLToolDragAndDrop::dad3dGiveInventory,		&LLToolDragAndDrop::dad3dUpdateInventory,			&LLToolDragAndDrop::dad3dNULL));  	addEntry(DAD_LINK, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,						&LLToolDragAndDrop::dad3dNULL)); +#if LL_MESH_ENABLED  	addEntry(DAD_MESH, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,		&LLToolDragAndDrop::dad3dMeshObject,			&LLToolDragAndDrop::dad3dNULL)); +#endif  	// TODO: animation on self could play it?  edit it?  	// TODO: gesture on self could play it?  edit it?  }; @@ -1035,6 +1037,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,  	hit_obj->sendTEUpdate();  } +#if LL_MESH_EANBLED  void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,  								 LLInventoryItem* item,  								 LLToolDragAndDrop::ESource source, @@ -1059,6 +1062,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,  	dialog_refresh_all();  } +#endif  /*  void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_face, LLInventoryItem* item) @@ -1501,7 +1505,9 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_  	case DAD_ANIMATION:  	case DAD_GESTURE:  	case DAD_CALLINGCARD: +#if LL_MESH_ENABLED  	case DAD_MESH: +#endif  	{  		LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;  		if(gInventory.getItem(inv_item->getUUID()) @@ -1858,10 +1864,12 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(  				dropTextureOneFace(obj, face, item, mSource, mSourceID);  			}  		} +#if LL_MESH_ENABLED  		else if (cargo_type == DAD_MESH)  		{  			dropMesh(obj, item, mSource, mSourceID);  		} +#endif  		else  		{  			llwarns << "unsupported asset type" << llendl; @@ -1886,11 +1894,13 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject(  	return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE);  } +#if LL_MESH_ENABLED  EAcceptance LLToolDragAndDrop::dad3dMeshObject(  	LLViewerObject* obj, S32 face, MASK mask, BOOL drop)  {  	return dad3dApplyToObject(obj, face, mask, drop, DAD_MESH);  } +#endif diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 596cc2ee88..ceeaa8c820 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -154,8 +154,10 @@ protected:  							   MASK mask, BOOL drop);  	EAcceptance dad3dTextureObject(LLViewerObject* obj, S32 face,  								   MASK mask, BOOL drop); +#if LL_MESH_ENABLED  	EAcceptance dad3dMeshObject(LLViewerObject* obj, S32 face,  								   MASK mask, BOOL drop); +#endif  //	EAcceptance dad3dTextureSelf(LLViewerObject* obj, S32 face,  //								 MASK mask, BOOL drop);  	EAcceptance dad3dWearItem(LLViewerObject* obj, S32 face, @@ -242,10 +244,12 @@ public:  									LLInventoryItem* item,  									ESource source,  									const LLUUID& src_id); +#if LL_MESH_ENABLED  	static void dropMesh(LLViewerObject* hit_obj,  						 LLInventoryItem* item,  						 ESource source,  						 const LLUUID& src_id); +#endif  	//static void	dropTextureOneFaceAvatar(LLVOAvatar* avatar,S32 hit_face,  	//									 LLInventoryItem* item) diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 8996157258..fa21b1a866 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -96,7 +96,7 @@ LLVisualParamHint::LLVisualParamHint(  	mCamTargetJoint(jointp)  {  	LLVisualParamHint::sInstances.insert( this ); -	mBackgroundp = LLUI::getUIImage("avatar_thumb_bkgrnd.j2c"); +	mBackgroundp = LLUI::getUIImage("avatar_thumb_bkgrnd.png");  	llassert(width != 0);  	llassert(height != 0); diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index 4c088a72b7..370767002a 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -85,7 +85,9 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()  	addEntry(LLViewerAssetType::AT_LINK, 				new ViewerAssetEntry(DAD_LINK));  	addEntry(LLViewerAssetType::AT_LINK_FOLDER, 		new ViewerAssetEntry(DAD_LINK)); +#if LL_MESH_ENABLED  	addEntry(LLViewerAssetType::AT_MESH, 				new ViewerAssetEntry(DAD_MESH)); +#endif  	addEntry(LLViewerAssetType::AT_NONE, 				new ViewerAssetEntry(DAD_NONE));  }; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 8bf61bc4c5..c953fb23e3 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -104,6 +104,7 @@  #include "llfloateruipreview.h"  #include "llfloaterurldisplay.h"  #include "llfloatervoicedevicesettings.h" +#include "llfloatervoiceeffect.h"  #include "llfloaterwater.h"  #include "llfloaterwhitelistentry.h"  #include "llfloaterwindlight.h" @@ -176,7 +177,9 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);  	LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>); +#if LL_MESH_ENABLED  	LLFloaterReg::add("import_collada", "floater_import_collada.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImportCollada>); +#endif  	LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>);  	LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>);  	LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); @@ -257,10 +260,13 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");  	LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");  	LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); +#if LL_MESH_ENABLED  	LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload"); +#endif  	LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>); -	 +	LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>); +  	LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);	  	LLFloaterWindowSizeUtil::registerFloater();  	LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);	 diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index face7124c2..40f15fe86a 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -883,12 +883,8 @@ void ModifiedCOFCallback::fire(const LLUUID& inv_item)  {  	LLAppearanceMgr::instance().updateAppearanceFromCOF(); -	if (LLSideTray::getInstance()->isPanelActive("sidepanel_appearance")) -	{ -		// *HACK: Edit the wearable that has just been worn -		//        only if the Appearance SP is currently opened. -		LLAgentWearables::editWearable(inv_item); -	} +	// Start editing the item if previously requested. +	gAgentWearables.editWearableIfRequested(inv_item);  	// TODO: camera mode may not be changed if a debug setting is tweaked  	if( gAgentCamera.cameraCustomizeAvatar() ) diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index dd65ca2d25..af4549f7e1 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -350,6 +350,7 @@ class LLFileUploadImage : public view_listener_t  	}  }; +#if LL_MESH_ENABLED  class LLFileUploadScene : public view_listener_t  {  	bool handleEvent(const LLSD& userdata) @@ -376,6 +377,7 @@ class LLFileUploadModel : public view_listener_t  		return TRUE;  	}  }; +#endif  class LLFileUploadSound : public view_listener_t  { @@ -1144,6 +1146,7 @@ void upload_new_resource(  	lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl;  	lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; +#if LL_MESH_ENABLED  	std::string url = gAgent.getRegion()->getCapability(  		"NewFileAgentInventory"); @@ -1171,8 +1174,8 @@ void upload_new_resource(  				asset_type));  	}  	else +#endif  	{ -		llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl;  		// check for adequate funds  		// TODO: do this check on the sim  		if (LLAssetType::AT_SOUND == asset_type || @@ -1217,6 +1220,7 @@ void upload_new_resource(  	}  } +#if LL_MESH_ENABLED  BOOL upload_new_variable_price_resource(  	const LLTransactionID &tid,   	LLAssetType::EType asset_type, @@ -1288,6 +1292,7 @@ BOOL upload_new_variable_price_resource(  		return FALSE;  	}  } +#endif  LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)  { @@ -1358,8 +1363,10 @@ void init_menu_file()  	view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage");  	view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");  	view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); +#if LL_MESH_ENABLED  	view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");  	view_listener_t::addCommit(new LLFileUploadScene(), "File.UploadScene"); +#endif  	view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");  	view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");  	view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 08444551a9..bb7cfce862 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -74,6 +74,7 @@ void upload_new_resource(  	S32 expected_upload_cost,  	void *userdata); +#if LL_MESH_ENABLED  // TODO* : Move all uploads to use this new function  // since at some point, that upload path will be deprecated and no longer  // used @@ -91,6 +92,7 @@ BOOL upload_new_variable_price_resource(  	U32 everyone_perms,  	const std::string& display_name,  	const LLSD& asset_resources); +#endif  LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);  void increase_new_upload_stats(LLAssetType::EType asset_type); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index d35be8e1bf..697e8afa65 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -535,7 +535,9 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const  			case LLAssetType::AT_BODYPART:		img_name = "Inv_Skin";		break;  			case LLAssetType::AT_ANIMATION:		img_name = "Inv_Animation";	break;  			case LLAssetType::AT_GESTURE:		img_name = "Inv_Gesture";	break; +#if LL_MESH_ENABLED  			case LLAssetType::AT_MESH:          img_name = "Inv_Mesh";	    break; +#endif  			default: llassert(0);  		} diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 78cb06cefd..b2c874e355 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -541,11 +541,6 @@ void LLViewerTexture::setBoostLevel(S32 level)  		if(mBoostLevel != LLViewerTexture::BOOST_NONE)  		{  			setNoDelete() ;		 - -			if(LLViewerTexture::BOOST_AVATAR_BAKED_SELF == mBoostLevel || LLViewerTexture::BOOST_AVATAR_BAKED == mBoostLevel) -			{ -				mCanResetMaxVirtualSize = false ; -			}  		}  		if(gAuditTexture)  		{ @@ -596,6 +591,11 @@ void LLViewerTexture::forceImmediateUpdate()  {  } +void LLViewerTexture::setResetMaxVirtualSizeFlag(bool flag)  +{ +	mCanResetMaxVirtualSize = flag ; +} +  void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const   {  	if(needs_gltexture) diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 1bd4cc793d..361f56e02f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -166,6 +166,7 @@ public:  	void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;  	void resetTextureStats();	 +	void setResetMaxVirtualSizeFlag(bool flag) ;  	virtual F32  getMaxVirtualSize() ; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fc4b590bf4..9f559331b0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -591,8 +591,10 @@ public:  		if (gSavedSettings.getBOOL("DebugShowUploadCost"))  		{ +#if LL_MESH_ENABLED  			addText(xpos, ypos, llformat("       Meshes: L$%d", gPipeline.mDebugMeshUploadCost));  			ypos += y_inc/2; +#endif  			addText(xpos, ypos, llformat("    Sculpties: L$%d", gPipeline.mDebugSculptUploadCost));  			ypos += y_inc/2;  			addText(xpos, ypos, llformat("     Textures: L$%d", gPipeline.mDebugTextureUploadCost)); @@ -602,6 +604,7 @@ public:  			ypos += y_inc;  		} +#if LL_MESH_ENABLED  		//temporary hack to give feedback on mesh upload progress  		if (!gMeshRepo.mUploads.empty())  		{ @@ -631,6 +634,7 @@ public:  			ypos += y_inc;  		} +#endif  	}  	void draw() diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 2e6dc7a76c..05114c1ca4 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4228,9 +4228,14 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel  	mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);  	mMinPixelArea = llmin(pixel_area, mMinPixelArea);  	imagep->resetTextureStats(); +	imagep->setResetMaxVirtualSizeFlag(false) ;  	imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures.  	imagep->addTextureStats(pixel_area / texel_area_ratio);  	imagep->setBoostLevel(boost_level); +	if(boost_level == LLViewerTexture::BOOST_AVATAR_BAKED_SELF) +	{ +		imagep->setAdditionalDecodePriority(1.0f) ; +	}  }  //virtual	 diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 5a22382a83..a4d888cd72 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1330,7 +1330,7 @@ BOOL LLVOAvatarSelf::isBakedTextureFinal(const LLVOAvatarDefines::EBakedTextureI  	if (!layerset) return FALSE;  	const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite();  	if (!layerset_buffer) return FALSE; -	return !layerset_buffer->uploadPending(); +	return !layerset_buffer->uploadNeeded();  }  BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const @@ -2030,7 +2030,11 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe  			F32 desired_pixels;  			desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());  			imagep->setBoostLevel(getAvatarBoostLevel()); + +			imagep->resetTextureStats(); +			imagep->setResetMaxVirtualSizeFlag(false) ;  			imagep->addTextureStats( desired_pixels / texel_area_ratio ); +			imagep->setAdditionalDecodePriority(1.0f) ;  			imagep->forceUpdateBindStats() ;  			if (imagep->getDiscardLevel() < 0)  			{ diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 1b4471a9fe..070663e22f 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -897,9 +897,9 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s  	else  	{  		LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL; -		// In case of incoming AvaLine call generated URI will be differ from original one. -		// This is because Avatar-2-Avatar URI is based on avatar UUID but Avaline is not. -		// See LLVoiceClient::sessionAddedEvent() -> setUUIDFromStringHash() +		// In the case of an incoming AvaLine call, the generated URI will be different from the +		// original one. This is because the P2P URI is based on avatar UUID but Avaline is not. +		// See LLVoiceClient::sessionAddedEvent()  		setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));  	} diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 573fab1f4f..074f9b8bba 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -113,7 +113,7 @@ protected:  	void doSetState(const EState& state);  	void setURI(std::string uri); -	// there can be two directions ICOMING and OUTGOING +	// there can be two directions INCOMING and OUTGOING  	EDirection mCallDirection;  	std::string	mURI; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 42e44634b6..e8635d7f1a 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -35,6 +35,7 @@  #include "llviewerwindow.h"  #include "llvoicevivox.h"  #include "llviewernetwork.h" +#include "llcommandhandler.h"  #include "llhttpnode.h"  #include "llnotificationsutil.h"  #include "llsdserialize.h" @@ -46,6 +47,39 @@ const F32 LLVoiceClient::VOLUME_MIN = 0.f;  const F32 LLVoiceClient::VOLUME_DEFAULT = 0.5f;  const F32 LLVoiceClient::VOLUME_MAX = 1.0f; + +// Support for secondlife:///app/voice SLapps +class LLVoiceHandler : public LLCommandHandler +{ +public: +	// requests will be throttled from a non-trusted browser +	LLVoiceHandler() : LLCommandHandler("voice", UNTRUSTED_THROTTLE) {} + +	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +	{ +		if (params[0].asString() == "effects") +		{ +			LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); +			// If the voice client doesn't support voice effects, we can't handle effects SLapps +			if (!effect_interface) +			{ +				return false; +			} + +			// Support secondlife:///app/voice/effects/refresh to update the voice effect list with new effects +			if (params[1].asString() == "refresh") +			{ +				effect_interface->refreshVoiceEffectLists(false); +				return true; +			} +		} +		return false; +	} +}; +LLVoiceHandler gVoiceHandler; + + +  std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserver::EStatusType inStatus)  {  	std::string result = "UNKNOWN"; @@ -77,13 +111,14 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv -  ///////////////////////////////////////////////////////////////////////////////////////////////  LLVoiceClient::LLVoiceClient()  	:  	mVoiceModule(NULL), -	m_servicePump(NULL) +	m_servicePump(NULL), +	mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled")), +	mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault"))  {  } @@ -567,7 +602,7 @@ std::string LLVoiceClient::getDisplayName(const LLUUID& id)  	}  } -bool LLVoiceClient::isVoiceWorking() +bool LLVoiceClient::isVoiceWorking() const  {  	if (mVoiceModule)   	{ @@ -710,6 +745,10 @@ std::string LLVoiceClient::sipURIFromID(const LLUUID &id)  	}  } +LLVoiceEffectInterface* LLVoiceClient::getVoiceEffectInterface() const +{ +	return getVoiceEffectEnabled() ? dynamic_cast<LLVoiceEffectInterface*>(mVoiceModule) : NULL; +}  ///////////////////  // version checking diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index e08fed7ae9..0e3d9a5435 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -42,6 +42,7 @@ class LLVOAvatar;  #include "llviewerregion.h"  #include "llcallingcard.h"   // for LLFriendObserver  #include "llsecapi.h" +#include "llcontrol.h"  // devices @@ -52,7 +53,7 @@ class LLVoiceClientParticipantObserver  {  public:  	virtual ~LLVoiceClientParticipantObserver() { } -	virtual void onChange() = 0; +	virtual void onParticipantsChanged() = 0;  }; @@ -109,7 +110,7 @@ public:  	virtual void updateSettings()=0; // call after loading settings and whenever they change -	virtual bool isVoiceWorking()=0; // connected to a voice server and voice channel +	virtual bool isVoiceWorking() const = 0; // connected to a voice server and voice channel  	virtual const LLVoiceVersionInfo& getVersion()=0; @@ -217,8 +218,6 @@ public:  	//////////////////////////  	/// @name nearby speaker accessors  	//@{ - -  	virtual BOOL getVoiceEnabled(const LLUUID& id)=0;		// true if we've received data for this avatar  	virtual std::string getDisplayName(const LLUUID& id)=0;  	virtual BOOL isOnlineSIP(const LLUUID &id)=0;	 @@ -261,6 +260,63 @@ public:  }; +////////////////////////////////// +/// @class LLVoiceEffectObserver +class LLVoiceEffectObserver +{ +public: +	virtual ~LLVoiceEffectObserver() { } +	virtual void onVoiceEffectChanged(bool effect_list_updated) = 0; +}; + +typedef std::multimap<const std::string, const LLUUID, LLDictionaryLess> voice_effect_list_t; + +////////////////////////////////// +/// @class LLVoiceEffectInterface +/// @brief Voice effect module interface +/// +/// Voice effect modules should provide an implementation for this interface. +///////////////////////////////// + +class LLVoiceEffectInterface +{ +public: +	LLVoiceEffectInterface() {} +	virtual ~LLVoiceEffectInterface() {} + +	////////////////////////// +	/// @name Accessors +	//@{ +	virtual bool setVoiceEffect(const LLUUID& id) = 0; +	virtual const LLUUID getVoiceEffect() = 0; +	virtual LLSD getVoiceEffectProperties(const LLUUID& id) = 0; + +	virtual void refreshVoiceEffectLists(bool clear_lists) = 0; +	virtual const voice_effect_list_t &getVoiceEffectList() const = 0; +	virtual const voice_effect_list_t &getVoiceEffectTemplateList() const = 0; +	//@} + +	////////////////////////////// +	/// @name Status notification +	//@{ +	virtual void addObserver(LLVoiceEffectObserver* observer) = 0; +	virtual void removeObserver(LLVoiceEffectObserver* observer) = 0; +	//@} + +	////////////////////////////// +	/// @name Preview buffer +	//@{ +	virtual void enablePreviewBuffer(bool enable) = 0; +	virtual void recordPreviewBuffer() = 0; +	virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) = 0; +	virtual void stopPreviewBuffer() = 0; + +	virtual bool isPreviewRecording() = 0; +	virtual bool isPreviewPlaying() = 0; +	//@} +}; + +  class LLVoiceClient: public LLSingleton<LLVoiceClient>  {  	LOG_CLASS(LLVoiceClient); @@ -281,7 +337,7 @@ public:  	void updateSettings(); // call after loading settings and whenever they change -	bool isVoiceWorking(); // connected to a voice server and voice channel +	bool isVoiceWorking() const; // connected to a voice server and voice channel  	// tuning  	void tuningStart(); @@ -403,10 +459,23 @@ public:  	void removeObserver(LLVoiceClientParticipantObserver* observer);  	std::string sipURIFromID(const LLUUID &id);	 -		 + +	////////////////////////// +	/// @name Voice effects +	//@{ +	bool getVoiceEffectEnabled() const { return mVoiceEffectEnabled; }; +	LLUUID getVoiceEffectDefault() const { return LLUUID(mVoiceEffectDefault); }; + +	// Returns NULL if voice effects are not supported, or not enabled. +	LLVoiceEffectInterface* getVoiceEffectInterface() const; +	//@} +  protected:  	LLVoiceModuleInterface* mVoiceModule;  	LLPumpIO *m_servicePump; + +	LLCachedControl<bool> mVoiceEffectEnabled; +	LLCachedControl<std::string> mVoiceEffectDefault;  };  /** diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index d6028b78cb..39649f0370 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -60,6 +60,7 @@  #include "llviewerparcelmgr.h"  //#include "llfirstuse.h"  #include "llspeakers.h" +#include "lltrans.h"  #include "llviewerwindow.h"  #include "llviewercamera.h" @@ -67,15 +68,11 @@  #include "llviewernetwork.h"  #include "llnotificationsutil.h" +#include "stringize.h" +  // for base64 decoding  #include "apr_base64.h" -// for SHA1 hash -#include "apr_sha1.h" - -// for MD5 hash -#include "llmd5.h" -  #define USE_SESSION_GROUPS 0  const F32 VOLUME_SCALE_VIVOX = 0.01f; @@ -100,14 +97,15 @@ const int MAX_LOGIN_RETRIES = 12;  // blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability.  const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50; +// How often to check for expired voice fonts in seconds +const F32 VOICE_FONT_EXPIRY_INTERVAL = 10.f; +// Time of day at which Vivox expires voice font subscriptions. +// Used to replace the time portion of received expiry timestamps. +static const std::string VOICE_FONT_EXPIRY_TIME = "T05:00:00Z"; + +// Maximum length of capture buffer recordings in seconds. +const F32 CAPTURE_BUFFER_MAX_TIME = 10.f; -static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str) -{ -	LLMD5 md5_uuid; -	md5_uuid.update((const unsigned char*)str.data(), str.size()); -	md5_uuid.finalize(); -	md5_uuid.raw_digest(uuid.mData); -}  static int scale_mic_volume(float volume)  { @@ -325,6 +323,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :  	mBuddyListMapPopulated(false),  	mBlockRulesListReceived(false),  	mAutoAcceptRulesListReceived(false), +  	mCaptureDeviceDirty(false),  	mRenderDeviceDirty(false),  	mSpatialCoordsDirty(false), @@ -348,10 +347,17 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :  	mVoiceEnabled(false),  	mWriteInProgress(false), -	mLipSyncEnabled(false) - +	mLipSyncEnabled(false), +	mVoiceFontsReceived(false), +	mVoiceFontsNew(false), +	mVoiceFontListDirty(false), +	mCaptureBufferMode(false), +	mCaptureBufferRecording(false), +	mCaptureBufferRecorded(false), +	mCaptureBufferPlaying(false), +	mPlayRequestCount(0)  {	  	mSpeakerVolume = scale_speaker_volume(0); @@ -654,6 +660,11 @@ std::string LLVivoxVoiceClient::state2string(LLVivoxVoiceClient::state inState)  		CASE(stateMicTuningStart);  		CASE(stateMicTuningRunning);  		CASE(stateMicTuningStop); +		CASE(stateCaptureBufferPaused); +		CASE(stateCaptureBufferRecStart); +		CASE(stateCaptureBufferRecording); +		CASE(stateCaptureBufferPlayStart); +		CASE(stateCaptureBufferPlaying);  		CASE(stateConnectorStart);  		CASE(stateConnectorStarting);  		CASE(stateConnectorStarted); @@ -662,6 +673,8 @@ std::string LLVivoxVoiceClient::state2string(LLVivoxVoiceClient::state inState)  		CASE(stateNeedsLogin);  		CASE(stateLoggingIn);  		CASE(stateLoggedIn); +		CASE(stateVoiceFontsWait); +		CASE(stateVoiceFontsReceived);  		CASE(stateCreatingSessionGroup);  		CASE(stateNoChannel);  		CASE(stateJoiningSession); @@ -775,8 +788,10 @@ void LLVivoxVoiceClient::stateMachine()  			// Clean up and reset everything.   			closeSocket();  			deleteAllSessions(); -			deleteAllBuddies();		 -			 +			deleteAllBuddies(); +			deleteAllVoiceFonts(); +			deleteVoiceFontTemplates(); +  			mConnectorHandle.clear();  			mAccountHandle.clear();  			mAccountPassword.clear(); @@ -1126,8 +1141,97 @@ void LLVivoxVoiceClient::stateMachine()  		}  		break; -												 -		//MARK: stateConnectorStart + +		//MARK: stateCaptureBufferPaused +		case stateCaptureBufferPaused: +			if (!mCaptureBufferMode) +			{ +				// Leaving capture mode. + +				mCaptureBufferRecording = false; +				mCaptureBufferRecorded = false; +				mCaptureBufferPlaying = false; + +				// Return to stateNoChannel to trigger reconnection to a channel. +				setState(stateNoChannel); +			} +			else if (mCaptureBufferRecording) +			{ +				setState(stateCaptureBufferRecStart); +			} +			else if (mCaptureBufferPlaying) +			{ +				setState(stateCaptureBufferPlayStart); +			} +		break; + +		//MARK: stateCaptureBufferRecStart +		case stateCaptureBufferRecStart: +			captureBufferRecordStartSendMessage(); + +			// Flag that something is recorded to allow playback. +			mCaptureBufferRecorded = true; + +			// Start the timer, recording will be stopped when it expires. +			mCaptureTimer.start(); +			mCaptureTimer.setTimerExpirySec(CAPTURE_BUFFER_MAX_TIME); + +			// Update UI, should really use a separate callback. +			notifyVoiceFontObservers(); + +			setState(stateCaptureBufferRecording); +		break; + +		//MARK: stateCaptureBufferRecording +		case stateCaptureBufferRecording: +			if (!mCaptureBufferMode || !mCaptureBufferRecording || +				mCaptureBufferPlaying || mCaptureTimer.hasExpired()) +			{ +				// Stop recording +				captureBufferRecordStopSendMessage(); +				mCaptureBufferRecording = false; + +				// Update UI, should really use a separate callback. +				notifyVoiceFontObservers(); + +				setState(stateCaptureBufferPaused); +			} +		break; + +		//MARK: stateCaptureBufferPlayStart +		case stateCaptureBufferPlayStart: +			captureBufferPlayStartSendMessage(mPreviewVoiceFont); + +			// Store the voice font being previewed, so that we know to restart if it changes. +			mPreviewVoiceFontLast = mPreviewVoiceFont; + +			// Update UI, should really use a separate callback. +			notifyVoiceFontObservers(); + +			setState(stateCaptureBufferPlaying); +		break; + +		//MARK: stateCaptureBufferPlaying +		case stateCaptureBufferPlaying: +			if (mCaptureBufferPlaying && mPreviewVoiceFont != mPreviewVoiceFontLast) +			{ +				// If the preview voice font changes, restart playing with the new font. +				setState(stateCaptureBufferPlayStart); +			} +			else if (!mCaptureBufferMode || !mCaptureBufferPlaying || mCaptureBufferRecording) +			{ +				// Stop playing. +				captureBufferPlayStopSendMessage(); +				mCaptureBufferPlaying = false; + +				// Update UI, should really use a separate callback. +				notifyVoiceFontObservers(); + +				setState(stateCaptureBufferPaused); +			} +		break; + +			//MARK: stateConnectorStart  		case stateConnectorStart:  			if(!mVoiceEnabled)  			{ @@ -1222,6 +1326,18 @@ void LLVivoxVoiceClient::stateMachine()  			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN); +			if (LLVoiceClient::instance().getVoiceEffectEnabled()) +			{ +				// Request the set of available voice fonts. +				setState(stateVoiceFontsWait); +				refreshVoiceEffectLists(true); +			} +			else +			{ +				// If voice effects are disabled, pretend we've received them and carry on. +				setState(stateVoiceFontsReceived); +			} +  			// request the current set of block rules (we'll need them when updating the friends list)  			accountListBlockRulesSendMessage(); @@ -1253,12 +1369,25 @@ void LLVivoxVoiceClient::stateMachine()  					writeString(stream.str());  				}  			} +		break; + +		//MARK: stateVoiceFontsWait +		case stateVoiceFontsWait:		// Await voice font list +			// accountGetSessionFontsResponse() will transition from here to +			// stateVoiceFontsReceived, to ensure we have the voice font list +			// before attempting to create a session. +		break; +		//MARK: stateVoiceFontsReceived +		case stateVoiceFontsReceived:	// Voice font list received +			// Set up the timer to check for expiring voice fonts +			mVoiceFontExpiryTimer.start(); +			mVoiceFontExpiryTimer.setTimerExpirySec(VOICE_FONT_EXPIRY_INTERVAL); +  #if USE_SESSION_GROUPS			  			// create the main session group -			sessionGroupCreateSendMessage(); -			  			setState(stateCreatingSessionGroup); +			sessionGroupCreateSendMessage();  #else  			// Not using session groups -- skip the stateCreatingSessionGroup state.  			setState(stateNoChannel); @@ -1306,6 +1435,10 @@ void LLVivoxVoiceClient::stateMachine()  				mTuningExitState = stateNoChannel;  				setState(stateMicTuningStart);  			} +			else if(mCaptureBufferMode) +			{ +				setState(stateCaptureBufferPaused); +			}  			else if(sessionNeedsRelog(mNextAudioSession))  			{  				requestRelog(); @@ -1316,6 +1449,7 @@ void LLVivoxVoiceClient::stateMachine()  				sessionState *oldSession = mAudioSession;  				mAudioSession = mNextAudioSession; +				mAudioSessionChanged = true;  				if(!mAudioSession->mReconnect)	  				{  					mNextAudioSession = NULL; @@ -1478,6 +1612,13 @@ void LLVivoxVoiceClient::stateMachine()  					enforceTether();  				} +				// Do notifications for expiring Voice Fonts. +				if (mVoiceFontExpiryTimer.hasExpired()) +				{ +					expireVoiceFonts(); +					mVoiceFontExpiryTimer.setTimerExpirySec(VOICE_FONT_EXPIRY_INTERVAL); +				} +  				// Send an update only if the ptt or mute state has changed (which shouldn't be able to happen that often  				// -- the user can only click so fast) or every 10hz, whichever is sooner.  				// Sending for every volume update causes an excessive flood of messages whenever a volume slider is dragged. @@ -1547,6 +1688,8 @@ void LLVivoxVoiceClient::stateMachine()  			mAccountHandle.clear();  			deleteAllSessions();  			deleteAllBuddies(); +			deleteAllVoiceFonts(); +			deleteVoiceFontTemplates();  			if(mVoiceEnabled && !mRelogRequested)  			{ @@ -1627,15 +1770,15 @@ void LLVivoxVoiceClient::stateMachine()  	} -	if(mAudioSession && mAudioSession->mParticipantsChanged) +	if (mAudioSessionChanged)  	{ -		mAudioSession->mParticipantsChanged = false; -		mAudioSessionChanged = true; +		mAudioSessionChanged = false; +		notifyParticipantObservers(); +		notifyVoiceFontObservers();  	} -	 -	if(mAudioSessionChanged) +	else if (mAudioSession && mAudioSession->mParticipantsChanged)  	{ -		mAudioSessionChanged = false; +		mAudioSession->mParticipantsChanged = false;  		notifyParticipantObservers();  	}  } @@ -1751,8 +1894,11 @@ void LLVivoxVoiceClient::sessionGroupCreateSendMessage()  void LLVivoxVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)  { -	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; -	 +	LL_DEBUGS("Voice") << "Requesting create: " << session->mSIPURI << LL_ENDL; + +	S32 font_index = getVoiceFontIndex(session->mVoiceFontID); +	LL_DEBUGS("Voice") << "With voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL; +  	session->mCreateInProgress = true;  	if(startAudio)  	{ @@ -1776,10 +1922,11 @@ void LLVivoxVoiceClient::sessionCreateSendMessage(sessionState *session, bool st  			<< "<Password>" << LLURI::escape(session->mHash, allowed_chars) << "</Password>"  			<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>";  	} -	 +  	stream  		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"  		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>" +		<< "<VoiceFontID>" << font_index << "</VoiceFontID>"  		<< "<Name>" << mChannelName << "</Name>"  	<< "</Request>\n\n\n";  	writeString(stream.str()); @@ -1787,8 +1934,11 @@ void LLVivoxVoiceClient::sessionCreateSendMessage(sessionState *session, bool st  void LLVivoxVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)  { -	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL; -	 +	LL_DEBUGS("Voice") << "Requesting create: " << session->mSIPURI << LL_ENDL; + +	S32 font_index = getVoiceFontIndex(session->mVoiceFontID); +	LL_DEBUGS("Voice") << "With voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL; +  	session->mCreateInProgress = true;  	if(startAudio)  	{ @@ -1814,6 +1964,7 @@ void LLVivoxVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session  		<< "<Name>" << mChannelName << "</Name>"  		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"  		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>" +		<< "<VoiceFontID>" << font_index << "</VoiceFontID>"  		<< "<Password>" << password << "</Password>"  		<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>"  	<< "</Request>\n\n\n" @@ -1824,7 +1975,10 @@ void LLVivoxVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session  void LLVivoxVoiceClient::sessionMediaConnectSendMessage(sessionState *session)  { -	LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL; +	LL_DEBUGS("Voice") << "Connecting audio to session handle: " << session->mHandle << LL_ENDL; + +	S32 font_index = getVoiceFontIndex(session->mVoiceFontID); +	LL_DEBUGS("Voice") << "With voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL;  	session->mMediaConnectInProgress = true; @@ -1834,6 +1988,7 @@ void LLVivoxVoiceClient::sessionMediaConnectSendMessage(sessionState *session)  	<< "<Request requestId=\"" << session->mHandle << "\" action=\"Session.MediaConnect.1\">"  		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"  		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>" +		<< "<VoiceFontID>" << font_index << "</VoiceFontID>"  		<< "<Media>Audio</Media>"  	<< "</Request>\n\n\n"; @@ -3156,7 +3311,7 @@ void LLVivoxVoiceClient::sessionAddedEvent(  			else  			{  				LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL; -				setUUIDFromStringHash(session->mCallerID, session->mSIPURI); +				session->mCallerID.generate(session->mSIPURI);  				session->mSynthesizedCallerID = true;  				// Can't look up the name in this case -- we have to extract it from the URI. @@ -3434,6 +3589,26 @@ void LLVivoxVoiceClient::accountLoginStateChangeEvent(  	}  } +void LLVivoxVoiceClient::mediaCompletionEvent(std::string &sessionGroupHandle, std::string &mediaCompletionType) +{ +	if (mediaCompletionType == "AuxBufferAudioCapture") +	{ +		mCaptureBufferRecording = false; +	} +	else if (mediaCompletionType == "AuxBufferAudioRender") +	{ +		// Ignore all but the last stop event +		if (--mPlayRequestCount <= 0) +		{ +			mCaptureBufferPlaying = false; +		} +	} +	else +	{ +		LL_DEBUGS("Voice") << "Unknown MediaCompletionType: " << mediaCompletionType << LL_ENDL; +	} +} +  void LLVivoxVoiceClient::mediaStreamUpdatedEvent(  	std::string &sessionHandle,   	std::string &sessionGroupHandle,  @@ -4142,8 +4317,8 @@ LLVivoxVoiceClient::participantState *LLVivoxVoiceClient::sessionState::addParti  			else  			{  				// Create a UUID by hashing the URI, but do NOT set mAvatarIDValid. -				// This tells code in LLVivoxVoiceClient that the ID will not be in the name cache. -				setUUIDFromStringHash(result->mAvatarID, uri); +				// This indicates that the ID will not be in the name cache. +				result->mAvatarID.generate(uri);  			}  		} @@ -4638,7 +4813,7 @@ BOOL LLVivoxVoiceClient::isOnlineSIP(const LLUUID &id)  	return result;  } -bool LLVivoxVoiceClient::isVoiceWorking() +bool LLVivoxVoiceClient::isVoiceWorking() const  {    //Added stateSessionTerminated state to avoid problems with call in parcels with disabled voice (EXT-4758)    // Condition with joining spatial num was added to take into account possible problems with connection to voice @@ -5660,7 +5835,12 @@ LLVivoxVoiceClient::sessionState *LLVivoxVoiceClient::addSession(const std::stri  		result = new sessionState();  		result->mSIPURI = uri;  		result->mHandle = handle; -		 + +		if (LLVoiceClient::instance().getVoiceEffectEnabled()) +		{ +			result->mVoiceFontID = LLVoiceClient::instance().getVoiceEffectDefault(); +		} +  		mSessions.insert(result);  		if(!result->mHandle.empty()) @@ -6085,8 +6265,8 @@ void LLVivoxVoiceClient::notifyParticipantObservers()  		)  	{  		LLVoiceClientParticipantObserver* observer = *it; -		observer->onChange(); -		// In case onChange() deleted an entry. +		observer->onParticipantsChanged(); +		// In case onParticipantsChanged() deleted an entry.  		it = mParticipantObservers.upper_bound(observer);  	}  } @@ -6249,6 +6429,660 @@ void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string  	}  } +bool LLVivoxVoiceClient::setVoiceEffect(const LLUUID& id) +{ +	if (!mAudioSession) +	{ +		return false; +	} + +	if (!id.isNull()) +	{ +		if (mVoiceFontMap.empty()) +		{ +			LL_DEBUGS("Voice") << "Voice fonts not available." << LL_ENDL; +			return false; +		} +		else if (mVoiceFontMap.find(id) == mVoiceFontMap.end()) +		{ +			LL_DEBUGS("Voice") << "Invalid voice font " << id << LL_ENDL; +			return false; +		} +	} + +	// *TODO: Check for expired fonts? +	mAudioSession->mVoiceFontID = id; + +	// *TODO: Separate voice font defaults for spatial chat and IM? +	gSavedPerAccountSettings.setString("VoiceEffectDefault", id.asString()); + +	sessionSetVoiceFontSendMessage(mAudioSession); +	notifyVoiceFontObservers(); + +	return true; +} + +const LLUUID LLVivoxVoiceClient::getVoiceEffect() +{ +	return mAudioSession ? mAudioSession->mVoiceFontID : LLUUID::null; +} + +LLSD LLVivoxVoiceClient::getVoiceEffectProperties(const LLUUID& id) +{ +	LLSD sd; + +	voice_font_map_t::iterator iter = mVoiceFontMap.find(id); +	if (iter != mVoiceFontMap.end()) +	{ +		sd["template_only"] = false; +	} +	else +	{ +		// Voice effect is not in the voice font map, see if there is a template +		iter = mVoiceFontTemplateMap.find(id); +		if (iter == mVoiceFontTemplateMap.end()) +		{ +			LL_WARNS("Voice") << "Voice effect " << id << "not found." << LL_ENDL; +			return sd; +		} +		sd["template_only"] = true; +	} + +	voiceFontEntry *font = iter->second; +	sd["name"] = font->mName; +	sd["expiry_date"] = font->mExpirationDate; +	sd["is_new"] = font->mIsNew; + +	return sd; +} + +LLVivoxVoiceClient::voiceFontEntry::voiceFontEntry(LLUUID& id) : +	mID(id), +	mFontIndex(0), +	mFontType(VOICE_FONT_TYPE_NONE), +	mFontStatus(VOICE_FONT_STATUS_NONE), +	mIsNew(false) +{ +	mExpiryTimer.stop(); +	mExpiryWarningTimer.stop(); +} + +LLVivoxVoiceClient::voiceFontEntry::~voiceFontEntry() +{ +} + +void LLVivoxVoiceClient::refreshVoiceEffectLists(bool clear_lists) +{ +	if (clear_lists) +	{ +		mVoiceFontsReceived = false; +		deleteAllVoiceFonts(); +		deleteVoiceFontTemplates(); +	} + +	accountGetSessionFontsSendMessage(); +	accountGetTemplateFontsSendMessage(); +} + +const voice_effect_list_t& LLVivoxVoiceClient::getVoiceEffectList() const +{ +	return mVoiceFontList; +} + +const voice_effect_list_t& LLVivoxVoiceClient::getVoiceEffectTemplateList() const +{ +	return mVoiceFontTemplateList; +} + +void LLVivoxVoiceClient::addVoiceFont(const S32 font_index, +								 const std::string &name, +								 const std::string &description, +								 const LLDate &expiration_date, +								 bool has_expired, +								 const S32 font_type, +								 const S32 font_status, +								 const bool template_font) +{ +	// Vivox SessionFontIDs are not guaranteed to remain the same between +	// sessions or grids so use a UUID for the name. + +	// If received name is not a UUID, fudge one by hashing the name and type. +	LLUUID font_id; +	if (LLUUID::validate(name)) +	{ +		font_id = LLUUID(name); +	} +	else +	{ +		font_id.generate(STRINGIZE(font_type << ":" << name)); +	} + +	voiceFontEntry *font = NULL; + +	voice_font_map_t& font_map = template_font ? mVoiceFontTemplateMap : mVoiceFontMap; +	voice_effect_list_t& font_list = template_font ? mVoiceFontTemplateList : mVoiceFontList; + +	// Check whether we've seen this font before. +	voice_font_map_t::iterator iter = font_map.find(font_id); +	bool new_font = (iter == font_map.end()); + +	// Override the has_expired flag if we have passed the expiration_date as a double check. +	if (expiration_date.secondsSinceEpoch() < (LLDate::now().secondsSinceEpoch() + VOICE_FONT_EXPIRY_INTERVAL)) +	{ +		has_expired = true; +	} + +	if (has_expired) +	{ +		LL_DEBUGS("Voice") << "Expired " << (template_font ? "Template " : "") +		<< expiration_date.asString() << " " << font_id +		<< " (" << font_index << ") " << name << LL_ENDL; + +		// Remove existing session fonts that have expired since we last saw them. +		if (!new_font && !template_font) +		{ +			deleteVoiceFont(font_id); +		} +		return; +	} + +	if (new_font) +	{ +		// If it is a new font create a new entry. +		font = new voiceFontEntry(font_id); +	} +	else +	{ +		// Not a new font, update the existing entry +		font = iter->second; +	} + +	if (font) +	{ +		font->mFontIndex = font_index; +		// Use the description for the human readable name if available, as the +		// "name" may be a UUID. +		font->mName = description.empty() ? name : description; +		font->mFontType = font_type; +		font->mFontStatus = font_status; + +		// If the font is new or the expiration date has changed the expiry timers need updating. +		if (!template_font && (new_font || font->mExpirationDate != expiration_date)) +		{ +			font->mExpirationDate = expiration_date; + +			// Set the expiry timer to trigger a notification when the voice font can no longer be used. +			font->mExpiryTimer.start(); +			font->mExpiryTimer.setExpiryAt(expiration_date.secondsSinceEpoch() - VOICE_FONT_EXPIRY_INTERVAL); + +			// Set the warning timer to some interval before actual expiry. +			S32 warning_time = gSavedSettings.getS32("VoiceEffectExpiryWarningTime"); +			if (warning_time != 0) +			{ +				font->mExpiryWarningTimer.start(); +				F64 expiry_time = (expiration_date.secondsSinceEpoch() - (F64)warning_time); +				font->mExpiryWarningTimer.setExpiryAt(expiry_time - VOICE_FONT_EXPIRY_INTERVAL); +			} +			else +			{ +				// Disable the warning timer. +				font->mExpiryWarningTimer.stop(); +			} + +			 // Only flag new session fonts after the first time we have fetched the list. +			if (mVoiceFontsReceived) +			{ +				font->mIsNew = true; +				mVoiceFontsNew = true; +			} +		} + +		LL_DEBUGS("Voice") << (template_font ? "Template " : "") +			<< font->mExpirationDate.asString() << " " << font->mID +			<< " (" << font->mFontIndex << ") " << name << LL_ENDL; + +		if (new_font) +		{ +			font_map.insert(voice_font_map_t::value_type(font->mID, font)); +			font_list.insert(voice_effect_list_t::value_type(font->mName, font->mID)); +		} + +		mVoiceFontListDirty = true; + +		// Debugging stuff + +		if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN) +		{ +			LL_DEBUGS("Voice") << "Unknown voice font type: " << font_type << LL_ENDL; +		} +		if (font_status < VOICE_FONT_STATUS_NONE || font_status >= VOICE_FONT_STATUS_UNKNOWN) +		{ +			LL_DEBUGS("Voice") << "Unknown voice font status: " << font_status << LL_ENDL; +		} +	} +} + +void LLVivoxVoiceClient::expireVoiceFonts() +{ +	// *TODO: If we are selling voice fonts in packs, there are probably +	// going to be a number of fonts with the same expiration time, so would +	// be more efficient to just keep a list of expiration times rather +	// than checking each font individually. + +	bool have_expired = false; +	bool will_expire = false; +	bool expired_in_use = false; + +	LLUUID current_effect = LLVoiceClient::instance().getVoiceEffectDefault(); + +	voice_font_map_t::iterator iter; +	for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter) +	{ +		voiceFontEntry* voice_font = iter->second; +		LLFrameTimer& expiry_timer  = voice_font->mExpiryTimer; +		LLFrameTimer& warning_timer = voice_font->mExpiryWarningTimer; + +		// Check for expired voice fonts +		if (expiry_timer.getStarted() && expiry_timer.hasExpired()) +		{ +			// Check whether it is the active voice font +			if (voice_font->mID == current_effect) +			{ +				// Reset to no voice effect. +				setVoiceEffect(LLUUID::null); +				expired_in_use = true; +			} + +			LL_DEBUGS("Voice") << "Voice Font " << voice_font->mName << " has expired." << LL_ENDL; +			deleteVoiceFont(voice_font->mID); +			have_expired = true; +		} + +		// Check for voice fonts that will expire in less that the warning time +		if (warning_timer.getStarted() && warning_timer.hasExpired()) +		{ +			LL_DEBUGS("Voice") << "Voice Font " << voice_font->mName << " will expire soon." << LL_ENDL; +			will_expire = true; +			warning_timer.stop(); +		} +	} + +	LLSD args; +	args["URL"] = LLTrans::getString("voice_morphing_url"); + +	// Give a notification if any voice fonts have expired. +	if (have_expired) +	{ +		if (expired_in_use) +		{ +			LLNotificationsUtil::add("VoiceEffectsExpiredInUse", args); +		} +		else +		{ +			LLNotificationsUtil::add("VoiceEffectsExpired", args); +		} + +		// Refresh voice font lists in the UI. +		notifyVoiceFontObservers(); +	} + +	// Give a warning notification if any voice fonts are due to expire. +	if (will_expire) +	{ +		S32 seconds = gSavedSettings.getS32("VoiceEffectExpiryWarningTime"); +		args["INTERVAL"] = llformat("%d", seconds / SEC_PER_DAY); + +		LLNotificationsUtil::add("VoiceEffectsWillExpire", args); +	} +} + +void LLVivoxVoiceClient::deleteVoiceFont(const LLUUID& id) +{ +	// Remove the entry from the voice font list. +	voice_effect_list_t::iterator list_iter = mVoiceFontList.begin(); +	while (list_iter != mVoiceFontList.end()) +	{ +		if (list_iter->second == id) +		{ +			LL_DEBUGS("Voice") << "Removing " << id << " from the voice font list." << LL_ENDL; +			mVoiceFontList.erase(list_iter++); +			mVoiceFontListDirty = true; +		} +		else +		{ +			++list_iter; +		} +	} + +	// Find the entry in the voice font map and erase its data. +	voice_font_map_t::iterator map_iter = mVoiceFontMap.find(id); +	if (map_iter != mVoiceFontMap.end()) +	{ +		delete map_iter->second; +	} + +	// Remove the entry from the voice font map. +	mVoiceFontMap.erase(map_iter); +} + +void LLVivoxVoiceClient::deleteAllVoiceFonts() +{ +	mVoiceFontList.clear(); + +	voice_font_map_t::iterator iter; +	for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter) +	{ +		delete iter->second; +	} +	mVoiceFontMap.clear(); +} + +void LLVivoxVoiceClient::deleteVoiceFontTemplates() +{ +	mVoiceFontTemplateList.clear(); + +	voice_font_map_t::iterator iter; +	for (iter = mVoiceFontTemplateMap.begin(); iter != mVoiceFontTemplateMap.end(); ++iter) +	{ +		delete iter->second; +	} +	mVoiceFontTemplateMap.clear(); +} + +S32 LLVivoxVoiceClient::getVoiceFontIndex(const LLUUID& id) const +{ +	S32 result = 0; +	if (!id.isNull()) +	{ +		voice_font_map_t::const_iterator it = mVoiceFontMap.find(id); +		if (it != mVoiceFontMap.end()) +		{ +			result = it->second->mFontIndex; +		} +		else +		{ +			LL_DEBUGS("Voice") << "Selected voice font " << id << " is not available." << LL_ENDL; +		} +	} +	return result; +} + +S32 LLVivoxVoiceClient::getVoiceFontTemplateIndex(const LLUUID& id) const +{ +	S32 result = 0; +	if (!id.isNull()) +	{ +		voice_font_map_t::const_iterator it = mVoiceFontTemplateMap.find(id); +		if (it != mVoiceFontTemplateMap.end()) +		{ +			result = it->second->mFontIndex; +		} +		else +		{ +			LL_DEBUGS("Voice") << "Selected voice font template " << id << " is not available." << LL_ENDL; +		} +	} +	return result; +} + +void LLVivoxVoiceClient::accountGetSessionFontsSendMessage() +{ +	if(!mAccountHandle.empty()) +	{ +		std::ostringstream stream; + +		LL_DEBUGS("Voice") << "Requesting voice font list." << LL_ENDL; + +		stream +		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.GetSessionFonts.1\">" +		<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>" +		<< "</Request>" +		<< "\n\n\n"; + +		writeString(stream.str()); +	} +} + +void LLVivoxVoiceClient::accountGetTemplateFontsSendMessage() +{ +	if(!mAccountHandle.empty()) +	{ +		std::ostringstream stream; + +		LL_DEBUGS("Voice") << "Requesting voice font template list." << LL_ENDL; + +		stream +		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.GetTemplateFonts.1\">" +		<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>" +		<< "</Request>" +		<< "\n\n\n"; + +		writeString(stream.str()); +	} +} + +void LLVivoxVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session) +{ +	S32 font_index = getVoiceFontIndex(session->mVoiceFontID); +	LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << "), session handle: " << session->mHandle << LL_ENDL; + +	std::ostringstream stream; + +	stream +	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetVoiceFont.1\">" +	<< "<SessionHandle>" << session->mHandle << "</SessionHandle>" +	<< "<SessionFontID>" << font_index << "</SessionFontID>" +	<< "</Request>\n\n\n"; + +	writeString(stream.str()); +} + +void LLVivoxVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString) +{ +	// Voice font list entries were updated via addVoiceFont() during parsing. +	if(getState() == stateVoiceFontsWait) +	{ +		setState(stateVoiceFontsReceived); +	} + +	notifyVoiceFontObservers(); +	mVoiceFontsReceived = true; +} + +void LLVivoxVoiceClient::accountGetTemplateFontsResponse(int statusCode, const std::string &statusString) +{ +	// Voice font list entries were updated via addVoiceFont() during parsing. +	notifyVoiceFontObservers(); +} +void LLVivoxVoiceClient::addObserver(LLVoiceEffectObserver* observer) +{ +	mVoiceFontObservers.insert(observer); +} + +void LLVivoxVoiceClient::removeObserver(LLVoiceEffectObserver* observer) +{ +	mVoiceFontObservers.erase(observer); +} + +void LLVivoxVoiceClient::notifyVoiceFontObservers() +{ +	LL_DEBUGS("Voice") << "Notifying voice effect observers. Lists changed: " << mVoiceFontListDirty << LL_ENDL; + +	for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin(); +		 it != mVoiceFontObservers.end(); +		 ) +	{ +		LLVoiceEffectObserver* observer = *it; +		observer->onVoiceEffectChanged(mVoiceFontListDirty); +		// In case onVoiceEffectChanged() deleted an entry. +		it = mVoiceFontObservers.upper_bound(observer); +	} +	mVoiceFontListDirty = false; + +	// If new Voice Fonts have been added notify the user. +	if (mVoiceFontsNew) +	{ +		if(mVoiceFontsReceived) +		{ +			LLNotificationsUtil::add("VoiceEffectsNew"); +		} +		mVoiceFontsNew = false; +	} +} + +void LLVivoxVoiceClient::enablePreviewBuffer(bool enable) +{ +	mCaptureBufferMode = enable; +	if(mCaptureBufferMode && getState() >= stateNoChannel) +	{ +		LL_DEBUGS("Voice") << "no channel" << LL_ENDL; +		sessionTerminate(); +	} +} + +void LLVivoxVoiceClient::recordPreviewBuffer() +{ +	if (!mCaptureBufferMode) +	{ +		LL_DEBUGS("Voice") << "Not in voice effect preview mode, cannot start recording." << LL_ENDL; +		mCaptureBufferRecording = false; +		return; +	} + +	mCaptureBufferRecording = true; +} + +void LLVivoxVoiceClient::playPreviewBuffer(const LLUUID& effect_id) +{ +	if (!mCaptureBufferMode) +	{ +		LL_DEBUGS("Voice") << "Not in voice effect preview mode, no buffer to play." << LL_ENDL; +		mCaptureBufferRecording = false; +		return; +	} + +	if (!mCaptureBufferRecorded) +	{ +		// Can't play until we have something recorded! +		mCaptureBufferPlaying = false; +		return; +	} + +	mPreviewVoiceFont = effect_id; +	mCaptureBufferPlaying = true; +} + +void LLVivoxVoiceClient::stopPreviewBuffer() +{ +	mCaptureBufferRecording = false; +	mCaptureBufferPlaying = false; +} + +bool LLVivoxVoiceClient::isPreviewRecording() +{ +	return (mCaptureBufferMode && mCaptureBufferRecording); +} + +bool LLVivoxVoiceClient::isPreviewPlaying() +{ +	return (mCaptureBufferMode && mCaptureBufferPlaying); +} + +void LLVivoxVoiceClient::captureBufferRecordStartSendMessage() +{	if(!mAccountHandle.empty()) +	{ +		std::ostringstream stream; + +		LL_DEBUGS("Voice") << "Starting audio capture to buffer." << LL_ENDL; + +		// Start capture +		stream +		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.StartBufferCapture.1\">" +		<< "</Request>" +		<< "\n\n\n"; + +		// Unmute the mic +		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">" +			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" +			<< "<Value>false</Value>" +		<< "</Request>\n\n\n"; + +		// Dirty the PTT state so that it will get reset when we finishing previewing +		mPTTDirty = true; + +		writeString(stream.str()); +	} +} + +void LLVivoxVoiceClient::captureBufferRecordStopSendMessage() +{ +	if(!mAccountHandle.empty()) +	{ +		std::ostringstream stream; + +		LL_DEBUGS("Voice") << "Stopping audio capture to buffer." << LL_ENDL; + +		// Mute the mic. PTT state was dirtied at recording start, so will be reset when finished previewing. +		stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">" +			<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>" +			<< "<Value>true</Value>" +		<< "</Request>\n\n\n"; + +		// Stop capture +		stream +		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.CaptureAudioStop.1\">" +			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>" +		<< "</Request>" +		<< "\n\n\n"; + +		writeString(stream.str()); +	} +} + +void LLVivoxVoiceClient::captureBufferPlayStartSendMessage(const LLUUID& voice_font_id) +{ +	if(!mAccountHandle.empty()) +	{ +		// Track how may play requests are sent, so we know how many stop events to +		// expect before play actually stops. +		++mPlayRequestCount; + +		std::ostringstream stream; + +		LL_DEBUGS("Voice") << "Starting audio buffer playback." << LL_ENDL; + +		S32 font_index = getVoiceFontTemplateIndex(voice_font_id); +		LL_DEBUGS("Voice") << "With voice font: " << voice_font_id << " (" << font_index << ")" << LL_ENDL; + +		stream +		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.PlayAudioBuffer.1\">" +			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>" +			<< "<TemplateFontID>" << font_index << "</TemplateFontID>" +			<< "<FontDelta />" +		<< "</Request>" +		<< "\n\n\n"; + +		writeString(stream.str()); +	} +} + +void LLVivoxVoiceClient::captureBufferPlayStopSendMessage() +{ +	if(!mAccountHandle.empty()) +	{ +		std::ostringstream stream; + +		LL_DEBUGS("Voice") << "Stopping audio buffer playback." << LL_ENDL; + +		stream +		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.RenderAudioStop.1\">" +			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>" +		<< "</Request>" +		<< "\n\n\n"; + +		writeString(stream.str()); +	} +}  LLVivoxProtocolParser::LLVivoxProtocolParser()  { @@ -6467,7 +7301,30 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)  			{  				LLVivoxVoiceClient::getInstance()->deleteAllAutoAcceptRules();  			} -			 +			else if (!stricmp("SessionFont", tag)) +			{ +				id = 0; +				nameString.clear(); +				descriptionString.clear(); +				expirationDate = LLDate(); +				hasExpired = false; +				fontType = 0; +				fontStatus = 0; +			} +			else if (!stricmp("TemplateFont", tag)) +			{ +				id = 0; +				nameString.clear(); +				descriptionString.clear(); +				expirationDate = LLDate(); +				hasExpired = false; +				fontType = 0; +				fontStatus = 0; +			} +			else if (!stricmp("MediaCompletionType", tag)) +			{ +				mediaCompletionType.clear(); +			}  		}  	}  	responseDepth++; @@ -6613,8 +7470,43 @@ void LLVivoxProtocolParser::EndTag(const char *tag)  			subscriptionHandle = string;  		else if (!stricmp("SubscriptionType", tag))  			subscriptionType = string; -		 -	 +		else if (!stricmp("SessionFont", tag)) +		{ +			LLVivoxVoiceClient::getInstance()->addVoiceFont(id, nameString, descriptionString, expirationDate, hasExpired, fontType, fontStatus, false); +		} +		else if (!stricmp("TemplateFont", tag)) +		{ +			LLVivoxVoiceClient::getInstance()->addVoiceFont(id, nameString, descriptionString, expirationDate, hasExpired, fontType, fontStatus, true); +		} +		else if (!stricmp("ID", tag)) +		{ +			id = strtol(string.c_str(), NULL, 10); +		} +		else if (!stricmp("Description", tag)) +		{ +			descriptionString = string; +		} +		else if (!stricmp("ExpirationDate", tag)) +		{ +			expirationDate = expiryTimeStampToLLDate(string); +		} +		else if (!stricmp("Expired", tag)) +		{ +			hasExpired = !stricmp(string.c_str(), "1"); +		} +		else if (!stricmp("Type", tag)) +		{ +			fontType = strtol(string.c_str(), NULL, 10); +		} +		else if (!stricmp("Status", tag)) +		{ +			fontStatus = strtol(string.c_str(), NULL, 10); +		} +		else if (!stricmp("MediaCompletionType", tag)) +		{ +			mediaCompletionType = string;; +		} +  		textBuffer.clear();  		accumulateText= false; @@ -6643,6 +7535,21 @@ void LLVivoxProtocolParser::CharData(const char *buffer, int length)  // -------------------------------------------------------------------------------- +LLDate LLVivoxProtocolParser::expiryTimeStampToLLDate(const std::string& vivox_ts) +{ +	// *HACK: Vivox reports the time incorrectly. LLDate also only parses a +	// subset of valid ISO 8601 dates (only handles Z, not offsets). +	// So just use the date portion and fix the time here. +	std::string time_stamp = vivox_ts.substr(0, 10); +	time_stamp += VOICE_FONT_EXPIRY_TIME; + +	LL_DEBUGS("VivoxProtocolParser") << "Vivox timestamp " << vivox_ts << " modified to: " << time_stamp << LL_ENDL; + +	return LLDate(time_stamp); +} + +// -------------------------------------------------------------------------------- +  void LLVivoxProtocolParser::processResponse(std::string tag)  {  	LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL; @@ -6696,7 +7603,17 @@ void LLVivoxProtocolParser::processResponse(std::string tag)  			 </Event>  			 */  			LLVivoxVoiceClient::getInstance()->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming); -		}		 +		} +		else if (!stricmp(eventTypeCstr, "MediaCompletionEvent")) +		{ +			/* +			<Event type="MediaCompletionEvent"> +			<SessionGroupHandle /> +			<MediaCompletionType>AuxBufferAudioCapture</MediaCompletionType> +			</Event> +			*/ +			LLVivoxVoiceClient::getInstance()->mediaCompletionEvent(sessionGroupHandle, mediaCompletionType); +		}  		else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent"))  		{  			/* @@ -6757,6 +7674,9 @@ void LLVivoxProtocolParser::processResponse(std::string tag)  		}  		else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))  		{ +			// These are really spammy in tuning mode +			squelchDebugOutput = true; +  			LLVivoxVoiceClient::getInstance()->auxAudioPropertiesEvent(energy);  		}  		else if (!stricmp(eventTypeCstr, "BuddyPresenceEvent")) @@ -6871,6 +7791,14 @@ void LLVivoxProtocolParser::processResponse(std::string tag)  			// We don't need to process these, but they're so spammy we don't want to log them.  			squelchDebugOutput = true;  		} +		else if (!stricmp(actionCstr, "Account.GetSessionFonts.1")) +		{ +			LLVivoxVoiceClient::getInstance()->accountGetSessionFontsResponse(statusCode, statusString); +		} +		else if (!stricmp(actionCstr, "Account.GetTemplateFonts.1")) +		{ +			LLVivoxVoiceClient::getInstance()->accountGetTemplateFontsResponse(statusCode, statusString); +		}  		/*  		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))  		 { diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 59fec8b954..f858f8f74e 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -57,15 +57,9 @@ class LLVivoxVoiceClientMuteListObserver;  class LLVivoxVoiceClientFriendsObserver;	 -class LLVivoxVoiceClientParticipantObserver -{ -public: -	virtual ~LLVivoxVoiceClientParticipantObserver() { } -	virtual void onChange() = 0; -}; - - -class LLVivoxVoiceClient: public LLSingleton<LLVivoxVoiceClient>, virtual public LLVoiceModuleInterface +class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>, +							virtual public LLVoiceModuleInterface, +							virtual public LLVoiceEffectInterface  {  	LOG_CLASS(LLVivoxVoiceClient);  public: @@ -84,7 +78,7 @@ public:  	virtual void updateSettings(); // call after loading settings and whenever they change  	// Returns true if vivox has successfully logged in and is not in error state	 -	virtual bool isVoiceWorking(); +	virtual bool isVoiceWorking() const;  	/////////////////////  	/// @name Tuning @@ -232,15 +226,49 @@ public:  	virtual void removeObserver(LLFriendObserver* observer);		  	virtual void addObserver(LLVoiceClientParticipantObserver* observer);  	virtual void removeObserver(LLVoiceClientParticipantObserver* observer); -	 -	 -	  	//@}  	virtual std::string sipURIFromID(const LLUUID &id);  	//@} -				 +	/// @name LLVoiceEffectInterface virtual implementations +	///  @see LLVoiceEffectInterface +	//@{ + +	////////////////////////// +	/// @name Accessors +	//@{ +	virtual bool setVoiceEffect(const LLUUID& id); +	virtual const LLUUID getVoiceEffect(); +	virtual LLSD getVoiceEffectProperties(const LLUUID& id); + +	virtual void refreshVoiceEffectLists(bool clear_lists); +	virtual const voice_effect_list_t& getVoiceEffectList() const; +	virtual const voice_effect_list_t& getVoiceEffectTemplateList() const; +	//@} + +	////////////////////////////// +	/// @name Status notification +	//@{ +	virtual void addObserver(LLVoiceEffectObserver* observer); +	virtual void removeObserver(LLVoiceEffectObserver* observer); +	//@} + +	////////////////////////////// +	/// @name Effect preview buffer +	//@{ +	virtual void enablePreviewBuffer(bool enable); +	virtual void recordPreviewBuffer(); +	virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null); +	virtual void stopPreviewBuffer(); + +	virtual bool isPreviewRecording(); +	virtual bool isPreviewPlaying(); +	//@} + +	//@} + +  protected:  	//////////////////////  	// Vivox Specific definitions	 @@ -278,14 +306,13 @@ protected:  		bool mIsSpeaking;  		bool mIsModeratorMuted;  		bool mOnMuteList;		// true if this avatar is on the user's mute list (and should be muted) -	       bool mVolumeSet;		// true if incoming volume messages should not change the volume +		bool mVolumeSet;		// true if incoming volume messages should not change the volume  		bool mVolumeDirty;		// true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)  		bool mAvatarIDValid;  		bool mIsSelf;  	};  	typedef std::map<const std::string, participantState*> participantMap; -	  	typedef std::map<const LLUUID, participantState*> participantUUIDMap;  	struct sessionState @@ -332,14 +359,17 @@ protected:  		bool		mIncoming;  		bool		mVoiceEnabled;  		bool		mReconnect;	// Whether we should try to reconnect to this session if it's dropped -		// Set to true when the mute state of someone in the participant list changes. + +		// Set to true when the volume/mute state of someone in the participant list changes.  		// The code will have to walk the list to find the changed participant(s).  		bool		mVolumeDirty; -	        bool		mMuteDirty; -		 +		bool		mMuteDirty; +  		bool		mParticipantsChanged;  		participantMap mParticipantsByURI;  		participantUUIDMap mParticipantsByUUID; + +		LLUUID		mVoiceFontID;  	};  	// internal state for a simple state machine.  This is used to deal with the asynchronous nature of some of the messages. @@ -356,6 +386,11 @@ protected:  		stateMicTuningStart,  		stateMicTuningRunning,		  		stateMicTuningStop, +		stateCaptureBufferPaused, +		stateCaptureBufferRecStart, +		stateCaptureBufferRecording, +		stateCaptureBufferPlayStart, +		stateCaptureBufferPlaying,  		stateConnectorStart,		// connector needs to be started  		stateConnectorStarting,		// waiting for connector handle  		stateConnectorStarted,		// connector handle received @@ -364,6 +399,8 @@ protected:  		stateNeedsLogin,			// send login request  		stateLoggingIn,				// waiting for account handle  		stateLoggedIn,				// account handle received +		stateVoiceFontsWait,		// Awaiting the list of voice fonts +		stateVoiceFontsReceived,	// List of voice fonts received  		stateCreatingSessionGroup,	// Creating the main session group  		stateNoChannel,				//   		stateJoiningSession,		// waiting for session handle @@ -436,8 +473,6 @@ protected:  	void tuningCaptureStartSendMessage(int duration);  	void tuningCaptureStopSendMessage(); -	bool inTuningStates(); -  	//----------------------------------  	// devices  	void clearCaptureDevices(); @@ -464,6 +499,7 @@ protected:  	void connectorShutdownResponse(int statusCode, std::string &statusString);  	void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state); +	void mediaCompletionEvent(std::string &sessionGroupHandle, std::string &mediaCompletionType);  	void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);  	void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming);  	void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString); @@ -591,8 +627,8 @@ protected:  	void deleteAllAutoAcceptRules(void);  	void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy);  	void accountListBlockRulesResponse(int statusCode, const std::string &statusString);						 -	void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);						 -	 +	void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString); +  	/////////////////////////////  	// session control messages @@ -621,7 +657,21 @@ protected:  	void lookupName(const LLUUID &id);  	static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);  	void avatarNameResolved(const LLUUID &id, const std::string &name); -		 + +	///////////////////////////// +	// Voice fonts + +	void addVoiceFont(const S32 id, +					  const std::string &name, +					  const std::string &description, +					  const LLDate &expiration_date, +					  bool  has_expired, +					  const S32 font_type, +					  const S32 font_status, +					  const bool template_font = false); +	void accountGetSessionFontsResponse(int statusCode, const std::string &statusString); +	void accountGetTemplateFontsResponse(int statusCode, const std::string &statusString);  +  private:  	LLVoiceVersionInfo mVoiceVersion; @@ -804,6 +854,88 @@ private:  	typedef std::set<LLFriendObserver*> friend_observer_set_t;  	friend_observer_set_t mFriendObservers;  	void notifyFriendObservers(); + +	// Voice Fonts + +	void expireVoiceFonts(); +	void deleteVoiceFont(const LLUUID& id); +	void deleteAllVoiceFonts(); +	void deleteVoiceFontTemplates(); + +	S32 getVoiceFontIndex(const LLUUID& id) const; +	S32 getVoiceFontTemplateIndex(const LLUUID& id) const; + +	void accountGetSessionFontsSendMessage(); +	void accountGetTemplateFontsSendMessage(); +	void sessionSetVoiceFontSendMessage(sessionState *session); + +	void notifyVoiceFontObservers(); + +	typedef enum e_voice_font_type +	{ +		VOICE_FONT_TYPE_NONE = 0, +		VOICE_FONT_TYPE_ROOT = 1, +		VOICE_FONT_TYPE_USER = 2, +		VOICE_FONT_TYPE_UNKNOWN +	} EVoiceFontType; + +	typedef enum e_voice_font_status +	{ +		VOICE_FONT_STATUS_NONE = 0, +		VOICE_FONT_STATUS_FREE = 1, +		VOICE_FONT_STATUS_NOT_FREE = 2, +		VOICE_FONT_STATUS_UNKNOWN +	} EVoiceFontStatus; + +	struct voiceFontEntry +	{ +		voiceFontEntry(LLUUID& id); +		~voiceFontEntry(); + +		LLUUID		mID; +		S32			mFontIndex; +		std::string mName; +		LLDate		mExpirationDate; +		S32			mFontType; +		S32			mFontStatus; +		bool		mIsNew; + +		LLFrameTimer	mExpiryTimer; +		LLFrameTimer	mExpiryWarningTimer; +	}; + +	bool mVoiceFontsReceived; +	bool mVoiceFontsNew; +	bool mVoiceFontListDirty; +	voice_effect_list_t	mVoiceFontList; +	voice_effect_list_t	mVoiceFontTemplateList; + +	typedef std::map<const LLUUID, voiceFontEntry*> voice_font_map_t; +	voice_font_map_t	mVoiceFontMap; +	voice_font_map_t	mVoiceFontTemplateMap; + +	typedef std::set<LLVoiceEffectObserver*> voice_font_observer_set_t; +	voice_font_observer_set_t mVoiceFontObservers; + +	LLFrameTimer	mVoiceFontExpiryTimer; + + +	// Audio capture buffer + +	void captureBufferRecordStartSendMessage(); +	void captureBufferRecordStopSendMessage(); +	void captureBufferPlayStartSendMessage(const LLUUID& voice_font_id = LLUUID::null); +	void captureBufferPlayStopSendMessage(); + +	bool mCaptureBufferMode;		// Disconnected from voice channels while using the capture buffer. +	bool mCaptureBufferRecording;	// A voice sample is being captured. +	bool mCaptureBufferRecorded;	// A voice sample is captured in the buffer ready to play. +	bool mCaptureBufferPlaying;		// A voice sample is being played. + +	LLTimer	mCaptureTimer; +	LLUUID mPreviewVoiceFont; +	LLUUID mPreviewVoiceFontLast; +	S32 mPlayRequestCount;  };  /**  @@ -890,7 +1022,13 @@ protected:  	int				numberOfAliases;  	std::string		subscriptionHandle;  	std::string		subscriptionType; -	 +	S32				id; +	std::string		descriptionString; +	LLDate			expirationDate; +	bool			hasExpired; +	S32				fontType; +	S32				fontStatus; +	std::string		mediaCompletionType;  	// Members for processing text between tags  	std::string		textBuffer; @@ -907,11 +1045,9 @@ protected:  	void			StartTag(const char *tag, const char **attr);  	void			EndTag(const char *tag);  	void			CharData(const char *buffer, int length); -	 +	LLDate			expiryTimeStampToLLDate(const std::string& vivox_ts);  };  #endif //LL_VIVOX_VOICE_CLIENT_H - - diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index db9e0b88e1..d66aa567a8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -926,6 +926,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  	BOOL is404 = FALSE; +#if LL_MESH_ENABLED  	if (isSculpted())  	{  		// if it's a mesh @@ -945,6 +946,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  			}  		}  	} +#endif  	// Check if we need to change implementations  	bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); @@ -989,10 +991,11 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  		updateSculptTexture(); +  		if (isSculpted())  		{  			updateSculptTexture(); - +#if LL_MESH_ENABLED  			// if it's a mesh  			if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)  			{ @@ -1008,6 +1011,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  				}  			}  			else // otherwise is sculptie +#endif  			{  				if (mSculptTexture.notNull())  				{ @@ -2659,12 +2663,13 @@ BOOL LLVOVolume::isMesh() const  	{  		LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);  		U8 sculpt_type = sculpt_params->getSculptType(); - +#if LL_MESH_ENABLED  		if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)  			// mesh is a mesh  		{  			return TRUE;	  		} +#endif  	}  	return FALSE; @@ -3010,6 +3015,7 @@ F32 LLVOVolume::getBinRadius()  	F32 scale = 1.f; +#if LL_MESH_ENABLED  	if (isSculpted())  	{  		LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); @@ -3031,6 +3037,7 @@ F32 LLVOVolume::getBinRadius()  			scale = 1.f/llmax(vert_count/1024.f, 1.f);  		}  	} +#endif  	const LLVector4a* ext = mDrawable->getSpatialExtents(); @@ -3513,9 +3520,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  		drawablep->clearState(LLDrawable::HAS_ALPHA); +#if LL_MESH_ENABLED  		bool rigged = vobj->isAttachment() &&   					vobj->isMesh() &&   					gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID()); +#endif  		bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); @@ -3526,6 +3535,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  			drawablep->updateFaceSize(i);  			LLFace* facep = drawablep->getFace(i); +#if LL_MESH_ENABLED  			if (rigged)   			{  				if (!facep->isState(LLFace::RIGGED)) @@ -3622,6 +3632,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					facep->clearState(LLFace::RIGGED);  				}  			} +#endif  			if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)  			{ diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 6c4774ba5a..6c410cf7a5 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -42,6 +42,7 @@  #include "llmenugl.h" // for LLContextMenu  #include "lltransutil.h"  #include "llviewerattachmenu.h" +#include "llvoavatarself.h"  class LLFindOutfitItems : public LLInventoryCollectFunctor  { @@ -258,6 +259,31 @@ BOOL LLPanelDeletableWearableListItem::postBuild()  } +// static +LLPanelAttachmentListItem* LLPanelAttachmentListItem::create(LLViewerInventoryItem* item) +{ +	LLPanelAttachmentListItem* list_item = NULL; +	if(item) +	{ +		list_item = new LLPanelAttachmentListItem(item); +		list_item->init(); +	} +	return list_item; +} + +void LLPanelAttachmentListItem::setTitle(const std::string& title, const std::string& highlit_text) +{ +	std::string title_joint = title; + +	if (mItem && isAgentAvatarValid() && gAgentAvatarp->isWearingAttachment(mItem->getLinkedUUID())) +	{ +		std::string joint = LLTrans::getString(gAgentAvatarp->getAttachedPointName(mItem->getLinkedUUID())); +		title_joint = title + " (" + joint + ")"; +	} + +	LLPanelDeletableWearableListItem::setTitle(title_joint, highlit_text); +} +  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 2fdb8f0ab8..f03336186c 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -116,6 +116,21 @@ protected:  	/*virtual*/ void init();  }; +/** Outfit list item for an attachment */ +class LLPanelAttachmentListItem : public LLPanelDeletableWearableListItem +{ +	LOG_CLASS(LLPanelAttachmentListItem); +public: +	static LLPanelAttachmentListItem* create(LLViewerInventoryItem* item); +	virtual ~LLPanelAttachmentListItem() {}; + +	/** Set item title. Joint name is added to the title in parenthesis */ +	/*virtual*/ void setTitle(const std::string& title, const std::string& highlit_text); + +protected: +	LLPanelAttachmentListItem(LLViewerInventoryItem* item) : LLPanelDeletableWearableListItem(item) {}; +}; +  /**   * @class LLPanelClothingListItem   * diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 583b3df0e5..c5c7277211 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2025,7 +2025,9 @@ void LLPipeline::rebuildPriorityGroups()  	assertInitialized(); +#if LL_MESH_ENABLED  	gMeshRepo.notifyLoadedMeshes(); +#endif  	// Iterate through all drawables on the priority build queue,  	for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); @@ -3859,6 +3861,7 @@ void LLPipeline::renderDebug()  		gPipeline.mDebugTextureUploadCost = textures.size() * 10;  		gPipeline.mDebugSculptUploadCost = sculpts.size()*10; +#if LL_MESH_ENABLED  		U32 mesh_cost = 0;  		for (std::set<LLUUID>::iterator iter = meshes.begin(); iter != meshes.end(); ++iter) @@ -3867,6 +3870,7 @@ void LLPipeline::renderDebug()  		}  		gPipeline.mDebugMeshUploadCost = mesh_cost; +#endif  	}  	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 4e8760947c..95f951b393 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -45,6 +45,7 @@  #include "llgl.h"  #include "lldrawable.h"  #include "llrendertarget.h" +#include "llmodel.h" //for LL_MESH_ENaBLED  #include <stack> @@ -61,7 +62,10 @@ class LLCullResult;  class LLVOAvatar;  class LLGLSLShader;  class LLCurlRequest; + +#if LL_MESH_ENABLED  class LLMeshResponder; +#endif  typedef enum e_avatar_skinning_method  { @@ -465,7 +469,9 @@ public:  	S32						 mDebugTextureUploadCost;  	S32						 mDebugSculptUploadCost; +#if LL_MESH_ENABLED  	S32						 mDebugMeshUploadCost; +#endif  	S32						 mLightingChanges;  	S32						 mGeometryChanges; @@ -712,13 +718,6 @@ public:  protected:  	std::vector<LLFace*>		mSelectedFaces; - -	typedef std::map<LLUUID, std::set<LLUUID> > mesh_load_map; -	mesh_load_map mLoadingMeshes[4]; -	 -	typedef std::list<LLMeshResponder*> mesh_response_list; -	mesh_response_list			mMeshResponseList; -  	LLPointer<LLViewerFetchedTexture>	mFaceSelectImagep;  	U32						mLightMask; diff --git a/indra/newview/skins/default/textures/avatar_thumb_bkgrnd.png b/indra/newview/skins/default/textures/avatar_thumb_bkgrnd.pngBinary files differ new file mode 100644 index 0000000000..84cc2159c1 --- /dev/null +++ b/indra/newview/skins/default/textures/avatar_thumb_bkgrnd.png diff --git a/indra/newview/skins/default/xui/de/panel_bottomtray.xml b/indra/newview/skins/default/xui/de/panel_bottomtray.xml index d52b8dcf4d..83f67344ca 100644 --- a/indra/newview/skins/default/xui/de/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/de/panel_bottomtray.xml @@ -9,7 +9,7 @@  	<layout_stack name="toolbar_stack">  		<layout_panel name="speak_panel">  			<talk_button name="talk"> -				<speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn" halign="right" /> +				<speak_button label="Sprechen" label_selected="Sprechen" name="speak_btn" />  			</talk_button>  		</layout_panel>  		<layout_panel name="gesture_panel"> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index f537c81860..c9b013099b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -33,7 +33,6 @@        name="panel_im_control_panel"        layout="topleft"        follows="left" -      label="IM Control Panel"        min_width="115"         auto_resize="false"        user_resize="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index f3d297c303..7d81c3e551 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -38,91 +38,129 @@      left="20"      top_pad="-30"      name="new_snapshot_btn" -    width="23" /> +    width="23" +    commit_callback.function="Snapshot.Refresh"/>    <line_editor      border_style="line"      border_thickness="1" -	  follows="left|top" -	  height="20" -		layout="topleft" +    follows="left|top" +    height="20" +    layout="topleft"      left="10" -		max_length="500" +    max_length="500"      name="description" -	  top_pad="15" -	  width="230" +    top_pad="15" +    width="230"      label="Description"/> +  <panel +   top_pad="20" +   left="10" +   height="83" +   name="panel_snapshot_main" +   width="130"> +    <button +     label="Share Snapshot" +     name="share" +     top="0" +     left="0" +     width="130" +     commit_callback.function="Snapshot.ShowButtons" +     commit_callback.parameter="share"/> +    <button +     label="Save Snapshot" +     name="save" +     top_pad="7" +     left_delta="0" +     width="130" +     commit_callback.function="Snapshot.ShowButtons" +     commit_callback.parameter="save"/> +    <button +     label="Set As Profile Pic" +     name="set_profile_pic" +     top_pad="7" +     left_delta="0" +     width="130"/> +  </panel> +  <panel +   top_delta="0" +   left_delta="0" +   height="83" +   name="panel_snapshot_share" +   width="130"> +    <button +     label="Share to Web" +     name="share_to_web" +     top="0" +     left="0" +     visible="false" +     width="130"/> +    <button +     label="Email Snapshot" +     name="share_to_email" +     top_pad="7" +     left_delta="0" +     width="130"/> +    <button +     label="Back" +     name="cancel_share" +     top_pad="7" +     left_delta="0" +     width="130" +     commit_callback.function="Snapshot.ShowButtons" +     commit_callback.parameter="main"/> +  </panel> +  <panel +   top_delta="0" +   left_delta="0" +   height="83" +   name="panel_snapshot_save" +   width="130"> +    <button +     label="Save to My Inventory" +     name="save_to_inventory" +     top="0" +     left="0" +     width="130"/> +    <button +     label="Save to My Computer" +     name="save_to_computer" +     top_pad="7" +     left_delta="0" +     width="130"/> +    <button +     label="Back" +     name="cancel_save" +     top_pad="7" +     left_delta="0" +     width="130" +     commit_callback.function="Snapshot.ShowButtons" +     commit_callback.parameter="main"/> +  </panel>    <button -   label="Share Snapshot"  -   name="share"  -   top_pad="20"  -   left="10"  -   width="130"/> +   follows="left" +   height="22" +   layout="topleft" +   left="210" +   name="show_advanced" +   image_overlay="TabIcon_Close_Off" +   bottom_delta="0" +   width="30" +   commit_callback.function="Snapshot.ShowAdvanced"/>    <button -   label="Share to Web"  -   name="share_to_web"  -   top_delta="0"  -   left="10"  +   follows="left" +   height="22" +   layout="topleft" +   left="210" +   name="hide_advanced" +   image_overlay="TabIcon_Open_Off" +   top_delta="0"     visible="false" -   width="130"/> -  <button -   label="Save to My Inventory"  -   name="save_to_inventory"  -   top_delta="0"  -   left="10"  -   width="130"/> -  <button -   label="Save Snapshot"  -   name="save"  -   top_pad="7"  -   left="10"  -   width="130"/> -  <button -   label="Email Snapshot"  -   name="share_to_email"  -   top_delta="0"  -   left="10"  -   width="130"/> -  <button -   label="Save to My Computer"  -   name="save_to_computer"  -   top_delta="0"  -   left="10"  -   width="130"/> -  <button -   label="Set As Profile Pic"  -   name="set_profile_pic"  -   top_pad="7"  -   left="10"  -   width="130"/> -  <button -   label="Back"  -   name="cancel"  -   top_delta="0"  -   left="10"  -   width="130"/> -  <button -     follows="left" -     height="22" -     layout="topleft" -     left="210" -    name="show_advanced" -    image_overlay="TabIcon_Close_Off" -    top_delta="1" -    width="30"/> -  <button -     follows="left" -     height="22" -     layout="topleft" -     left="210" -     visible="false"  -     name="hide_advanced" -     image_overlay="TabIcon_Open_Off" -     top_delta="0" -     width="30"/> +   width="30" +   commit_callback.function="Snapshot.HideAdvanced"/>    <panel  -    visible="false"  -    left="250"  -    top="17"     -    name="snapshot_advanced"  -    filename="panel_snapshot_advanced.xml"/> +   visible="false" +   left="250" +   top="17" +   name="snapshot_advanced" +   filename="panel_snapshot_advanced.xml"/>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index 5b77f11d71..0569b4d515 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -3,7 +3,7 @@   can_resize="true"   can_minimize="true"   can_close="false" - height="202" + height="205"   layout="topleft"   min_height="124"   min_width="190" @@ -50,7 +50,7 @@            user_resize="false"            auto_resize="false"            layout="topleft" -         height="26" +         height="20"           name="my_panel">              <avatar_icon               enabled="false" @@ -86,23 +86,38 @@               visible="true"               width="20" />          </layout_panel> -         <layout_panel -          auto_resize="false" -          user_resize="false"  -          follows="top|left" -          height="26" -          visible="true" -          layout="topleft" -          name="leave_call_btn_panel" -          width="100"> -           <button -          follows="right|top" -            height="23" -            top_pad="0" -            label="Leave Call" -            name="leave_call_btn" -            width="100" /> -         </layout_panel> +        <layout_stack +         clip="true" +         auto_resize="false" +         follows="left|top|right" +         height="26" +         layout="topleft" +         mouse_opaque="false" +         name="voice_effect_and_leave_call_stack" +         orientation="horizontal" +         width="262"> +          <panel +           class="panel_voice_effect" +           name="panel_voice_effect" +           visiblity_control="VoiceMorphingEnabled" +           filename="panel_voice_effect.xml" /> +          <layout_panel +           auto_resize="false" +           user_resize="false" +           follows="top|right" +           height="23" +           visible="true" +           layout="topleft" +           name="leave_call_btn_panel" +           width="100"> +            <button +             follows="right|top" +             height="23" +             label="Leave Call" +             name="leave_call_btn" +             width="100" /> +          </layout_panel> +        </layout_stack>        <layout_panel            follows="all"            layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml new file mode 100644 index 0000000000..edc25348e4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_effect.xml @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + height="420" + name="voice_effects" + help_topic="voice_effects" + title="PREVIEW VOICE MORPHING" + background_visible="true" + follows="all" + label="Places" + layout="topleft" + min_height="350" + min_width="330" + width="455"> +  <string name="no_voice_effect"> +    (No Voice Morph) +  </string> +  <string name="active_voice_effect"> +    (Active) +  </string> +  <string name="unsubscribed_voice_effect"> +    (Unsubscribed) +  </string> +  <string name="new_voice_effect"> +    (New!) +  </string> +  <text +   height="68" +   word_wrap="true" +   use_ellipses="true" +   type="string" +   follows="left|top|right" +   layout="topleft" +   left="10" +   name="status_text" +   right="-10" +   top="25"> +To preview any of the Voice Morphing effects, click the Record button to record a short snippet of voice, then click any Voice Morph in the list to hear how it will sound. + +To reconnect to Nearby Voice simply close this window. +  </text> +  <button +   follows="left|top" +   height="23" +   label="Record Sample" +   layout="topleft" +   left="10" +   name="record_btn" +   tool_tip="Record a sample of your voice." +   top_pad="5" +   width="150"> +    <button.commit_callback +     function="VoiceEffect.Record" /> +  </button> +  <button +   follows="left|top" +   height="23" +   label="Stop" +   layout="topleft" +   left_delta="0" +   name="record_stop_btn" +   top_delta="0" +   width="150"> +    <button.commit_callback +     function="VoiceEffect.Stop" /> +  </button> +  <text +   height="18" +   halign="right" +   use_ellipses="true" +   type="string" +   follows="left|top|right" +   layout="topleft" +   left_pad="10" +   name="voice_morphing_link" +   right="-10" +   top_delta="5"> +    [[URL] Get Voice Morphing] +  </text> +  <scroll_list +   bottom="-10" +   draw_heading="true" +   follows="all" +   layout="topleft" +   left="10" +   multi_select="false" +   name="voice_effect_list" +   right="-10" +   tool_tip="Record a sample of your voice, then click an effect to preview." +   top="128"> +    <scroll_list.columns +     label="Voice Morph" +     name="name" relative_width="0.41"/> +    <scroll_list.columns +     dynamic_width="true" +     label="Expires" +     name="expires" +	 relative_width="0.59" /> +  </scroll_list> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml index 4e6a07d020..62365f7cc2 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -61,14 +61,6 @@      <menu_item_separator       layout="topleft" />      <menu_item_call -     label="Empty Trash" -     layout="topleft" -     name="empty_trash"> -        <on_click -         function="Inventory.GearDefault.Custom.Action" -         parameter="empty_trash" /> -    </menu_item_call> -    <menu_item_call       label="Empty Lost and Found"       layout="topleft"       name="empty_lostnfound"> @@ -111,4 +103,15 @@  			 function="Inventory.GearDefault.Enable"  			 parameter="find_links" />          </menu_item_call> +    <menu_item_separator +     layout="topleft" /> + +    <menu_item_call +     label="Empty Trash" +     layout="topleft" +     name="empty_trash"> +        <on_click +         function="Inventory.GearDefault.Custom.Action" +         parameter="empty_trash" /> +    </menu_item_call>  </menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0c230d76a2..d512293305 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -80,6 +80,17 @@               function="Floater.Toggle"               parameter="gestures" />          </menu_item_check> +        <menu_item_check +         label="My Voice" +         name="ShowVoice" +         visibility_control="VoiceMorphingEnabled"> +            <menu_item_check.on_check +             function="Floater.Visible" +             parameter="voice_effect" /> +            <menu_item_check.on_click +             function="Floater.Toggle" +             parameter="voice_effect" /> +        </menu_item_check>          <menu           label="My Status"           name="Status" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 8a599370ce..68a929adc4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6004,6 +6004,50 @@ We are creating a voice channel for you. This may take up to one minute.    </notification>    <notification +   icon="notify.tga" +   name="VoiceEffectsExpired" +   sound="UISndAlert" +   persist="true" +   type="notify"> +One or more of your subscribed Voice Morphs has expired. +[[URL] Click here] to renew your subscription. +    <unique/> +  </notification> + +  <notification +   icon="notify.tga" +   name="VoiceEffectsExpiredInUse" +   sound="UISndAlert" +   persist="true" +   type="notify"> +The active Voice Morph has expired, your normal voice settings have been applied. +[[URL] Click here] to renew your subscription. +    <unique/> +  </notification> + +  <notification +   icon="notify.tga" +   name="VoiceEffectsWillExpire" +   sound="UISndAlert" +   persist="true" +   type="notify"> +One or more of your Voice Morphs will expire in less than [INTERVAL] days. +[[URL] Click here] to renew your subscription. +    <unique/> +  </notification> +		LLNotificationsUtil::add("VoiceEffectsNew"); + +  <notification +   icon="notify.tga" +   name="VoiceEffectsNew" +   sound="UISndAlert" +   persist="true" +   type="notify"> +New Voice Morphs are available! +    <unique/> +  </notification> + +  <notification     icon="notifytip.tga"     name="Cannot enter parcel: not a group member"     type="notifytip"> @@ -6279,36 +6323,39 @@ Avatar '[NAME]' entered appearance mode.  Avatar '[NAME]' left appearance mode.    </notification> -    <notification +  <notification     icon="alertmodal.tga"     name="NoConnect"     type="alertmodal"> -        We're having trouble connecting using [PROTOCOL] [HOSTID]. -        Please check your network and firewall setup. -        <form name="form"> -            <button -               default="true" -               index="0" -               name="OK" -               text="OK"/> -        </form> -    </notification> +We're having trouble connecting using [PROTOCOL] [HOSTID]. +Please check your network and firewall setup. +    <form name="form"> +      <button +       default="true" +       index="0" +       name="OK" +       text="OK"/> +    </form> +  </notification> -    <notification -          icon="alertmodal.tga" -          name="NoVoiceConnect" -          type="alertmodal"> -        We're having trouble connecting your voiceserver using [HOSTID]. -        Voice communications will not be available. -        Please check your network and firewall setup. -        <form name="form"> -            <button -               default="true" -               index="0" -               name="OK" -               text="OK"/> -        </form> -    </notification> +  <notification +   icon="alertmodal.tga" +   name="NoVoiceConnect" +   type="alertmodal"> +We're having trouble connecting to your voice server: + +[HOSTID] + +Voice communications will not be available. +Please check your network and firewall setup. +    <form name="form"> +      <button +       default="true" +       index="0" +       name="OK" +       text="OK"/> +    </form> +  </notification>    <notification     icon="notifytip.tga" @@ -6336,7 +6383,7 @@ Are you sure you want to leave this call?       name="okcancelignore"       notext="No"       yestext="Yes"/> -     <unique/> +    <unique/>    </notification>    <notification @@ -6353,7 +6400,7 @@ Mute everyone?       name="okcancelignore"       yestext="Ok"       notext="Cancel"/> -     <unique/> +    <unique/>    </notification>    <global name="UnsupportedCPU">  - Your CPU speed does not meet the minimum requirements. diff --git a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml index a0bbc8f2ee..4e5f594ffe 100644 --- a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   follows="top|right|left" - height="25" + height="23"   layout="topleft"   left="0"   name="wearable_item" @@ -45,7 +45,7 @@       use_ellipses="true"       name="item_name"       text_color="white" -     top="4" +     top="5"       value="..."       width="359" />      <panel @@ -74,10 +74,10 @@       name="btn_edit_panel"       layout="topleft"       follows="top|right" -     top="0" +     top="1"       left_pad="3" -     height="24" -     width="27" +     height="23" +     width="26"       tab_stop="false">           <button             name="btn_edit" @@ -86,8 +86,8 @@            image_overlay="Edit_Wrench"            top="0"            left="0" -          height="24" -          width="24" +          height="23" +          width="23"            tab_stop="false" />        </panel>      <icon @@ -97,7 +97,7 @@       layout="bottomleft"       left="0"       name="wearable_type_separator_icon" -     top="3" +     top="0"       visible="true"       width="380"/>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 82b2405ec9..4eff5bc48a 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -90,7 +90,7 @@                   label="Speak"                   label_selected="Speak"                   name="speak_btn" -                 pad_right="22" +                 pad_right="20"                   tab_stop="true"                   use_ellipses="true" />              </talk_button> diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml index e41141f6bd..5d81aebbd5 100644 --- a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml @@ -33,7 +33,7 @@       follows="top|left"       image_unselected="Toast_CloseBtn"       image_selected="Toast_CloseBtn" -     top="2" +     top="3"       left="0"       height="18"       width="18" @@ -56,7 +56,7 @@       use_ellipses="true"       name="item_name"       text_color="white" -     top="4" +     top="5"       value="..."       width="359" />      <button  @@ -64,20 +64,20 @@       layout="topleft"       follows="top|right"       image_overlay="UpArrow_Off" -     top="0" +     top="1"       left="0" -     height="24" -     width="24" +     height="23" +     width="23"       tab_stop="false" />      <button        name="btn_move_down"       layout="topleft"       follows="top|right"       image_overlay="DownArrow_Off" -     top="0" +     top="1"       left_pad="3" -     height="24" -     width="24" +     height="23" +     width="23"       tab_stop="false" />      <panel       background_visible="false" @@ -107,18 +107,18 @@       follows="top|right"       top="0"       left_pad="3" -     height="24" -     width="27" +     height="23" +     width="26"       tab_stop="false">          <button            name="btn_edit"           layout="topleft"           follows="top|right"           image_overlay="Edit_Wrench" -         top="0" +         top="1"           left="0" -         height="24" -         width="24" +         height="23" +         width="23"           tab_stop="false" />        </panel>      <icon diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 5f34c24bca..d36c2a4e6f 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -11,7 +11,7 @@      <accordion       fit_parent="true"       follows="all" -     height="200" +     height="198"       layout="topleft"       left="0"       single_expansion="true" @@ -28,6 +28,7 @@               allow_select="true"               follows="all"               height="10" +             item_pad="2"               layout="topleft"               left="0"               multi_select="true" @@ -43,6 +44,7 @@               allow_select="true"               follows="all"               height="10" +             item_pad="2"               layout="topleft"               left="0"               multi_select="true" @@ -58,6 +60,7 @@               allow_select="true"               follows="all"               height="10" +             item_pad="2"               layout="topleft"               left="0"               multi_select="true" diff --git a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml index b006d125ee..45031859f1 100644 --- a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   follows="top|right|left" - height="25" + height="23"   layout="topleft"   left="0"   name="deletable_wearable_item" @@ -33,7 +33,7 @@       follows="top|left"       image_unselected="Toast_CloseBtn"       image_selected="Toast_CloseBtn" -     top="2" +     top="3"       left="0"       height="18"       width="18" @@ -56,7 +56,7 @@       use_ellipses="true"       name="item_name"       text_color="white" -     top="4" +     top="5"       value="..."       width="359" />      <icon @@ -66,7 +66,7 @@       layout="bottomleft"       left="0"       name="wearable_type_separator_icon" -     top="3" +     top="0"       visible="true"       width="380"/>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml index 6c43635d49..20652df918 100644 --- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <panel   follows="top|right|left" - height="25" + height="23"   layout="topleft"   left="0"   name="dummy_clothing_item" @@ -56,8 +56,8 @@       image_overlay="AddItem_Off"       top="0"       left="0" -     height="24" -     width="24" +     height="23" +     width="23"       tab_stop="false" />      <icon       follows="left|right|top" @@ -66,7 +66,7 @@       layout="bottomleft"       left="0"       name="wearable_type_separator_icon" -     top="3" +     top="0"       visible="true"       width="380"/>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 67ff71cef1..645ee8a435 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -7,6 +7,7 @@   label="Wearable"   layout="topleft"  left="0" + help_topic="edit_wearable"   name="panel_edit_wearable"  	top="0"   width="333"> @@ -235,7 +236,7 @@ left="0"  	 </panel>  	 <panel  		 follows="all" -		 height="408" +		 height="433"  		 layout="topleft"  		 left="0"  		 name="edit_subpanel_container" @@ -246,7 +247,7 @@ left="0"  		 <panel  			 filename="panel_edit_shape.xml"  			 follows="all" -			 height="408" +			 height="433"  			 layout="topleft"  			 left="0"  			 name="edit_shape_panel" @@ -256,7 +257,7 @@ left="0"  		 <panel  			 filename="panel_edit_skin.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_skin_panel" @@ -266,7 +267,7 @@ left="0"  		 <panel  			 filename="panel_edit_hair.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_hair_panel" @@ -276,7 +277,7 @@ left="0"  		 <panel  			 filename="panel_edit_eyes.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_eyes_panel" @@ -286,7 +287,7 @@ left="0"  		 <panel  			 filename="panel_edit_shirt.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_shirt_panel" @@ -296,7 +297,7 @@ left="0"  		 <panel  			 filename="panel_edit_pants.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_pants_panel" @@ -306,7 +307,7 @@ left="0"  		 <panel  			 filename="panel_edit_shoes.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_shoes_panel" @@ -316,7 +317,7 @@ left="0"  		 <panel  			 filename="panel_edit_socks.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_socks_panel" @@ -326,7 +327,7 @@ left="0"  		 <panel  			 filename="panel_edit_jacket.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_jacket_panel" @@ -336,7 +337,7 @@ left="0"  		 <panel  			 filename="panel_edit_skirt.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_skirt_panel" @@ -346,7 +347,7 @@ left="0"  		 <panel  			 filename="panel_edit_gloves.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_gloves_panel" @@ -356,7 +357,7 @@ left="0"  		 <panel  			 filename="panel_edit_undershirt.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_undershirt_panel" @@ -366,7 +367,7 @@ left="0"  		 <panel  			 filename="panel_edit_underpants.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_underpants_panel" @@ -376,7 +377,7 @@ left="0"  		 <panel  			 filename="panel_edit_alpha.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_alpha_panel" @@ -386,7 +387,7 @@ left="0"  		 <panel  			 filename="panel_edit_tattoo.xml"  			 follows="all" -			 height="400" +			 height="425"  			 layout="topleft"  			 left="0"  			 name="edit_tattoo_panel" @@ -394,65 +395,7 @@ left="0"  			 visible="false"  			 width="333" />  	 </panel> -     <panel -        follows="bottom|left|right" -        height="25" -        label="gear_buttom_panel" -        layout="topleft" -        left="0" -        name="gear_buttom_panel" -        top_pad="0" -        width="333"> -        <button -            follows="bottom|left" -            tool_tip="Options" -            height="25" -            image_hover_unselected="Toolbar_Left_Over" -            image_disabled="OptionsMenu_Disabled" -            image_overlay="OptionsMenu_Off" -            image_selected="Toolbar_Left_Selected" -            image_unselected="Toolbar_Left_Off" -            layout="topleft" -            left="10" -            name="friends_viewsort_btn" -            top="0" -            width="31" /> -        <button -            follows="bottom|left" -            height="25" -            image_hover_unselected="Toolbar_Middle_Over" -            image_overlay="AddItem_Off" -            image_selected="Toolbar_Middle_Selected" -            image_unselected="Toolbar_Middle_Off" -            image_disabled="AddItem_Disabled" -            layout="topleft" -            left_pad="1" -            name="add_btn" -            tool_tip="TODO" -            width="31" /> -        <icon -            follows="bottom|left|right" -            height="25" -            image_name="Toolbar_Middle_Off" -            layout="topleft" -            left_pad="1" -            name="dummy_right_icon" -            width="218" > -        </icon> -        <button -            follows="bottom|right" -            height="25" -            image_hover_unselected="Toolbar_Right_Over" -            image_overlay="TrashItem_Off" -            image_selected="Toolbar_Right_Selected" -            image_unselected="Toolbar_Right_Off" -            image_disabled="TrashItem_Disabled" -            layout="topleft" -            left_pad="1" -            name="del_btn" -            tool_tip="TODO" -            width="31" /> -     </panel> +  	 <panel  		 follows="bottom|left|right"  		 height="23" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 769f9b7bbf..c9802a269c 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -5,8 +5,8 @@   border="false"   height="600"   follows="all" - label="Outfit Edit"   layout="topleft" + help_topic="edit_outfit"   left="0"   min_height="350"   name="outfit_edit" @@ -85,7 +85,6 @@       bevel_style="none"       follows="top|left|right"       height="40" -     label="bottom_panel"       layout="topleft"       left="6"       name="header_panel" @@ -106,7 +105,6 @@               bevel_style="none"               follows="top|right"               height="38" -             label="bottom_panel"               layout="topleft"               left_pad="5"               name="outfit_name_and_status" @@ -160,7 +158,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap          <layout_panel           layout="topleft"           height="187" -         label="IM Control Panel"           min_height="100"           name="outfit_wearables_panel"           width="313" @@ -183,7 +180,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap                   bg_alpha_color="DkGray2"                   layout="topleft"                   height="154" -                 label="add_button_and_combobox"                   name="add_button_and_combobox"                   width="311"                   user_resize="false" @@ -256,15 +252,14 @@ It is calculated as border_size + 2*UIResizeBarOverlap  		             background_image="TextField_Search_Off"  		             enabled="true"  		             follows="left|right|top" -		             font="SansSerif" -		             label="Filter" +		             label="Filter Inventory Wearables"  		             layout="topleft"  		             left="5"  		             width="290"  		             height="25"  		             name="look_item_filter" +		             search_button_visible="true"  		             text_color="black" -		             text_pad_left="25"  		             visible="true"/>                  </layout_panel> @@ -344,7 +339,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap       bevel_style="none"       follows="bottom|left|right"       height="27" -     label="bottom_panel"       layout="topleft"       left="5"       name="no_add_wearables_button_bar" @@ -379,7 +373,6 @@ It is calculated as border_size + 2*UIResizeBarOverlap       bevel_style="none"       follows="left|right|bottom"       height="27" -     label="add_wearables_button_bar"       layout="topleft"       left="5"       name="add_wearables_button_bar" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 13e1f5ba5c..de1f2cf31b 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -30,6 +30,7 @@             height="490"             name="outfitslist_tab"             background_visible="true" +           help_topic="my_outfits_tab"             follows="all"             label="MY OUTFITS"             layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_list.xml b/indra/newview/skins/default/xui/en/panel_outfits_list.xml index 5cf94c25d7..5c9ae51a48 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_list.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_list.xml @@ -14,6 +14,7 @@       background_visible="true"       bg_alpha_color="DkGray2"       bg_opaque_color="DkGray2" +     empty_accordion_text.value="Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]."       follows="all"       height="400"       layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index b79ef1e287..da28773c74 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -173,6 +173,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M         		 background_visible="true"         		 bg_alpha_color="DkGray2"         		 bg_opaque_color="DkGray2" +             empty_accordion_text.value=""               follows="all"               height="356"               layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index c9e41edd5a..59f1f6d638 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -2,7 +2,7 @@  <panel   background_visible="true"   follows="all" - height="570" + height="610"   layout="topleft"   left="0"   min_height="350" @@ -181,7 +181,7 @@      <scroll_container       color="DkGray2"       follows="all" -     height="532" +     height="572"       layout="topleft"       left="9"       name="place_scroll" @@ -191,7 +191,7 @@          <panel           bg_alpha_color="DkGray2"           follows="left|top|right" -         height="540" +         height="580"           layout="topleft"           left="0"           min_height="300" @@ -337,21 +337,22 @@              <accordion               fit_parent="true"               follows="all" -             height="223" +             height="268"               layout="topleft"               single_expansion="true"               left="0"               name="advanced_info_accordion" -             top_pad="10" +             top_pad="5"               width="313">                  <accordion_tab -                 height="170" +                 fit_panel="false" +                 height="175"                   layout="topleft"                   name="parcel_characteristics_tab"                   title="Parcel">                      <panel                       follows="all" -                     height="160" +                     height="175"                       layout="topleft"                       left="0"                       name="parcel_characteristics_panel" @@ -548,8 +549,8 @@                           name="about_land_btn"                           right="-5"                           tab_stop="false" -                         top="138" -                         width="90"> +                         top_pad="2" +                         width="140">                              <click_callback                               function="Floater.Show"                               parameter="about_land" /> @@ -558,7 +559,8 @@                  </accordion_tab>                  <accordion_tab                   expanded="false" -                 height="150" +                 fit_panel="false" +                 height="125"                   layout="topleft"                   name="region_information_tab"                   title="Region"> @@ -677,7 +679,8 @@                           name="region_info_btn"                           right="-5"                           tab_stop="false" -                         width="105"> +                         top_pad="2" +                         width="180">                              <click_callback                               function="Floater.Show"                               parameter="region_info" /> @@ -686,13 +689,14 @@                  </accordion_tab>                  <accordion_tab                   expanded="false" -                 height="190" +                 fit_panel="false" +                 height="180"                   layout="topleft"                   name="estate_information_tab"                   title="Estate">                      <panel                       follows="all" -                     height="189" +                     height="180"                       layout="topleft"                       left="0"                       name="estate_information_panel" @@ -775,13 +779,14 @@                  </accordion_tab>                  <accordion_tab                   expanded="false" -                 height="320" +                 fit_panel="false" +                 height="290"                   layout="topleft"                   name="sales_tab"                   title="For Sale">                      <panel                       follows="all" -                     height="300" +                     height="290"                       layout="topleft"                       left="0"                       name="sales_panel" diff --git a/indra/newview/skins/default/xui/en/panel_voice_effect.xml b/indra/newview/skins/default/xui/en/panel_voice_effect.xml new file mode 100644 index 0000000000..c575ca468c --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_voice_effect.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="all" + height="26" + layout="topleft" + name="panel_voice_effect" + width="200"> +  <string name="no_voice_effect"> +    No Voice Morph +  </string> +  <string name="preview_voice_effects"> +    Preview Voice Morphing  ▶ +  </string> +  <string name="get_voice_effects"> +    Get Voice Morphing  ▶ +  </string> +  <combo_box +   enabled="false" +   follows="left|top|right" +   height="23" +   name="voice_effect" +   tool_tip="Select a Voice Morphing effect to change your voice." +   top_pad="0" +   width="200"> +    <combo_box.item +     label="No Voice Morph" +     name="no_voice_effect" +	 top_pad="0" +     value="0" /> +    <combo_box.commit_callback +     function="Voice.CommitVoiceEffect" /> +  </combo_box> +</panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index 3d7b0b7edc..ae08a13793 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -111,6 +111,7 @@ width="333">     label="Filter Outfits"     max_length="300"     name="Filter" +   search_button_visible="true"     top_pad="10"     width="303" />     <panel diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9dcb295ff5..d73f11c4e0 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3094,6 +3094,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  		The session initialization is timed out  	</string> +  <string name="voice_morphing_url">http://secondlife.com/landing/voicemorphing</string> +    <!-- Financial operations strings -->    <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT]</string>    <string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion.xml b/indra/newview/skins/default/xui/en/widgets/accordion.xml new file mode 100644 index 0000000000..b817ba56ca --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/accordion.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<accordion + height="100" + name="accordion" + width="200"> +    <empty_accordion_text +     follows="all" +     height="100" +     h_pad="10" +     name="no_visible_items_msg" +     value="There are no visible content here." +     v_pad="15" +     width="200" +     wrap="true "/> +</accordion> diff --git a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml index dfd301a770..48b987d7e8 100644 --- a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml +++ b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml @@ -4,5 +4,6 @@                name="color_swatch">    <color_swatch.caption_text name="caption"                               halign="center" -                             follows="left|right|bottom"/> +                             follows="left|right|bottom" +                             v_pad="2"/>  </color_swatch> diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml index 33c3475eb2..757f0f49d1 100644 --- a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml +++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml @@ -3,7 +3,8 @@    <multiselect_text font="SansSerifSmall"/>    <caption_text text="Multiple"                   halign="center"  -                font="SansSerifSmall"/> +                font="SansSerifSmall" +                v_pad="2"/>    <border bevel_style="in"/>  </texture_picker> diff --git a/indra/newview/skins/default/xui/ja/menu_bottomtray.xml b/indra/newview/skins/default/xui/ja/menu_bottomtray.xml index 0e69671f06..e5703c559b 100644 --- a/indra/newview/skins/default/xui/ja/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/ja/menu_bottomtray.xml @@ -4,11 +4,11 @@  	<menu_item_check label="移動ボタン" name="ShowMoveButton"/>  	<menu_item_check label="視界ボタン" name="ShowCameraButton"/>  	<menu_item_check label="スナップショットボタン" name="ShowSnapshotButton"/> -	<menu_item_check label="サイドバーのボタン" name="ShowSidebarButton"/> -	<menu_item_check label="制作のボタン" name="ShowBuildButton"/> -	<menu_item_check label="検索のボタン" name="ShowSearchButton"/> -	<menu_item_check label="地図のボタン" name="ShowWorldMapButton"/> -	<menu_item_check label="ミニマップのボタン" name="ShowMiniMapButton"/> +	<menu_item_check label="サイドバーボタン" name="ShowSidebarButton"/> +	<menu_item_check label="制作ボタン" name="ShowBuildButton"/> +	<menu_item_check label="検索ボタン" name="ShowSearchButton"/> +	<menu_item_check label="地図ボタン" name="ShowWorldMapButton"/> +	<menu_item_check label="ミニマップボタン" name="ShowMiniMapButton"/>  	<menu_item_call label="切り取り" name="NearbyChatBar_Cut"/>  	<menu_item_call label="コピー" name="NearbyChatBar_Copy"/>  	<menu_item_call label="貼り付け" name="NearbyChatBar_Paste"/> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 1ac7677b07..c82f1198a4 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -349,7 +349,7 @@ L$ が不足しているのでこのグループに参加することができ  		<usetemplate name="okcancelbuttons" notext="もう一度試す" yestext="新しいアカウントを作成"/>  	</notification>  	<notification name="InvalidCredentialFormat"> -		「ユーザー名」欄にアバターのファーストネームとラストネーム両方を入力してからログインしてください。 +		「ユーザーネーム」欄にアバターのファーストネームとラストネーム両方を入力してからログインしてください。  	</notification>  	<notification name="AddClassified">  		クラシファイド広告は、検索ディレクトリと [http://secondlife.com/community/classifieds secondlife.com] の「クラシファイド広告」セクションに一週間掲載されます。 diff --git a/indra/newview/skins/default/xui/ja/panel_login.xml b/indra/newview/skins/default/xui/ja/panel_login.xml index f0ebc67ef5..47d7a88b4c 100644 --- a/indra/newview/skins/default/xui/ja/panel_login.xml +++ b/indra/newview/skins/default/xui/ja/panel_login.xml @@ -9,9 +9,9 @@  	<layout_stack name="login_widgets">  		<layout_panel name="login">  			<text name="username_text"> -				ユーザー名: +				ユーザーネーム:  			</text> -			<line_editor label="ユーザー名" name="username_edit" tool_tip="[SECOND_LIFE] ユーザー名"/> +			<line_editor label="ユーザーネーム" name="username_edit" tool_tip="[SECOND_LIFE] ユーザーネーム"/>  			<text name="password_text">  				パスワード:  			</text> diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 7671f58691..4044110b47 100644 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -26,9 +26,9 @@ Placa gráfica: [GRAPHICS_CARD]  Versão libcurl: [LIBCURL_VERSION]  Versão J2C Decoder: [J2C_VERSION] -Versão do driver de áudio: [AUDIO_DRIVER_VERSION]  +Versão do driver de áudio: [AUDIO_DRIVER_VERSION]  Versão Qt Webkit: [QT_WEBKIT_VERSION] -Versão Vivox: [VIVOX_VERSION] +Versão do servidor de voz: [VOICE_VERSION]  	</floater.string>  	<floater.string name="none">  		(nenhum) diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml index 787836a8bd..56ffcbdece 100644 --- a/indra/newview/skins/default/xui/pt/floater_about_land.xml +++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml @@ -63,6 +63,9 @@  				Nenhum lote selecionado.  Vá para o menu Mundo > Sobre o terreno ou selecione outro lote para mostrar os detalhes.  			</panel.string> +			<panel.string name="time_stamp_template"> +				[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] +			</panel.string>  			<text name="Name:">  				Nome:  			</text> diff --git a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml index 5fb64f64b3..9473ee7ce9 100644 --- a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml @@ -3,41 +3,48 @@  	<floater.string name="InvalidAvatar">  		AVATAR INVÁLIDO  	</floater.string> -	<text name="composite_label"> -		Texturas compostas -	</text> -	<button label="Tombar" label_selected="Tombar" name="Dump"/>  	<scroll_container name="profile_scroll">  		<panel name="scroll_content_panel"> -			<texture_picker label="Cabelo" name="hair-baked"/> -			<texture_picker label="Cabelo" name="hair_grain"/> -			<texture_picker label="Cabelo alpha" name="hair_alpha"/> -			<texture_picker label="Cabeça" name="head-baked"/> -			<texture_picker label="Maquilagem" name="head_bodypaint"/> -			<texture_picker label="Cabeça Alpha" name="head_alpha"/> -			<texture_picker label="Tatuagem na cabeça" name="head_tattoo"/> -			<texture_picker label="Olhos" name="eyes-baked"/> -			<texture_picker label="Olho" name="eyes_iris"/> -			<texture_picker label="Olhos Alpha" name="eyes_alpha"/> -			<texture_picker label="Cintura acima" name="upper-baked"/> -			<texture_picker label="Pintura corporal, cintura para cima" name="upper_bodypaint"/> -			<texture_picker label="Camiseta" name="upper_undershirt"/> -			<texture_picker label="Luvas" name="upper_gloves"/> -			<texture_picker label="Camisa" name="upper_shirt"/> -			<texture_picker label="Jaqueta (cima)" name="upper_jacket"/> -			<texture_picker label="Alpha de cima" name="upper_alpha"/> -			<texture_picker label="Tatuagem parte de cima" name="upper_tattoo"/> -			<texture_picker label="Cintura para baixo" name="lower-baked"/> -			<texture_picker label="Pintura corporal, cintura para baixo" name="lower_bodypaint"/> -			<texture_picker label="Roupa de baixo" name="lower_underpants"/> -			<texture_picker label="Meias" name="lower_socks"/> -			<texture_picker label="Sapatos" name="lower_shoes"/> -			<texture_picker label="Calças" name="lower_pants"/> -			<texture_picker label="Jaqueta" name="lower_jacket"/> -			<texture_picker label="Alpha inferior" name="lower_alpha"/> -			<texture_picker label="Tatuagem de baixo" name="lower_tattoo"/> -			<texture_picker label="Saia" name="skirt-baked"/> -			<texture_picker label="Saia" name="skirt"/> +			<text name="label"> +				Pronto +Texturas +			</text> +			<text name="composite_label"> +				Compósito: +Texturas +			</text> +			<button label="Enviar IDs para painel" label_selected="Dump" name="Dump"/> +			<panel name="scroll_content_panel"> +				<texture_picker label="Cabelo" name="hair-baked"/> +				<texture_picker label="Cabelo" name="hair_grain"/> +				<texture_picker label="Cabelo alpha" name="hair_alpha"/> +				<texture_picker label="Cabeça" name="head-baked"/> +				<texture_picker label="Maquilagem" name="head_bodypaint"/> +				<texture_picker label="Cabeça Alpha" name="head_alpha"/> +				<texture_picker label="Tatuagem na cabeça" name="head_tattoo"/> +				<texture_picker label="Olhos" name="eyes-baked"/> +				<texture_picker label="Olho" name="eyes_iris"/> +				<texture_picker label="Olhos Alpha" name="eyes_alpha"/> +				<texture_picker label="Cintura acima" name="upper-baked"/> +				<texture_picker label="Pintura corporal, cintura para cima" name="upper_bodypaint"/> +				<texture_picker label="Camiseta" name="upper_undershirt"/> +				<texture_picker label="Luvas" name="upper_gloves"/> +				<texture_picker label="Camisa" name="upper_shirt"/> +				<texture_picker label="Jaqueta (cima)" name="upper_jacket"/> +				<texture_picker label="Alpha de cima" name="upper_alpha"/> +				<texture_picker label="Tatuagem parte de cima" name="upper_tattoo"/> +				<texture_picker label="Cintura para baixo" name="lower-baked"/> +				<texture_picker label="Cintura para baixo" name="lower_bodypaint"/> +				<texture_picker label="Roupa de baixo" name="lower_underpants"/> +				<texture_picker label="Meias" name="lower_socks"/> +				<texture_picker label="Sapatos" name="lower_shoes"/> +				<texture_picker label="Calças" name="lower_pants"/> +				<texture_picker label="Jaqueta" name="lower_jacket"/> +				<texture_picker label="Alpha inferior" name="lower_alpha"/> +				<texture_picker label="Tatuagem de baixo" name="lower_tattoo"/> +				<texture_picker label="Saia" name="skirt-baked"/> +				<texture_picker label="Saia" name="skirt"/> +			</panel>  		</panel>  	</scroll_container>  </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency_html.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency_html.xml new file mode 100644 index 0000000000..24e41ac8c8 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/floater_buy_currency_html.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_buy_currency_html" title="COMPRAR MOEDA"/> diff --git a/indra/newview/skins/default/xui/pt/floater_map.xml b/indra/newview/skins/default/xui/pt/floater_map.xml index 3a04528228..f8e4e76752 100644 --- a/indra/newview/skins/default/xui/pt/floater_map.xml +++ b/indra/newview/skins/default/xui/pt/floater_map.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Map" title="Mini Mapa"> +<floater name="Map" title="">  	<floater.string name="mini_map_north">  		N  	</floater.string> diff --git a/indra/newview/skins/default/xui/pt/floater_moveview.xml b/indra/newview/skins/default/xui/pt/floater_moveview.xml index 9c02570076..b1dc65e3af 100644 --- a/indra/newview/skins/default/xui/pt/floater_moveview.xml +++ b/indra/newview/skins/default/xui/pt/floater_moveview.xml @@ -6,18 +6,48 @@  	<string name="walk_back_tooltip">  		Andar para trás (flecha para baixo ou S)  	</string> +	<string name="walk_left_tooltip"> +		Andar para a esquerda (Shift + Seta esquerda ou A) +	</string> +	<string name="walk_right_tooltip"> +		Andar para a direita (Shift + Seta direita ou D) +	</string>  	<string name="run_forward_tooltip">  		Correr para frente (flecha para cima ou W)  	</string>  	<string name="run_back_tooltip">  		Correr para trás (flecha para baixo ou S)  	</string> +	<string name="run_left_tooltip"> +		Correr para a esquerda (Shift + Seta esquerda ou A) +	</string> +	<string name="run_right_tooltip"> +		Correr para a direita (Shift + Seta direita ou D) +	</string>  	<string name="fly_forward_tooltip">  		Voar para frente (flecha para cima ou W)  	</string>  	<string name="fly_back_tooltip">  		Voar para trás (flecha para baixo ou S)  	</string> +	<string name="fly_left_tooltip"> +		Voar para a esquerda (Shift + Seta esquerda ou A) +	</string> +	<string name="fly_right_tooltip"> +		Voar para a direita (Shift + Seta direita ou D) +	</string> +	<string name="fly_up_tooltip"> +		Voar para cima (tecla E) +	</string> +	<string name="fly_down_tooltip"> +		Voar para baixo (tecla C) +	</string> +	<string name="jump_tooltip"> +		Pular (tecla E) +	</string> +	<string name="crouch_tooltip"> +		Agachar (tecla C) +	</string>  	<string name="walk_title">  		Andar  	</string> @@ -28,10 +58,12 @@  		Voar  	</string>  	<panel name="panel_actions"> -		<button label="" label_selected="" name="turn left btn" tool_tip="Virar à esquerda (flecha ESQ ou A)"/> -		<button label="" label_selected="" name="turn right btn" tool_tip="Virar à direita (flecha DIR ou D)"/>  		<button label="" label_selected="" name="move up btn" tool_tip="Voar para cima (tecla E)"/> +		<button label="" label_selected="" name="turn left btn" tool_tip="Virar à esquerda (flecha ESQ ou A)"/> +		<joystick_slide name="move left btn" tool_tip="Andar para a esquerda (Shift + Seta esquerda ou A)"/>  		<button label="" label_selected="" name="move down btn" tool_tip="Voar para baixo (tecla C)"/> +		<button label="" label_selected="" name="turn right btn" tool_tip="Virar à direita (flecha DIR ou D)"/> +		<joystick_slide name="move right btn" tool_tip="Andar para a direita (Shift + Seta direita ou D)"/>  		<joystick_turn name="forward btn" tool_tip="Andar para frente (flecha para cima ou W)"/>  		<joystick_turn name="backward btn" tool_tip="Andar para trás (flecha para baixo ou S)"/>  	</panel> diff --git a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml index e648a7d873..d094c1b63a 100644 --- a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml @@ -9,9 +9,6 @@  	<floater.string name="Title">  		Anotação: [NAME]  	</floater.string> -	<floater.string label="Salvar" label_selected="Salvar" name="Save"> -		Salvar -	</floater.string>  	<text name="desc txt">  		Descrição:  	</text> @@ -19,4 +16,5 @@  		Carregando...  	</text_editor>  	<button label="Salvar" label_selected="Salvar" name="Save"/> +	<button label="Excluir" label_selected="Excluir" name="Delete"/>  </floater> diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml index 74b45f1d1e..dbc8b3ffbe 100644 --- a/indra/newview/skins/default/xui/pt/floater_tools.xml +++ b/indra/newview/skins/default/xui/pt/floater_tools.xml @@ -67,9 +67,9 @@  	<text name="RenderingCost" tool_tip="Mostra o cálculo do custo de renderização do objeto">  		þ: [COUNT]  	</text> -	<check_box name="checkbox uniform"/> -	<text name="checkbox uniform label"> -		Esticar ambos os lados +	<check_box label="" name="checkbox uniform"/> +	<text label="Esticar ambos lados" name="checkbox uniform label"> +		Esticar ambos lados  	</text>  	<check_box initial_value="true" label="Esticar texturas" name="checkbox stretch textures"/>  	<check_box initial_value="true" label="Mostrar na grade" name="checkbox snap to grid"/> diff --git a/indra/newview/skins/default/xui/pt/menu_attachment_self.xml b/indra/newview/skins/default/xui/pt/menu_attachment_self.xml index de3178b946..5cb1b211cf 100644 --- a/indra/newview/skins/default/xui/pt/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_attachment_self.xml @@ -5,7 +5,7 @@  	<menu_item_call label="Tirar" name="Detach"/>  	<menu_item_call label="Largar" name="Drop"/>  	<menu_item_call label="Ficar de pé" name="Stand Up"/> -	<menu_item_call label="Minha aparência" name="Appearance..."/> +	<menu_item_call label="Trocar de look" name="Change Outfit"/>  	<menu_item_call label="Meus amigos" name="Friends..."/>  	<menu_item_call label="Meus grupos" name="Groups..."/>  	<menu_item_call label="Meu perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml index ccbb921ebc..62055303b5 100644 --- a/indra/newview/skins/default/xui/pt/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/pt/menu_avatar_self.xml @@ -20,7 +20,9 @@  		<context_menu label="Tirar  ▶" name="Object Detach"/>  		<menu_item_call label="Tirar tudo" name="Detach All"/>  	</context_menu> -	<menu_item_call label="Minha aparência" name="Appearance..."/> +	<menu_item_call label="Trocar de look" name="Chenge Outfit"/> +	<menu_item_call label="Editar meu look" name="Edit Outfit"/> +	<menu_item_call label="Editar meu corpo" name="Edit My Shape"/>  	<menu_item_call label="Meus amigos" name="Friends..."/>  	<menu_item_call label="Meus grupos" name="Groups..."/>  	<menu_item_call label="Meu perfil" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/pt/menu_bottomtray.xml b/indra/newview/skins/default/xui/pt/menu_bottomtray.xml index 43b446a67e..479d02512f 100644 --- a/indra/newview/skins/default/xui/pt/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/pt/menu_bottomtray.xml @@ -4,6 +4,11 @@  	<menu_item_check label="Botão de movimento" name="ShowMoveButton"/>  	<menu_item_check label="Botão de ver" name="ShowCameraButton"/>  	<menu_item_check label="Botão de fotos" name="ShowSnapshotButton"/> +	<menu_item_check label="Botão da Barra lateral" name="ShowSidebarButton"/> +	<menu_item_check label="Botão Construir" name="ShowBuildButton"/> +	<menu_item_check label="Botão Buscar" name="ShowSearchButton"/> +	<menu_item_check label="Botão Mapa" name="ShowWorldMapButton"/> +	<menu_item_check label="Botão do Mini Mapa" name="ShowMiniMapButton"/>  	<menu_item_call label="Cortar" name="NearbyChatBar_Cut"/>  	<menu_item_call label="Copiar" name="NearbyChatBar_Copy"/>  	<menu_item_call label="Colar" name="NearbyChatBar_Paste"/> diff --git a/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml index effc970eb8..c3e0608954 100644 --- a/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/pt/menu_inspect_self_gear.xml @@ -1,7 +1,7 @@  <?xml version="1.0" encoding="utf-8"?>  <menu name="Gear Menu">  	<menu_item_call label="Ficar de pé" name="stand_up"/> -	<menu_item_call label="Minha aparência" name="my_appearance"/> +	<menu_item_call label="Trocar de look" name="change_outfit"/>  	<menu_item_call label="Meu perfil" name="my_profile"/>  	<menu_item_call label="Meus amigos" name="my_friends"/>  	<menu_item_call label="Meus grupos" name="my_groups"/> diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml index 345534261a..1b86b37075 100644 --- a/indra/newview/skins/default/xui/pt/menu_inventory.xml +++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml @@ -54,6 +54,7 @@  	<menu_item_call label="Remover item" name="Purge Item"/>  	<menu_item_call label="Restaurar item" name="Restore Item"/>  	<menu_item_call label="Abrir" name="Open"/> +	<menu_item_call label="Abrir original" name="Open Original"/>  	<menu_item_call label="Propriedades" name="Properties"/>  	<menu_item_call label="Renomear" name="Rename"/>  	<menu_item_call label="Copiar item UUID" name="Copy Asset UUID"/> diff --git a/indra/newview/skins/default/xui/pt/menu_login.xml b/indra/newview/skins/default/xui/pt/menu_login.xml index 8ea87a06d1..a43ac271a9 100644 --- a/indra/newview/skins/default/xui/pt/menu_login.xml +++ b/indra/newview/skins/default/xui/pt/menu_login.xml @@ -2,7 +2,7 @@  <menu_bar name="Login Menu">  	<menu label="Eu" name="File">  		<menu_item_call label="Preferências" name="Preferences..."/> -		<menu_item_call label="Sair" name="Quit"/> +		<menu_item_call label="Sair do [APP_NAME]" name="Quit"/>  	</menu>  	<menu label="Ajuda" name="Help">  		<menu_item_call label="Ajuda do [SECOND_LIFE]" name="Second Life Help"/> diff --git a/indra/newview/skins/default/xui/pt/menu_participant_list.xml b/indra/newview/skins/default/xui/pt/menu_participant_list.xml index c0db7752af..01f1d4ef80 100644 --- a/indra/newview/skins/default/xui/pt/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/pt/menu_participant_list.xml @@ -14,8 +14,8 @@  	<context_menu label="Opções do moderador >" name="Moderator Options">  		<menu_item_check label="Pode bater papo por escrito" name="AllowTextChat"/>  		<menu_item_call label="Silenciar este participante" name="ModerateVoiceMuteSelected"/> -		<menu_item_call label="Silenciar os demais" name="ModerateVoiceMuteOthers"/>  		<menu_item_call label="Desfazer silenciar deste participante" name="ModerateVoiceUnMuteSelected"/> -		<menu_item_call label="Desfazer silenciar dos demais" name="ModerateVoiceUnMuteOthers"/> +		<menu_item_call label="Silenciar todos" name="ModerateVoiceMute"/> +		<menu_item_call label="Desfazer silenciar para todos" name="ModerateVoiceUnmute"/>  	</context_menu>  </context_menu> diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml index 84ad056df6..b091cc2c97 100644 --- a/indra/newview/skins/default/xui/pt/menu_viewer.xml +++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml @@ -7,7 +7,7 @@  		</menu_item_call>  		<menu_item_call label="Comprar L$" name="Buy and Sell L$"/>  		<menu_item_call label="Meu perfil" name="Profile"/> -		<menu_item_call label="Minha aparência" name="Appearance"/> +		<menu_item_call label="Trocar de look" name="ChangeOutfit"/>  		<menu_item_check label="Meu inventário" name="Inventory"/>  		<menu_item_check label="Meu inventário" name="ShowSidetrayInventory"/>  		<menu_item_check label="Meus gestos" name="Gestures"/> @@ -162,6 +162,7 @@  			<menu_item_check label="Objetos flexíveis" name="Flexible Objects"/>  		</menu>  		<menu_item_check label="Executar diversas instâncias" name="Run Multiple Threads"/> +		<menu_item_check label="Usar plugin de leitura de threads" name="Use Plugin Read Thread"/>  		<menu_item_call label="Limpar cache de grupo" name="ClearGroupCache"/>  		<menu_item_check label="Smoothing de mouse" name="Mouse Smoothing"/>  		<menu label="Atalhos" name="Shortcuts"> @@ -188,7 +189,6 @@  			<menu_item_call label="Mais zoom" name="Zoom In"/>  			<menu_item_call label="Zoom padrão" name="Zoom Default"/>  			<menu_item_call label="Menos zoom" name="Zoom Out"/> -			<menu_item_call label="Alternar tela inteira" name="Toggle Fullscreen"/>  		</menu>  		<menu_item_call label="Mostrar configurações de depuração" name="Debug Settings"/>  		<menu_item_check label="Show Develop Menu" name="Debug Mode"/> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 462dcf2b21..e64940ecb1 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -323,6 +323,9 @@ Você precisa de uma conta para entrar no [SECOND_LIFE]. Você gostaria de abrir  		</url>  		<usetemplate name="okcancelbuttons" notext="Tentar novamente" yestext="Abrir conta"/>  	</notification> +	<notification name="InvalidCredentialFormat"> +		Digite o nome e sobrenome do seu avatar no campo Nome de usuário, depois faça o login novamente. +	</notification>  	<notification name="AddClassified">  		Os anúncios serão publicados na seção 'Classificados' das buscas e em [http://secondlife.com/community/classifieds secondlife.com] durante uma semana.  Escreva seu anúncio e clique em 'Publicar...'  @@ -603,6 +606,11 @@ Esperada [VALIDS]  	<notification name="CannotEncodeFile">  		Impossível codificar o arquivo: [FILE]  	</notification> +	<notification name="CorruptedProtectedDataStore"> +		Não foi possível fazer a leitura dos dados protegidos, redefinindo. +   Isso pode ocorrer após mudanças na configuração da rede. +		<usetemplate name="okbutton" yestext="OK"/> +	</notification>  	<notification name="CorruptResourceFile">  		Fonte do arquivo corrompida: [FILE]  	</notification> @@ -962,6 +970,12 @@ em TODOS OS TERRENOS deste sim?  Por favor, insira um valor maior.  	</notification> +	<notification name="ConfirmItemDeleteHasLinks"> +		Pelo menos um dos itens possui links que levam a ele.  Ao excluir o item, os links não funcionarão mais.   Por isso, recomendamos excluir os links primeiro. + +Tem certeza de que quer excluir estes items? +		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> +	</notification>  	<notification name="ConfirmObjectDeleteLock">  		Pelo menos um dos itens que você selecionou está trancado. @@ -1103,6 +1117,42 @@ Pressione a tecla F1 para ajuda ou aprender mais sobre [SECOND_LIFE].  Por favor, escolha se o seu avatar é feminino ou masculino. Você pode mudar de idéia depois.  		<usetemplate name="okcancelbuttons" notext="Feminino" yestext="Masculino"/>  	</notification> +	<notification name="CantTeleportToGrid"> +		Não foi possível ir para [SLURL], que fica em outro grid ([GRID]) em relação ao grid atual, ([CURRENT_GRID]).  Feche o Visualizador e tente novamente. +		<usetemplate name="okbutton" yestext="OK"/> +	</notification> +	<notification name="GeneralCertificateError"> +		Falha de conexão com o servidor. +[REASON] + +SubjectName: [SUBJECT_NAME_STRING] +IssuerName: [ISSUER_NAME_STRING] +Válido de: [VALID_FROM] +Válido até: [VALID_TO] +MD5 Fingerprint: [SHA1_DIGEST] +Impressão digital SHA1: [MD5_DIGEST] +Uso da chave: [KEYUSAGE] +Uso estendido da chave: [EXTENDEDKEYUSAGE] +Identificador chave de assunto: [SUBJECTKEYIDENTIFIER] +		<usetemplate name="okbutton" yestext="OK"/> +	</notification> +	<notification name="TrustCertificateError"> +		A autoridade de certificação deste servidor é desconhecida. + +Dados do certificado: +SubjectName: [SUBJECT_NAME_STRING] +IssuerName: [ISSUER_NAME_STRING] +Válido de: [VALID_FROM] +Válido até: [VALID_TO] +MD5 Fingerprint: [SHA1_DIGEST] +Impressão digital SHA1: [MD5_DIGEST] +Uso da chave: [KEYUSAGE] +Uso estendido da chave: [EXTENDEDKEYUSAGE] +Identificador chave de assunto: [SUBJECTKEYIDENTIFIER] + +Confiar nesta autoridade? +		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Confiança"/> +	</notification>  	<notification name="NotEnoughCurrency">  		[NAME] L$ [PRICE] Você não possui suficientes L$ para fazer isso.  	</notification> @@ -1493,9 +1543,9 @@ Ir para o Banco de Conhecimento para maiores informações sobre Classificaçõe  		Você não é permitido nesta região devido à sua Classificação de maturidade.  	</notification>  	<notification name="RegionEntryAccessBlocked_Change"> -		Você não pode entrar nessa região devido à sua seleção de maturidade.  +		Você não pode entrar nessa região devido à sua seleção de maturidade. -Clique em 'Mudar preferência' para aumentar o nível de maturidade e entrar nessa região.  De agora em diante você pode buscar e acessar conteúdo [REGIONMATURITY] .  Para modificar esta configuração, vá à Eu > Preferências > Geral. +Clique em 'Mudar preferência' para aumentar seu nível de maturidade e ganhar acesso imediato. Você então poderá fazer buscas e acessar conteúdo [REGIONMATURITY]. Para modificar o nível de maturidade, use o menu Eu > Preferências > Gerais.  		<form name="form">  			<button name="OK" text="Mudar preferência"/>  			<button default="true" name="Cancel" text="Fechar"/> @@ -2262,15 +2312,6 @@ Por favor, tente novamente em alguns instantes.  			<button name="Mute" text="Bloquear"/>  		</form>  	</notification> -	<notification name="ObjectGiveItemUnknownUser"> -		Um objeto chamado [OBJECTFROMNAME] de (residente desconhecido) lhe deu [OBJECTTYPE]: -[ITEM_SLURL] -		<form name="form"> -			<button name="Keep" text="Segure"/> -			<button name="Discard" text="Descarte"/> -			<button name="Mute" text="Bloquear"/> -		</form> -	</notification>  	<notification name="UserGiveItem">  		[NAME_SLURL] lhe deu [OBJECTTYPE]:  [ITEM_SLURL] @@ -2583,8 +2624,52 @@ O botão será exibido quando houver espaço suficente.  	<notification name="ShareNotification">  		Arraste itens do inventário para uma pessoa no seletor de residentes  	</notification> +	<notification name="DeedToGroupFail"> +		Ocorreu uma falha durante a doação ao grupo. +	</notification>  	<notification name="AvatarRezNotification"> -		O avatar de '[NAME]' renderizou em [TIME] s. +		( [EXISTENCE] segundos de vida ) +O avatar de '[NAME]' emergiu em [TIME] segundos. +	</notification> +	<notification name="AvatarRezSelfNotification"> +		( [EXISTENCE] segundos de vida ) +Você confeccionou seu look em [TIME] segundos. +	</notification> +	<notification name="AvatarRezCloudNotification"> +		( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' transformou-se em nuvem. +	</notification> +	<notification name="AvatarRezArrivedNotification"> +		( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' surgiu. +	</notification> +	<notification name="AvatarRezLeftCloudNotification"> +		( [EXISTENCE] segundos de vida ) +O avatar de '[NAME]' transformou-se em nuvem depois de [TIME] segundos. +	</notification> +	<notification name="AvatarRezEnteredAppearanceNotification"> +		( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' entrou no modo aparência. +	</notification> +	<notification name="AvatarRezLeftAppearanceNotification"> +		( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' sair do modo aparecer. +	</notification> +	<notification name="AvatarRezLeftNotification"> +		( [EXISTENCE] segundos de vida ) +Avatar '[NAME]' saiu totalmente carregado. +	</notification> +	<notification name="ConfirmLeaveCall"> +		Tem certeza de que quer sair desta ligação? +		<usetemplate ignoretext="Confirmar antes de deixar ligação" name="okcancelignore" notext="Não" yestext="Sim"/> +	</notification> +	<notification name="ConfirmMuteAll"> +		Você silenciou todos os participantes de uma ligação de grupo. +Todos os demais residentes que entrarem na ligação mais tarde também serão silenciados, mesmo se você sair da ligação. + + +Silenciar todos? +		<usetemplate ignoretext="Confirmar antes de silenciar todos os participantes em ligações de grupo." name="okcancelignore" notext="OK" yestext="Cancelar"/>  	</notification>  	<global name="UnsupportedCPU">  		- A velocidade da sua CPU não suporta os requisitos mínimos exigidos. diff --git a/indra/newview/skins/default/xui/pt/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/pt/panel_body_parts_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_body_parts_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> +	<text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/pt/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..094a03553b --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> +	<button label="Trocar" name="switch_btn"/> +	<button label="Comprar >" name="bodyparts_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_bottomtray.xml b/indra/newview/skins/default/xui/pt/panel_bottomtray.xml index 092135bd42..9fd7da55df 100644 --- a/indra/newview/skins/default/xui/pt/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/pt/panel_bottomtray.xml @@ -1,11 +1,7 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel name="bottom_tray"> -	<string name="SpeakBtnToolTip"> -		Liga e desliga o microfone -	</string> -	<string name="VoiceControlBtnToolTip"> -		Mostra/oculta os controles de voz -	</string> +	<string name="SpeakBtnToolTip" value="Liga e desliga o microfone"/> +	<string name="VoiceControlBtnToolTip" value="Mostra/oculta os controles de voz"/>  	<layout_stack name="toolbar_stack">  		<layout_panel name="speak_panel">  			<talk_button name="talk"> @@ -24,6 +20,21 @@  		<layout_panel name="snapshot_panel">  			<button label="" name="snapshots" tool_tip="Tirar foto"/>  		</layout_panel> +		<layout_panel name="sidebar_btn_panel"> +			<button label="Barra lateral" name="sidebar_btn" tool_tip="Mostra/oculta a barra lateral"/> +		</layout_panel> +		<layout_panel name="build_btn_panel"> +			<button label="Construir" name="build_btn" tool_tip="Mostra/oculta ferramentas de Construção"/> +		</layout_panel> +		<layout_panel name="search_btn_panel"> +			<button label="Busca" name="search_btn" tool_tip="Mostra/oculta os gestos"/> +		</layout_panel> +		<layout_panel name="world_map_btn_panel"> +			<button label="Mapa" name="world_map_btn" tool_tip="Mostra/oculta o Mapa Múndi"/> +		</layout_panel> +		<layout_panel name="mini_map_btn_panel"> +			<button label="Mini Mapa" name="mini_map_btn" tool_tip="Mostra/oculta o Mini Mapa"/> +		</layout_panel>  		<layout_panel name="im_well_panel">  			<chiclet_im_well name="im_well">  				<button name="Unread IM messages" tool_tip="Conversas"/> diff --git a/indra/newview/skins/default/xui/pt/panel_clothing_list_button_bar.xml b/indra/newview/skins/default/xui/pt/panel_clothing_list_button_bar.xml new file mode 100644 index 0000000000..bfdc7290d2 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_clothing_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> +	<button label="Adicionar +" name="add_btn"/> +	<button label="Comprar >" name="clothing_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/pt/panel_clothing_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> +	<text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_cof_wearables.xml b/indra/newview/skins/default/xui/pt/panel_cof_wearables.xml new file mode 100644 index 0000000000..3e4b12b001 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_cof_wearables.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="cof_wearables"> +	<accordion name="cof_wearables_accordion"> +		<accordion_tab name="tab_attachments" title="Anexos"/> +		<accordion_tab name="tab_clothing" title="Vestuário"/> +		<accordion_tab name="tab_body_parts" title="Corpo"/> +	</accordion> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/pt/panel_deletable_wearable_list_item.xml new file mode 100644 index 0000000000..91d90a5660 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_deletable_wearable_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="deletable_wearable_item"> +	<text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/pt/panel_dummy_clothing_list_item.xml new file mode 100644 index 0000000000..6af84de0c7 --- /dev/null +++ b/indra/newview/skins/default/xui/pt/panel_dummy_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="dummy_clothing_item"> +	<text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_shape.xml b/indra/newview/skins/default/xui/pt/panel_edit_shape.xml index 504486c3bb..6b9ac94cac 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_shape.xml @@ -1,14 +1,8 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel name="edit_shape_panel"> -	<panel name="avatar_sex_panel"> -		<text name="gender_text"> -			Sexo: -		</text> -		<radio_group name="sex_radio"> -			<radio_item label="Feminino" name="radio"/> -			<radio_item label="Masculino" name="radio2"/> -		</radio_group> -	</panel> +	<text name="avatar_height"> +		[HEIGHT] metros de altura +	</text>  	<panel label="Camisa" name="accordion_panel">  		<accordion name="wearable_accordion">  			<accordion_tab name="shape_body_tab" title="Corpo"/> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml index 23cde50acc..f85bb3c499 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml @@ -4,5 +4,6 @@  		<texture_picker label="Tatuagem de cabeça" name="Head Tattoo" tool_tip="Clique para escolher uma foto"/>  		<texture_picker label="Tatuagem superior" name="Upper Tattoo" tool_tip="Selecione uma foto"/>  		<texture_picker label="Tatuagem inferior" name="Lower Tattoo" tool_tip="Selecione uma foto"/> +		<color_swatch label="Cor/Tonalidade" name="Color/Tint" tool_tip="Selecionar a cor"/>  	</panel>  </panel> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml index a78539f274..f14a04f440 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml @@ -93,6 +93,12 @@  	<text name="edit_wearable_title" value="Editando forma"/>  	<panel label="Camisa" name="wearable_type_panel">  		<text name="description_text" value="Forma:"/> +		<radio_group name="sex_radio"> +			<radio_item label="" name="sex_male" tool_tip="Masculino" value="1"/> +			<radio_item label="" name="sex_female" tool_tip="Feminino" value="0"/> +		</radio_group> +		<icon name="male_icon" tool_tip="Masculino"/> +		<icon name="female_icon" tool_tip="Feminino"/>  	</panel>  	<panel label="gear_buttom_panel" name="gear_buttom_panel">  		<button name="friends_viewsort_btn" tool_tip="Opções"/> diff --git a/indra/newview/skins/default/xui/pt/panel_group_land_money.xml b/indra/newview/skins/default/xui/pt/panel_group_land_money.xml index 6f21b78b10..e57a85a726 100644 --- a/indra/newview/skins/default/xui/pt/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/pt/panel_group_land_money.xml @@ -6,6 +6,9 @@  	<panel.string name="cant_view_group_land_text">  		Você não está autorizado a acessar terrenos de grupos  	</panel.string> +	<panel.string name="epmty_view_group_land_text"> +		Nada consta +	</panel.string>  	<panel.string name="cant_view_group_accounting_text">  		Você não está autorizado a acessar os dados de contabilidade do grupo.  	</panel.string> diff --git a/indra/newview/skins/default/xui/pt/panel_group_notices.xml b/indra/newview/skins/default/xui/pt/panel_group_notices.xml index 4b5a00c761..9ccb85cdf6 100644 --- a/indra/newview/skins/default/xui/pt/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/pt/panel_group_notices.xml @@ -39,6 +39,7 @@ Cada grupo pode enviar no máximo 200 avisos/dia  		<text name="string">  			Arrastar e soltar o item aqui para anexá-lo:  		</text> +		<button label="Inventário" name="open_inventory" tool_tip="Inventário aberto"/>  		<button label="Tirar" label_selected="Remover o anexo" name="remove_attachment" tool_tip="Remover anexo da notificação."/>  		<button label="Enviar" label_selected="Enviar" name="send_notice"/>  		<group_drop_target name="drop_target" tool_tip="Arrastar um item do inventário para a caixa para enviá-lo com o aviso. É preciso ter autorização de cópia e transferência do item para anexá-lo ao aviso."/> diff --git a/indra/newview/skins/default/xui/pt/panel_login.xml b/indra/newview/skins/default/xui/pt/panel_login.xml index 588b8deaa3..94a885960a 100644 --- a/indra/newview/skins/default/xui/pt/panel_login.xml +++ b/indra/newview/skins/default/xui/pt/panel_login.xml @@ -8,18 +8,15 @@  	</panel.string>  	<layout_stack name="login_widgets">  		<layout_panel name="login"> -			<text name="first_name_text"> -				Primeiro nome: +			<text name="username_text"> +				Nome de usuário:  			</text> -			<line_editor label="Nome" name="first_name_edit" tool_tip="[SECOND_LIFE] First Name"/> -			<text name="last_name_text"> -				Sobrenome: -			</text> -			<line_editor label="Sobrenome" name="last_name_edit" tool_tip="[SECOND_LIFE] Last Name"/> +			<line_editor label="Nome de usuário" name="username_edit" tool_tip="[SECOND_LIFE] Nome de usuário"/>  			<text name="password_text">  				Senha:  			</text>  			<check_box label="Lembrar senha" name="remember_check"/> +			<button label="conectar" name="connect_btn"/>  			<text name="start_location_text">  				Começar em:  			</text> @@ -27,7 +24,6 @@  				<combo_box.item label="Última posição" name="MyLastLocation"/>  				<combo_box.item label="Meu início" name="MyHome"/>  			</combo_box> -			<button label="conectar" name="connect_btn"/>  		</layout_panel>  		<layout_panel name="links">  			<text name="create_new_account_text"> diff --git a/indra/newview/skins/default/xui/pt/panel_main_inventory.xml b/indra/newview/skins/default/xui/pt/panel_main_inventory.xml index 104c3bface..dbf8e4fa52 100644 --- a/indra/newview/skins/default/xui/pt/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/pt/panel_main_inventory.xml @@ -9,62 +9,20 @@  	<text name="ItemcountText">  		Itens:  	</text> -	<menu_bar name="Inventory Menu"> -		<menu label="Arquivo" name="File"> -			<menu_item_call label="Abrir" name="Open"/> -			<menu label="Upload" name="upload"> -				<menu_item_call label="Imagem (L$[COST])..." name="Upload Image"/> -				<menu_item_call label="Som (L$[COST])..." name="Upload Sound"/> -				<menu_item_call label="Animação (L$[COST])..." name="Upload Animation"/> -				<menu_item_call label="Volume (L$[COST] per file)..." name="Bulk Upload"/> -			</menu> -			<menu_item_call label="Nova janela" name="New Window"/> -			<menu_item_call label="Mostrar filtros" name="Show Filters"/> -			<menu_item_call label="Restabelecer filtros" name="Reset Current"/> -			<menu_item_call label="Fechar todas as pastas" name="Close All Folders"/> -			<menu_item_call label="Esvaziar lixeira" name="Empty Trash"/> -			<menu_item_call label="Esvaziar achados e perdidos" name="Empty Lost And Found"/> -		</menu> -		<menu label="Crie" name="Create"> -			<menu_item_call label="Nova pasta" name="New Folder"/> -			<menu_item_call label="Novo script" name="New Script"/> -			<menu_item_call label="Nova anotação" name="New Note"/> -			<menu_item_call label="Novo gesto" name="New Gesture"/> -			<menu label="Novas roupas" name="New Clothes"> -				<menu_item_call label="Nova camisa" name="New Shirt"/> -				<menu_item_call label="Novas calças" name="New Pants"/> -				<menu_item_call label="Novos sapatos" name="New Shoes"/> -				<menu_item_call label="Novas meias" name="New Socks"/> -				<menu_item_call label="Nova blusa" name="New Jacket"/> -				<menu_item_call label="Nova saia" name="New Skirt"/> -				<menu_item_call label="Novas luvas" name="New Gloves"/> -				<menu_item_call label="Nova camiseta" name="New Undershirt"/> -				<menu_item_call label="Novas roupa de baixo" name="New Underpants"/> -				<menu_item_call label="Novo alpha" name="New Alpha"/> -				<menu_item_call label="Nova tatuagem" name="New Tattoo"/> -			</menu> -			<menu label="Nova parte do corpo" name="New Body Parts"> -				<menu_item_call label="Nova forma" name="New Shape"/> -				<menu_item_call label="Nova pele" name="New Skin"/> -				<menu_item_call label="Novo cabelo" name="New Hair"/> -				<menu_item_call label="Novos olhos" name="New Eyes"/> -			</menu> -		</menu> -		<menu label="Classificar" name="Sort"> -			<menu_item_check label="Por nome" name="By Name"/> -			<menu_item_check label="Por data" name="By Date"/> -			<menu_item_check label="Pastas sempre por nome" name="Folders Always By Name"/> -			<menu_item_check label="Pastas do sistema no topo" name="System Folders To Top"/> -		</menu> -	</menu_bar>  	<filter_editor label="Filtro" name="inventory search editor"/>  	<tab_container name="inventory filter tabs">  		<inventory_panel label="Todos os itens" name="All Items"/> -		<inventory_panel label="Itens recentes" name="Recent Items"/> +		<recent_inventory_panel label="Itens recentes" name="Recent Items"/>  	</tab_container> -	<panel name="bottom_panel"> -		<button name="options_gear_btn" tool_tip="Mostrar opções adicionais"/> -		<button name="add_btn" tool_tip="Adicionar novo item"/> -		<dnd_button name="trash_btn" tool_tip="Remover item selecionado"/> -	</panel> +	<layout_stack name="bottom_panel"> +		<layout_panel name="options_gear_btn_panel"> +			<button name="options_gear_btn" tool_tip="Mostrar opções adicionais"/> +		</layout_panel> +		<layout_panel name="add_btn_panel"> +			<button name="add_btn" tool_tip="Adicionar novo item"/> +		</layout_panel> +		<layout_panel name="trash_btn_panel"> +			<dnd_button name="trash_btn" tool_tip="Remover item selecionado"/> +		</layout_panel> +	</layout_stack>  </panel> diff --git a/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml b/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml index 3dc8b4cc75..61e470586e 100644 --- a/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/pt/panel_outfit_edit.xml @@ -2,6 +2,8 @@  <!-- Side tray Outfit Edit panel -->  <panel label="Editar look" name="outfit_edit">  	<string name="No Outfit" value="Nenhum"/> +	<string name="unsaved_changes" value="Mudanças não salvas"/> +	<string name="now_editing" value="Editando..."/>  	<panel.string name="not_available">  		(N\A)  	</panel.string> @@ -21,18 +23,13 @@  	</panel>  	<layout_stack name="im_panels">  		<layout_panel label="Painel de controle de MIs" name="outfit_wearables_panel"> -			<scroll_list name="look_items_list"> -				<scroll_list.columns label="Ver item" name="look_item"/> -				<scroll_list.columns label="Ordenar itens" name="look_item_sort"/> -			</scroll_list>  			<panel label="bottom_panel" name="edit_panel"/>  		</layout_panel>  		<layout_panel name="add_wearables_panel"> -			<filter_editor label="Filtro" name="look_item_filter"/> +			<text name="add_to_outfit_label" value="Adicionar ao look:"/>  			<layout_stack name="filter_panels"> -				<layout_panel label="Painel de controle de MIs" name="filter_button_panel"> -					<text name="add_to_outfit_label" value="Adicionar ao look:"/> -					<button label="O" name="filter_button"/> +				<layout_panel label="Painel de controle de MIs" name="filter_panel"> +					<filter_editor label="Filtro" name="look_item_filter"/>  				</layout_panel>  			</layout_stack>  			<panel label="add_wearables_button_bar" name="add_wearables_button_bar"> diff --git a/indra/newview/skins/default/xui/pt/panel_people.xml b/indra/newview/skins/default/xui/pt/panel_people.xml index 17f5b6cbac..efeea89fa9 100644 --- a/indra/newview/skins/default/xui/pt/panel_people.xml +++ b/indra/newview/skins/default/xui/pt/panel_people.xml @@ -2,9 +2,9 @@  <!-- Side tray panel -->  <panel label="Pessoas" name="people_panel">  	<string name="no_recent_people" value="Ninguém, recentemente. Em busca de alguém para conversar? Use a [secondlife:///app/search/people Busca] ou o [secondlife:///app/worldmap Mapa-Múndi]."/> -	<string name="no_filtered_recent_people" value="Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]."/> +	<string name="no_filtered_recent_people" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]."/>  	<string name="no_one_near" value="Ninguém por perto Em busca de alguém para conversar? Use a [secondlife:///app/search/people Busca] ou o [secondlife:///app/worldmap Mapa-Múndi]."/> -	<string name="no_one_filtered_near" value="Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]."/> +	<string name="no_one_filtered_near" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]."/>  	<string name="no_friends_online" value="Nenhum amigo online"/>  	<string name="no_friends" value="Nenhum amigo"/>  	<string name="no_friends_msg"> @@ -12,11 +12,11 @@  Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa-Múndi].  	</string>  	<string name="no_filtered_friends_msg"> -		Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]. +		Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search].  	</string>  	<string name="people_filter_label" value="Filtro de pessoas"/>  	<string name="groups_filter_label" value="Filtro de grupos"/> -	<string name="no_filtered_groups_msg" value="Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]."/> +	<string name="no_filtered_groups_msg" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/groups/[SEARCH_TERM] Search]."/>  	<string name="no_groups_msg" value="À procura de grupos interessantes? Tente fazer uma [secondlife:///app/search/groups Busca]."/>  	<filter_editor label="Filtro" name="filter_input"/>  	<tab_container name="tabs"> @@ -55,8 +55,8 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa-  		<button label="Perfil" name="view_profile_btn" tool_tip="Exibir fotografia, grupos e outras informações dos residentes" width="50"/>  		<button label="MI" name="im_btn" tool_tip="Iniciar MI" width="24"/>  		<button label="Chamada" name="call_btn" tool_tip="Ligar para este residente" width="61"/> -		<button label="Compartilhar" name="share_btn" width="82"/> -		<button label="Teletransporte" name="teleport_btn" tool_tip="Oferecer teletransporte"  width="86"/> +		<button label="Compartilhar" name="share_btn" tool_tip="Compartilhar item de inventário" width="82"/> +		<button label="Teletransporte" name="teleport_btn" tool_tip="Oferecer teletransporte" width="86"/>  		<button label="Perfil do grupo" name="group_info_btn" tool_tip="Exibir informação de grupo"/>  		<button label="Bate-papo de grupo" name="chat_btn" tool_tip="Iniciar bate-papo"/>  		<button label="Ligar para o grupo" name="group_call_btn" tool_tip="Ligar para este grupo"/> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml index 6f2cae0476..885aafc350 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml @@ -13,6 +13,7 @@  	</text>  	<check_box label="Construção/Edição" name="edit_camera_movement" tool_tip="Use o posicionamento automático da câmera quando entrar e sair do modo de edição"/>  	<check_box label="Aparência" name="appearance_camera_movement" tool_tip="Use o posicionamento automático da câmera quando em modo de edição"/> +	<check_box initial_value="1" label="Barra lateral" name="appearance_sidebar_positioning" tool_tip="Usar posicionamento automático da câmera na barra lateral"/>  	<check_box label="Mostre-me em visão de mouse" name="first_person_avatar_visible"/>  	<check_box label="Teclas de seta sempre me movem" name="arrow_keys_move_avatar_check"/>  	<check_box label="Dê dois toques e pressione para correr" name="tap_tap_hold_to_run"/> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml index e566fde27c..02b0ef35fe 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml @@ -45,6 +45,7 @@  	</text>  	<check_box initial_value="true" label="Executar animação digitada quando estiver conversando" name="play_typing_animation"/>  	<check_box label="Enviar MIs por email se estiver desconectado" name="send_im_to_email"/> +	<check_box label="Ativar MIs e bate-papos de texto simples" name="plain_text_chat_history"/>  	<text name="show_ims_in_label">  		Mostrar MIs em:  	</text> diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml index eb38323940..ccf213099e 100644 --- a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml @@ -1,8 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel label="Gráficos" name="Display panel"> -	<text name="UI Size:"> -		Interface: -	</text>  	<text name="QualitySpeed">  		Qualidade e velocidade:  	</text> @@ -53,6 +50,10 @@ rápido  			m  		</text>  		<slider label="Contador máx. de partículas:" name="MaxParticleCount"/> +		<slider label="Distância máx. desenho avatar:" name="MaxAvatarDrawDistance"/> +		<text name="DrawDistanceMeterText3"> +			m +		</text>  		<slider label="Qualidade de Pós-processamento:" name="RenderPostProcess"/>  		<text name="MeshDetailText">  			Detalhes de Malha: diff --git a/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml b/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml index b8bbb4051a..f075f45b8f 100644 --- a/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_appearance.xml @@ -1,9 +1,13 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel label="Looks" name="appearance panel">  	<string name="No Outfit" value="Nenhum"/> +	<string name="Unsaved Changes" value="Mudanças não salvas"/> +	<string name="Now Wearing" value="Look atual..."/>  	<panel name="panel_currentlook"> -		<text name="currentlook_title"> -			(não salvo) +		<button label="E" name="editappearance_btn"/> +		<button label="O" name="openoutfit_btn"/> +		<text name="currentlook_status"> +			(Status)  		</text>  	</panel>  	<filter_editor label="Filtrar looks" name="Filter"/> diff --git a/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml b/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml index f634236cd2..31c96cad4c 100644 --- a/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/pt/sidepanel_inventory.xml @@ -4,6 +4,7 @@  		<panel name="button_panel">  			<button label="Perfil" name="info_btn"/>  			<button label="Compartilhar" name="share_btn"/> +			<button label="Comprar" name="shop_btn"/>  			<button label="Vestir" name="wear_btn"/>  			<button label="Tocar" name="play_btn"/>  			<button label="Teletransportar" name="teleport_btn"/> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 51b6581d42..f865124009 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -88,6 +88,24 @@  	<string name="LoginDownloadingClothing">  		Baixando roupas...  	</string> +	<string name="InvalidCertificate"> +		O servidor respondeu com um certificado inválido ou corrompido. Por favor contate o administrador do Grid. +	</string> +	<string name="CertInvalidHostname"> +		Um hostname inválido foi usado para acessar o servidor. Verifique o SLURL ou hostname do Grid. +	</string> +	<string name="CertExpired"> +		O certificado dado pelo Grid parece estar vencido.  Verifique o relógio do sistema ou contate o administrador do Grid. +	</string> +	<string name="CertKeyUsage"> +		O certificado dado pelo servidor não pôde ser usado para SSL.  Por favor contate o administrador do Grid. +	</string> +	<string name="CertBasicConstraints"> +		A cadeia de certificados do servidor tinha certificados demais.  Por favor contate o administrador do Grid. +	</string> +	<string name="CertInvalidSignature"> +		A assinatura do certificado dado pelo servidor do Grid não pôde ser verificada.  Por favor contate o administrador do Grid. +	</string>  	<string name="LoginFailedNoNetwork">  		Erro de rede: Não foi possível estabelecer a conexão, verifique sua conexão de rede.  	</string> @@ -819,6 +837,42 @@  	<string name="invalid">  		Inválido  	</string> +	<string name="shirt_not_worn"> +		Camisa não vestida +	</string> +	<string name="pants_not_worn"> +		Calças não vestidas +	</string> +	<string name="shoes_not_worn"> +		Sapatos não calçados +	</string> +	<string name="socks_not_worn"> +		Meias não calçadas +	</string> +	<string name="jacket_not_worn"> +		Jaqueta não vestida +	</string> +	<string name="gloves_not_worn"> +		Luvas não calçadas +	</string> +	<string name="undershirt_not_worn"> +		Camiseta não vestida +	</string> +	<string name="underpants_not_worn"> +		Roupa de baixo não vestida +	</string> +	<string name="skirt_not_worn"> +		Saia não vestida +	</string> +	<string name="alpha_not_worn"> +		Alpha não vestido +	</string> +	<string name="tattoo_not_worn"> +		Tatuagem não usada +	</string> +	<string name="invalid_not_worn"> +		inválido +	</string>  	<string name="NewWearable">  		Novo [WEARABLE_ITEM]  	</string> @@ -889,7 +943,10 @@  		Pressione ESC para retornar para visão do mundo  	</string>  	<string name="InventoryNoMatchingItems"> -		Não encontrou o que procura? Tente fazer uma [secondlife:///app/search/groups Busca]. +		Não encontrou o que procura? Tente buscar no [secondlife:///app/search/people/[SEARCH_TERM] Search]. +	</string> +	<string name="PlacesNoMatchingItems"> +		Não encontrou o que procura? Tente buscar no [secondlife:///app/search/groups/[SEARCH_TERM] Search].  	</string>  	<string name="FavoritesNoMatchingItems">  		Arraste um marco para adicioná-lo aos seus favoritos. @@ -919,6 +976,7 @@  	<string name="Wave" value="Acenar"/>  	<string name="HelloAvatar" value="Olá, avatar!"/>  	<string name="ViewAllGestures" value="Ver todos>>"/> +	<string name="GetMoreGestures" value="Mais >>"/>  	<string name="Animations" value="Animações,"/>  	<string name="Calling Cards" value="Cartões de visitas,"/>  	<string name="Clothing" value="Vestuário,"/> @@ -1542,6 +1600,9 @@  	<string name="MuteGroup">  		(grupo)  	</string> +	<string name="MuteExternal"> +		(Externo) +	</string>  	<string name="RegionNoCovenant">  		Não foi definido um contrato para essa região.  	</string> @@ -3299,11 +3360,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="answered_call">  		Ligação atendida  	</string> -	<string name="started_call"> -		Iniciou uma ligação de voz +	<string name="you_started_call"> +		Você iniciou uma ligação de voz +	</string> +	<string name="you_joined_call"> +		Você entrou na ligação  	</string> -	<string name="joined_call"> -		Entrou na ligação +	<string name="name_started_call"> +		[NAME] iniciou uma ligação de voz  	</string>  	<string name="ringing-im">  		Entrando em ligação de voz... @@ -3502,6 +3566,90 @@ Denunciar abuso  	<string name="Contents">  		Conteúdo  	</string> +	<string name="Gesture"> +		Gesto +	</string> +	<string name="Male Gestures"> +		Gestos masculinos +	</string> +	<string name="Female Gestures"> +		Gestos femininos +	</string> +	<string name="Other Gestures"> +		Outros gestos +	</string> +	<string name="Speech Gestures"> +		Gestos da fala +	</string> +	<string name="Common Gestures"> +		Gestos comuns +	</string> +	<string name="Male - Excuse me"> +		Perdão - masculino +	</string> +	<string name="Male - Get lost"> +		Deixe-me em paz - masculino +	</string> +	<string name="Male - Blow kiss"> +		Mandar beijo - masculino +	</string> +	<string name="Male - Boo"> +		Vaia - masculino +	</string> +	<string name="Male - Bored"> +		Maçante - masculino +	</string> +	<string name="Male - Hey"> +		Ôpa! - masculino +	</string> +	<string name="Male - Laugh"> +		Risada - masculino +	</string> +	<string name="Male - Repulsed"> +		Quero distância! - masculino +	</string> +	<string name="Male - Shrug"> +		Encolher de ombros - masculino +	</string> +	<string name="Male - Stick tougue out"> +		Mostrar a língua - masculino +	</string> +	<string name="Male - Wow"> +		Wow - masculino +	</string> +	<string name="FeMale - Excuse me"> +		Perdão - masc/fem +	</string> +	<string name="FeMale - Get lost"> +		Deixe-me em paz - feminino +	</string> +	<string name="FeMale - Blow kiss"> +		Mandar beijo - masc/fem +	</string> +	<string name="FeMale - Boo"> +		Vaia - masc/fem +	</string> +	<string name="Female - Bored"> +		Maçante - feminino +	</string> +	<string name="Female - Hey"> +		Ôpa - feminino +	</string> +	<string name="Female - Laugh"> +		Risada - feminina +	</string> +	<string name="Female - Repulsed"> +		Quero distância! - feminino +	</string> +	<string name="Female - Shrug"> +		Encolher ombros - feminino +	</string> +	<string name="Female - Stick tougue out"> +		Mostrar a língua - feminino +	</string> +	<string name="Female - Wow"> +		Wow - feminino +	</string>  	<string name="AvatarBirthDateFormat">  		[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]  	</string> | 
