diff options
| author | Tofu Linden <tofu.linden@lindenlab.com> | 2010-01-26 12:52:44 -0800 | 
|---|---|---|
| committer | Tofu Linden <tofu.linden@lindenlab.com> | 2010-01-26 12:52:44 -0800 | 
| commit | 2795661869e3dbbfe1e6becec1d6bb3635eafd3b (patch) | |
| tree | c5f090db2907c0904bb6436b894761e82b10349d | |
| parent | 22bcd0e0eaeda849fbb1a8ecd78eeee7a219c614 (diff) | |
| parent | 92f5e24c58f4a33e237c327c5266bb5fab6f9531 (diff) | |
Merge from viewer2 trunk.
116 files changed, 2279 insertions, 877 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index cf10ecccfb..2e4d803252 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -500,6 +500,7 @@ Ringo Tuxing  	CT-231  	CT-321  Robin Cornelius +	SNOW-108  	SNOW-204  	VWR-2488  	VWR-9557 diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index ac7cc2cdac..9ead183a9e 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -50,7 +50,7 @@ set(llcommon_SOURCE_FILES      lleventdispatcher.cpp      lleventfilter.cpp      llevents.cpp -    llfasttimer.cpp +    llfasttimer_class.cpp      llfile.cpp      llfindlocale.cpp      llfixedbuffer.cpp @@ -250,7 +250,7 @@ list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})  if(LLCOMMON_LINK_SHARED)      add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) -	ll_stage_sharedlib(llcommon) +    ll_stage_sharedlib(llcommon)  else(LLCOMMON_LINK_SHARED)      add_library (llcommon ${llcommon_SOURCE_FILES})  endif(LLCOMMON_LINK_SHARED) diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 9920921a58..476d75380f 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -34,7 +34,7 @@  #ifndef LL_LLERRORLEGACY_H  #define LL_LLERRORLEGACY_H - +#include "llpreprocessor.h"  /*  	LEGACY -- DO NOT USE THIS STUFF ANYMORE @@ -107,7 +107,7 @@ const int LL_ERR_PRICE_MISMATCH = -23018;  #define llwarning(msg, num)		llwarns << "Warning # " << num << ": " << msg << llendl; -#define llassert_always(func)	if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl; +#define llassert_always(func)	if (LL_UNLIKELY(!(func))) llerrs << "ASSERT (" << #func << ")" << llendl;  #ifdef SHOW_ASSERT  #define llassert(func)			llassert_always(func) diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 8af79c90fd..48461df6ae 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -1,6 +1,6 @@  /**   * @file llfasttimer.h - * @brief Declaration of a fast timer. + * @brief Inline implementations of fast timers.   *   * $LicenseInfo:firstyear=2004&license=viewergpl$   * @@ -33,13 +33,13 @@  #ifndef LL_FASTTIMER_H  #define LL_FASTTIMER_H -#include "llinstancetracker.h" - -#define FAST_TIMER_ON 1 -#define TIME_FAST_TIMERS 0 +// pull in the actual class definition +#include "llfasttimer_class.h"  #if LL_WINDOWS -#define LL_INLINE __forceinline +// +// Windows implementation of CPU clock +//  //  // NOTE: put back in when we aren't using platform sdk anymore @@ -52,21 +52,21 @@  //#undef _interlockedbittestandset  //#undef _interlockedbittestandreset -//inline U32 get_cpu_clock_count_32() +//inline U32 LLFastTimer::getCPUClockCount32()  //{  //	U64 time_stamp = __rdtsc();  //	return (U32)(time_stamp >> 8);  //}  //  //// return full timer value, *not* shifted by 8 bits -//inline U64 get_cpu_clock_count_64() +//inline U64 LLFastTimer::getCPUClockCount64()  //{  //	return __rdtsc();  //}  // shift off lower 8 bits for lower resolution but longer term timing  // on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing -inline U32 get_cpu_clock_count_32() +inline U32 LLFastTimer::getCPUClockCount32()  {  	U32 ret_val;  	__asm @@ -82,7 +82,7 @@ inline U32 get_cpu_clock_count_32()  }  // return full timer value, *not* shifted by 8 bits -inline U64 get_cpu_clock_count_64() +inline U64 LLFastTimer::getCPUClockCount64()  {  	U64 ret_val;  	__asm @@ -96,269 +96,71 @@ inline U64 get_cpu_clock_count_64()  	}      return ret_val;  } -#else -#define LL_INLINE  #endif -#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) -inline U32 get_cpu_clock_count_32() + +#if LL_LINUX || LL_SOLARIS +// +// Linux and Solaris implementation of CPU clock - all architectures. +// +// Try to use the MONOTONIC clock if available, this is a constant time counter +// with nanosecond resolution (but not necessarily accuracy) and attempts are made +// to synchronize this value between cores at kernel start. It should not be affected +// by CPU frequency. If not available use the REALTIME clock, but this may be affected by +// NTP adjustments or other user activity affecting the system time. +inline U64 LLFastTimer::getCPUClockCount64() +{ +	struct timespec tp; +	 +#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time? +	if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME +#endif +		clock_gettime(CLOCK_REALTIME,&tp); + +	return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec;         +} + +inline U32 LLFastTimer::getCPUClockCount32() +{ +	return (U32)(LLFastTimer::getCPUClockCount64() >> 8); +} +#endif // (LL_LINUX || LL_SOLARIS)) + + +#if (LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +// +// Mac x86 implementation of CPU clock +inline U32 LLFastTimer::getCPUClockCount32()  {  	U64 x;  	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); -	return (U32)x >> 8; +	return (U32)(x >> 8);  } -inline U32 get_cpu_clock_count_64() +inline U64 LLFastTimer::getCPUClockCount64()  {  	U64 x;  	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); -	return x >> 8; +	return x;  }  #endif -#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__)) + +#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__)))  // -// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock +// Mac PPC (deprecated) implementation of CPU clock  //  // Just use gettimeofday implementation for now -inline U32 get_cpu_clock_count_32() +inline U32 LLFastTimer::getCPUClockCount32()  { -	return (U32)get_clock_count(); +	return (U32)(get_clock_count()>>8);  } -inline U32 get_cpu_clock_count_64() +inline U64 LLFastTimer::getCPUClockCount64()  {  	return get_clock_count();  }  #endif -class LLMutex; - -#include <queue> -#include "llsd.h" - -class LL_COMMON_API LLFastTimer -{ -public: - -	class NamedTimer; - -	struct LL_COMMON_API FrameState -	{ -		FrameState(NamedTimer* timerp); - -		U32 				mSelfTimeCounter; -		U32 				mCalls; -		FrameState*			mParent;		// info for caller timer -		FrameState*			mLastCaller;	// used to bootstrap tree construction -		NamedTimer*			mTimer; -		U16					mActiveCount;	// number of timers with this ID active on stack -		bool				mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame -	}; - -	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances -	class LL_COMMON_API NamedTimer -	:	public LLInstanceTracker<NamedTimer> -	{ -		friend class DeclareTimer; -	public: -		~NamedTimer(); - -		enum { HISTORY_NUM = 60 }; - -		const std::string& getName() const { return mName; } -		NamedTimer* getParent() const { return mParent; } -		void setParent(NamedTimer* parent); -		S32 getDepth(); -		std::string getToolTip(S32 history_index = -1); - -		typedef std::vector<NamedTimer*>::const_iterator child_const_iter; -		child_const_iter beginChildren(); -		child_const_iter endChildren(); -		std::vector<NamedTimer*>& getChildren(); - -		void setCollapsed(bool collapsed) { mCollapsed = collapsed; } -		bool getCollapsed() const { return mCollapsed; } - -		U32 getCountAverage() const { return mCountAverage; } -		U32 getCallAverage() const { return mCallAverage; } - -		U32 getHistoricalCount(S32 history_index = 0) const; -		U32 getHistoricalCalls(S32 history_index = 0) const; - -		static NamedTimer& getRootNamedTimer(); - -		S32 getFrameStateIndex() const { return mFrameStateIndex; } - -		FrameState& getFrameState() const; - -	private: -		friend class LLFastTimer; -		friend class NamedTimerFactory; - -		// -		// methods -		// -		NamedTimer(const std::string& name); -		// recursive call to gather total time from children -		static void accumulateTimings(); - -		// updates cumulative times and hierarchy, -		// can be called multiple times in a frame, at any point -		static void processTimes(); - -		static void buildHierarchy(); -		static void resetFrame(); -		static void reset(); - -		// -		// members -		// -		S32			mFrameStateIndex; - -		std::string	mName; - -		U32 		mTotalTimeCounter; - -		U32 		mCountAverage; -		U32			mCallAverage; - -		U32*		mCountHistory; -		U32*		mCallHistory; - -		// tree structure -		NamedTimer*					mParent;				// NamedTimer of caller(parent) -		std::vector<NamedTimer*>	mChildren; -		bool						mCollapsed;				// don't show children -		bool						mNeedsSorting;			// sort children whenever child added -	}; - -	// used to statically declare a new named timer -	class LL_COMMON_API DeclareTimer -	:	public LLInstanceTracker<DeclareTimer> -	{ -		friend class LLFastTimer; -	public: -		DeclareTimer(const std::string& name, bool open); -		DeclareTimer(const std::string& name); - -		static void updateCachedPointers(); - -	private: -		NamedTimer&		mTimer; -		FrameState*		mFrameState; -	}; - -public: -	LLFastTimer(LLFastTimer::FrameState* state); - -	LL_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer) -	:	mFrameState(timer.mFrameState) -	{ -#if TIME_FAST_TIMERS -		U64 timer_start = get_cpu_clock_count_64(); -#endif -#if FAST_TIMER_ON -		LLFastTimer::FrameState* frame_state = mFrameState; -		mStartTime = get_cpu_clock_count_32(); - -		frame_state->mActiveCount++; -		frame_state->mCalls++; -		// keep current parent as long as it is active when we are -		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); - -		LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData; -		mLastTimerData = *cur_timer_data; -		cur_timer_data->mCurTimer = this; -		cur_timer_data->mFrameState = frame_state; -		cur_timer_data->mChildTime = 0; -#endif -#if TIME_FAST_TIMERS -		U64 timer_end = get_cpu_clock_count_64(); -		sTimerCycles += timer_end - timer_start; -#endif -	} - -	LL_INLINE ~LLFastTimer() -	{ -#if TIME_FAST_TIMERS -		U64 timer_start = get_cpu_clock_count_64(); -#endif -#if FAST_TIMER_ON -		LLFastTimer::FrameState* frame_state = mFrameState; -		U32 total_time = get_cpu_clock_count_32() - mStartTime; - -		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime; -		frame_state->mActiveCount--; - -		// store last caller to bootstrap tree creation -		// do this in the destructor in case of recursion to get topmost caller -		frame_state->mLastCaller = mLastTimerData.mFrameState; - -		// we are only tracking self time, so subtract our total time delta from parents -		mLastTimerData.mChildTime += total_time; - -		LLFastTimer::sCurTimerData = mLastTimerData; -#endif -#if TIME_FAST_TIMERS -		U64 timer_end = get_cpu_clock_count_64(); -		sTimerCycles += timer_end - timer_start; -		sTimerCalls++; -#endif -	} - -public: -	static LLMutex*			sLogLock; -	static std::queue<LLSD> sLogQueue; -	static BOOL				sLog; -	static BOOL				sMetricLog; -	static bool 			sPauseHistory; -	static bool 			sResetHistory; -	static U64				sTimerCycles; -	static U32				sTimerCalls; - -	typedef std::vector<FrameState> info_list_t; -	static info_list_t& getFrameStateList(); - - -	// call this once a frame to reset timers -	static void nextFrame(); - -	// dumps current cumulative frame stats to log -	// call nextFrame() to reset timers -	static void dumpCurTimes(); - -	// call this to reset timer hierarchy, averages, etc. -	static void reset(); - -	static U64 countsPerSecond(); -	static S32 getLastFrameIndex() { return sLastFrameIndex; } -	static S32 getCurFrameIndex() { return sCurFrameIndex; } - -	static void writeLog(std::ostream& os); -	static const NamedTimer* getTimerByName(const std::string& name); - -	struct CurTimerData -	{ -		LLFastTimer*	mCurTimer; -		FrameState*		mFrameState; -		U32				mChildTime; -	}; -	static CurTimerData		sCurTimerData; - -private: -	static S32				sCurFrameIndex; -	static S32				sLastFrameIndex; -	static U64				sLastFrameTime; -	static info_list_t*		sTimerInfos; - -	U32							mStartTime; -	LLFastTimer::FrameState*	mFrameState; -	LLFastTimer::CurTimerData	mLastTimerData; - -}; - -typedef class LLFastTimer LLFastTimer; -  #endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp new file mode 100644 index 0000000000..fae0a66873 --- /dev/null +++ b/indra/llcommon/llfasttimer_class.cpp @@ -0,0 +1,751 @@ +/**  + * @file llfasttimer_class.cpp + * @brief Implementation of the fast timer. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + *  + * Copyright (c) 2004-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "linden_common.h" + +#include "llfasttimer.h" + +#include "llmemory.h" +#include "llprocessor.h" +#include "llsingleton.h" +#include "lltreeiterators.h" +#include "llsdserialize.h" + +#include <boost/bind.hpp> + +#if LL_WINDOWS +#elif LL_LINUX || LL_SOLARIS +#include <sys/time.h> +#include <sched.h> +#elif LL_DARWIN +#include <sys/time.h> +#include "lltimer.h"	// get_clock_count() +#else  +#error "architecture not supported" +#endif + +////////////////////////////////////////////////////////////////////////////// +// statics + +S32 LLFastTimer::sCurFrameIndex = -1; +S32 LLFastTimer::sLastFrameIndex = -1; +U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64(); +bool LLFastTimer::sPauseHistory = 0; +bool LLFastTimer::sResetHistory = 0; +LLFastTimer::CurTimerData LLFastTimer::sCurTimerData; +BOOL LLFastTimer::sLog = FALSE; +BOOL LLFastTimer::sMetricLog = FALSE; +LLMutex* LLFastTimer::sLogLock = NULL; +std::queue<LLSD> LLFastTimer::sLogQueue; + +#if LL_LINUX || LL_SOLARIS +U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution +#else +U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution +#endif + +std::vector<LLFastTimer::FrameState>* LLFastTimer::sTimerInfos = NULL; +U64				LLFastTimer::sTimerCycles = 0; +U32				LLFastTimer::sTimerCalls = 0; + + +// FIXME: move these declarations to the relevant modules + +// helper functions +typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t; + +static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id)  +{  +	return timer_tree_bottom_up_iterator_t(&id,  +							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),  +							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1)); +} + +static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()  +{  +	return timer_tree_bottom_up_iterator_t();  +} + +typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t; + + +static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)  +{  +	return timer_tree_dfs_iterator_t(&id,  +		boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),  +							boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1)); +} + +static timer_tree_dfs_iterator_t end_timer_tree()  +{  +	return timer_tree_dfs_iterator_t();  +} + + + +// factory class that creates NamedTimers via static DeclareTimer objects +class NamedTimerFactory : public LLSingleton<NamedTimerFactory> +{ +public: +	NamedTimerFactory()  +	{} + +	/*virtual */ void initSingleton() +	{ +		mTimerRoot = new LLFastTimer::NamedTimer("root"); + +		mActiveTimerRoot = new LLFastTimer::NamedTimer("Frame"); +		mActiveTimerRoot->setCollapsed(false); + +		mRootFrameState = new LLFastTimer::FrameState(mActiveTimerRoot); +		mRootFrameState->mParent = &mTimerRoot->getFrameState(); +		mActiveTimerRoot->setParent(mTimerRoot); + +		mAppTimer = new LLFastTimer(mRootFrameState); +	} + +	~NamedTimerFactory() +	{ +		std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer()); + +		delete mAppTimer; +		delete mActiveTimerRoot;  +		delete mTimerRoot; +		delete mRootFrameState; +	} + +	LLFastTimer::NamedTimer& createNamedTimer(const std::string& name) +	{ +		timer_map_t::iterator found_it = mTimers.find(name); +		if (found_it != mTimers.end()) +		{ +			return *found_it->second; +		} + +		LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name); +		timer->setParent(mTimerRoot); +		mTimers.insert(std::make_pair(name, timer)); + +		return *timer; +	} + +	LLFastTimer::NamedTimer* getTimerByName(const std::string& name) +	{ +		timer_map_t::iterator found_it = mTimers.find(name); +		if (found_it != mTimers.end()) +		{ +			return found_it->second; +		} +		return NULL; +	} + +	LLFastTimer::NamedTimer* getActiveRootTimer() { return mActiveTimerRoot; } +	LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; } +	const LLFastTimer* getAppTimer() { return mAppTimer; } +	LLFastTimer::FrameState& getRootFrameState() { return *mRootFrameState; } + +	typedef std::map<std::string, LLFastTimer::NamedTimer*> timer_map_t; +	timer_map_t::iterator beginTimers() { return mTimers.begin(); } +	timer_map_t::iterator endTimers() { return mTimers.end(); } +	S32 timerCount() { return mTimers.size(); } + +private: +	timer_map_t mTimers; + +	LLFastTimer::NamedTimer*		mActiveTimerRoot; +	LLFastTimer::NamedTimer*		mTimerRoot; +	LLFastTimer*						mAppTimer; +	LLFastTimer::FrameState*		mRootFrameState; +}; + +void update_cached_pointers_if_changed() +{ +	// detect when elements have moved and update cached pointers +	static LLFastTimer::FrameState* sFirstTimerAddress = NULL; +	if (&*(LLFastTimer::getFrameStateList().begin()) != sFirstTimerAddress) +	{ +		LLFastTimer::DeclareTimer::updateCachedPointers(); +	} +	sFirstTimerAddress = &*(LLFastTimer::getFrameStateList().begin()); +} + +LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open ) +:	mTimer(NamedTimerFactory::instance().createNamedTimer(name)) +{ +	mTimer.setCollapsed(!open); +	mFrameState = &mTimer.getFrameState(); +	update_cached_pointers_if_changed(); +} + +LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name) +:	mTimer(NamedTimerFactory::instance().createNamedTimer(name)) +{ +	mFrameState = &mTimer.getFrameState(); +	update_cached_pointers_if_changed(); +} + +// static +void LLFastTimer::DeclareTimer::updateCachedPointers() +{ +	// propagate frame state pointers to timer declarations +	for (DeclareTimer::instance_iter it = DeclareTimer::beginInstances(); +		it != DeclareTimer::endInstances(); +		++it) +	{ +		// update cached pointer +		it->mFrameState = &it->mTimer.getFrameState(); +	} +} + +//static +#if LL_LINUX || LL_SOLARIS || ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__)) ) +U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer +{ +	return sClockResolution >> 8; +} +#else // windows or x86-mac +U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer +{ +	static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50)); + +	// we drop the low-order byte in out timers, so report a lower frequency +	return sCPUClockFrequency >> 8; +} +#endif + +LLFastTimer::FrameState::FrameState(LLFastTimer::NamedTimer* timerp) +:	mActiveCount(0), +	mCalls(0), +	mSelfTimeCounter(0), +	mParent(NULL), +	mLastCaller(NULL), +	mMoveUpTree(false), +	mTimer(timerp) +{} + + +LLFastTimer::NamedTimer::NamedTimer(const std::string& name) +:	mName(name), +	mCollapsed(true), +	mParent(NULL), +	mTotalTimeCounter(0), +	mCountAverage(0), +	mCallAverage(0), +	mNeedsSorting(false) +{ +	info_list_t& frame_state_list = getFrameStateList(); +	mFrameStateIndex = frame_state_list.size(); +	getFrameStateList().push_back(FrameState(this)); + +	mCountHistory = new U32[HISTORY_NUM]; +	memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM); +	mCallHistory = new U32[HISTORY_NUM]; +	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM); +} + +LLFastTimer::NamedTimer::~NamedTimer() +{ +	delete[] mCountHistory; +	delete[] mCallHistory; +} + +std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx) +{ +	if (history_idx < 0) +	{ +		// by default, show average number of calls +		return llformat("%s (%d calls)", getName().c_str(), (S32)getCallAverage()); +	} +	else +	{ +		return llformat("%s (%d calls)", getName().c_str(), (S32)getHistoricalCalls(history_idx)); +	} +} + +void LLFastTimer::NamedTimer::setParent(NamedTimer* parent) +{ +	llassert_always(parent != this); +	llassert_always(parent != NULL); + +	if (mParent) +	{ +		// subtract our accumulated from previous parent +		for (S32 i = 0; i < HISTORY_NUM; i++) +		{ +			mParent->mCountHistory[i] -= mCountHistory[i]; +		} + +		// subtract average timing from previous parent +		mParent->mCountAverage -= mCountAverage; + +		std::vector<NamedTimer*>& children = mParent->getChildren(); +		std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this); +		if (found_it != children.end()) +		{ +			children.erase(found_it); +		} +	} + +	mParent = parent; +	if (parent) +	{ +		getFrameState().mParent = &parent->getFrameState(); +		parent->getChildren().push_back(this); +		parent->mNeedsSorting = true; +	} +} + +S32 LLFastTimer::NamedTimer::getDepth() +{ +	S32 depth = 0; +	NamedTimer* timerp = mParent; +	while(timerp) +	{ +		depth++; +		timerp = timerp->mParent; +	} +	return depth; +} + +// static +void LLFastTimer::NamedTimer::processTimes() +{ +	if (sCurFrameIndex < 0) return; + +	buildHierarchy(); +	accumulateTimings(); +} + +// sort timer info structs by depth first traversal order +struct SortTimersDFS +{ +	bool operator()(const LLFastTimer::FrameState& i1, const LLFastTimer::FrameState& i2) +	{ +		return i1.mTimer->getFrameStateIndex() < i2.mTimer->getFrameStateIndex(); +	} +}; + +// sort child timers by name +struct SortTimerByName +{ +	bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2) +	{ +		return i1->getName() < i2->getName(); +	} +}; + +//static +void LLFastTimer::NamedTimer::buildHierarchy() +{ +	if (sCurFrameIndex < 0 ) return; + +	// set up initial tree +    for (instance_iter it = NamedTimer::beginInstances(); +		it != endInstances(); +		++it) +	{ +		NamedTimer& timer = *it; +		if (&timer == NamedTimerFactory::instance().getRootTimer()) continue; + +		// bootstrap tree construction by attaching to last timer to be on stack +		// when this timer was called +		if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer()) +		{ +			timer.setParent(timer.getFrameState().mLastCaller->mTimer); +			// no need to push up tree on first use, flag can be set spuriously +			timer.getFrameState().mMoveUpTree = false; +		} +	} + +	// bump timers up tree if they've been flagged as being in the wrong place +	// do this in a bottom up order to promote descendants first before promoting ancestors +	// this preserves partial order derived from current frame's observations +	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer()); +		it != end_timer_tree_bottom_up(); +		++it) +	{ +		NamedTimer* timerp = *it; +		// skip root timer +		if (timerp == NamedTimerFactory::instance().getRootTimer()) continue; + +		if (timerp->getFrameState().mMoveUpTree) +		{ +			// since ancestors have already been visited, reparenting won't affect tree traversal +			//step up tree, bringing our descendants with us +			//llinfos << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() << +			//	" to child of " << timerp->getParent()->getParent()->getName() << llendl; +			timerp->setParent(timerp->getParent()->getParent()); +			timerp->getFrameState().mMoveUpTree = false; + +			// don't bubble up any ancestors until descendants are done bubbling up +			it.skipAncestors(); +		} +	} + +	// sort timers by time last called, so call graph makes sense +	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); +		it != end_timer_tree(); +		++it) +	{ +		NamedTimer* timerp = (*it); +		if (timerp->mNeedsSorting) +		{ +			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName()); +		} +		timerp->mNeedsSorting = false; +	} +} + +//static +void LLFastTimer::NamedTimer::accumulateTimings() +{ +	U32 cur_time = getCPUClockCount32(); + +	// walk up stack of active timers and accumulate current time while leaving timing structures active +	LLFastTimer* cur_timer = sCurTimerData.mCurTimer; +	// root defined by parent pointing to self +	CurTimerData* cur_data = &sCurTimerData; +	while(cur_timer->mLastTimerData.mCurTimer != cur_timer) +	{ +		U32 cumulative_time_delta = cur_time - cur_timer->mStartTime; +		U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime; +		cur_data->mChildTime = 0; +		cur_timer->mFrameState->mSelfTimeCounter += self_time_delta; +		cur_timer->mStartTime = cur_time; + +		cur_data = &cur_timer->mLastTimerData; +		cur_data->mChildTime += cumulative_time_delta; + +		cur_timer = cur_timer->mLastTimerData.mCurTimer; +	} + +	// traverse tree in DFS post order, or bottom up +	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getActiveRootTimer()); +		it != end_timer_tree_bottom_up(); +		++it) +	{ +		NamedTimer* timerp = (*it); +		timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter; +		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it) +		{ +			timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter; +		} + +		S32 cur_frame = sCurFrameIndex; +		if (cur_frame >= 0) +		{ +			// update timer history +			int hidx = cur_frame % HISTORY_NUM; + +			timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter; +			timerp->mCountAverage = (timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1); +			timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls; +			timerp->mCallAverage = (timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1); +		} +	} +} + +// static +void LLFastTimer::NamedTimer::resetFrame() +{ +	if (sLog) +	{ //output current frame counts to performance log +		F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency + +		F64 total_time = 0; +		LLSD sd; + +		for (NamedTimer::instance_iter it = NamedTimer::beginInstances(); +					it != NamedTimer::endInstances(); +					++it) +		{ +			NamedTimer& timer = *it; +			FrameState& info = timer.getFrameState(); +			sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);	 +			sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls; +			 +			// computing total time here because getting the root timer's getCountHistory +			// doesn't work correctly on the first frame +			total_time = total_time + info.mSelfTimeCounter * iclock_freq; +		} + +		sd["Total"]["Time"] = (LLSD::Real) total_time; +		sd["Total"]["Calls"] = (LLSD::Integer) 1; + +		{		 +			LLMutexLock lock(sLogLock); +			sLogQueue.push(sd); +		} +	} + + +	// tag timers by position in depth first traversal of tree +	S32 index = 0; +	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); +		it != end_timer_tree(); +		++it) +	{ +		NamedTimer* timerp = (*it); +		 +		timerp->mFrameStateIndex = index; +		index++; + +		llassert_always(timerp->mFrameStateIndex < (S32)getFrameStateList().size()); +	} + +	// sort timers by dfs traversal order to improve cache coherency +	std::sort(getFrameStateList().begin(), getFrameStateList().end(), SortTimersDFS()); + +	// update pointers into framestatelist now that we've sorted it +	DeclareTimer::updateCachedPointers(); + +	// reset for next frame +	for (NamedTimer::instance_iter it = NamedTimer::beginInstances(); +		it != NamedTimer::endInstances(); +		++it) +	{ +		NamedTimer& timer = *it; + +		FrameState& info = timer.getFrameState(); +		info.mSelfTimeCounter = 0; +		info.mCalls = 0; +		info.mLastCaller = NULL; +		info.mMoveUpTree = false; +		// update parent pointer in timer state struct +		if (timer.mParent) +		{ +			info.mParent = &timer.mParent->getFrameState(); +		} +	} + +	//sTimerCycles = 0; +	//sTimerCalls = 0; +} + +//static +void LLFastTimer::NamedTimer::reset() +{ +	resetFrame(); // reset frame data + +	// walk up stack of active timers and reset start times to current time +	// effectively zeroing out any accumulated time +	U32 cur_time = getCPUClockCount32(); + +	// root defined by parent pointing to self +	CurTimerData* cur_data = &sCurTimerData; +	LLFastTimer* cur_timer = cur_data->mCurTimer; +	while(cur_timer->mLastTimerData.mCurTimer != cur_timer) +	{ +		cur_timer->mStartTime = cur_time; +		cur_data->mChildTime = 0; + +		cur_data = &cur_timer->mLastTimerData; +		cur_timer = cur_data->mCurTimer; +	} + +	// reset all history +	for (NamedTimer::instance_iter it = NamedTimer::beginInstances(); +		it != NamedTimer::endInstances(); +		++it) +	{ +		NamedTimer& timer = *it; +		if (&timer != NamedTimerFactory::instance().getRootTimer())  +		{ +			timer.setParent(NamedTimerFactory::instance().getRootTimer()); +		} + +		timer.mCountAverage = 0; +		timer.mCallAverage = 0; +		memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM); +		memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM); +	} + +	sLastFrameIndex = 0; +	sCurFrameIndex = 0; +} + +//static  +LLFastTimer::info_list_t& LLFastTimer::getFrameStateList()  +{  +	if (!sTimerInfos)  +	{  +		sTimerInfos = new info_list_t();  +	}  +	return *sTimerInfos;  +} + + +U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const +{ +	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; +	return mCountHistory[history_idx]; +} + +U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const +{ +	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; +	return mCallHistory[history_idx]; +} + +LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const +{ +	llassert_always(mFrameStateIndex >= 0); +	if (this == NamedTimerFactory::instance().getActiveRootTimer())  +	{ +		return NamedTimerFactory::instance().getRootFrameState(); +	} +	return getFrameStateList()[mFrameStateIndex]; +} + +// static +LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer() +{  +	return *NamedTimerFactory::instance().getActiveRootTimer();  +} + +std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren() +{  +	return mChildren.begin();  +} + +std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren() +{ +	return mChildren.end(); +} + +std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren() +{ +	return mChildren; +} + +//static +void LLFastTimer::nextFrame() +{ +	countsPerSecond(); // good place to calculate clock frequency +	U64 frame_time = getCPUClockCount64(); +	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff) +	{ +		llinfos << "Slow frame, fast timers inaccurate" << llendl; +	} + +	if (sPauseHistory) +	{ +		sResetHistory = true; +	} +	else if (sResetHistory) +	{ +		sLastFrameIndex = 0; +		sCurFrameIndex = 0; +		sResetHistory = false; +	} +	else // not paused +	{ +		NamedTimer::processTimes(); +		sLastFrameIndex = sCurFrameIndex++; +	} +	 +	// get ready for next frame +	NamedTimer::resetFrame(); +	sLastFrameTime = frame_time; +} + +//static +void LLFastTimer::dumpCurTimes() +{ +	// accumulate timings, etc. +	NamedTimer::processTimes(); +	 +	F64 clock_freq = (F64)countsPerSecond(); +	F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds + +	// walk over timers in depth order and output timings +	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); +		it != end_timer_tree(); +		++it) +	{ +		NamedTimer* timerp = (*it); +		F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq); +		// Don't bother with really brief times, keep output concise +		if (total_time_ms < 0.1) continue; + +		std::ostringstream out_str; +		for (S32 i = 0; i < timerp->getDepth(); i++) +		{ +			out_str << "\t"; +		} + + +		out_str << timerp->getName() << " "  +			<< std::setprecision(3) << total_time_ms << " ms, " +			<< timerp->getHistoricalCalls(0) << " calls"; + +		llinfos << out_str.str() << llendl; +	} +} + +//static  +void LLFastTimer::reset() +{ +	NamedTimer::reset(); +} + + +//static +void LLFastTimer::writeLog(std::ostream& os) +{ +	while (!sLogQueue.empty()) +	{ +		LLSD& sd = sLogQueue.front(); +		LLSDSerialize::toXML(sd, os); +		LLMutexLock lock(sLogLock); +		sLogQueue.pop(); +	} +} + +//static +const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name) +{ +	return NamedTimerFactory::instance().getTimerByName(name); +} + +LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state) +:	mFrameState(state) +{ +	U32 start_time = getCPUClockCount32(); +	mStartTime = start_time; +	mFrameState->mActiveCount++; +	LLFastTimer::sCurTimerData.mCurTimer = this; +	LLFastTimer::sCurTimerData.mFrameState = mFrameState; +	LLFastTimer::sCurTimerData.mChildTime = 0; +	mLastTimerData = LLFastTimer::sCurTimerData; +} + + +////////////////////////////////////////////////////////////////////////////// diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h new file mode 100644 index 0000000000..ddb1a74793 --- /dev/null +++ b/indra/llcommon/llfasttimer_class.h @@ -0,0 +1,272 @@ +/** + * @file llfasttimer_class.h + * @brief Declaration of a fast timer. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-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_FASTTIMER_CLASS_H +#define LL_FASTTIMER_CLASS_H + +#include "llinstancetracker.h" + +#define FAST_TIMER_ON 1 +#define TIME_FAST_TIMERS 0 + +class LLMutex; + +#include <queue> +#include "llsd.h" + +class LL_COMMON_API LLFastTimer +{ +public: +	class NamedTimer; + +	struct LL_COMMON_API FrameState +	{ +		FrameState(NamedTimer* timerp); + +		U32 				mSelfTimeCounter; +		U32 				mCalls; +		FrameState*			mParent;		// info for caller timer +		FrameState*			mLastCaller;	// used to bootstrap tree construction +		NamedTimer*			mTimer; +		U16					mActiveCount;	// number of timers with this ID active on stack +		bool				mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame +	}; + +	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances +	class LL_COMMON_API NamedTimer +	:	public LLInstanceTracker<NamedTimer> +	{ +		friend class DeclareTimer; +	public: +		~NamedTimer(); + +		enum { HISTORY_NUM = 60 }; + +		const std::string& getName() const { return mName; } +		NamedTimer* getParent() const { return mParent; } +		void setParent(NamedTimer* parent); +		S32 getDepth(); +		std::string getToolTip(S32 history_index = -1); + +		typedef std::vector<NamedTimer*>::const_iterator child_const_iter; +		child_const_iter beginChildren(); +		child_const_iter endChildren(); +		std::vector<NamedTimer*>& getChildren(); + +		void setCollapsed(bool collapsed) { mCollapsed = collapsed; } +		bool getCollapsed() const { return mCollapsed; } + +		U32 getCountAverage() const { return mCountAverage; } +		U32 getCallAverage() const { return mCallAverage; } + +		U32 getHistoricalCount(S32 history_index = 0) const; +		U32 getHistoricalCalls(S32 history_index = 0) const; + +		static NamedTimer& getRootNamedTimer(); + +		S32 getFrameStateIndex() const { return mFrameStateIndex; } + +		FrameState& getFrameState() const; + +	private: +		friend class LLFastTimer; +		friend class NamedTimerFactory; + +		// +		// methods +		// +		NamedTimer(const std::string& name); +		// recursive call to gather total time from children +		static void accumulateTimings(); + +		// updates cumulative times and hierarchy, +		// can be called multiple times in a frame, at any point +		static void processTimes(); + +		static void buildHierarchy(); +		static void resetFrame(); +		static void reset(); + +		// +		// members +		// +		S32			mFrameStateIndex; + +		std::string	mName; + +		U32 		mTotalTimeCounter; + +		U32 		mCountAverage; +		U32			mCallAverage; + +		U32*		mCountHistory; +		U32*		mCallHistory; + +		// tree structure +		NamedTimer*					mParent;				// NamedTimer of caller(parent) +		std::vector<NamedTimer*>	mChildren; +		bool						mCollapsed;				// don't show children +		bool						mNeedsSorting;			// sort children whenever child added +	}; + +	// used to statically declare a new named timer +	class LL_COMMON_API DeclareTimer +	:	public LLInstanceTracker<DeclareTimer> +	{ +		friend class LLFastTimer; +	public: +		DeclareTimer(const std::string& name, bool open); +		DeclareTimer(const std::string& name); + +		static void updateCachedPointers(); + +	private: +		NamedTimer&		mTimer; +		FrameState*		mFrameState; +	}; + +public: +	LLFastTimer(LLFastTimer::FrameState* state); + +	LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer) +	:	mFrameState(timer.mFrameState) +	{ +#if TIME_FAST_TIMERS +		U64 timer_start = getCPUClockCount64(); +#endif +#if FAST_TIMER_ON +		LLFastTimer::FrameState* frame_state = mFrameState; +		mStartTime = getCPUClockCount32(); + +		frame_state->mActiveCount++; +		frame_state->mCalls++; +		// keep current parent as long as it is active when we are +		frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); + +		LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData; +		mLastTimerData = *cur_timer_data; +		cur_timer_data->mCurTimer = this; +		cur_timer_data->mFrameState = frame_state; +		cur_timer_data->mChildTime = 0; +#endif +#if TIME_FAST_TIMERS +		U64 timer_end = getCPUClockCount64(); +		sTimerCycles += timer_end - timer_start; +#endif +	} + +	LL_FORCE_INLINE ~LLFastTimer() +	{ +#if TIME_FAST_TIMERS +		U64 timer_start = getCPUClockCount64(); +#endif +#if FAST_TIMER_ON +		LLFastTimer::FrameState* frame_state = mFrameState; +		U32 total_time = getCPUClockCount32() - mStartTime; + +		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime; +		frame_state->mActiveCount--; + +		// store last caller to bootstrap tree creation +		// do this in the destructor in case of recursion to get topmost caller +		frame_state->mLastCaller = mLastTimerData.mFrameState; + +		// we are only tracking self time, so subtract our total time delta from parents +		mLastTimerData.mChildTime += total_time; + +		LLFastTimer::sCurTimerData = mLastTimerData; +#endif +#if TIME_FAST_TIMERS +		U64 timer_end = getCPUClockCount64(); +		sTimerCycles += timer_end - timer_start; +		sTimerCalls++; +#endif +	} + +public: +	static LLMutex*			sLogLock; +	static std::queue<LLSD> sLogQueue; +	static BOOL				sLog; +	static BOOL				sMetricLog; +	static bool 			sPauseHistory; +	static bool 			sResetHistory; +	static U64				sTimerCycles; +	static U32				sTimerCalls; + +	typedef std::vector<FrameState> info_list_t; +	static info_list_t& getFrameStateList(); + + +	// call this once a frame to reset timers +	static void nextFrame(); + +	// dumps current cumulative frame stats to log +	// call nextFrame() to reset timers +	static void dumpCurTimes(); + +	// call this to reset timer hierarchy, averages, etc. +	static void reset(); + +	static U64 countsPerSecond(); +	static S32 getLastFrameIndex() { return sLastFrameIndex; } +	static S32 getCurFrameIndex() { return sCurFrameIndex; } + +	static void writeLog(std::ostream& os); +	static const NamedTimer* getTimerByName(const std::string& name); + +	struct CurTimerData +	{ +		LLFastTimer*	mCurTimer; +		FrameState*		mFrameState; +		U32				mChildTime; +	}; +	static CurTimerData		sCurTimerData; + +private: +	static U32 getCPUClockCount32(); +	static U64 getCPUClockCount64(); +	static U64 sClockResolution; + +	static S32				sCurFrameIndex; +	static S32				sLastFrameIndex; +	static U64				sLastFrameTime; +	static info_list_t*		sTimerInfos; + +	U32							mStartTime; +	LLFastTimer::FrameState*	mFrameState; +	LLFastTimer::CurTimerData	mLastTimerData; + +}; + +typedef class LLFastTimer LLFastTimer; + +#endif // LL_LLFASTTIMER_CLASS_H diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 5eefa6a16b..1c1503ca7b 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -55,13 +55,28 @@  #define LL_BIG_ENDIAN 1  #endif +  // Per-compiler switches +  #ifdef __GNUC__  #define LL_FORCE_INLINE inline __attribute__((always_inline))  #else  #define LL_FORCE_INLINE __forceinline  #endif +// Mark-up expressions with branch prediction hints.  Do NOT use +// this with reckless abandon - it's an obfuscating micro-optimization +// outside of inner loops or other places where you are OVERWHELMINGLY +// sure which way an expression almost-always evaluates. +#if __GNUC__ >= 3 +# define LL_LIKELY(EXPR) __builtin_expect (!!(EXPR), true) +# define LL_UNLIKELY(EXPR) __builtin_expect (!!(EXPR), false) +#else +# define LL_LIKELY(EXPR) (EXPR) +# define LL_UNLIKELY(EXPR) (EXPR) +#endif + +  // Figure out differences between compilers  #if defined(__GNUC__)  	#define GCC_VERSION (__GNUC__ * 10000 \ diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index cd493481d5..46478ba3c9 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -436,6 +436,8 @@ void LLImageGL::init(BOOL usemipmaps)  	mLastBindTime = 0.f;  	mPickMask = NULL; +	mPickMaskWidth = 0; +	mPickMaskHeight = 0;  	mUseMipMaps = usemipmaps;  	mHasExplicitFormat = FALSE;  	mAutoGenMips = FALSE; @@ -527,7 +529,12 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)  // 			llwarns << "Setting Size of LLImageGL with existing mTexName = " << mTexName << llendl;  			destroyGLTexture();  		} -		 + +		// pickmask validity depends on old image size, delete it +		delete [] mPickMask; +		mPickMask = NULL; +		mPickMaskWidth = mPickMaskHeight = 0; +  		mWidth = width;  		mHeight = height;  		mComponents = ncomponents; @@ -1675,12 +1682,14 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)  		return ;  	} +	delete [] mPickMask; +	mPickMask = NULL; +	mPickMaskWidth = mPickMaskHeight = 0; +  	if (mFormatType != GL_UNSIGNED_BYTE ||  	    mFormatPrimary != GL_RGBA)  	{  		//cannot generate a pick mask for this texture -		delete [] mPickMask; -		mPickMask = NULL;  		return;  	} @@ -1688,11 +1697,10 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)  	U32 pick_height = height/2;  	U32 size = llmax(pick_width, (U32) 1) * llmax(pick_height, (U32) 1); -  	size = size/8 + 1; - -	delete[] mPickMask;  	mPickMask = new U8[size]; +	mPickMaskWidth = pick_width; +	mPickMaskHeight = pick_height;  	memset(mPickMask, 0, sizeof(U8) * size); @@ -1727,35 +1735,34 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)  	if (mPickMask)  	{ -		S32 width = getWidth()/2; -		S32 height = getHeight()/2; -  		F32 u = tc.mV[0] - floorf(tc.mV[0]);  		F32 v = tc.mV[1] - floorf(tc.mV[1]); -		if (u < 0.f || u > 1.f || -		    v < 0.f || v > 1.f) +		if (LL_UNLIKELY(u < 0.f || u > 1.f || +				v < 0.f || v > 1.f))  		{  			LL_WARNS_ONCE("render") << "Ugh, u/v out of range in image mask pick" << LL_ENDL;  			u = v = 0.f;  			llassert(false);  		} + +		llassert(mPickMaskWidth > 0 && mPickMaskHeight > 0); -		S32 x = (S32)(u * width); -		S32 y = (S32)(v * height); +		S32 x = (S32)(u * mPickMaskWidth); +		S32 y = (S32)(v * mPickMaskHeight); -		if (x >= width) +		if (LL_UNLIKELY(x >= mPickMaskWidth))  		{  			LL_WARNS_ONCE("render") << "Ooh, width overrun on pick mask read, that coulda been bad." << LL_ENDL; -			x = llmax(0, width-1); +			x = llmax(0, mPickMaskWidth-1);  		} -		if (y >= height) +		if (LL_UNLIKELY(y >= mPickMaskHeight))  		{  			LL_WARNS_ONCE("render") << "Ooh, height overrun on pick mask read, that woulda been bad." << LL_ENDL; -			y = llmax(0, height-1); +			y = llmax(0, mPickMaskHeight-1);  		} -		S32 idx = y*width+x; +		S32 idx = y*mPickMaskWidth+x;  		S32 offset = idx%8;  		res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index facfb7bd62..f0870c3fc4 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -193,6 +193,8 @@ public:  private:  	LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL  	U8* mPickMask;  //downsampled bitmap approximation of alpha channel.  NULL if no alpha channel +	U16 mPickMaskWidth; +	U16 mPickMaskHeight;  	S8 mUseMipMaps;  	S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents)  	S8 mAutoGenMips; diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index b5e870228a..d0c73fbfbc 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -63,6 +63,8 @@ static LLDefaultChildRegistry::Register<LLAccordionCtrl>	t2("accordion");  LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)   , mFitParent(params.fit_parent) + , mAutoScrolling( false ) + , mAutoScrollRate( 0.f )  {    mSingleExpansion = params.single_expansion;  	if(mFitParent && !mSingleExpansion) @@ -72,6 +74,8 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)  }  LLAccordionCtrl::LLAccordionCtrl() : LLPanel() + , mAutoScrolling( false ) + , mAutoScrollRate( 0.f )  {  	mSingleExpansion = false;  	mFitParent = false; @@ -81,6 +85,19 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel()  //---------------------------------------------------------------------------------  void LLAccordionCtrl::draw()  { +	if (mAutoScrolling) +	{ +		// add acceleration to autoscroll +		mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE); +	} +	else +	{ +		// reset to minimum for next time +		mAutoScrollRate = MIN_AUTO_SCROLL_RATE; +	} +	// clear this flag to be set on next call to autoScroll +	mAutoScrolling = false; +  	LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);  	LLLocalClipRect clip(local_rect); @@ -420,6 +437,64 @@ BOOL LLAccordionCtrl::handleKeyHere			(KEY key, MASK mask)  	return LLPanel::handleKeyHere(key,mask);  } +BOOL LLAccordionCtrl::handleDragAndDrop		(S32 x, S32 y, MASK mask, +											 BOOL drop, +											 EDragAndDropType cargo_type, +											 void* cargo_data, +											 EAcceptance* accept, +											 std::string& tooltip_msg) +{ +	// Scroll folder view if needed.  Never accepts a drag or drop. +	*accept = ACCEPT_NO; +	BOOL handled = autoScroll(x, y); + +	if( !handled ) +	{ +		handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, +											cargo_data, accept, tooltip_msg) != NULL; +	} +	return TRUE; +} + +BOOL LLAccordionCtrl::autoScroll		(S32 x, S32 y) +{ +	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); + +	bool scrolling = false; +	if( mScrollbar->getVisible() ) +	{ +		LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 ); +		LLRect screen_local_extents; + +		// clip rect against root view +		screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents); +		rect_local.intersectWith(screen_local_extents); + +		// autoscroll region should take up no more than one third of visible scroller area +		S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10); +		S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32()); + +		LLRect bottom_scroll_rect = screen_local_extents; +		bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height; +		if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()) ) +		{ +			mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed ); +			mAutoScrolling = true; +			scrolling = true; +		} + +		LLRect top_scroll_rect = screen_local_extents; +		top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height; +		if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() > 0) ) +		{ +			mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed ); +			mAutoScrolling = true; +			scrolling = true; +		} +	} +	return scrolling; +} +  void	LLAccordionCtrl::updateLayout	(S32 width, S32 height)  {  	S32 panel_top = height - BORDER_MARGIN ; diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index 4cb0f38281..d57a42df32 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -81,6 +81,11 @@ public:  	virtual BOOL handleRightMouseDown	( S32 x, S32 y, MASK mask);   	virtual BOOL handleScrollWheel		( S32 x, S32 y, S32 clicks );  	virtual BOOL handleKeyHere			(KEY key, MASK mask); +	virtual BOOL handleDragAndDrop		(S32 x, S32 y, MASK mask, BOOL drop, +										 EDragAndDropType cargo_type, +										 void* cargo_data, +										 EAcceptance* accept, +										 std::string& tooltip_msg);  	//  	// Call reshape after changing splitter's size @@ -112,11 +117,15 @@ private:  	void	showScrollbar			(S32 width, S32 height);  	void	hideScrollbar			(S32 width, S32 height); +	BOOL	autoScroll				(S32 x, S32 y); +  private:  	LLRect			mInnerRect;  	LLScrollbar*	mScrollbar;  	bool			mSingleExpansion;  	bool			mFitParent; +	bool			mAutoScrolling; +	F32				mAutoScrollRate;  }; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 4bfe44135a..daa9e08f14 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -45,6 +45,7 @@ static const std::string DD_HEADER_NAME = "dd_header";  static const S32 HEADER_HEIGHT = 20;  static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;  static const S32 HEADER_TEXT_LEFT_OFFSET = 30; +static const F32 AUTO_OPEN_TIME = 1.f;  static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab"); @@ -73,6 +74,11 @@ public:  	virtual void onMouseEnter(S32 x, S32 y, MASK mask);  	virtual void onMouseLeave(S32 x, S32 y, MASK mask);  	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); +	virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +								   EDragAndDropType cargo_type, +								   void* cargo_data, +								   EAcceptance* accept, +								   std::string& tooltip_msg);  private:  	LLTextBox* mHeaderTextbox; @@ -92,6 +98,8 @@ private:  	LLUIColor mHeaderBGColor;  	bool mNeedsHighlight; + +	LLFrameTimer mAutoOpenTimer;  };  LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params() @@ -209,6 +217,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MA  {  	LLUICtrl::onMouseLeave(x, y, mask);  	mNeedsHighlight = false; +	mAutoOpenTimer.stop();  }  BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)  { @@ -218,8 +227,33 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask,  	}  	return LLUICtrl::handleKey(key, mask, called_from_parent);  } +BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask, +																	 BOOL drop, +																	 EDragAndDropType cargo_type, +																	 void* cargo_data, +																	 EAcceptance* accept, +																	 std::string& tooltip_msg) +{ +	LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent()); +	if ( parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose() ) +	{ +		if (mAutoOpenTimer.getStarted()) +		{ +			if (mAutoOpenTimer.getElapsedTimeF32() > AUTO_OPEN_TIME) +			{ +				parent->changeOpenClose(false); +				mAutoOpenTimer.stop(); +				return TRUE; +			} +		} +		else +			mAutoOpenTimer.start(); +	} +	return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type, +									   cargo_data, accept, tooltip_msg); +}  LLAccordionCtrlTab::Params::Params()  	: title("title")  	,display_children("expanded", true) diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index b200d43438..2e0260ab16 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -115,6 +115,7 @@ public:  	void changeOpenClose(bool is_open);  	void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; +	bool canOpenClose() const { return mCanOpenClose; };  	virtual BOOL postBuild(); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 73e4d126f3..cb5aea272d 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -70,6 +70,8 @@ const S32   SCROLL_INCREMENT_DEL = 4;	// make space for baskspacing  const F32   AUTO_SCROLL_TIME = 0.05f;  const F32	TRIPLE_CLICK_INTERVAL = 0.3f;	// delay between double and triple click. *TODO: make this equal to the double click interval? +const std::string PASSWORD_ASTERISK( "\xE2\x97\x8F" ); // U+25CF BLACK CIRCLE +  static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor");  // Compiler optimization, generate extern template @@ -401,7 +403,7 @@ void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )  	{  		for (S32 i = 0; i < mText.length(); i++)  		{ -			asterix_text += '*'; +			asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);  		}  		wtext = asterix_text.c_str();  	} @@ -1599,7 +1601,7 @@ void LLLineEditor::draw()  		std::string text;  		for (S32 i = 0; i < mText.length(); i++)  		{ -			text += '*'; +			text += PASSWORD_ASTERISK;  		}  		mText = text;  	} diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 4e84013db0..78386220d9 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -498,7 +498,7 @@ void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)  {  	S32 height = llmin( getRequiredRect().getHeight(), max_height );  	if(mPageLines) -		height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height ); +		height = llmin( mPageLines * mLineHeight + 2*mBorderThickness + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );  	S32 width = getRect().getWidth(); @@ -2760,9 +2760,13 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition  LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)  { -	if (!item_p.validateBlock()) return NULL; -  	LLScrollListItem *new_item = new LLScrollListItem(item_p); +	return addRow(new_item, item_p, pos); +} + +LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos) +{ +	if (!item_p.validateBlock() || !new_item) return NULL;  	new_item->setNumColumns(mColumns.size());  	// Add any columns we don't already have diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 907dc90bea..d2d2379328 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -148,6 +148,7 @@ public:  	// "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid  	// Creates missing columns automatically.  	virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); +	virtual LLScrollListItem* addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);  	virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);  	// Simple add element. Takes a single array of:  	// [ "value" => value, "font" => font, "font-style" => style ] diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 15b86cc945..25ce846d90 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -95,7 +95,7 @@ public:  	void	setUserdata( void* userdata )	{ mUserdata = userdata; }  	void*	getUserdata() const 			{ return mUserdata; } -	LLUUID	getUUID() const					{ return mItemValue.asUUID(); } +	virtual LLUUID	getUUID() const			{ return mItemValue.asUUID(); }  	LLSD	getValue() const				{ return mItemValue; }  	void	setRect(LLRect rect)			{ mRectangle = rect; } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 17aecaf32f..8abbc833e5 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -244,7 +244,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  LLTextBase::~LLTextBase()  { -	delete mPopupMenu; +	// Menu, like any other LLUICtrl, is deleted by its parent - gMenuHolder +  	clearSegments();  } @@ -1009,6 +1010,16 @@ void LLTextBase::draw()  void LLTextBase::setColor( const LLColor4& c )  {  	mFgColor = c; +	//textsegments have own style property ,  +	//so we have to update it also to apply changes, EXT-4433 +	for(segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); it++) +	{ +		LLTextSegment* segment = it->get();  +		if(segment) +		{ +			segment->setColor(mFgColor); +		} +	}  }  //virtual  @@ -1501,6 +1512,25 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params&  	onValueChange(0, getLength());  } +void LLTextBase::addBlackListUrl(const std::string &url) +{ +	mBlackListUrls.push_back(url); +} + +bool LLTextBase::isBlackListUrl(const std::string &url) const +{ +	std::vector<std::string>::const_iterator it; +	for (it = mBlackListUrls.begin(); it != mBlackListUrls.end(); ++it) +	{ +		const std::string &blacklist_url = *it; +		if (url.find(blacklist_url) != std::string::npos) +		{ +			return true; +		} +	} +	return false; +} +  //virtual  std::string LLTextBase::getText() const  { @@ -1575,20 +1605,29 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c  					prepend_newline = false;  				}  			} -			// output the styled Url -			appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params); -			prepend_newline = false; -			// set the tooltip for the Url label -			if (! match.getTooltip().empty()) +			// output the styled Url (unless we've been asked to suppress it) +			if (isBlackListUrl(match.getUrl()))  			{ -				segment_set_t::iterator it = getSegIterContaining(getLength()-1); -				if (it != mSegments.end()) +				std::string orig_url = text.substr(start, end-start); +				appendAndHighlightText(orig_url, prepend_newline, part, style_params); +			} +			else +			{ +				appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params); + +				// set the tooltip for the Url label +				if (! match.getTooltip().empty())  				{ -					LLTextSegmentPtr segment = *it; -					segment->setToolTip(match.getTooltip()); +					segment_set_t::iterator it = getSegIterContaining(getLength()-1); +					if (it != mSegments.end()) +						{ +							LLTextSegmentPtr segment = *it; +							segment->setToolTip(match.getTooltip()); +						}  				}  			} +			prepend_newline = false;  			// move on to the rest of the text after the Url  			if (end < (S32)text.length())  diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 038b9eaa62..e1c6cc36ab 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -41,6 +41,7 @@  #include "llpanel.h"  #include <string> +#include <vector>  #include <set>  #include <boost/signals2.hpp> @@ -186,6 +187,9 @@ public:  	const LLFontGL*			getDefaultFont() const					{ return mDefaultFont; }  	LLStyle::Params			getDefaultStyle(); +	// tell the text object to suppress auto highlighting of a specific URL +	void                    addBlackListUrl(const std::string &url); +  public:  	// Fired when a URL link is clicked  	commit_signal_t mURLClickSignal; @@ -308,6 +312,7 @@ protected:  	void							updateRects();  	void							needsScroll() { mScrollNeeded = TRUE; }  	void							replaceUrlLabel(const std::string &url, const std::string &label); +	bool                            isBlackListUrl(const std::string &url) const;  protected:  	// text segmentation and flow @@ -359,6 +364,9 @@ protected:  	LLView*						mDocumentView;  	class LLScrollContainer*	mScroller; +	// list of URLs to suppress from automatic hyperlinking +	std::vector<std::string>    mBlackListUrls; +  	// transient state  	bool						mReflowNeeded;		// need to reflow text because of change to text contents or display region  	bool						mScrollNeeded;		// need to change scroll region because of change to cursor position diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index f2c3879a6c..06ba0d80e9 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2040,6 +2040,20 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)  																				LLMenuHolderGL::child_registry_t::instance());  	} +	// Route menu to this class +	// previously this was done in ::handleRightMoseDown: +	//if(hasTabStop()) +	// setFocus(TRUE)  - why? weird... +	// and then inside setFocus +	// .... +	//    gEditMenuHandler = this; +	// .... +	// but this didn't work in all cases and just weird... +    //why not here?  +	// (all this was done for EXT-4443) + +	gEditMenuHandler = this; +  	S32 screen_x, screen_y;  	localPointToScreen(x, y, &screen_x, &screen_y);  	mContextMenu->show(screen_x, screen_y); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2701c0b3c1..c8db67d3d5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -351,7 +351,6 @@ set(viewer_SOURCE_FILES      llpanelprimmediacontrols.cpp      llpanelprofile.cpp      llpanelprofileview.cpp -    llpanelshower.cpp      llpanelteleporthistory.cpp      llpanelvolume.cpp      llpanelvolumepulldown.cpp @@ -858,7 +857,6 @@ set(viewer_HEADER_FILES      llpanelprimmediacontrols.h      llpanelprofile.h      llpanelprofileview.h -    llpanelshower.h      llpanelteleporthistory.h      llpanelvolume.h      llpanelvolumepulldown.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ffe8762f03..a73c75da88 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -298,17 +298,6 @@        <key>Value</key>        <integer>1</integer>      </map> -    <key>AudioStreamingVideo</key> -    <map> -      <key>Comment</key> -      <string>Enable streaming video</string> -      <key>Persist</key> -      <integer>1</integer> -      <key>Type</key> -      <string>Boolean</string> -      <key>Value</key> -      <integer>1</integer> -    </map>    <key>AuditTexture</key>    <map>      <key>Comment</key> @@ -10337,6 +10326,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>VoiceDefaultInternalLevel</key> +    <map> +      <key>Comment</key> +      <string>Internal level of voice set by default. Is equivalent to 0.5 (from 0.0-1.0 range) external voice level (internal = 400 * external^2).</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>100</integer> +    </map>      <key>VoiceEarLocation</key>      <map>        <key>Comment</key> diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt index cc8f6780e3..887dab66d1 100644 --- a/indra/newview/gpu_table.txt +++ b/indra/newview/gpu_table.txt @@ -192,9 +192,9 @@ NVIDIA GeForce 7100				.*NVIDIA.*GeForce 71.*				0		1  NVIDIA GeForce 7200				.*NVIDIA.*GeForce 72.*				1		1  NVIDIA GeForce 7300				.*NVIDIA.*GeForce 73.*				1		1  NVIDIA GeForce 7500				.*NVIDIA.*GeForce 75.*				1		1 -NVIDIA GeForce 7600				.*NVIDIA.*GeForce 76.*				2		1 -NVIDIA GeForce 7800				.*NVIDIA.*GeForce.*78.*				2		1 -NVIDIA GeForce 7900				.*NVIDIA.*GeForce.*79.*				2		1 +NVIDIA GeForce 7600				.*NVIDIA.*GeForce 76.*				3		1 +NVIDIA GeForce 7800				.*NVIDIA.*GeForce.*78.*				3		1 +NVIDIA GeForce 7900				.*NVIDIA.*GeForce.*79.*				3		1  NVIDIA GeForce 8100				.*NVIDIA.*GeForce 81.*				1		1  NVIDIA GeForce 8200				.*NVIDIA.*GeForce 82.*				1		1  NVIDIA GeForce 8300				.*NVIDIA.*GeForce 83.*				1		1 @@ -207,8 +207,8 @@ NVIDIA GeForce 8800				.*NVIDIA.*GeForce 88.*				3		1  NVIDIA GeForce 9300M			.*NVIDIA.*GeForce 9300M.*			1		1  NVIDIA GeForce 9400M			.*NVIDIA.*GeForce 9400M.*			1		1  NVIDIA GeForce 9500M			.*NVIDIA.*GeForce 9500M.*			2		1 -NVIDIA GeForce 9600M			.*NVIDIA.*GeForce 9600M.*			2		1 -NVIDIA GeForce 9700M			.*NVIDIA.*GeForce 9700M.*			2		1 +NVIDIA GeForce 9600M			.*NVIDIA.*GeForce 9600M.*			3		1 +NVIDIA GeForce 9700M			.*NVIDIA.*GeForce 9700M.*			3		1  NVIDIA GeForce 9300				.*NVIDIA.*GeForce 93.*				1		1  NVIDIA GeForce 9400				.*GeForce 94.*						1		1  NVIDIA GeForce 9500				.*NVIDIA.*GeForce 95.*				2		1 diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 03180b6a9d..1dec8c7bd8 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -35,6 +35,7 @@  #include "llagent.h"  #include "llagentwearables.h"  #include "llappearancemgr.h" +#include "llcommandhandler.h"  #include "llfloatercustomize.h"  #include "llgesturemgr.h"  #include "llinventorybridge.h" @@ -47,6 +48,23 @@  #include "llviewerregion.h"  #include "llwearablelist.h" +// support for secondlife:///app/appearance SLapps +class LLAppearanceHandler : public LLCommandHandler +{ +public: +	// requests will be throttled from a non-trusted browser +	LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {} + +	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +	{ +		// support secondlife:///app/appearance/show, but for now we just +		// make all secondlife:///app/appearance SLapps behave this way +		LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD()); +		return true; +	} +}; +LLAppearanceHandler gAppearanceHandler; +  class LLWearInventoryCategoryCallback : public LLInventoryCallback  {  public: diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 40c9bb6afa..7eed2e7b9a 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -250,31 +250,25 @@ void LLAvatarActions::startAdhocCall(const std::vector<LLUUID>& ids)  	make_ui_sound("UISndStartIM");  } +/* AD *TODO: Is this function needed any more? +	I fixed it a bit(added check for canCall), but it appears that it is not used +	anywhere. Maybe it should be removed?  // static  bool LLAvatarActions::isCalling(const LLUUID &id)  { -	if (id.isNull()) +	if (id.isNull() || !canCall())  	{  		return false;  	}  	LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);  	return (LLIMModel::getInstance()->findIMSession(session_id) != NULL); -} +}*/  //static -bool LLAvatarActions::canCall(const LLUUID &id) +bool LLAvatarActions::canCall()  { -	// For now we do not need to check whether passed UUID is ID of agent's friend. -	// Use common check of Voice Client state. -	{ -		// don't need to check online/offline status because "usual resident" (resident that is not a friend) -		// can be only ONLINE. There is no way to see "usual resident" in OFFLINE status. If we see "usual -		// resident" it automatically means that the resident is ONLINE. So to make a call to the "usual resident" -		// we need to check only that "our" voice is enabled. -		return LLVoiceClient::voiceEnabled(); -	} - +		return LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();  }  // static diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index a4504ae679..c751661acf 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -126,13 +126,16 @@ public:  	/**  	 * Return true if the avatar is in a P2P voice call with a given user  	 */ -	static bool isCalling(const LLUUID &id); +	/* AD *TODO: Is this function needed any more? +		I fixed it a bit(added check for canCall), but it appears that it is not used +		anywhere. Maybe it should be removed? +	static bool isCalling(const LLUUID &id);*/  	/** -	 * @return true if call to the resident can be made (resident is online and voice is enabled) +	 * @return true if call to the resident can be made  	 */ -	static bool canCall(const LLUUID &id); +	static bool canCall();  	/**  	 * Invite avatar to a group.  	 */	 diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 66ab32f3e8..2bcd097717 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -440,17 +440,17 @@ LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap()  // static  void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item)  { +	//speaking indicator width + padding +	S32 speaking_indicator_width = avatar_item->getRect().getWidth() - avatar_item->mSpeakingIndicator->getRect().mLeft; +  	//profile btn width + padding -	S32 profile_btn_width = avatar_item->getRect().getWidth() - avatar_item->mProfileBtn->getRect().mLeft; +	S32 profile_btn_width = avatar_item->mSpeakingIndicator->getRect().mLeft - avatar_item->mProfileBtn->getRect().mLeft;  	//info btn width + padding  	S32 info_btn_width = avatar_item->mProfileBtn->getRect().mLeft - avatar_item->mInfoBtn->getRect().mLeft; -	//speaking indicator width + padding -	S32 speaking_indicator_width = avatar_item->mInfoBtn->getRect().mLeft - avatar_item->mSpeakingIndicator->getRect().mLeft; -  	// last interaction time textbox width + padding -	S32 last_interaction_time_width = avatar_item->mSpeakingIndicator->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft; +	S32 last_interaction_time_width = avatar_item->mInfoBtn->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft;  	// icon width + padding  	S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft; @@ -462,9 +462,9 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item)  	sChildrenWidths[--index] = icon_width;  	sChildrenWidths[--index] = 0; // for avatar name we don't need its width, it will be calculated as "left available space"  	sChildrenWidths[--index] = last_interaction_time_width; -	sChildrenWidths[--index] = speaking_indicator_width;  	sChildrenWidths[--index] = info_btn_width;  	sChildrenWidths[--index] = profile_btn_width; +	sChildrenWidths[--index] = speaking_indicator_width;  }  void LLAvatarListItem::updateChildren() diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 479a4833cb..61c0a8660e 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -129,9 +129,9 @@ private:  	 * @see updateChildren()  	 */  	typedef enum e_avatar_item_child { +		ALIC_SPEAKER_INDICATOR,  		ALIC_PROFILE_BUTTON,  		ALIC_INFO_BUTTON, -		ALIC_SPEAKER_INDICATOR,  		ALIC_INTERACTION_TIME,  		ALIC_NAME,  		ALIC_ICON, diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index d4c8adadc6..f62fd44bc0 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -43,6 +43,7 @@  #include "llavatariconctrl.h"  #include "llavatarlist.h"  #include "llbottomtray.h" +#include "lldraghandle.h"  #include "llimfloater.h"  #include "llfloaterreg.h"  #include "llparticipantlist.h" @@ -158,6 +159,13 @@ BOOL LLCallFloater::postBuild()  	connectToChannel(LLVoiceChannel::getCurrentVoiceChannel()); +	setIsChrome(true); +	//chrome="true" hides floater caption  +	if (mDragHandle) +		mDragHandle->setTitleVisible(TRUE); +	 +	updateSession(); +  	return TRUE;  } @@ -240,7 +248,7 @@ void LLCallFloater::updateSession()  		}  	} -	const LLUUID& session_id = voice_channel->getSessionID(); +	const LLUUID& session_id = voice_channel ? voice_channel->getSessionID() : LLUUID::null;  	lldebugs << "Set speaker manager for session: " << session_id << llendl;  	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); @@ -562,33 +570,46 @@ void LLCallFloater::updateParticipantsVoiceState()  		if (!found)  		{ -			// If an avatarID is not found in a speakers list from VoiceClient and -			// a panel with this ID has a JOINED status this means that this person -			// HAS LEFT the call. -			if ((getState(participant_id) == STATE_JOINED)) -			{ -				setState(item, STATE_LEFT); +			updateNotInVoiceParticipantState(item); +		} +	} +} -				LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId()); -				if (speaker.isNull()) -				{ -					continue; -				} +void LLCallFloater::updateNotInVoiceParticipantState(LLAvatarListItem* item) +{ +	LLUUID participant_id = item->getAvatarId(); +	ESpeakerState current_state = getState(participant_id); -				speaker->mHasLeftCurrentCall = TRUE; -			} -			// If an avatarID is not found in a speakers list from VoiceClient and -			// a panel with this ID has a LEFT status this means that this person -			// HAS ENTERED session but it is not in voice chat yet. So, set INVITED status -			else if ((getState(participant_id) != STATE_LEFT)) -			{ -				setState(item, STATE_INVITED); -			} -			else +	switch (current_state) +	{ +	case STATE_JOINED: +		// If an avatarID is not found in a speakers list from VoiceClient and +		// a panel with this ID has a JOINED status this means that this person +		// HAS LEFT the call. +		setState(item, STATE_LEFT); + +		{ +			LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id); +			if (speaker.notNull())  			{ -				llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName()  << llendl; +				speaker->mHasLeftCurrentCall = TRUE;  			}  		} +		break; +	case STATE_INVITED: +	case STATE_LEFT: +		// nothing to do. These states should not be changed. +		break; +	case STATE_UNKNOWN: +		// If an avatarID is not found in a speakers list from VoiceClient and +		// a panel with this ID has an UNKNOWN status this means that this person +		// HAS ENTERED session but it is not in voice chat yet. So, set INVITED status +		setState(item, STATE_INVITED); +		break; +	default: +		// for possible new future states. +		llwarns << "Unsupported (" << getState(participant_id) << ") state for: " << item->getAvatarName()  << llendl; +		break;  	}  } diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index eded3a426b..766191379b 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -145,6 +145,10 @@ private:  	 */  	void updateParticipantsVoiceState(); +	/** +	 * Updates voice state of participant not in current voice channel depend on its current state. +	 */ +	void updateNotInVoiceParticipantState(LLAvatarListItem* item);  	void setState(LLAvatarListItem* item, ESpeakerState state);  	void setState(const LLUUID& speaker_id, ESpeakerState state)  	{ diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index a46cd84b60..d6a7edee5b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -550,8 +550,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		if (mLastFromName == chat.mFromName   			&& mLastFromID == chat.mFromID  			&& mLastMessageTime.notNull()  -			&& (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0  -			) +			&& (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 +			&& mLastMessageTimeStr.size() == chat.mTimeStr.size())  //*HACK to distinguish between current and previous chat session's histories  		{  			view = getSeparator();  			p.top_pad = mTopSeparatorPad; @@ -585,6 +585,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_  		mLastFromName = chat.mFromName;  		mLastFromID = chat.mFromID;  		mLastMessageTime = new_message_time; +		mLastMessageTimeStr = chat.mTimeStr;  	}  	std::string message = irc_me ? chat.mText.substr(3) : chat.mText; diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index f2d403f639..c2c60e60cf 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -125,6 +125,8 @@ class LLChatHistory : public LLUICtrl  		std::string mLastFromName;  		LLUUID mLastFromID;  		LLDate mLastMessageTime; +		std::string mLastMessageTimeStr; +  		std::string mMessageHeaderFilename;  		std::string mMessageSeparatorFilename; diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 47f1b7c9f5..5c05a54120 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -446,19 +446,17 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,  		if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )  		{ -			//TODO* CHAT: how to show this? -			//LLSD args; -			//args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound); -			//LLNotificationsUtil::add("SystemMessage", args); +			LLSD args; +			args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound"); +			LLNotificationsUtil::add("SystemMessage", args);  			buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mScriptName;  		}  		else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)  		{ -			//TODO* CHAT: how to show this? -			//LLSD args; -			//args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound); -			//LLNotificationsUtil::add("SystemMessage", args); +			LLSD args; +			args["MESSAGE"] = LLTrans::getString("CompileQueueInsufficientPermDownload"); +			LLNotificationsUtil::add("SystemMessage", args);  			buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mScriptName;  		} diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index ef69f39ad2..04f4ddf996 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -187,6 +187,12 @@ BOOL LLFloaterAbout::postBuild()  		support << '\n' << getString("AboutTraffic", args);  	} +	// don't make the sim hostname be a hyperlink +	if (info.has("HOSTNAME")) +	{ +		support_widget->addBlackListUrl(info["HOSTNAME"].asString()); +	} +	  	support_widget->appendText(support.str(),   								FALSE,   								LLStyle::Params() diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 29f415bd43..c71764c2e5 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -75,7 +75,7 @@ LLFloaterGroupPicker::~LLFloaterGroupPicker()  void LLFloaterGroupPicker::setPowersMask(U64 powers_mask)  {  	mPowersMask = powers_mask; -	postBuild(); +	init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID(), mPowersMask);  } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index fc036cb354..e77c93b5f8 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -327,6 +327,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)  	mCommitCallbackRegistrar.add("Pref.AutoDetectAspect",       boost::bind(&LLFloaterPreference::onCommitAutoDetectAspect, this));	  	mCommitCallbackRegistrar.add("Pref.ParcelMediaAutoPlayEnable",       boost::bind(&LLFloaterPreference::onCommitParcelMediaAutoPlayEnable, this));	  	mCommitCallbackRegistrar.add("Pref.MediaEnabled",           boost::bind(&LLFloaterPreference::onCommitMediaEnabled, this));	 +	mCommitCallbackRegistrar.add("Pref.MusicEnabled",           boost::bind(&LLFloaterPreference::onCommitMusicEnabled, this));	  	mCommitCallbackRegistrar.add("Pref.onSelectAspectRatio",    boost::bind(&LLFloaterPreference::onKeystrokeAspectRatio, this));	  	mCommitCallbackRegistrar.add("Pref.QualityPerformance",     boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));	  	mCommitCallbackRegistrar.add("Pref.applyUIColor",			boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2)); @@ -1001,12 +1002,14 @@ void LLFloaterPreference::onCommitMediaEnabled()  {  	LLCheckBoxCtrl *media_enabled_ctrl = getChild<LLCheckBoxCtrl>("media_enabled");  	bool enabled = media_enabled_ctrl->get(); -	gSavedSettings.setBOOL("AudioStreamingVideo", enabled); -	gSavedSettings.setBOOL("AudioStreamingMusic", enabled);  	gSavedSettings.setBOOL("AudioStreamingMedia", enabled); -	media_enabled_ctrl->setTentative(false); -	// Update enabled state of the "autoplay" checkbox -	getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(enabled); +} + +void LLFloaterPreference::onCommitMusicEnabled() +{ +	LLCheckBoxCtrl *music_enabled_ctrl = getChild<LLCheckBoxCtrl>("music_enabled"); +	bool enabled = music_enabled_ctrl->get(); +	gSavedSettings.setBOOL("AudioStreamingMusic", enabled);  }  void LLFloaterPreference::refresh() @@ -1424,17 +1427,16 @@ BOOL LLPanelPreference::postBuild()  	}  	//////////////////////PanelPrivacy /////////////////// -	if(hasChild("media_enabled")) +	if (hasChild("media_enabled"))  	{ -		bool video_enabled = gSavedSettings.getBOOL("AudioStreamingVideo"); -		bool music_enabled = gSavedSettings.getBOOL("AudioStreamingMusic");  		bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); -		bool enabled = video_enabled || music_enabled || media_enabled; -		 -		LLCheckBoxCtrl *media_enabled_ctrl = getChild<LLCheckBoxCtrl>("media_enabled");	 -		media_enabled_ctrl->set(enabled); -		media_enabled_ctrl->setTentative(!(video_enabled == music_enabled == media_enabled)); -		getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(enabled); +		getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2)); +		getChild<LLCheckBoxCtrl>("media_enabled")->set(media_enabled); +		getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(media_enabled); +	} +	if (hasChild("music_enabled")) +	{ +		getChild<LLCheckBoxCtrl>("music_enabled")->set(gSavedSettings.getBOOL("AudioStreamingMusic"));  	}  	apply(); @@ -1485,6 +1487,14 @@ void LLPanelPreference::saveSettings()  	}	  } +void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& value) +{ +	if (checkbox && checkbox->getValue()) +	{ +		LLNotificationsUtil::add("FriendsAndGroupsOnly"); +	} +} +  void LLPanelPreference::cancel()  {  	for (control_values_map_t::iterator iter =  mSavedValues.begin(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 6f382620ee..8778d76a5a 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -134,6 +134,7 @@ public:  	void onCommitAutoDetectAspect();  	void onCommitParcelMediaAutoPlayEnable();  	void onCommitMediaEnabled(); +	void onCommitMusicEnabled();  	void applyResolution();  	void applyUIColor(LLUICtrl* ctrl, const LLSD& param);  	void getUIColor(LLUICtrl* ctrl, const LLSD& param);	 @@ -166,6 +167,9 @@ public:  	virtual void saveSettings();  private: +	//for "Only friends and groups can call or IM me" +	static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); +  	typedef std::map<LLControlVariable*, LLSD> control_values_map_t;  	control_values_map_t mSavedValues; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 2efae0c8db..4a1eb51dbe 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -324,7 +324,7 @@ void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string  	std::string avatar_link = LLSLURL::buildCommand("agent", mObjectID, "inspect");  	childSetText("owner_name", avatar_link); -	childSetText("object_name", avatar_name); // name +	childSetText("object_name", avatar_name);  	childSetText("abuser_name_edit", avatar_name);  } diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 0964ad7f91..8875e35821 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -528,7 +528,16 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild()  	std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");  	childSetValue("loading_text", LLSD(msg_waiting)); -	 + +	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list"); + +	//set all columns to resizable mode even if some columns will be empty +	for(S32 column = 0; column < list->getNumColumns(); column++) +	{ +		LLScrollListColumn* columnp = list->getColumn(column); +		columnp->mHeader->setHasResizableElement(TRUE); +	} +  	return StartRequestChain();  } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index e75d35bea4..e01709aa3a 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -48,6 +48,7 @@  #include "lltextutil.h"  #include "llviewercontrol.h"	// for gSavedSettings  #include "llviewermenu.h"		// for gMenuHolder +#include "llvoiceclient.h"  static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");  S32 LLGroupListItem::sIconWidth = 0; @@ -271,6 +272,9 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)  	if (userdata.asString() == "activate")  		return gAgent.getGroupID() != selected_group_id; +	if (userdata.asString() == "call") +		return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking(); +  	return real_group_selected;  } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c2a7969c0d..f90a51c3f3 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -95,7 +95,8 @@ void toast_callback(const LLSD& msg){  	}  	// check whether incoming IM belongs to an active session or not -	if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"]) +	if (LLIMModel::getInstance()->getActiveSessionID().notNull() +			&& LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"])  	{  		return;  	} @@ -1577,7 +1578,7 @@ void LLCallDialog::setIcon(const LLSD& session_id, const LLSD& participant_id)  	}  } -bool LLOutgoingCallDialog::lifetimeHasExpired() +bool LLCallDialog::lifetimeHasExpired()  {  	if (mLifetimeTimer.getStarted())  	{ @@ -1590,7 +1591,7 @@ bool LLOutgoingCallDialog::lifetimeHasExpired()  	return false;  } -void LLOutgoingCallDialog::onLifetimeExpired() +void LLCallDialog::onLifetimeExpired()  {  	mLifetimeTimer.stop();  	closeFloater(); @@ -1680,6 +1681,7 @@ void LLOutgoingCallDialog::show(const LLSD& key)  	case LLVoiceChannel::STATE_ERROR :  		getChild<LLTextBox>("noanswer")->setVisible(true);  		getChild<LLButton>("Cancel")->setVisible(false); +		setCanClose(true);  		mLifetimeTimer.start();  		break;  	case LLVoiceChannel::STATE_HUNG_UP : @@ -1692,6 +1694,7 @@ void LLOutgoingCallDialog::show(const LLSD& key)  			getChild<LLTextBox>("nearby")->setVisible(true);  		}  		getChild<LLButton>("Cancel")->setVisible(false); +		setCanClose(true);  		mLifetimeTimer.start();  	} @@ -1742,19 +1745,6 @@ LLCallDialog(payload)  {  } -bool LLIncomingCallDialog::lifetimeHasExpired() -{ -	if (mLifetimeTimer.getStarted()) -	{ -		F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32(); -		if (elapsed_time > mLifetime)  -		{ -			return true; -		} -	} -	return false; -} -  void LLIncomingCallDialog::onLifetimeExpired()  {  	// check whether a call is valid or not @@ -3216,6 +3206,42 @@ public:  	}  }; +LLCallInfoDialog::LLCallInfoDialog(const LLSD& payload) : LLCallDialog(payload) +{ +} + +BOOL LLCallInfoDialog::postBuild() +{ +	// init notification's lifetime +	std::istringstream ss( getString("lifetime") ); +	if (!(ss >> mLifetime)) +	{ +		mLifetime = DEFAULT_LIFETIME; +	} +	return LLCallDialog::postBuild(); +} + +void LLCallInfoDialog::onOpen(const LLSD& key) +{ +	if(key.has("msg")) +	{ +		std::string msg = key["msg"]; +		getChild<LLTextBox>("msg")->setValue(msg); +	} + +	mLifetimeTimer.start(); +} + +void LLCallInfoDialog::show(const std::string& status_name, const LLSD& args) +{ +	LLUIString message = LLTrans::getString(status_name); +	message.setArgs(args); + +	LLSD payload; +	payload["msg"] = message; +	LLFloaterReg::showInstance("call_info", payload); +} +  LLHTTPRegistration<LLViewerChatterBoxSessionStartReply>     gHTTPRegistrationMessageChatterboxsessionstartreply(  	   "/message/ChatterBoxSessionStartReply"); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index a3b4f78af0..0386ff234d 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -512,8 +512,8 @@ protected:  	// notification's lifetime in seconds  	S32		mLifetime;  	static const S32 DEFAULT_LIFETIME = 5; -	virtual bool lifetimeHasExpired() {return false;}; -	virtual void onLifetimeExpired() {}; +	virtual bool lifetimeHasExpired(); +	virtual void onLifetimeExpired();  	virtual void getAllowedRect(LLRect& rect); @@ -543,7 +543,6 @@ public:  	static void onStartIM(void* user_data);  private: -	/*virtual*/ bool lifetimeHasExpired();  	/*virtual*/ void onLifetimeExpired();  	void processCallResponse(S32 response);  }; @@ -562,8 +561,16 @@ public:  private:  	// hide all text boxes  	void hideAllText(); -	/*virtual*/ bool lifetimeHasExpired(); -	/*virtual*/ void onLifetimeExpired(); +}; + +class LLCallInfoDialog : public LLCallDialog +{ +public: +	LLCallInfoDialog(const LLSD& payload); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +	static void show(const std::string& status_name, const LLSD& args);  };  // Globals diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 4b0539337b..3a41aebf28 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -229,6 +229,7 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd)  	mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn",   		boost::bind(&LLInspectAvatar::onVisibleZoomIn, this));  	mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this)); +	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall));  	mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this));  	mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this)); diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 0ab3b07aea..5981baab60 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -589,8 +589,16 @@ void LLPanelStandStopFlying::setVisible(BOOL visible)  		updatePosition();  	} -	//change visibility of parent layout_panel to animate in/out -	if (getParent()) getParent()->setVisible(visible); +	// do not change parent visibility in case panel is attached into Move Floater: EXT-3632, EXT-4646 +	if (!mAttached)  +	{ +		//change visibility of parent layout_panel to animate in/out. EXT-2504 +		if (getParent()) getParent()->setVisible(visible); +	} + +	// also change own visibility to avoid displaying the panel in mouselook (broken when EXT-2504 was implemented). +	// See EXT-4718. +	LLPanel::setVisible(visible);  }  BOOL LLPanelStandStopFlying::handleToolTip(S32 x, S32 y, MASK mask) @@ -614,7 +622,7 @@ void LLPanelStandStopFlying::reparent(LLFloaterMove* move_view)  	LLPanel* parent = dynamic_cast<LLPanel*>(getParent());  	if (!parent)  	{ -		llwarns << "Stand/stop flying panel parent is unset" << llendl; +		llwarns << "Stand/stop flying panel parent is unset, already attached?: " << mAttached << ", new parent: " << (move_view == NULL ? "NULL" : "Move Floater") << llendl;  		return;  	} @@ -684,6 +692,7 @@ void LLPanelStandStopFlying::onStopFlyingButtonClick()  	gAgent.setFlying(FALSE);  	setFocus(FALSE); // EXT-482 +	setVisible(FALSE);  }  /** diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 7ee4c64f8f..c1666f5666 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -52,23 +52,15 @@  #include <boost/tokenizer.hpp> -#include "llcrc.h" -#include "lldir.h"  #include "lldispatcher.h" -#include "llsdserialize.h"  #include "llxfermanager.h" -#include "message.h"  #include "llagent.h"  #include "llviewergenericmessage.h"	// for gGenericDispatcher -#include "llviewerwindow.h"  #include "llworld.h" //for particle system banning -#include "llchat.h"  #include "llimpanel.h"  #include "llimview.h"  #include "llnotifications.h" -#include "lluistring.h" -#include "llviewerobject.h"   #include "llviewerobjectlist.h"  #include "lltrans.h" @@ -219,61 +211,17 @@ LLMuteList* LLMuteList::getInstance()  // LLMuteList()  //-----------------------------------------------------------------------------  LLMuteList::LLMuteList() : -	mIsLoaded(FALSE), -	mUserVolumesLoaded(FALSE) +	mIsLoaded(FALSE)  {  	gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);  } -void LLMuteList::loadUserVolumes() -{ -	// call once, after LLDir::setLindenUserDir() has been called -	if (mUserVolumesLoaded) -		return; -	mUserVolumesLoaded = TRUE; -	 -	// load per-resident voice volume information -	// conceptually, this is part of the mute list information, although it is only stored locally -	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); - -	LLSD settings_llsd; -	llifstream file; -	file.open(filename); -	if (file.is_open()) -	{ -		LLSDSerialize::fromXML(settings_llsd, file); -	} - -	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); -		 iter != settings_llsd.endMap(); ++iter) -	{ -		mUserVolumeSettings.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal())); -	} -} -  //-----------------------------------------------------------------------------  // ~LLMuteList()  //-----------------------------------------------------------------------------  LLMuteList::~LLMuteList()  { -	// If we quit from the login screen we will not have an SL account -	// name.  Don't try to save, otherwise we'll dump a file in -	// C:\Program Files\SecondLife\ or similar. JC -	std::string user_dir = gDirUtilp->getLindenUserDir(); -	if (!user_dir.empty()) -	{ -		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); -		LLSD settings_llsd; - -		for(user_volume_map_t::iterator iter = mUserVolumeSettings.begin(); iter != mUserVolumeSettings.end(); ++iter) -		{ -			settings_llsd[iter->first.asString()] = iter->second; -		} -		llofstream file; -		file.open(filename); -		LLSDSerialize::toPrettyXML(settings_llsd, file); -	}  }  BOOL LLMuteList::isLinden(const std::string& name) const @@ -715,8 +663,6 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) c  //-----------------------------------------------------------------------------  void LLMuteList::requestFromServer(const LLUUID& agent_id)  { -	loadUserVolumes(); -	  	std::string agent_id_string;  	std::string filename;  	agent_id.toString(agent_id_string); @@ -751,26 +697,6 @@ void LLMuteList::cache(const LLUUID& agent_id)  	}  } -void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume) -{ -	// store new value in volume settings file -	mUserVolumeSettings[id] = volume; -} - -F32 LLMuteList::getSavedResidentVolume(const LLUUID& id) -{ -	const F32 DEFAULT_VOLUME = 0.5f; - -	user_volume_map_t::iterator found_it = mUserVolumeSettings.find(id); -	if (found_it != mUserVolumeSettings.end()) -	{ -		return found_it->second; -	} -	//FIXME: assumes default, should get this from somewhere -	return DEFAULT_VOLUME; -} - -  //-----------------------------------------------------------------------------  // Static message handlers  //----------------------------------------------------------------------------- diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 409b637bf2..e1e81a24b4 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -127,12 +127,7 @@ public:  	// call this method on logout to save everything.  	void cache(const LLUUID& agent_id); -	void setSavedResidentVolume(const LLUUID& id, F32 volume); -	F32 getSavedResidentVolume(const LLUUID& id); -  private: -	void loadUserVolumes(); -	  	BOOL loadFromFile(const std::string& filename);  	BOOL saveToFile(const std::string& filename); @@ -179,12 +174,8 @@ private:  	observer_set_t mObservers;  	BOOL mIsLoaded; -	BOOL mUserVolumesLoaded;  	friend class LLDispatchEmptyMuteList; - -	typedef std::map<LLUUID, F32> user_volume_map_t;  -	user_volume_map_t mUserVolumeSettings;  };  class LLMuteListObserver diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 6375362ae2..9f04558d50 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -148,7 +148,7 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)  		&& column_index == mNameColumnIndex)  	{  		// ...this is the column with the avatar name -		LLUUID avatar_id = getItemId(hit_item); +		LLUUID avatar_id = hit_item->getUUID();  		if (avatar_id.notNull())  		{  			// ...valid avatar id @@ -230,14 +230,15 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(  	std::string& suffix)  {  	LLUUID id = name_item.value().asUUID(); -	LLScrollListItem* item = NULL; +	LLNameListItem* item = NULL;  	// Store item type so that we can invoke the proper inspector.  	// *TODO Vadim: Is there a more proper way of storing additional item data?  	{ -		LLNameListCtrl::NameItem name_item_(name_item); -		name_item_.value = LLSD().with("uuid", id).with("is_group", name_item.target() == GROUP); -		item = LLScrollListCtrl::addRow(name_item_, pos); +		LLNameListCtrl::NameItem item_p(name_item); +		item_p.value = LLSD().with("uuid", id).with("is_group", name_item.target() == GROUP); +		item = new LLNameListItem(item_p); +		LLScrollListCtrl::addRow(item, item_p, pos);  	}  	if (!item) return NULL; @@ -298,7 +299,7 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)  	for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)  	{  		LLScrollListItem* item = *it; -		if (getItemId(item) == agent_id) +		if (item->getUUID() == agent_id)  		{  			idx = getItemIndex(item);  			break; @@ -335,7 +336,7 @@ void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first,  	for (iter = getItemList().begin(); iter != getItemList().end(); iter++)  	{  		LLScrollListItem* item = *iter; -		if (getItemId(item) == id) +		if (item->getUUID() == id)  		{  			LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(0);  			cell = item->getColumn(mNameColumnIndex); @@ -375,9 +376,3 @@ void LLNameListCtrl::updateColumns()  		}  	}  } - -// static -LLUUID LLNameListCtrl::getItemId(LLScrollListItem* item) -{ -	return item->getValue()["uuid"].asUUID(); -} diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 192a3a5afa..23b1cb6897 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -122,7 +122,6 @@ public:  	/*virtual*/ void updateColumns();  private:  	void showInspector(const LLUUID& avatar_id, bool is_group); -	static LLUUID getItemId(LLScrollListItem* item);  private:  	S32    			mNameColumnIndex; @@ -130,4 +129,24 @@ private:  	BOOL			mAllowCallingCardDrop;  }; +/** + * LLNameListCtrl item + *  + * We don't use LLScrollListItem to be able to override getUUID(), which is needed + * because the name list item value is not simply an UUID but a map (uuid, is_group). + */ +class LLNameListItem : public LLScrollListItem +{ +public: +	LLUUID	getUUID() const		{ return getValue()["uuid"].asUUID(); } + +protected: +	friend class LLNameListCtrl; + +	LLNameListItem( const LLScrollListItem::Params& p ) +	:	LLScrollListItem(p) +	{ +	} +}; +  #endif diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a7c1e73328..0a8d020b4f 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -101,6 +101,11 @@ BOOL LLNearbyChat::postBuild()  			getDockTongue(), LLDockControl::TOP, boost::bind(&LLNearbyChat::getAllowedRect, this, _1)));  	} +	setIsChrome(true); +	//chrome="true" hides floater caption  +	if (mDragHandle) +		mDragHandle->setTitleVisible(TRUE); +  	return true;  } diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index c50e049d4c..a1a9d84c14 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -356,12 +356,17 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)  		initChannel();  	} +	/* +	//comment all this due to EXT-4432 +	..may clean up after some time... +  	//only messages from AGENTS  	if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType)  	{  		if(chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG)  			return;//ok for now we don't skip messeges from object, so skip only debug messages  	} +	*/  	LLUUID id;  	id.generate(); diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index fba5773602..02f948eca9 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -123,7 +123,14 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  				message);  		// restore active session id -		LLIMModel::instance().setActiveSessionID(active_session_id); +		if (active_session_id.isNull()) +		{ +			LLIMModel::instance().resetActiveSessionID(); +		} +		else +		{ +			LLIMModel::instance().setActiveSessionID(active_session_id); +		}  	}  } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 85e95ca1d6..fe5b20813a 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -165,6 +165,8 @@ BOOL LLPanelAvatarNotes::postBuild()  	resetControls();  	resetData(); +	gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this); +  	return TRUE;  } @@ -337,6 +339,8 @@ LLPanelAvatarNotes::~LLPanelAvatarNotes()  	if(getAvatarId().notNull())  	{  		LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +		if(LLVoiceClient::getInstance()) +			LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);  	}  } @@ -346,6 +350,17 @@ void LLPanelAvatarNotes::changed(U32 mask)  	childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId()));  } +// virtual +void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +	{ +		return; +	} + +	childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); +} +  void LLPanelAvatarNotes::setAvatarId(const LLUUID& id)  {  	if(id.notNull()) @@ -437,7 +452,6 @@ void LLPanelProfileTab::updateButtons()  	bool enable_map_btn = is_avatar_online && gAgent.isGodlike() || is_agent_mappable(getAvatarId());  	childSetEnabled("show_on_map_btn", enable_map_btn); -	childSetEnabled("call", LLAvatarActions::canCall(getAvatarId()));  }  ////////////////////////////////////////////////////////////////////////// @@ -485,6 +499,8 @@ BOOL LLPanelAvatarProfile::postBuild()  	pic = getChild<LLTextureCtrl>("real_world_pic");  	pic->setFallbackImageName("default_profile_picture.j2c"); +	gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this); +  	resetControls();  	resetData(); @@ -568,8 +584,6 @@ void LLPanelAvatarProfile::processProfileProperties(const LLAvatarData* avatar_d  	fillPartnerData(avatar_data); -	fillOnlineStatus(avatar_data); -  	fillAccountStatus(avatar_data);  } @@ -637,21 +651,6 @@ void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data)  	}  } -void LLPanelAvatarProfile::fillOnlineStatus(const LLAvatarData* avatar_data) -{ -	bool online = avatar_data->flags & AVATAR_ONLINE; -	if(LLAvatarActions::isFriend(avatar_data->avatar_id)) -	{ -		// Online status NO could be because they are hidden -		// If they are a friend, we may know the truth! -		online = LLAvatarTracker::instance().isBuddyOnline(avatar_data->avatar_id); -	} -	childSetValue("online_status", online ? -		"Online" : "Offline"); -	childSetColor("online_status", online ?  -		LLColor4::green : LLColor4::red); -} -  void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data)  {  	LLStringUtil::format_map_t args; @@ -757,6 +756,8 @@ LLPanelAvatarProfile::~LLPanelAvatarProfile()  	if(getAvatarId().notNull())  	{  		LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); +		if(LLVoiceClient::getInstance()) +			LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);  	}  } @@ -766,6 +767,17 @@ void LLPanelAvatarProfile::changed(U32 mask)  	childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId()));  } +// virtual +void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +	{ +		return; +	} + +	childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); +} +  void LLPanelAvatarProfile::setAvatarId(const LLUUID& id)  {  	if(id.notNull()) diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 22efa5dc35..ce59f1e93d 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -36,6 +36,7 @@  #include "llpanel.h"  #include "llavatarpropertiesprocessor.h"  #include "llcallingcard.h" +#include "llvoiceclient.h"  class LLComboBox;  class LLLineEditor; @@ -122,6 +123,7 @@ private:  class LLPanelAvatarProfile  	: public LLPanelProfileTab  	, public LLFriendObserver +	, public LLVoiceClientStatusObserver  {  public:  	LLPanelAvatarProfile(); @@ -134,6 +136,10 @@ public:  	 */  	virtual void changed(U32 mask); +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); +  	/*virtual*/ void setAvatarId(const LLUUID& id);  	/** @@ -172,11 +178,6 @@ protected:  	virtual void fillPartnerData(const LLAvatarData* avatar_data);  	/** -	 * Fills Avatar's online status. -	 */ -	virtual void fillOnlineStatus(const LLAvatarData* avatar_data); - -	/**  	 * Fills account status.  	 */  	virtual void fillAccountStatus(const LLAvatarData* avatar_data); @@ -257,6 +258,7 @@ private:  class LLPanelAvatarNotes   	: public LLPanelProfileTab  	, public LLFriendObserver +	, public LLVoiceClientStatusObserver  {  public:  	LLPanelAvatarNotes(); @@ -269,6 +271,10 @@ public:  	 */  	virtual void changed(U32 mask); +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); +  	/*virtual*/ void onOpen(const LLSD& key);  	/*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index c30ef3221d..1d447a22d7 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -101,6 +101,8 @@ LLPanelGroup::LLPanelGroup()  LLPanelGroup::~LLPanelGroup()  {  	LLGroupMgr::getInstance()->removeObserver(this); +	if(LLVoiceClient::getInstance()) +		LLVoiceClient::getInstance()->removeObserver(this);  }  void LLPanelGroup::onOpen(const LLSD& key) @@ -188,6 +190,8 @@ BOOL LLPanelGroup::postBuild()  	if(panel_general)  		panel_general->setupCtrls(this); + +	gVoiceClient->addObserver(this);  	return TRUE;  } @@ -300,6 +304,17 @@ void LLPanelGroup::changed(LLGroupChange gc)  	update(gc);  } +// virtual +void LLPanelGroup::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +	{ +		return; +	} + +	childSetEnabled("btn_call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); +} +  void LLPanelGroup::notifyObservers()  {  	changed(GC_ALL); @@ -356,6 +371,13 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)  	for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)  		(*it)->setGroupID(group_id); +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); +	if(gdatap) +	{ +		childSetValue("group_name", gdatap->mName); +		childSetToolTip("group_name",gdatap->mName); +	} +  	LLButton* button_apply = findChild<LLButton>("btn_apply");  	LLButton* button_refresh = findChild<LLButton>("btn_refresh");  	LLButton* button_create = findChild<LLButton>("btn_create"); @@ -457,17 +479,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)  	}  	reposButtons(); - -	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); - -	if(gdatap) -	{ -		childSetValue("group_name", gdatap->mName); -		childSetToolTip("group_name",gdatap->mName); -		 -		//group data is already present, call update manually -		update(GC_ALL); -	}  }  bool LLPanelGroup::apply(LLPanelGroupTab* tab) diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index 7ea5e67b44..8c84695677 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -35,6 +35,7 @@  #include "llgroupmgr.h"  #include "llpanel.h"  #include "lltimer.h" +#include "llvoiceclient.h"  struct LLOfferInfo; @@ -47,7 +48,8 @@ class LLAgent;  class LLPanelGroup : public LLPanel, -					 public LLGroupMgrObserver  +					 public LLGroupMgrObserver, +					 public LLVoiceClientStatusObserver  {  public:  	LLPanelGroup(); @@ -64,6 +66,10 @@ public:  	// Group manager observer trigger.  	virtual void changed(LLGroupChange gc); +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); +  	void showNotice(const std::string& subject,  					const std::string& message,  					const bool& has_inventory, diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 45f0381d6f..c6287472fe 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -867,7 +867,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()  	for (itor = selection.begin();  		 itor != selection.end(); ++itor)  	{ -		LLUUID member_id = (*itor)->getValue()["uuid"]; +		LLUUID member_id = (*itor)->getUUID();  		selected_members.push_back( member_id );  		// Get this member's power mask including any unsaved changes @@ -1093,7 +1093,7 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()  	for (itor = selection.begin() ;   		 itor != selection.end(); ++itor)  	{ -		LLUUID member_id = (*itor)->getValue()["uuid"]; +		LLUUID member_id = (*itor)->getUUID();  		selected_members.push_back( member_id );  	} @@ -1151,7 +1151,7 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,  		 itor != selection.end(); ++itor)  	{ -		member_id = (*itor)->getValue()["uuid"]; +		member_id = (*itor)->getUUID();  		//see if we requested a change for this member before  		if ( mMemberRoleChangeData.find(member_id) == mMemberRoleChangeData.end() ) @@ -1242,7 +1242,7 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()  	LLScrollListItem* selected = mMembersList->getFirstSelected();  	if (selected)  	{ -		LLUUID member_id = selected->getValue()["uuid"]; +		LLUUID member_id = selected->getUUID();  		LLAvatarActions::showProfile( member_id );  	}  } @@ -1632,7 +1632,7 @@ void LLPanelGroupMembersSubTab::updateMembers()  			LLScrollListItem* member = mMembersList->addElement(row);//, ADD_SORTED); -			LLUUID id = member->getValue()["uuid"]; +			LLUUID id = member->getUUID();  			mHasMatch = TRUE;  		}  	} diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index a334eb9d68..ff1e43b526 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -64,21 +64,52 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked()  	LLFloaterReg::showInstance("voice_controls");  } +void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +	{ +		return; +	} + +	updateCallButton(); +} +  void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)  {  	updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);  } +void LLPanelChatControlPanel::updateCallButton() +{ +	// hide/show call button +	bool voice_enabled = LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking(); + +	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); +	if (!session) return; + +	bool session_initialized = session->mSessionInitialized; +	bool callback_enabled = session->mCallBackEnabled; + +	BOOL enable_connect = session_initialized +		&& voice_enabled +		&& callback_enabled; +	childSetEnabled("call_btn", enable_connect); +} +  void LLPanelChatControlPanel::updateButtons(bool is_call_started)  {  	childSetVisible("end_call_btn_panel", is_call_started);  	childSetVisible("voice_ctrls_btn_panel", is_call_started);  	childSetVisible("call_btn_panel", ! is_call_started); +	updateCallButton(); +	  }  LLPanelChatControlPanel::~LLPanelChatControlPanel()  {  	mVoiceChannelStateChangeConnection.disconnect(); +	if(LLVoiceClient::getInstance()) +		LLVoiceClient::getInstance()->removeObserver(this);  }  BOOL LLPanelChatControlPanel::postBuild() @@ -87,26 +118,9 @@ BOOL LLPanelChatControlPanel::postBuild()  	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));  	childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this)); -	return TRUE; -} - -void LLPanelChatControlPanel::draw() -{ -	// hide/show start call and end call buttons -	bool voice_enabled = LLVoiceClient::voiceEnabled(); - -	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); -	if (!session) return; +	gVoiceClient->addObserver(this); -	bool session_initialized = session->mSessionInitialized; -	bool callback_enabled = session->mCallBackEnabled; - -	BOOL enable_connect = session_initialized -		&& voice_enabled -		&& callback_enabled; -	childSetEnabled("call_btn", enable_connect); - -	LLPanel::draw(); +	return TRUE;  }  void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) @@ -266,6 +280,8 @@ void LLPanelGroupControlPanel::draw()  	// Need to resort the participant list if it's in sort by recent speaker order.  	if (mParticipantList)  		mParticipantList->updateRecentSpeakersOrder(); +	//* TODO: find better way to properly enable call button for group and remove this call from draw() +	updateCallButton();  	LLPanelChatControlPanel::draw();  } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 25fdf944c9..3ab505a084 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -39,7 +39,9 @@  class LLParticipantList; -class LLPanelChatControlPanel : public LLPanel +class LLPanelChatControlPanel  +	: public LLPanel +	, public LLVoiceClientStatusObserver  {  public:  	LLPanelChatControlPanel() : @@ -47,15 +49,21 @@ public:  	~LLPanelChatControlPanel();  	virtual BOOL postBuild(); -	virtual void draw();  	void onCallButtonClicked();  	void onEndCallButtonClicked();  	void onOpenVoiceControlsClicked(); +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); +  	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);  	void updateButtons(bool is_call_started); +	 +	// Enables/disables call button depending on voice availability +	void updateCallButton();  	virtual void setSessionId(const LLUUID& session_id);  	const LLUUID& getSessionId() { return mSessionId; } diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 9654e17659..c792fd4fe3 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -98,10 +98,10 @@ void LLPanelLandmarkInfo::resetLocation()  {  	LLPanelPlaceInfo::resetLocation(); -	std::string not_available = getString("not_available"); -	mCreator->setText(not_available); -	mOwner->setText(not_available); -	mCreated->setText(not_available); +	std::string loading = LLTrans::getString("LoadingData"); +	mCreator->setText(loading); +	mOwner->setText(loading); +	mCreated->setText(loading);  	mLandmarkTitle->setText(LLStringUtil::null);  	mLandmarkTitleEditor->setText(LLStringUtil::null);  	mNotesEditor->setText(LLStringUtil::null); diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index ece93125b3..0f0fb4b94e 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -198,8 +198,6 @@ void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_d  {  	fillCommonData(avatar_data); -	fillOnlineStatus(avatar_data); -  	fillPartnerData(avatar_data);  	fillAccountStatus(avatar_data); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index c14b282488..b01cdcc832 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -462,6 +462,9 @@ LLPanelPeople::~LLPanelPeople()  	delete mFriendListUpdater;  	delete mRecentListUpdater; +	if(LLVoiceClient::getInstance()) +		LLVoiceClient::getInstance()->removeObserver(this); +  	LLView::deleteViewByHandle(mGroupPlusMenuHandle);  	LLView::deleteViewByHandle(mNearbyViewSortMenuHandle);  	LLView::deleteViewByHandle(mFriendsViewSortMenuHandle); @@ -612,6 +615,8 @@ BOOL LLPanelPeople::postBuild()  	if(recent_view_sort)  		mRecentViewSortMenuHandle  = recent_view_sort->getHandle(); +	gVoiceClient->addObserver(this); +  	// call this method in case some list is empty and buttons can be in inconsistent state  	updateButtons(); @@ -621,6 +626,17 @@ BOOL LLPanelPeople::postBuild()  	return TRUE;  } +// virtual +void LLPanelPeople::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) +	{ +		return; +	} +	 +	updateButtons(); +} +  void LLPanelPeople::updateFriendList()  {  	if (!mOnlineFriendList || !mAllFriendList) @@ -775,41 +791,20 @@ void LLPanelPeople::updateButtons()  		}  	} +	bool enable_calls = gVoiceClient->voiceWorking() && gVoiceClient->voiceEnabled(); +  	buttonSetEnabled("teleport_btn",		friends_tab_active && item_selected && isFriendOnline(selected_uuids.front()));  	buttonSetEnabled("view_profile_btn",	item_selected);  	buttonSetEnabled("im_btn",				multiple_selected); // allow starting the friends conference for multiple selection -	buttonSetEnabled("call_btn",			multiple_selected && canCall()); +	buttonSetEnabled("call_btn",			multiple_selected && enable_calls);  	buttonSetEnabled("share_btn",			item_selected); // not implemented yet  	bool none_group_selected = item_selected && selected_id.isNull();  	buttonSetEnabled("group_info_btn", !none_group_selected); -	buttonSetEnabled("group_call_btn", !none_group_selected); +	buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls);  	buttonSetEnabled("chat_btn", !none_group_selected);  } -bool LLPanelPeople::canCall() -{ -	std::vector<LLUUID> selected_uuids; -	getCurrentItemIDs(selected_uuids); - -	bool result = false; - -	std::vector<LLUUID>::const_iterator -		id = selected_uuids.begin(), -		uuids_end = selected_uuids.end(); - -	for (;id != uuids_end; ++id) -	{ -		if (LLAvatarActions::canCall(*id)) -		{ -			result = true; -			break; -		} -	} - -	return result; -} -  std::string LLPanelPeople::getActiveTabName() const  {  	return mTabContainer->getCurrentPanel()->getName(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 7580fdbeef..6d3d436156 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -36,13 +36,16 @@  #include <llpanel.h>  #include "llcallingcard.h" // for avatar tracker +#include "llvoiceclient.h"  class LLFilterEditor;  class LLTabContainer;  class LLAvatarList;  class LLGroupList; -class LLPanelPeople : public LLPanel +class LLPanelPeople  +	: public LLPanel +	, public LLVoiceClientStatusObserver  {  	LOG_CLASS(LLPanelPeople);  public: @@ -52,6 +55,9 @@ public:  	/*virtual*/ BOOL 	postBuild();  	/*virtual*/ void	onOpen(const LLSD& key);  	/*virtual*/ bool	notifyChildren(const LLSD& info); +	// Implements LLVoiceClientStatusObserver::onChange() to enable call buttons +	// when voice is available +	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);  	// internals  	class Updater; @@ -73,7 +79,6 @@ private:  	bool					isFriendOnline(const LLUUID& id);  	bool					isItemsFreeOfFriends(const std::vector<LLUUID>& uuids); -	bool 					canCall();  	void					updateButtons();  	std::string				getActiveTabName() const; diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index c1c10e6022..d9651a6045 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -183,20 +183,7 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)  	}  	else if (item == std::string("can_call"))  	{ -		bool result = false; -		std::vector<LLUUID>::const_iterator -			id = mUUIDs.begin(), -			uuids_end = mUUIDs.end(); - -		for (;id != uuids_end; ++id) -		{ -			if (LLAvatarActions::canCall(*id)) -			{ -				result = true; -				break; -			} -		} -		return result; +		return LLAvatarActions::canCall();  	}  	return false;  } diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 0c10f11bfc..5f75668722 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -43,6 +43,8 @@  #include "lliconctrl.h"  #include "lltextbox.h" +#include "lltrans.h" +  #include "llagent.h"  #include "llexpandabletextbox.h"  #include "llpanelpick.h" @@ -99,12 +101,12 @@ void LLPanelPlaceInfo::resetLocation()  	mRequestedID.setNull();  	mPosRegion.clearVec(); -	std::string not_available = getString("not_available"); -	mMaturityRatingIcon->setValue(not_available); -	mMaturityRatingText->setValue(not_available); -	mRegionName->setText(not_available); -	mParcelName->setText(not_available); -	mDescEditor->setText(not_available); +	std::string loading = LLTrans::getString("LoadingData"); +	mMaturityRatingIcon->setValue(loading); +	mMaturityRatingText->setValue(loading); +	mRegionName->setText(loading); +	mParcelName->setText(loading); +	mDescEditor->setText(loading);  	mSnapshotCtrl->setImageAssetID(LLUUID::null);  	mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c"); @@ -206,6 +208,10 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)  	{  		mDescEditor->setText(parcel_data.desc);  	} +	else +	{ +		mDescEditor->setText(getString("not_available")); +	}  	S32 region_x;  	S32 region_y; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index d892e2885b..3c798639d4 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -42,6 +42,8 @@  #include "lltextbox.h"  #include "lltexteditor.h" +#include "lltrans.h" +  #include "llaccordionctrl.h"  #include "llaccordionctrltab.h"  #include "llagent.h" @@ -163,45 +165,45 @@ void LLPanelPlaceProfile::resetLocation()  	mForSalePanel->setVisible(FALSE);  	mYouAreHerePanel->setVisible(FALSE); -	std::string not_available = getString("not_available"); -	mParcelOwner->setValue(not_available); - -	mParcelRatingIcon->setValue(not_available); -	mParcelRatingText->setText(not_available); -	mVoiceIcon->setValue(not_available); -	mVoiceText->setText(not_available); -	mFlyIcon->setValue(not_available); -	mFlyText->setText(not_available); -	mPushIcon->setValue(not_available); -	mPushText->setText(not_available); -	mBuildIcon->setValue(not_available); -	mBuildText->setText(not_available); -	mScriptsIcon->setValue(not_available); -	mScriptsText->setText(not_available); -	mDamageIcon->setValue(not_available); -	mDamageText->setText(not_available); - -	mRegionNameText->setValue(not_available); -	mRegionTypeText->setValue(not_available); -	mRegionRatingIcon->setValue(not_available); -	mRegionRatingText->setValue(not_available); -	mRegionOwnerText->setValue(not_available); -	mRegionGroupText->setValue(not_available); - -	mEstateNameText->setValue(not_available); -	mEstateRatingText->setValue(not_available); -	mEstateOwnerText->setValue(not_available); -	mCovenantText->setValue(not_available); - -	mSalesPriceText->setValue(not_available); -	mAreaText->setValue(not_available); -	mTrafficText->setValue(not_available); -	mPrimitivesText->setValue(not_available); -	mParcelScriptsText->setValue(not_available); -	mTerraformLimitsText->setValue(not_available); -	mSubdivideText->setValue(not_available); -	mResaleText->setValue(not_available); -	mSaleToText->setValue(not_available); +	std::string loading = LLTrans::getString("LoadingData"); +	mParcelOwner->setValue(loading); + +	mParcelRatingIcon->setValue(loading); +	mParcelRatingText->setText(loading); +	mVoiceIcon->setValue(loading); +	mVoiceText->setText(loading); +	mFlyIcon->setValue(loading); +	mFlyText->setText(loading); +	mPushIcon->setValue(loading); +	mPushText->setText(loading); +	mBuildIcon->setValue(loading); +	mBuildText->setText(loading); +	mScriptsIcon->setValue(loading); +	mScriptsText->setText(loading); +	mDamageIcon->setValue(loading); +	mDamageText->setText(loading); + +	mRegionNameText->setValue(loading); +	mRegionTypeText->setValue(loading); +	mRegionRatingIcon->setValue(loading); +	mRegionRatingText->setValue(loading); +	mRegionOwnerText->setValue(loading); +	mRegionGroupText->setValue(loading); + +	mEstateNameText->setValue(loading); +	mEstateRatingText->setValue(loading); +	mEstateOwnerText->setValue(loading); +	mCovenantText->setValue(loading); + +	mSalesPriceText->setValue(loading); +	mAreaText->setValue(loading); +	mTrafficText->setValue(loading); +	mPrimitivesText->setValue(loading); +	mParcelScriptsText->setValue(loading); +	mTerraformLimitsText->setValue(loading); +	mSubdivideText->setValue(loading); +	mResaleText->setValue(loading); +	mSaleToText->setValue(loading);  }  // virtual diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index a4f0e55a93..7272a8a652 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -34,7 +34,7 @@  #include "llpanelplaces.h"  #include "llassettype.h" -#include "llwindow.h" +#include "lltimer.h"  #include "llinventory.h"  #include "lllandmark.h" @@ -49,6 +49,8 @@  #include "lltrans.h"  #include "lluictrlfactory.h" +#include "llwindow.h" +  #include "llagent.h"  #include "llagentpicksinfo.h"  #include "llavatarpropertiesprocessor.h" @@ -73,6 +75,7 @@  #include "llviewerwindow.h"  static const S32 LANDMARK_FOLDERS_MENU_WIDTH = 250; +static const F32 PLACE_INFO_UPDATE_INTERVAL = 3.0;  static const std::string AGENT_INFO_TYPE			= "agent";  static const std::string CREATE_LANDMARK_INFO_TYPE	= "create_landmark";  static const std::string LANDMARK_INFO_TYPE			= "landmark"; @@ -384,6 +387,10 @@ void LLPanelPlaces::onOpen(const LLSD& key)  	// Otherwise stop using land selection and deselect land.  	if (mPlaceInfoType == AGENT_INFO_TYPE)  	{ +		// We don't know if we are already added to LLViewerParcelMgr observers list +		// so try to remove observer not to add an extra one. +		parcel_mgr->removeObserver(mParcelObserver); +  		parcel_mgr->addObserver(mParcelObserver);  		parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());  	} @@ -826,6 +833,10 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)  		{  			mPlaceProfile->resetLocation(); +			// Do not reset location info until mResetInfoTimer has expired +			// to avoid text blinking. +			mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL); +  			LLRect rect = getRect();  			LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);  			mPlaceProfile->reshape(new_rect.getWidth(), new_rect.getHeight()); @@ -898,6 +909,8 @@ void LLPanelPlaces::changedParcelSelection()  	if (!region || !parcel)  		return; +	LLVector3d prev_pos_global = mPosGlobal; +  	// If agent is inside the selected parcel show agent's region<X, Y, Z>,  	// otherwise show region<X, Y, Z> of agent's selection point.  	bool is_current_parcel = is_agent_in_selected_parcel(parcel); @@ -914,7 +927,14 @@ void LLPanelPlaces::changedParcelSelection()  		}  	} -	mPlaceProfile->resetLocation(); +	// Reset location info only if global position has changed +	// and update timer has expired to reduce unnecessary text and icons updates. +	if (prev_pos_global != mPosGlobal && mResetInfoTimer.hasExpired()) +	{ +		mPlaceProfile->resetLocation(); +		mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL); +	} +  	mPlaceProfile->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel);  	updateVerbs(); diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 0eba7f3afc..a098974659 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -34,6 +34,8 @@  #include "llpanel.h" +class LLTimer; +  class LLInventoryItem;  class LLFilterEditor;  class LLLandmark; @@ -132,6 +134,10 @@ private:  	// be available (hence zero)  	LLVector3d					mPosGlobal; +	// Sets a period of time during which the requested place information +	// is expected to be updated and doesn't need to be reset. +	LLTimer						mResetInfoTimer; +  	// Information type currently shown in Place Information panel  	std::string					mPlaceInfoType; diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index 7832f63e6a..044036ea50 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -101,8 +101,6 @@ void LLPanelProfileView::onOpen(const LLSD& key)  		id = key["id"];  	} -	// subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself -	mAvatarStatusObserver->subscribe();  	if(id.notNull() && getAvatarId() != id)  	{  		setAvatarId(id); @@ -111,12 +109,9 @@ void LLPanelProfileView::onOpen(const LLSD& key)  	// Update the avatar name.  	gCacheName->get(getAvatarId(), FALSE,  		boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4)); -/* -// disable this part of code according to EXT-2022. See processOnlineStatus -	// status should only show if viewer has permission to view online/offline. EXT-453  -	mStatusText->setVisible(isGrantedToSeeOnlineStatus()); +  	updateOnlineStatus(); -*/ +  	LLPanelProfile::onOpen(key);  } @@ -164,27 +159,43 @@ bool LLPanelProfileView::isGrantedToSeeOnlineStatus()  	// *NOTE: GRANT_ONLINE_STATUS is always set to false while changing any other status.  	// When avatar disallow me to see her online status processOfflineNotification Message is received by the viewer  	// see comments for ChangeUserRights template message. EXT-453. -//	return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); -	return true; +	// If GRANT_ONLINE_STATUS flag is changed it will be applied when viewer restarts. EXT-3880 +	return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS);  } +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880  void LLPanelProfileView::updateOnlineStatus()  { +	// set text box visible to show online status for non-friends who has not set in Preferences +	// "Only Friends & Groups can see when I am online" +	mStatusText->setVisible(TRUE); +  	const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());  	if (NULL == relationship) -		return; +	{ +		// this is non-friend avatar. Status will be updated from LLAvatarPropertiesProcessor. +		// in LLPanelProfileView::processOnlineStatus() -	bool online = relationship->isOnline(); +		// subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself. +		// do not subscribe for friend avatar because online status can be wrong overridden +		// via LLAvatarData::flags if Preferences: "Only Friends & Groups can see when I am online" is set. +		mAvatarStatusObserver->subscribe(); +		return; +	} +	// For friend let check if he allowed me to see his status -	std::string status = getString(online ? "status_online" : "status_offline"); +	// status should only show if viewer has permission to view online/offline. EXT-453, EXT-3880 +	mStatusText->setVisible(isGrantedToSeeOnlineStatus()); -	mStatusText->setValue(status); +	bool online = relationship->isOnline(); +	processOnlineStatus(online);  }  void LLPanelProfileView::processOnlineStatus(bool online)  { -	mAvatarIsOnline = online; -	mStatusText->setVisible(online); +	std::string status = getString(online ? "status_online" : "status_offline"); + +	mStatusText->setValue(status);  }  void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group) @@ -193,17 +204,4 @@ void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string&  	getChild<LLUICtrl>("user_name", FALSE)->setValue(first_name + " " + last_name);  } -void LLPanelProfileView::togglePanel(LLPanel* panel, const LLSD& key) -{ -	// *TODO: unused method? - -	LLPanelProfile::togglePanel(panel); -	if(FALSE == panel->getVisible()) -	{ -		// LLPanelProfile::togglePanel shows/hides all children, -		// we don't want to display online status for non friends, so re-hide it here -		mStatusText->setVisible(mAvatarIsOnline); -	} -} -  // EOF diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h index 5dc617d4a0..9b87e146a8 100644 --- a/indra/newview/llpanelprofileview.h +++ b/indra/newview/llpanelprofileview.h @@ -64,8 +64,6 @@ public:  	/*virtual*/ BOOL postBuild(); -	/*virtual*/ void togglePanel(LLPanel* panel, const LLSD& key = LLSD()); -  	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,  						   BOOL drop, EDragAndDropType cargo_type,  						   void *cargo_data, EAcceptance *accept, @@ -81,8 +79,21 @@ public:  protected:  	void onBackBtnClick(); -	bool isGrantedToSeeOnlineStatus(); // deprecated after EXT-2022 is implemented -	void updateOnlineStatus(); // deprecated after EXT-2022 is implemented +	bool isGrantedToSeeOnlineStatus(); + +	/** +	 * Displays avatar's online status if possible. +	 * +	 * Requirements from EXT-3880: +	 * For friends: +	 * - Online when online and privacy settings allow to show +	 * - Offline when offline and privacy settings allow to show +	 * - Else: nothing +	 * For other avatars: +	 *  - Online when online and was not set in Preferences/"Only Friends & Groups can see when I am online" +	 *  - Else: Offline +	 */ +	void updateOnlineStatus();  	void processOnlineStatus(bool online);  private: @@ -96,7 +107,6 @@ private:  	LLTextBox* mStatusText;  	AvatarStatusObserver* mAvatarStatusObserver; -	bool mAvatarIsOnline;  };  #endif //LL_LLPANELPROFILEVIEW_H diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 88b706fb6b..d54cbfe203 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -433,6 +433,12 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(  		"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); +	// AD *TODO: This is workaround for EXT-4725- way to properly enable/disable "Call" menu item in +	// enableContextMenuItem() should be found. +	bool not_agent = mUUIDs.front() != gAgentID; +	bool can_call = not_agent && LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking(); +	main_menu->setItemEnabled("Call", can_call); +  	// Don't show sort options for P2P chat  	bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);  	main_menu->setItemVisible("SortByName", is_sort_visible); @@ -628,7 +634,9 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&  	}  	else if (item == "can_call")  	{ -		return LLVoiceClient::voiceEnabled(); +		bool not_agent = mUUIDs.front() != gAgentID; +		bool can_call = not_agent && LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking(); +		return can_call;  	}  	return true; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 9608cd1263..6f9a1ccdbe 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -70,8 +70,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy  	{  		mDisplayName = name;  	} - -	gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));  } diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index a08e77e3d8..c79a66892d 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -68,7 +68,6 @@  #include "llviewermedia.h"  #include "llvoavatarself.h"  #include "llviewermediafocus.h" -#include "llvovolume.h"  #include "llworld.h"  #include "llui.h"  #include "llweb.h" @@ -630,14 +629,12 @@ static bool needs_tooltip(LLSelectNode* nodep)  		return false;  	LLViewerObject* object = nodep->getObject(); -	LLVOVolume* vovolume = dynamic_cast<LLVOVolume*>(object);  	LLViewerObject *parent = (LLViewerObject *)object->getParent();  	if (object->flagHandleTouch()  		|| (parent && parent->flagHandleTouch())  		|| object->flagTakesMoney()  		|| (parent && parent->flagTakesMoney())  		|| object->flagAllowInventoryAdd() -		|| (vovolume && vovolume->hasMedia())  		)  	{  		return true; diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp index c9bfe178ce..9d39aa5182 100644 --- a/indra/newview/lltransientdockablefloater.cpp +++ b/indra/newview/lltransientdockablefloater.cpp @@ -48,6 +48,14 @@ LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockContro  LLTransientDockableFloater::~LLTransientDockableFloater()  {  	LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this); +	LLView* dock = getDockWidget(); +	LLTransientFloaterMgr::getInstance()->removeControlView( +			LLTransientFloaterMgr::DOCKED, this); +	if (dock != NULL) +	{ +		LLTransientFloaterMgr::getInstance()->removeControlView( +				LLTransientFloaterMgr::DOCKED, dock); +	}  }  void LLTransientDockableFloater::setVisible(BOOL visible) @@ -55,18 +63,18 @@ void LLTransientDockableFloater::setVisible(BOOL visible)  	LLView* dock = getDockWidget();  	if(visible && isDocked())  	{ -		LLTransientFloaterMgr::getInstance()->addControlView(this); +		LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, this);  		if (dock != NULL)  		{ -			LLTransientFloaterMgr::getInstance()->addControlView(dock); +			LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, dock);  		}  	}  	else  	{ -		LLTransientFloaterMgr::getInstance()->removeControlView(this); +		LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, this);  		if (dock != NULL)  		{ -			LLTransientFloaterMgr::getInstance()->removeControlView(dock); +			LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, dock);  		}  	} @@ -78,18 +86,18 @@ void LLTransientDockableFloater::setDocked(bool docked, bool pop_on_undock)  	LLView* dock = getDockWidget();  	if(docked)  	{ -		LLTransientFloaterMgr::getInstance()->addControlView(this); +		LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, this);  		if (dock != NULL)  		{ -			LLTransientFloaterMgr::getInstance()->addControlView(dock); +			LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, dock);  		}  	}  	else  	{ -		LLTransientFloaterMgr::getInstance()->removeControlView(this); +		LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, this);  		if (dock != NULL)  		{ -			LLTransientFloaterMgr::getInstance()->removeControlView(dock); +			LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, dock);  		}  	} diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp index 8f1a738453..d82403070b 100644 --- a/indra/newview/lltransientfloatermgr.cpp +++ b/indra/newview/lltransientfloatermgr.cpp @@ -46,6 +46,7 @@ LLTransientFloaterMgr::LLTransientFloaterMgr()  			&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));  	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>())); +	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(DOCKED, std::set<LLView*>()));  	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));  } @@ -132,7 +133,8 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,  		return;  	} -	bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y); +	bool hide = isControlClicked(mGroupControls.find(DOCKED)->second, x, y) +			&& isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);  	if (hide)  	{  		hideTransientFloaters(x, y); diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h index 1f99325a7f..9c5ae295f2 100644 --- a/indra/newview/lltransientfloatermgr.h +++ b/indra/newview/lltransientfloatermgr.h @@ -51,7 +51,7 @@ protected:  public:  	enum ETransientGroup  	{ -		GLOBAL, IM +		GLOBAL, DOCKED, IM  	};  	void registerTransientFloater(LLTransientFloater* floater); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index f650bdbbd1..2d9e2ef7c9 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -208,6 +208,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);  	LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>); +	LLFloaterReg::add("call_info", "floater_call_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallInfoDialog>);  	LLFloaterReg::add("parcel_info", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterParcelInfo>);  	LLFloaterPayUtil::registerFloater(); diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp index 5af79b4fd3..b82538dacb 100644 --- a/indra/newview/llviewerhelp.cpp +++ b/indra/newview/llviewerhelp.cpp @@ -33,6 +33,7 @@  #include "llviewerprecompiledheaders.h" +#include "llcommandhandler.h"  #include "llfloaterhelpbrowser.h"  #include "llfloaterreg.h"  #include "llfocusmgr.h" @@ -43,6 +44,33 @@  #include "llviewerhelputil.h"  #include "llviewerhelp.h" +// support for secondlife:///app/help/{TOPIC} SLapps +class LLHelpHandler : public LLCommandHandler +{ +public: +	// requests will be throttled from a non-trusted browser +	LLHelpHandler() : LLCommandHandler("help", UNTRUSTED_THROTTLE) {} + +	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +	{ +		LLViewerHelp* vhelp = LLViewerHelp::getInstance(); +		if (! vhelp) +		{ +			return false; +		} + +		// get the requested help topic name, or use the fallback if none +		std::string help_topic = vhelp->defaultTopic(); +		if (params.size() >= 1) +		{ +			help_topic = params[0].asString(); +		} + +		vhelp->showTopic(help_topic); +		return true; +	} +}; +LLHelpHandler gHelpHandler;  //////////////////////////////  // implement LLHelp interface @@ -65,18 +93,16 @@ void LLViewerHelp::showTopic(const std::string &topic)  		help_topic = defaultTopic();  	} -	// f1 help topic means: if user not logged in yet, show the -	// pre-login topic, otherwise show help for the focused item +	// f1 help topic means: if the user is not logged in yet, show +	// the pre-login topic instead of the default fallback topic, +	// otherwise show help for the focused item  	if (help_topic == f1HelpTopic())  	{ -		if (! LLLoginInstance::getInstance()->authSuccess()) +		help_topic = getTopicFromFocus(); +		if (help_topic == defaultTopic() && ! LLLoginInstance::getInstance()->authSuccess())  		{  			help_topic = preLoginTopic();  		} -		else -		{ -			help_topic = getTopicFromFocus(); -		}  	}  	// work out the URL for this topic and display it  diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 917b8747ea..7f3f019b07 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -58,7 +58,6 @@ public:  protected:  	~LLViewerInventoryItem( void ); // ref counted  	BOOL extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const { return extractSortFieldAndDisplayName(mName, sortField, displayName); } -	static char getSeparator() { return '@'; }  	mutable std::string mDisplayName;  public: @@ -67,6 +66,7 @@ public:  	virtual const std::string& getName() const;  	virtual const std::string& getDisplayName() const;  	static std::string getDisplayName(const std::string& name); +	static char getSeparator() { return '@'; }  	virtual S32 getSortField() const;  	virtual void setSortField(S32 sortField);  	virtual void rename(const std::string& new_name); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index d712446d83..98d8780b34 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -940,7 +940,6 @@ bool LLViewerMedia::firstRunCallback(const LLSD& notification, const LLSD& respo  	{  		// user has elected to automatically play media.  		gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE); -		gSavedSettings.setBOOL("AudioStreamingVideo", TRUE);  		gSavedSettings.setBOOL("AudioStreamingMusic", TRUE);  		gSavedSettings.setBOOL("AudioStreamingMedia", TRUE); @@ -961,7 +960,6 @@ bool LLViewerMedia::firstRunCallback(const LLSD& notification, const LLSD& respo  	{  		gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE);  		gSavedSettings.setBOOL("AudioStreamingMedia", FALSE); -		gSavedSettings.setBOOL("AudioStreamingVideo", FALSE);  		gSavedSettings.setBOOL("AudioStreamingMusic", FALSE);  	}  	return false; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 79aae9463b..0801e53fbf 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6389,10 +6389,9 @@ void handle_selected_texture_info(void*)     		msg.assign("Texture info for: ");     		msg.append(node->mName); -		//TODO* CHAT: how to show this? -		//LLSD args; -		//args["MESSAGE"] = msg; -		//LLNotificationsUtil::add("SystemMessage", args); +		LLSD args; +		args["MESSAGE"] = msg; +		LLNotificationsUtil::add("SystemMessage", args);     		U8 te_count = node->getObject()->getNumTEs();     		// map from texture ID to list of faces using it @@ -6425,10 +6424,9 @@ void handle_selected_texture_info(void*)     				msg.append( llformat("%d ", (S32)(it->second[i])));     			} -			//TODO* CHAT: how to show this? -			//LLSD args; -			//args["MESSAGE"] = msg; -			//LLNotificationsUtil::add("SystemMessage", args); +			LLSD args; +			args["MESSAGE"] = msg; +			LLNotificationsUtil::add("SystemMessage", args);     		}  	}  } @@ -7959,6 +7957,7 @@ void initialize_menus()  	commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));  	view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");  	view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call"); +	enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));  	view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");  	view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c463beb375..79c887844a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1365,10 +1365,9 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const  			if (check_offer_throttle(mFromName, true))  			{  				log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); -				//TODO* CHAT: how to show this? -				//LLSD args; -				//args["MESSAGE"] = log_message; -				//LLNotificationsUtil::add("SystemMessage", args); +				LLSD args; +				args["MESSAGE"] = log_message; +				LLNotificationsUtil::add("SystemMessage", args);  			}  			// we will want to open this item when it comes back. @@ -1410,11 +1409,10 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const  			// send the message  			msg->sendReliable(mHost); -			//TODO* CHAT: how to show this? -			//log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; -			//LLSD args; -			//args["MESSAGE"] = log_message; -			//LLNotificationsUtil::add("SystemMessage", args); +			log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; +			LLSD args; +			args["MESSAGE"] = log_message; +			LLNotificationsUtil::add("SystemMessage", args);  			if (busy &&	(!mFromGroup && !mFromObject))  			{ @@ -1436,6 +1434,31 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const  	return false;  } +std::string get_display_name(const std::string& name) +{ +	// We receive landmark name as \'<n>@name\' where <n> is a number +	// LLViewerInventoryItem::getDisplayName will remove \'<n>@ though we need the \' +	// Lets save all chars preceding @ and insert them back after <n>@ was removed + +	std::string saved; + +	if(std::string::npos != name.find(LLViewerInventoryItem::getSeparator())) +	{ +		int n = 0; +		while(!isdigit(name[n]) && LLViewerInventoryItem::getSeparator() != name[n]) +		{ +			++n; +		} +		saved = name.substr(0, n); +	} + +	std::string d_name = LLViewerInventoryItem::getDisplayName(name); +	d_name.insert(0, saved); +	LLStringUtil::trim(d_name); + +	return d_name; +} +  void inventory_offer_handler(LLOfferInfo* info)  {  	//Until throttling is implmented, busy mode should reject inventory instead of silently @@ -1475,7 +1498,7 @@ void inventory_offer_handler(LLOfferInfo* info)  	if(LLAssetType::AT_LANDMARK == info->mType)  	{ -		msg = LLViewerInventoryItem::getDisplayName(msg); +		msg = get_display_name(msg);  	}  	LLSD args; @@ -1843,11 +1866,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				// history.  Pretend the chat is from a local agent,  				// so it will go into the history but not be shown on screen. -				//TODO* CHAT: how to show this? -				//and this is not system message... -				//LLSD args; -				//args["MESSAGE"] = buffer; -				//LLNotificationsUtil::add("SystemMessage", args); +				LLSD args; +				args["MESSAGE"] = buffer; +				LLNotificationsUtil::add("SystemMessageTip", args);  			}  		}  		break; @@ -3078,10 +3099,9 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)  		{  			// Chat the "back" SLURL. (DEV-4907) -			//TODO* CHAT: how to show this? -			//LLSD args; -			//args["MESSAGE"] = message; -			//LLNotificationsUtil::add("SystemMessage", args); +			LLSD args; +			args["MESSAGE"] = "Teleport completed from " + gAgent.getTeleportSourceSLURL(); +			LLNotificationsUtil::add("SystemMessageTip", args);  			// Set the new position  			avatarp->setPositionAgent(agent_pos); diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index e87dbe5c07..c4fc2e5cab 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -179,7 +179,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel)  	if (!parcel) return; -	if (!gSavedSettings.getBOOL("AudioStreamingMedia") || !gSavedSettings.getBOOL("AudioStreamingVideo")) +	if (!gSavedSettings.getBOOL("AudioStreamingMedia"))  		return;  	std::string media_url = parcel->getMediaURL(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 73dc9745cb..7e6a4c00c6 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2777,7 +2777,6 @@ void LLViewerMediaTexture::updateClass()  #if 0  	//force to play media.  	gSavedSettings.setBOOL("AudioStreamingMedia", true) ; -	gSavedSettings.setBOOL("AudioStreamingVideo", true) ;  #endif  	for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); ) diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index 917d69fe16..589999c026 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -389,13 +389,13 @@ void LLVoiceChannel::setState(EState state)  	switch(state)  	{  	case STATE_RINGING: -		gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs); +		LLCallInfoDialog::show("ringing", mNotifyArgs);  		break;  	case STATE_CONNECTED: -		gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs); +		LLCallInfoDialog::show("connected", mNotifyArgs);  		break;  	case STATE_HUNG_UP: -		gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs); +		LLCallInfoDialog::show("hang_up", mNotifyArgs);  		break;  	default:  		break; @@ -635,7 +635,7 @@ void LLVoiceChannelGroup::setState(EState state)  	case STATE_RINGING:  		if ( !mIsRetrying )  		{ -			gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs); +			LLCallInfoDialog::show("ringing", mNotifyArgs);  		}  		doSetState(state); @@ -698,7 +698,7 @@ void LLVoiceChannelProximal::handleStatusChange(EStatusType status)  		// do not notify user when leaving proximal channel  		return;  	case STATUS_VOICE_DISABLED: -		 gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs); +		LLCallInfoDialog::show("unavailable", mNotifyArgs);  		return;  	default:  		break; @@ -897,7 +897,7 @@ void LLVoiceChannelP2P::setState(EState state)  		// so provide a special purpose message here  		if (mReceivedCall && state == STATE_RINGING)  		{ -			gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs); +			LLCallInfoDialog::show("answering", mNotifyArgs);  			doSetState(state);  			return;  		} diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index c84afa5af1..8ca0fd6ef6 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -37,8 +37,10 @@  // library includes  #include "llnotificationsutil.h" +#include "llsdserialize.h"  #include "llsdutil.h" +  // project includes  #include "llvoavatar.h"  #include "llbufferstream.h" @@ -1092,6 +1094,119 @@ static void killGateway()  #endif +class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage> +{ +	LOG_CLASS(LLSpeakerVolumeStorage); +public: + +	/** +	 * Sets internal voluem level for specified user. +	 * +	 * @param[in] speaker_id - LLUUID of user to store volume level for +	 * @param[in] volume - internal volume level to be stored for user. +	 */ +	void storeSpeakerVolume(const LLUUID& speaker_id, S32 volume); + +	/** +	 * Gets stored internal volume level for specified speaker. +	 * +	 * If specified user is not found default level will be returned. It is equivalent of  +	 * external level 0.5 from the 0.0..1.0 range. +	 * Default internal level is calculated as: internal = 400 * external^2 +	 * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100 +	 * +	 * @param[in] speaker_id - LLUUID of user to get his volume level +	 */ +	S32 getSpeakerVolume(const LLUUID& speaker_id); + +private: +	friend class LLSingleton<LLSpeakerVolumeStorage>; +	LLSpeakerVolumeStorage(); +	~LLSpeakerVolumeStorage(); + +	const static std::string SETTINGS_FILE_NAME; + +	void load(); +	void save(); + +	typedef std::map<LLUUID, S32> speaker_data_map_t; +	speaker_data_map_t mSpeakersData; +}; + +const std::string LLSpeakerVolumeStorage::SETTINGS_FILE_NAME = "volume_settings.xml"; + +LLSpeakerVolumeStorage::LLSpeakerVolumeStorage() +{ +	load(); +} + +LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage() +{ +	save(); +} + +void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, S32 volume) +{ +	mSpeakersData[speaker_id] = volume; +} + +S32 LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id) +{ +	// default internal level of user voice. +	const static LLUICachedControl<S32> DEFAULT_INTERNAL_VOLUME_LEVEL("VoiceDefaultInternalLevel", 100); +	S32 ret_val = DEFAULT_INTERNAL_VOLUME_LEVEL; +	speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id); +	 +	if (it != mSpeakersData.end()) +	{ +		ret_val = it->second; +	} +	return ret_val; +} + +void LLSpeakerVolumeStorage::load() +{ +	// load per-resident voice volume information +	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME); + +	LLSD settings_llsd; +	llifstream file; +	file.open(filename); +	if (file.is_open()) +	{ +		LLSDSerialize::fromXML(settings_llsd, file); +	} + +	for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); +		iter != settings_llsd.endMap(); ++iter) +	{ +		mSpeakersData.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); +	} +} + +void LLSpeakerVolumeStorage::save() +{ +	// If we quit from the login screen we will not have an SL account +	// name.  Don't try to save, otherwise we'll dump a file in +	// C:\Program Files\SecondLife\ or similar. JC +	std::string user_dir = gDirUtilp->getLindenUserDir(); +	if (!user_dir.empty()) +	{ +		std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME); +		LLSD settings_llsd; + +		for(speaker_data_map_t::const_iterator iter = mSpeakersData.begin(); iter != mSpeakersData.end(); ++iter) +		{ +			settings_llsd[iter->first.asString()] = iter->second; +		} + +		llofstream file; +		file.open(filename); +		LLSDSerialize::toPrettyXML(settings_llsd, file); +	} +} + +  ///////////////////////////////////////////////////////////////////////////////////////////////  LLVoiceClient::LLVoiceClient() : @@ -4914,7 +5029,9 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con  		}  		mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result)); -		 + +		result->mUserVolume = LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID); +  		LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;  	} @@ -5853,6 +5970,11 @@ bool LLVoiceClient::voiceEnabled()  	return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice");  } +bool LLVoiceClient::voiceWorking() +{ +	return (stateLoggedIn <= mState) && (mState <= stateLeavingSession); +} +  void LLVoiceClient::setLipSyncEnabled(BOOL enabled)  {  	mLipSyncEnabled = enabled; @@ -6158,6 +6280,9 @@ void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)  			participant->mUserVolume = llclamp(ivol, 0, 400);  			participant->mVolumeDirty = TRUE;  			mAudioSession->mVolumeDirty = TRUE; + +			// store this volume setting for future sessions +			LLSpeakerVolumeStorage::getInstance()->storeSpeakerVolume(id, participant->mUserVolume);  		}  	}  } diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 6231c6ba29..8f668dff19 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -191,6 +191,8 @@ static	void updatePosition(void);  		void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs  		void setVoiceEnabled(bool enabled);  		static bool voiceEnabled(); +		// Checks is voice working judging from mState +		bool voiceWorking();  		void setUsePTT(bool usePTT);  		void setPTTIsToggle(bool PTTIsToggle);  		bool getPTTIsToggle(); diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 0b48ba9321..b4d2dabc5c 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -18,7 +18,8 @@   single_instance="true"    width="320">    <string name="nudge_parabuild">Nudge 1</string> -  <string name="test_the_vlt">This string CHANGE is extracted.</string> +  <string name="test_the_vlt">This string CHANGE2 is extracted.</string> +  <string name="testing_eli">Just a test. change here. more change.</string>    <chat_history     allow_html="true"     bg_readonly_color="ChatHistoryBgColor" 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 613530b7aa..d2e5473157 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -11,7 +11,7 @@   can_dock="false"   can_minimize="true"   can_close="true" - visible="true" + visible="false"   width="360"   can_resize="true"   min_width="250" diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index b0bb282abd..775e7d66f7 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -2,9 +2,9 @@  <floater   legacy_header_height="13"   can_resize="true" - height="646" + height="546"   layout="topleft" - min_height="646" + min_height="546"   min_width="670"   name="floater_search"   help_topic="floater_search" @@ -21,7 +21,7 @@          Done      </floater.string>      <layout_stack -     bottom="641" +     bottom="541"       follows="left|right|top|bottom"       layout="topleft"       left="10" @@ -42,7 +42,7 @@               left="0"               name="browser"               top="0" -             height="600" +             height="500"               width="650" />              <text               follows="bottom|left" 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 f473a51ff6..c4411db8c5 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -56,7 +56,7 @@               height="18"               default_icon_name="Generic_Person"               layout="topleft" -             left="0" +             left="5"               name="user_icon"               top="0"               width="18" /> @@ -78,6 +78,7 @@               follows="top|right"               height="16"               layout="topleft" +             right="-3"               name="speaking_indicator"               left_pad="5"               visible="true" diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index 5b94645b60..c5b31c7f63 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -30,6 +30,8 @@       name="Call">          <menu_item_call.on_click           function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="Avatar.EnableCall" />      </menu_item_call>        <menu_item_call           label="Invite to Group" diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml index 0ad41546d2..ac9101cfd9 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -30,6 +30,8 @@       name="Call">          <menu_item_call.on_click           function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="Avatar.EnableCall" />      </menu_item_call>        <menu_item_call           label="Invite to Group" diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml index dde92f23b6..85ec174829 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml @@ -32,6 +32,8 @@     name="call">      <menu_item_call.on_click       function="InspectAvatar.Call"/> +    <menu_item_call.on_enable +     function="InspectAvatar.Gear.EnableCall"/>    </menu_item_call>    <menu_item_call     label="Teleport" diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index a0dec346a4..5f38522758 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -10,6 +10,7 @@      <menu       create_jump_keys="true"       label="Me" +     tear_off="true"       name="File">          <menu_item_call           label="Preferences" @@ -39,6 +40,7 @@      <menu       create_jump_keys="true"       label="Help" +     tear_off="true"       name="Help">          <menu_item_call           label="[SECOND_LIFE] Help" diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml index 805ffbae66..04e02d0f6c 100644 --- a/indra/newview/skins/default/xui/en/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -57,9 +57,6 @@       name="Call">           <menu_item_call.on_click           function="Avatar.Call" /> -        <menu_item_call.on_enable -         function="ParticipantList.EnableItem" -         parameter="can_call" />      </menu_item_call>      <menu_item_call       enabled="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4279097f62..0fe4e19bf1 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -244,6 +244,16 @@ Save all changes to clothing/body parts?    <notification     icon="alertmodal.tga" +   name="FriendsAndGroupsOnly" +   type="alertmodal"> +    Non-friends won't know that you've choosen to ignore their calls and instant messages. +    <usetemplate +     name="okbutton" +     yestext="Yes"/> +  </notification> + +  <notification +   icon="alertmodal.tga"     name="GrantModifyRights"     type="alertmodal">  Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission. diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index 615ade99a2..c605975c8e 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -65,28 +65,18 @@       height="15"       layout="topleft"       left_pad="5" +     right="-72"       name="last_interaction"       text_color="LtGray_50"       value="0s"       width="24" /> -    <output_monitor -     auto_update="true" -     follows="right" -     draw_border="false" -     height="16" -     layout="topleft" -     left_pad="5" -     mouse_opaque="true" -     name="speaking_indicator" -     visible="true" -     width="20" />      <button       follows="right"       height="16"       image_pressed="Info_Press"       image_unselected="Info_Over"       left_pad="3" -     right="-31" +     right="-53"       name="info_btn"       top_delta="-2"       width="16" /> @@ -96,9 +86,21 @@       image_overlay="ForwardArrow_Off"       layout="topleft"       left_pad="5" -     right="-3" +     right="-28"       name="profile_btn"       tool_tip="View profile"       top_delta="-2"       width="20" /> +    <output_monitor +     auto_update="true" +     follows="right" +     draw_border="false" +     height="16" +     layout="topleft" +     left_pad="5" +     right="-3" +     mouse_opaque="true" +     name="speaking_indicator" +     visible="true" +     width="20" />  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 2075d7e05b..db156f7877 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -2,7 +2,7 @@  <panel   border="false"   follows="all" - height="380" + height="420"   label="Land & L$"   layout="topleft"   left="0" @@ -237,7 +237,7 @@      </text>      <tab_container       follows="all" -     height="173" +     height="180"       halign="center"       layout="topleft"       left="0" @@ -250,7 +250,7 @@          <panel           border="false"           follows="all" -         height="173" +         height="180"           label="PLANNING"           layout="topleft"           left="0" @@ -275,7 +275,7 @@        <panel           border="false"           follows="all" -         height="173" +         height="180"           label="DETAILS"           layout="topleft"           left="0" @@ -296,41 +296,44 @@               word_wrap="true">                  Loading...              </text_editor> + +          <button +             height="20" +             image_overlay="Arrow_Left_Off" +             layout="topleft" +             left="5" +             name="earlier_details_button" +             tool_tip="Go back in time" +             top_pad="10" +             width="25" />              <button -	     follows="left|top" -	     height="18" -	     image_overlay="Arrow_Left_Off" -	     layout="topleft" -	     name="earlier_details_button" -	     tool_tip="Back" -             right="-45" -             bottom="0" -	     width="25" /> -             <button -	     follows="left|top" -	     height="18" -	     image_overlay="Arrow_Right_Off" -	     layout="topleft" -	     left_pad="10" -       name="later_details_button" -	     tool_tip="Next" -	     width="25" /> -        </panel> +             height="20" +             image_overlay="Arrow_Right_Off" +             layout="topleft" +             left_pad="5" +             name="later_details_button" +             tool_tip="Go forward in time" +             top_delta="0" +             width="25" />   + + +      </panel>        <panel           border="false"           follows="all" -         height="173" +         height="180"           label="SALES"           layout="topleft"           left_delta="0"           help_topic="group_money_sales_tab" +         mouse_opaque="false"           name="group_money_sales_tab"           top="0"           width="300">              <text_editor               type="string"               follows="all" -             height="140" +             height="130"               layout="topleft"               left="0"               max_length="4096" @@ -340,25 +343,24 @@               word_wrap="true">                  Loading...              </text_editor> -                         <button -             bottom="0" -	     follows="left|top" -	     height="18" -	     image_overlay="Arrow_Left_Off" -	     layout="topleft" -	     name="earlier_sales_button" -	     tool_tip="Back" -         right="-45" -	     width="25" /> -             <button -	     follows="left|top" -	     height="18" -	     image_overlay="Arrow_Right_Off" -	     layout="topleft" -	     left_pad="10" -         name="later_sales_button" -	     tool_tip="Next" -	     width="25" /> +            <button +             height="20" +             image_overlay="Arrow_Left_Off" +             layout="topleft" +             left="5" +             name="earlier_sales_button" +             tool_tip="Go back in time" +             top_pad="10" +             width="25" /> +            <button +             height="20" +             image_overlay="Arrow_Right_Off" +             layout="topleft" +             left_pad="5" +             name="later_sales_button" +             tool_tip="Go forward in time" +             top_delta="0" +             width="25" />          </panel>      </tab_container>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index a8e24366f2..0aaeb6114e 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -78,19 +78,19 @@       top_pad="10"       width="350" />  	<check_box -     control_name="MediaEnabled" +     name="media_enabled" +     control_name="AudioStreamingMedia"       height="16"       label="Media Enabled"       layout="topleft"       left="30" -     name="media_enabled"       top_pad="10"       width="350">         <check_box.commit_callback            function="Pref.MediaEnabled" />      </check_box>  	<check_box -	 enabled_control="MediaEnabled" +	 enabled_control="AudioStreamingMedia"       control_name="ParcelMediaAutoPlayEnable"       height="16"       label="Allow Media to auto-play" @@ -102,7 +102,19 @@         <check_box.commit_callback            function="Pref.ParcelMediaAutoPlayEnable" />      </check_box> -   <text +	<check_box +     control_name="AudioStreamingMusic" +     height="16" +     label="Music Enabled" +     layout="topleft" +     left="30" +     name="music_enabled" +     top_pad="10" +     width="350"> +       <check_box.commit_callback +          function="Pref.MusicEnabled" /> +    </check_box> +	<text        type="string"      length="1"      follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 17ababe854..8723e0a832 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -279,7 +279,7 @@        width="480" />      <radio_item        height="20" -      label="Use my browser (IE, Firefox)" +      label="Use my browser (IE, Firefox, Safari)"        layout="topleft"        left_delta="0"        name="external" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml index 4f40e00815..c5f3fcc27d 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml @@ -41,6 +41,7 @@       height="20"       layout="topleft"       left_pad="5" +     allow_html="false"       use_ellipses="true"       name="region"       text_color="white" diff --git a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml index ad3872587c..0552cd3108 100644 --- a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml @@ -33,7 +33,7 @@  	<button label="√ Tout" label_selected="Tout" name="check_all"/>  	<button label="Effacer" label_selected="Aucun" name="check_none"/>  	<text name="newperms"> -		Nouvelles permissions relatives au contenu +		Nouvelles permissions  	</text>  	<text name="GroupLabel">  		Groupe : diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml index 5d3a2e6312..4ca251f3d9 100644 --- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml @@ -28,7 +28,7 @@  		1234  	</line_editor>  	<text name="buying_label"> -		Pour le prix +		Pour  	</text>  	<text left_delta="68" name="currency_est" width="138">  		environ [LOCALAMOUNT] @@ -57,7 +57,7 @@  	<text bottom_delta="16" name="purchase_warning_notenough">  		Vous n'achetez pas assez de L$. Veuillez augmenter le montant.  	</text> -	<button label="Acheter maintenant" name="buy_btn"/> +	<button label="Acheter" name="buy_btn"/>  	<button label="Annuler" name="cancel_btn"/>  	<text left="5" name="info_cannot_buy" right="-5">  		Achat impossible diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml index 7727e1b657..52f8597dc2 100644 --- a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml +++ b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml @@ -13,8 +13,7 @@  	<check_box label="Photos" name="check_snapshot"/>  	<button label="Tout" label_selected="Tout" name="All" width="70"/>  	<button bottom_delta="0" label="Aucun" label_selected="Aucun" left="83" name="None" width="70"/> -	<check_box bottom_delta="-20" label="Toujours montrer  -les dossiers" name="check_show_empty"/> +	<check_box bottom_delta="-20" label="Toujours montrer  les dossiers" name="check_show_empty"/>  	<check_box bottom_delta="-36" label="Depuis la déconnexion" name="check_since_logoff"/>  	<text name="- OR -">  		Ou il y a... diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml index 2d5def55f3..9639e8415d 100644 --- a/indra/newview/skins/default/xui/fr/menu_viewer.xml +++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml @@ -49,7 +49,7 @@  		<menu_item_check label="Mini-carte" name="Mini-Map"/>  		<menu_item_check label="Carte du monde" name="World Map"/>  		<menu_item_call label="Photo" name="Take Snapshot"/> -		<menu label="Soleil" name="Environment Settings"> +		<menu label="Luminosité" name="Environment Settings">  			<menu_item_call label="Aube" name="Sunrise"/>  			<menu_item_call label="Milieu de journée" name="Noon"/>  			<menu_item_call label="Coucher de soleil" name="Sunset"/> diff --git a/indra/newview/skins/default/xui/fr/panel_edit_skin.xml b/indra/newview/skins/default/xui/fr/panel_edit_skin.xml index 5f9f49c9e8..649b91d66d 100644 --- a/indra/newview/skins/default/xui/fr/panel_edit_skin.xml +++ b/indra/newview/skins/default/xui/fr/panel_edit_skin.xml @@ -1,9 +1,9 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel name="edit_skin_panel">  	<panel name="avatar_skin_color_panel"> -		<texture_picker label="Tatouages tête" name="Head Tattoos" tool_tip="Cliquez pour sélectionner une image"/> -		<texture_picker label="Tatouages haut" name="Upper Tattoos" tool_tip="Cliquez pour sélectionner une image"/> -		<texture_picker label="Tatouages bas" name="Lower Tattoos" tool_tip="Cliquez pour sélectionner une image"/> +		<texture_picker label="Tatouage tête" name="Head Tattoos" tool_tip="Cliquez pour sélectionner une image"/> +		<texture_picker label="Tatouage haut" name="Upper Tattoos" tool_tip="Cliquez pour sélectionner une image"/> +		<texture_picker label="Tatouage bas" name="Lower Tattoos" tool_tip="Cliquez pour sélectionner une image"/>  	</panel>  	<accordion name="wearable_accordion">  		<accordion_tab name="skin_color_tab" title="Couleur de peau"/> diff --git a/indra/newview/skins/default/xui/fr/panel_main_inventory.xml b/indra/newview/skins/default/xui/fr/panel_main_inventory.xml index ea6cee1da5..9a98581cb4 100644 --- a/indra/newview/skins/default/xui/fr/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/fr/panel_main_inventory.xml @@ -15,7 +15,7 @@  	</panel>  	<menu_bar name="Inventory Menu">  		<menu label="Fichier" name="File"> -			<menu_item_call label="Ouvert" name="Open"/> +			<menu_item_call label="Ouvrir" name="Open"/>  			<menu label="Charger" name="upload">  				<menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>  				<menu_item_call label="Son ([COST] L$)..." name="Upload Sound"/> diff --git a/indra/newview/skins/default/xui/fr/panel_notes.xml b/indra/newview/skins/default/xui/fr/panel_notes.xml index 7fa583c32b..0195118fd8 100644 --- a/indra/newview/skins/default/xui/fr/panel_notes.xml +++ b/indra/newview/skins/default/xui/fr/panel_notes.xml @@ -1,10 +1,10 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel label="Notes et vie privée" name="panel_notes"> +<panel label="Notes/Perso" name="panel_notes">  	<layout_stack name="layout">  		<panel name="notes_stack">  			<scroll_container name="profile_scroll">  				<panel name="profile_scroll_panel"> -					<text name="status_message" value="Mes notes privées :"/> +					<text name="status_message" value="Mes notes perso :"/>  					<text name="status_message2" value="Autoriser cette personne à :"/>  					<check_box label="Afficher mon statut en ligne" name="status_check"/>  					<check_box label="Me situer sur la carte" name="map_check"/> diff --git a/indra/newview/skins/default/xui/fr/panel_people.xml b/indra/newview/skins/default/xui/fr/panel_people.xml index fb669f129b..ae2b96da3c 100644 --- a/indra/newview/skins/default/xui/fr/panel_people.xml +++ b/indra/newview/skins/default/xui/fr/panel_people.xml @@ -10,7 +10,7 @@  	<string name="groups_filter_label" value="Filtrer les groupes"/>  	<filter_editor label="Filtre" name="filter_input"/>  	<tab_container name="tabs"> -		<panel label="PROCHES" name="nearby_panel"> +		<panel label="PRÈS DE VOUS" name="nearby_panel">  			<panel label="bottom_panel" name="bottom_panel">  				<button name="nearby_view_sort_btn" tool_tip="Options"/>  				<button name="add_friend_btn" tool_tip="Ajouter le résident sélectionné à votre liste d'amis"/> diff --git a/indra/newview/skins/default/xui/fr/panel_picks.xml b/indra/newview/skins/default/xui/fr/panel_picks.xml index 63a518f8a6..cf110c27b5 100644 --- a/indra/newview/skins/default/xui/fr/panel_picks.xml +++ b/indra/newview/skins/default/xui/fr/panel_picks.xml @@ -10,7 +10,7 @@  		<accordion_tab name="tab_classifieds" title="Petites annonces"/>  	</accordion>  	<panel label="bottom_panel" name="edit_panel"> -		<button name="new_btn" tool_tip="Ajouter cet endroit à mes Favoris"/> +		<button name="new_btn" tool_tip="Ajouter cet endroit à mes Préférences"/>  	</panel>  	<panel name="buttons_cucks">  		<button label="Infos" name="info_btn"/> diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml index 13b467d205..d292b002f6 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml @@ -1,9 +1,9 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel label="Chat écrit" name="chat">  	<radio_group name="chat_font_size"> -		<radio_item label="Petite" name="radio"/> +		<radio_item label="Moins" name="radio"/>  		<radio_item label="Moyenne" name="radio2"/> -		<radio_item label="Grande" name="radio3"/> +		<radio_item label="Plus" name="radio3"/>  	</radio_group>  	<color_swatch label="Vous" name="user"/>  	<text name="text_box1"> diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_general.xml b/indra/newview/skins/default/xui/fr/panel_preferences_general.xml index 783bd3bcba..6d331704ea 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_general.xml @@ -38,15 +38,15 @@  	</combo_box>  	<check_box initial_value="true" label="Afficher à la connexion" name="show_location_checkbox"/>  	<text name="name_tags_textbox"> -		Étiquettes : +		Affichage des noms :  	</text>  	<radio_group name="Name_Tag_Preference"> -		<radio_item label="Désactivée" name="radio"/> -		<radio_item label="Activée" name="radio2"/> +		<radio_item label="Désactivé" name="radio"/> +		<radio_item label="Activé" name="radio2"/>  		<radio_item label="Afficher brièvement" name="radio3"/>  	</radio_group>  	<check_box label="Afficher mon nom" name="show_my_name_checkbox1"/> -	<check_box initial_value="true" label="Étiquettes courtes" name="small_avatar_names_checkbox"/> +	<check_box initial_value="true" label="Affichage en petit" name="small_avatar_names_checkbox"/>  	<check_box label="Afficher les titres de groupe" name="show_all_title_checkbox1"/>  	<text name="effects_color_textbox">  		Mes effets : diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml index b4b1783190..4459244395 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml @@ -12,7 +12,7 @@  		<combo_box.item label="1024 x 768" name="1024x768"/>  	</combo_box>  	<text name="UI Size:"> -		Taille de l'UI : +		Taille de l'interface :  	</text>  	<text name="QualitySpeed">  		Qualité et vitesse : @@ -21,7 +21,7 @@  		Plus rapide  	</text>  	<text name="BetterText"> -		Mieux +		Meilleur  	</text>  	<text name="ShadersPrefText">  		Faible diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml index c86a6da037..4bb6c76617 100644 --- a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml @@ -21,7 +21,7 @@  	<check_box label="Inclure les heures" name="show_timestamps_check_im"/>  	<line_editor left="308" name="log_path_string" right="-20"/>  	<text name="log_path_desc"> -		Emplacement des journaux +		Emplacement  	</text>  	<button label="Parcourir" label_selected="Parcourir" name="log_path_button" width="150"/>  	<button label="Liste des ignorés" name="block_list"/> diff --git a/indra/newview/skins/default/xui/fr/panel_profile_view.xml b/indra/newview/skins/default/xui/fr/panel_profile_view.xml index 146095a25f..8f57dd89c7 100644 --- a/indra/newview/skins/default/xui/fr/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/fr/panel_profile_view.xml @@ -11,6 +11,6 @@  	<tab_container name="tabs">  		<panel label="PROFIL" name="panel_profile"/>  		<panel label="FAVORIS" name="panel_picks"/> -		<panel label="NOTES ET VIE PRIVÉE" name="panel_notes"/> +		<panel label="NOTES/PERSO" name="panel_notes"/>  	</tab_container>  </panel> diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index a8e3ff1442..b45a016822 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -1729,7 +1729,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Taille du ventre  	</string>  	<string name="Big"> -		Maxi +		Plus  	</string>  	<string name="Big Butt">  		Grosses fesses @@ -1858,7 +1858,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Favoris  	</string>  	<string name="Chin Depth"> -		Profondeur du menton +		Profondeur  	</string>  	<string name="Chin Heavy">  		Menton lourd @@ -1873,7 +1873,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Menton-cou  	</string>  	<string name="Clear"> -		Effacer +		Clair  	</string>  	<string name="Cleft">  		Fendu @@ -1987,7 +1987,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Arc  	</string>  	<string name="Eyebrow Density"> -		Épaisseur +		Épaisseur sourcils  	</string>  	<string name="Eyebrow Height">  		Hauteur @@ -2041,7 +2041,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Jambes larges  	</string>  	<string name="Flat"> -		Plates +		Plat  	</string>  	<string name="Flat Butt">  		Fesses plates @@ -2107,13 +2107,13 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Sens de la coiffure  	</string>  	<string name="Hair Thickess"> -		Épaisseur +		Épaisseur cheveux  	</string>  	<string name="Hair Thickness"> -		Épaisseur +		Épaisseur cheveux  	</string>  	<string name="Hair Tilt"> -		Inclinaison des cheveux +		Inclinaison  	</string>  	<string name="Hair Tilted Left">  		Vers la gauche @@ -2200,7 +2200,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Plis de la veste  	</string>  	<string name="Jaw Angle"> -		Angle de la mâchoire +		Angle mâchoire  	</string>  	<string name="Jaw Jut">  		Saillie de la mâchoire @@ -2221,7 +2221,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Genoux rapprochés  	</string>  	<string name="Large"> -		Grand +		Plus  	</string>  	<string name="Large Hands">  		Grandes mains @@ -2230,16 +2230,16 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Raie à gauche  	</string>  	<string name="Leg Length"> -		Longueur de la jambe +		Longueur  	</string>  	<string name="Leg Muscles"> -		Muscles de la jambe +		Muscles  	</string>  	<string name="Less">  		Moins  	</string>  	<string name="Less Body Fat"> -		Moins de graisse +		Moins  	</string>  	<string name="Less Curtains">  		Moins @@ -2266,13 +2266,13 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Moins  	</string>  	<string name="Less Round"> -		Moins +		Moins ronde  	</string>  	<string name="Less Saddle">  		Moins  	</string>  	<string name="Less Square"> -		Moins +		Moins carrée  	</string>  	<string name="Less Volume">  		Moins @@ -2299,10 +2299,10 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Proportion des lèvres  	</string>  	<string name="Lip Thickness"> -		Épaisseur des lèvres +		Épaisseur  	</string>  	<string name="Lip Width"> -		Largeur des lèvres +		Largeur  	</string>  	<string name="Lipgloss">  		Brillant à lèvres @@ -2545,7 +2545,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Épaisseur du nez  	</string>  	<string name="Nose Tip Angle"> -		Angle du bout du nez +		Bout du nez  	</string>  	<string name="Nose Tip Shape">  		Bout du nez @@ -2629,7 +2629,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Raie  	</string>  	<string name="Part Bangs"> -		Séparation de la frange +		Séparation frange  	</string>  	<string name="Pectorals">  		Pectoraux @@ -2677,7 +2677,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Paupières  	</string>  	<string name="Rainbow Color"> -		Couleur de l'arc en ciel +		Couleur arc en ciel  	</string>  	<string name="Red Hair">  		Cheveux roux @@ -2725,10 +2725,10 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Front  	</string>  	<string name="Shear Left Up"> -		Haut gauche dégagé +		Haut gauche décalé  	</string>  	<string name="Shear Right Up"> -		Haut droit dégagé +		Haut droit décalé  	</string>  	<string name="Sheared Back">  		Dégagé derrière @@ -2758,7 +2758,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Hauteur  	</string>  	<string name="Short"> -		Mini +		Moins  	</string>  	<string name="Short Arms">  		Bras courts @@ -2833,7 +2833,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Fente : Droite  	</string>  	<string name="Small"> -		Mini +		Moins  	</string>  	<string name="Small Hands">  		Petites mains @@ -2842,7 +2842,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Petite tête  	</string>  	<string name="Smooth"> -		Lisse +		Lisses  	</string>  	<string name="Smooth Hair">  		Cheveux lisses @@ -2887,13 +2887,13 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Vers l'avant  	</string>  	<string name="Tall"> -		Maxi +		Plus  	</string>  	<string name="Taper Back"> -		Biseauter à l'arrière +		Arrière  	</string>  	<string name="Taper Front"> -		Biseauter à l'avant +		Avant  	</string>  	<string name="Thick Heels">  		Talons épais @@ -2980,7 +2980,7 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].  		Très rouge  	</string>  	<string name="Waist Height"> -		Hauteur de la taille +		Hauteur taille  	</string>  	<string name="Well-Fed">  		Ronde | 
