diff options
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 |