diff options
195 files changed, 6571 insertions, 2433 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index db5495091e..b159092592 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -35,13 +35,13 @@ if (WINDOWS) # Don't build DLLs. set(BUILD_SHARED_LIBS OFF) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd" + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP" CACHE STRING "C++ compiler debug options" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD" + "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP" CACHE STRING "C++ compiler release-with-debug options" FORCE) set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD" + "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP" CACHE STRING "C++ compiler release options" FORCE) set(CMAKE_CXX_STANDARD_LIBRARIES "") diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index e68672d46f..528a7bb4a5 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -273,13 +273,13 @@ void LLCharacter::removeAnimationData(std::string name) //----------------------------------------------------------------------------- // setVisualParamWeight() //----------------------------------------------------------------------------- -BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL set_by_user) +BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL upload_bake) { S32 index = which_param->getID(); visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); if (index_iter != mVisualParamIndexMap.end()) { - index_iter->second->setWeight(weight, set_by_user); + index_iter->second->setWeight(weight, upload_bake); return TRUE; } return FALSE; @@ -288,7 +288,7 @@ BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, B //----------------------------------------------------------------------------- // setVisualParamWeight() //----------------------------------------------------------------------------- -BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user) +BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake) { std::string tname(param_name); LLStringUtil::toLower(tname); @@ -296,7 +296,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr); if (name_iter != mVisualParamNameMap.end()) { - name_iter->second->setWeight(weight, set_by_user); + name_iter->second->setWeight(weight, upload_bake); return TRUE; } llwarns << "LLCharacter::setVisualParamWeight() Invalid visual parameter: " << param_name << llendl; @@ -306,12 +306,12 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL //----------------------------------------------------------------------------- // setVisualParamWeight() //----------------------------------------------------------------------------- -BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user) +BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake) { visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index); if (index_iter != mVisualParamIndexMap.end()) { - index_iter->second->setWeight(weight, set_by_user); + index_iter->second->setWeight(weight, upload_bake); return TRUE; } llwarns << "LLCharacter::setVisualParamWeight() Invalid visual parameter index: " << index << llendl; diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index cb44a32e8a..27e2a51c62 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -203,9 +203,9 @@ public: void addVisualParam(LLVisualParam *param); void addSharedVisualParam(LLVisualParam *param); - virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE ); - virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE ); - virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE ); + virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); + virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); // get visual param weight by param or name F32 getVisualParamWeight(LLVisualParam *distortion); diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp index 6232c7588b..297322fe58 100644 --- a/indra/llcharacter/llvisualparam.cpp +++ b/indra/llcharacter/llvisualparam.cpp @@ -225,7 +225,7 @@ BOOL LLVisualParam::parseData(LLXmlTreeNode *node) //----------------------------------------------------------------------------- // setWeight() //----------------------------------------------------------------------------- -void LLVisualParam::setWeight(F32 weight, BOOL set_by_user) +void LLVisualParam::setWeight(F32 weight, BOOL upload_bake) { if (mIsAnimating) { @@ -243,19 +243,19 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user) if (mNext) { - mNext->setWeight(weight, set_by_user); + mNext->setWeight(weight, upload_bake); } } //----------------------------------------------------------------------------- // setAnimationTarget() //----------------------------------------------------------------------------- -void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user) +void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake) { // don't animate dummy parameters if (mIsDummy) { - setWeight(target_value, set_by_user); + setWeight(target_value, upload_bake); return; } @@ -274,7 +274,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user) if (mNext) { - mNext->setAnimationTarget(target_value, set_by_user); + mNext->setAnimationTarget(target_value, upload_bake); } } @@ -291,24 +291,24 @@ void LLVisualParam::setNextParam( LLVisualParam *next ) //----------------------------------------------------------------------------- // animate() //----------------------------------------------------------------------------- -void LLVisualParam::animate( F32 delta, BOOL set_by_user ) +void LLVisualParam::animate( F32 delta, BOOL upload_bake ) { if (mIsAnimating) { F32 new_weight = ((mTargetWeight - mCurWeight) * delta) + mCurWeight; - setWeight(new_weight, set_by_user); + setWeight(new_weight, upload_bake); } } //----------------------------------------------------------------------------- // stopAnimating() //----------------------------------------------------------------------------- -void LLVisualParam::stopAnimating(BOOL set_by_user) +void LLVisualParam::stopAnimating(BOOL upload_bake) { if (mIsAnimating && getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) { mIsAnimating = FALSE; - setWeight(mTargetWeight, set_by_user); + setWeight(mTargetWeight, upload_bake); } } diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index eec56d7844..12b45e6ebe 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -113,10 +113,10 @@ public: //virtual BOOL parseData( LLXmlTreeNode *node ) = 0; virtual void apply( ESex avatar_sex ) = 0; // Default functions - virtual void setWeight(F32 weight, BOOL set_by_user); - virtual void setAnimationTarget( F32 target_value, BOOL set_by_user ); - virtual void animate(F32 delta, BOOL set_by_user); - virtual void stopAnimating(BOOL set_by_user); + virtual void setWeight(F32 weight, BOOL upload_bake); + virtual void setAnimationTarget( F32 target_value, BOOL upload_bake ); + virtual void animate(F32 delta, BOOL upload_bake); + virtual void stopAnimating(BOOL upload_bake); virtual BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); virtual void resetDrivenParams(); diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index f40359790a..e41c75846b 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -41,6 +41,7 @@ set(llcommon_SOURCE_FILES llerror.cpp llerrorthread.cpp llevent.cpp + lleventapi.cpp lleventcoro.cpp lleventdispatcher.cpp lleventfilter.cpp @@ -140,6 +141,7 @@ set(llcommon_HEADER_FILES llerrorlegacy.h llerrorthread.h llevent.h + lleventapi.h lleventcoro.h lleventdispatcher.h lleventfilter.h @@ -276,6 +278,7 @@ LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldependencies "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp new file mode 100644 index 0000000000..1dd104da8f --- /dev/null +++ b/indra/llcommon/lleventapi.cpp @@ -0,0 +1,30 @@ +/** + * @file lleventapi.cpp + * @author Nat Goodspeed + * @date 2009-11-10 + * @brief Implementation for lleventapi. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "lleventapi.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const std::string& field): + lbase(name, field), + ibase(name), + mDesc(desc) +{ +} + +LLEventAPI::~LLEventAPI() +{ +} diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h new file mode 100644 index 0000000000..2cd3b5bf89 --- /dev/null +++ b/indra/llcommon/lleventapi.h @@ -0,0 +1,53 @@ +/** + * @file lleventapi.h + * @author Nat Goodspeed + * @date 2009-10-28 + * @brief LLEventAPI is the base class for every class that wraps a C++ API + * in an event API + * (see https://wiki.lindenlab.com/wiki/Incremental_Viewer_Automation/Event_API). + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEVENTAPI_H) +#define LL_LLEVENTAPI_H + +#include "lleventdispatcher.h" +#include "llinstancetracker.h" +#include <string> + +/** + * LLEventAPI not only provides operation dispatch functionality, inherited + * from LLDispatchListener -- it also gives us event API introspection. + * Deriving from LLInstanceTracker lets us enumerate instances. + */ +class LL_COMMON_API LLEventAPI: public LLDispatchListener, + public LLInstanceTracker<LLEventAPI, std::string> +{ + typedef LLDispatchListener lbase; + typedef LLInstanceTracker<LLEventAPI, std::string> ibase; + +public: + /** + * @param name LLEventPump name on which this LLEventAPI will listen. This + * also serves as the LLInstanceTracker instance key. + * @param desc Documentation string shown to a client trying to discover + * available event APIs. + * @param field LLSD::Map key used by LLDispatchListener to look up the + * subclass method to invoke [default "op"]. + */ + LLEventAPI(const std::string& name, const std::string& desc, const std::string& field="op"); + virtual ~LLEventAPI(); + + /// Get the string name of this LLEventAPI + std::string getName() const { return ibase::getKey(); } + /// Get the documentation string + std::string getDesc() const { return mDesc; } + +private: + std::string mDesc; +}; + +#endif /* ! defined(LL_LLEVENTAPI_H) */ diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp index 6b1413d054..017bf3a521 100644 --- a/indra/llcommon/lleventdispatcher.cpp +++ b/indra/llcommon/lleventdispatcher.cpp @@ -36,9 +36,11 @@ LLEventDispatcher::~LLEventDispatcher() } /// Register a callable by name -void LLEventDispatcher::add(const std::string& name, const Callable& callable, const LLSD& required) +void LLEventDispatcher::add(const std::string& name, const std::string& desc, + const Callable& callable, const LLSD& required) { - mDispatch[name] = DispatchMap::mapped_type(callable, required); + mDispatch.insert(DispatchMap::value_type(name, + DispatchMap::mapped_type(callable, desc, required))); } void LLEventDispatcher::addFail(const std::string& name, const std::string& classname) const @@ -98,14 +100,14 @@ bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event) } // Found the name, so it's plausible to even attempt the call. But first, // validate the syntax of the event itself. - std::string mismatch(llsd_matches(found->second.second, event)); + std::string mismatch(llsd_matches(found->second.mRequired, event)); if (! mismatch.empty()) { LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ") calling '" << name << "': bad request: " << mismatch << LL_ENDL; } // Event syntax looks good, go for it! - (found->second.first)(event); + (found->second.mFunc)(event); return true; // tell caller we were able to call } @@ -116,7 +118,7 @@ LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) cons { return Callable(); } - return found->second.first; + return found->second.mFunc; } LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key): diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 5a86b90bff..eba7b607f1 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -44,7 +44,10 @@ public: * is used to validate the structure of each incoming event (see * llsd_matches()). */ - void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); + void add(const std::string& name, + const std::string& desc, + const Callable& callable, + const LLSD& required=LLSD()); /** * Special case: a subclass of this class can pass an unbound member @@ -52,18 +55,22 @@ public: * <tt>boost::bind()</tt> expression. */ template <class CLASS> - void add(const std::string& name, void (CLASS::*method)(const LLSD&), + void add(const std::string& name, + const std::string& desc, + void (CLASS::*method)(const LLSD&), const LLSD& required=LLSD()) { - addMethod<CLASS>(name, method, required); + addMethod<CLASS>(name, desc, method, required); } /// Overload for both const and non-const methods template <class CLASS> - void add(const std::string& name, void (CLASS::*method)(const LLSD&) const, + void add(const std::string& name, + const std::string& desc, + void (CLASS::*method)(const LLSD&) const, const LLSD& required=LLSD()) { - addMethod<CLASS>(name, method, required); + addMethod<CLASS>(name, desc, method, required); } /// Unregister a callable @@ -86,7 +93,8 @@ public: private: template <class CLASS, typename METHOD> - void addMethod(const std::string& name, const METHOD& method, const LLSD& required) + void addMethod(const std::string& name, const std::string& desc, + const METHOD& method, const LLSD& required) { CLASS* downcast = dynamic_cast<CLASS*>(this); if (! downcast) @@ -95,7 +103,7 @@ private: } else { - add(name, boost::bind(method, downcast, _1), required); + add(name, desc, boost::bind(method, downcast, _1), required); } } void addFail(const std::string& name, const std::string& classname) const; @@ -103,7 +111,18 @@ private: bool attemptCall(const std::string& name, const LLSD& event) const; std::string mDesc, mKey; - typedef std::map<std::string, std::pair<Callable, LLSD> > DispatchMap; + struct DispatchEntry + { + DispatchEntry(const Callable& func, const std::string& desc, const LLSD& required): + mFunc(func), + mDesc(desc), + mRequired(required) + {} + Callable mFunc; + std::string mDesc; + LLSD mRequired; + }; + typedef std::map<std::string, DispatchEntry> DispatchMap; DispatchMap mDispatch; }; diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 192d79b27d..f52cf33fd8 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -45,10 +45,12 @@ #include "llsingleton.h" #include "lldependencies.h" +/*==========================================================================*| // override this to allow binding free functions with more parameters #ifndef LLEVENTS_LISTENER_ARITY #define LLEVENTS_LISTENER_ARITY 10 #endif +|*==========================================================================*/ // hack for testing #ifndef testable diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index ea50acbbc5..11fe523651 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -38,42 +38,73 @@ #include "string_table.h" #include <boost/utility.hpp> - -// This mix-in class adds support for tracking all instances of the specified class parameter T -// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup -// If KEY is not provided, then instances are stored in a simple set -// *NOTE: see explicit specialization below for default KEY==T* case +#include <boost/function.hpp> +#include <boost/bind.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/iterator/indirect_iterator.hpp> + +/// This mix-in class adds support for tracking all instances of the specified class parameter T +/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup +/// If KEY is not provided, then instances are stored in a simple set +/// @NOTE: see explicit specialization below for default KEY==T* case template<typename T, typename KEY = T*> class LLInstanceTracker : boost::noncopyable { + typedef typename std::map<KEY, T*> InstanceMap; + typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter; + typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter; public: - typedef typename std::map<KEY, T*>::iterator instance_iter; - typedef typename std::map<KEY, T*>::const_iterator instance_const_iter; - - static T* getInstance(const KEY& k) { instance_iter found = getMap().find(k); return (found == getMap().end()) ? NULL : found->second; } + /// Dereferencing key_iter gives you a const KEY& + typedef boost::transform_iterator<KeyGetter, typename InstanceMap::iterator> key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator< boost::transform_iterator<InstancePtrGetter, typename InstanceMap::iterator> > instance_iter; + + static T* getInstance(const KEY& k) + { + typename InstanceMap::const_iterator found = getMap_().find(k); + return (found == getMap_().end()) ? NULL : found->second; + } - static instance_iter beginInstances() { return getMap().begin(); } - static instance_iter endInstances() { return getMap().end(); } - static S32 instanceCount() { return getMap().size(); } + static key_iter beginKeys() + { + return boost::make_transform_iterator(getMap_().begin(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static key_iter endKeys() + { + return boost::make_transform_iterator(getMap_().end(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static instance_iter beginInstances() + { + return instance_iter(boost::make_transform_iterator(getMap_().begin(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static instance_iter endInstances() + { + return instance_iter(boost::make_transform_iterator(getMap_().end(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static S32 instanceCount() { return getMap_().size(); } protected: - LLInstanceTracker(KEY key) { add(key); } - virtual ~LLInstanceTracker() { remove(); } - virtual void setKey(KEY key) { remove(); add(key); } + LLInstanceTracker(KEY key) { add_(key); } + virtual ~LLInstanceTracker() { remove_(); } + virtual void setKey(KEY key) { remove_(); add_(key); } virtual const KEY& getKey() const { return mKey; } private: - void add(KEY key) + void add_(KEY key) { mKey = key; - getMap()[key] = static_cast<T*>(this); + getMap_()[key] = static_cast<T*>(this); } - void remove() { getMap().erase(mKey); } + void remove_() { getMap_().erase(mKey); } - static std::map<KEY, T*>& getMap() + static InstanceMap& getMap_() { if (! sInstances) { - sInstances = new std::map<KEY, T*>; + sInstances = new InstanceMap; } return *sInstances; } @@ -81,41 +112,48 @@ private: private: KEY mKey; - static std::map<KEY, T*>* sInstances; + static InstanceMap* sInstances; }; -// explicit specialization for default case where KEY is T* -// use a simple std::set<T*> +/// explicit specialization for default case where KEY is T* +/// use a simple std::set<T*> template<typename T> class LLInstanceTracker<T, T*> { + typedef typename std::set<T*> InstanceSet; public: - typedef typename std::set<T*>::iterator instance_iter; - typedef typename std::set<T*>::const_iterator instance_const_iter; - - static instance_iter beginInstances() { return getSet().begin(); } - static instance_iter endInstances() { return getSet().end(); } - static S32 instanceCount() { return getSet().size(); } + /// Dereferencing key_iter gives you a T* (since T* is the key) + typedef typename InstanceSet::iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator<key_iter> instance_iter; + + /// for completeness of analogy with the generic implementation + static T* getInstance(T* k) { return k; } + static key_iter beginKeys() { return getSet_().begin(); } + static key_iter endKeys() { return getSet_().end(); } + static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } + static instance_iter endInstances() { return instance_iter(getSet_().end()); } + static S32 instanceCount() { return getSet_().size(); } protected: - LLInstanceTracker() { getSet().insert(static_cast<T*>(this)); } - virtual ~LLInstanceTracker() { getSet().erase(static_cast<T*>(this)); } + LLInstanceTracker() { getSet_().insert(static_cast<T*>(this)); } + virtual ~LLInstanceTracker() { getSet_().erase(static_cast<T*>(this)); } - LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast<T*>(this)); } + LLInstanceTracker(const LLInstanceTracker& other) { getSet_().insert(static_cast<T*>(this)); } - static std::set<T*>& getSet() // called after getReady() but before go() + static InstanceSet& getSet_() // called after getReady() but before go() { if (! sInstances) { - sInstances = new std::set<T*>; + sInstances = new InstanceSet; } return *sInstances; } - static std::set<T*>* sInstances; + static InstanceSet* sInstances; }; -template <typename T, typename KEY> std::map<KEY, T*>* LLInstanceTracker<T, KEY>::sInstances = NULL; -template <typename T> std::set<T*>* LLInstanceTracker<T, T*>::sInstances = NULL; +template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL; +template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL; #endif diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index ea5b0c03ef..ef3e8dbc94 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -583,13 +583,13 @@ void LLEventTimer::updateClass() std::list<LLEventTimer*> completed_timers; for (instance_iter iter = beginInstances(); iter != endInstances(); ) { - LLEventTimer* timer = *iter++; - F32 et = timer->mEventTimer.getElapsedTimeF32(); - if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { - timer->mEventTimer.reset(); - if ( timer->tick() ) + LLEventTimer& timer = *iter++; + F32 et = timer.mEventTimer.getElapsedTimeF32(); + if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { + timer.mEventTimer.reset(); + if ( timer.tick() ) { - completed_timers.push_back( timer ); + completed_timers.push_back( &timer ); } } } diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp new file mode 100644 index 0000000000..7415f2d33b --- /dev/null +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -0,0 +1,160 @@ +/** + * @file llinstancetracker_test.cpp + * @author Nat Goodspeed + * @date 2009-11-10 + * @brief Test for llinstancetracker. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinstancetracker.h" +// STL headers +#include <string> +#include <vector> +#include <set> +#include <algorithm> // std::sort() +// std headers +// external library headers +#include <boost/scoped_ptr.hpp> +// other Linden headers +#include "../test/lltut.h" + +struct Keyed: public LLInstanceTracker<Keyed, std::string> +{ + Keyed(const std::string& name): + LLInstanceTracker<Keyed, std::string>(name), + mName(name) + {} + std::string mName; +}; + +struct Unkeyed: public LLInstanceTracker<Unkeyed> +{ +}; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llinstancetracker_data + { + }; + typedef test_group<llinstancetracker_data> llinstancetracker_group; + typedef llinstancetracker_group::object object; + llinstancetracker_group llinstancetrackergrp("llinstancetracker"); + + template<> template<> + void object::test<1>() + { + ensure_equals(Keyed::instanceCount(), 0); + { + Keyed one("one"); + ensure_equals(Keyed::instanceCount(), 1); + Keyed* found = Keyed::getInstance("one"); + ensure("couldn't find stack Keyed", found); + ensure_equals("found wrong Keyed instance", found, &one); + { + boost::scoped_ptr<Keyed> two(new Keyed("two")); + ensure_equals(Keyed::instanceCount(), 2); + Keyed* found = Keyed::getInstance("two"); + ensure("couldn't find heap Keyed", found); + ensure_equals("found wrong Keyed instance", found, two.get()); + } + ensure_equals(Keyed::instanceCount(), 1); + } + Keyed* found = Keyed::getInstance("one"); + ensure("Keyed key lives too long", ! found); + ensure_equals(Keyed::instanceCount(), 0); + } + + template<> template<> + void object::test<2>() + { + ensure_equals(Unkeyed::instanceCount(), 0); + { + Unkeyed one; + ensure_equals(Unkeyed::instanceCount(), 1); + Unkeyed* found = Unkeyed::getInstance(&one); + ensure_equals(found, &one); + { + boost::scoped_ptr<Unkeyed> two(new Unkeyed); + ensure_equals(Unkeyed::instanceCount(), 2); + Unkeyed* found = Unkeyed::getInstance(two.get()); + ensure_equals(found, two.get()); + } + ensure_equals(Unkeyed::instanceCount(), 1); + } + ensure_equals(Unkeyed::instanceCount(), 0); + } + + template<> template<> + void object::test<3>() + { + Keyed one("one"), two("two"), three("three"); + // We don't want to rely on the underlying container delivering keys + // in any particular order. That allows us the flexibility to + // reimplement LLInstanceTracker using, say, a hash map instead of a + // std::map. We DO insist that every key appear exactly once. + typedef std::vector<std::string> StringVector; + StringVector keys(Keyed::beginKeys(), Keyed::endKeys()); + std::sort(keys.begin(), keys.end()); + StringVector::const_iterator ki(keys.begin()); + ensure_equals(*ki++, "one"); + ensure_equals(*ki++, "three"); + ensure_equals(*ki++, "two"); + // Use ensure() here because ensure_equals would want to display + // mismatched values, and frankly that wouldn't help much. + ensure("didn't reach end", ki == keys.end()); + + // Use a somewhat different approach to order independence with + // beginInstances(): explicitly capture the instances we know in a + // set, and delete them as we iterate through. + typedef std::set<Keyed*> InstanceSet; + InstanceSet instances; + instances.insert(&one); + instances.insert(&two); + instances.insert(&three); + for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances()); + ii != iend; ++ii) + { + Keyed& ref = *ii; + ensure_equals("spurious instance", instances.erase(&ref), 1); + } + ensure_equals("unreported instance", instances.size(), 0); + } + + template<> template<> + void object::test<4>() + { + Unkeyed one, two, three; + typedef std::set<Unkeyed*> KeySet; + KeySet keys; + keys.insert(&one); + keys.insert(&two); + keys.insert(&three); + for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys()); + ki != kend; ++ki) + { + ensure_equals("spurious key", keys.erase(*ki), 1); + } + ensure_equals("unreported key", keys.size(), 0); + + KeySet instances; + instances.insert(&one); + instances.insert(&two); + instances.insert(&three); + for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); + ii != iend; ++ii) + { + Unkeyed& ref = *ii; + ensure_equals("spurious instance", instances.erase(&ref), 1); + } + ensure_equals("unreported instance", instances.size(), 0); + } +} // namespace tut diff --git a/indra/llmath/llinterp.h b/indra/llmath/llinterp.h index 8beeef480b..36ca2e9865 100644 --- a/indra/llmath/llinterp.h +++ b/indra/llmath/llinterp.h @@ -32,6 +32,13 @@ #ifndef LL_LLINTERP_H #define LL_LLINTERP_H +#if defined(LL_WINDOWS) +// macro definitions for common math constants (e.g. M_PI) are declared under the _USE_MATH_DEFINES +// on Windows system. +// So, let's define _USE_MATH_DEFINES before including math.h + #define _USE_MATH_DEFINES +#endif + #include "math.h" // Class from which different types of interpolators can be derived diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index acbf51d75c..104629c157 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -106,7 +106,7 @@ void LLAres::QueryResponder::queryError(int code) LLAres::LLAres() : chan_(NULL), mInitSuccess(false), - mListener(new LLAresListener("LLAres", this)) + mListener(new LLAresListener(this)) { if (ares_init(&chan_) != ARES_SUCCESS) { diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp index a8beb8cbde..7db3675b77 100644 --- a/indra/llmessage/llareslistener.cpp +++ b/indra/llmessage/llareslistener.cpp @@ -22,13 +22,18 @@ #include "llevents.h" #include "llsdutil.h" -LLAresListener::LLAresListener(const std::string& pumpname, LLAres* llares): - LLDispatchListener(pumpname, "op"), +LLAresListener::LLAresListener(LLAres* llares): + LLEventAPI("LLAres", + "LLAres listener to request DNS operations"), mAres(llares) { // add() every method we want to be able to invoke via this event API. - // Optional third parameter validates expected LLSD request structure. - add("rewriteURI", &LLAresListener::rewriteURI, + // Optional last parameter validates expected LLSD request structure. + add("rewriteURI", + "Given [\"uri\"], return on [\"reply\"] an array of alternative URIs.\n" + "On failure, returns an array containing only the original URI, so\n" + "failure case can be processed like success case.", + &LLAresListener::rewriteURI, LLSD().insert("uri", LLSD()).insert("reply", LLSD())); } diff --git a/indra/llmessage/llareslistener.h b/indra/llmessage/llareslistener.h index bf093b3d3d..33cef79c09 100644 --- a/indra/llmessage/llareslistener.h +++ b/indra/llmessage/llareslistener.h @@ -14,18 +14,17 @@ #if ! defined(LL_LLARESLISTENER_H) #define LL_LLARESLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" class LLAres; class LLSD; /// Listen on an LLEventPump with specified name for LLAres request events. -class LLAresListener: public LLDispatchListener +class LLAresListener: public LLEventAPI { public: - /// Specify the pump name on which to listen, and bind the LLAres instance - /// to use (e.g. gAres) - LLAresListener(const std::string& pumpname, LLAres* llares); + /// Bind the LLAres instance to use (e.g. gAres) + LLAresListener(LLAres* llares); private: /// command["op"] == "rewriteURI" diff --git a/indra/llprimitive/tests/llmediaentry_test.cpp b/indra/llprimitive/tests/llmediaentry_test.cpp index dfac5f26c7..277e370ca4 100644 --- a/indra/llprimitive/tests/llmediaentry_test.cpp +++ b/indra/llprimitive/tests/llmediaentry_test.cpp @@ -9,7 +9,14 @@ #include "linden_common.h" #include "lltut.h" -#include "boost/lexical_cast.hpp" +#if LL_WINDOWS +#pragma warning (push) +#pragma warning (disable : 4702) // boost::lexical_cast generates this warning +#endif +#include <boost/lexical_cast.hpp> +#if LL_WINDOWS +#pragma warning (pop) +#endif #include "llstring.h" #include "llsdutil.h" #include "llsdserialize.h" diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index d9520b3bf6..f0df3bcf90 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -61,8 +61,11 @@ BOOL LLRenderTarget::sUseFBO = FALSE; LLRenderTarget::LLRenderTarget() : mResX(0), mResY(0), + mViewportWidth(0), + mViewportHeight(0), mTex(0), mFBO(0), + mColorFmt(0), mDepth(0), mStencil(0), mUseDepth(FALSE), @@ -86,13 +89,31 @@ void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo) { + // only reallocate if something changed + if (mResX == resx + && mResY == resy + && mUseDepth == depth + && mStencil == stencil + && mUsage == usage + && (mFBO != 0) == ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) + && mColorFmt == color_fmt) + { + // nothing to do + return; + } + stop_glerror(); mResX = resx; mResY = resy; + // default viewport to entire texture + mViewportWidth = mResX; + mViewportHeight = mResY; mStencil = stencil; mUsage = usage; mUseDepth = depth; + mFBO = 0; + mColorFmt = color_fmt; release(); @@ -312,7 +333,7 @@ void LLRenderTarget::bindTarget() } } - glViewport(0, 0, mResX, mResY); + glViewport(0, 0, mViewportWidth, mViewportHeight); sBoundTarget = this; } @@ -515,12 +536,18 @@ BOOL LLRenderTarget::isComplete() const return (!mTex.empty() || mDepth) ? TRUE : FALSE; } +void LLRenderTarget::setViewport(U32 width, U32 height) +{ + mViewportWidth = llmin(width, mResX); + mViewportHeight = llmin(height, mResY); +} + void LLRenderTarget::getViewport(S32* viewport) { viewport[0] = 0; viewport[1] = 0; - viewport[2] = mResX; - viewport[3] = mResY; + viewport[2] = mViewportWidth; + viewport[3] = mViewportHeight; } //================================================== @@ -581,7 +608,7 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) check_framebuffer_status(); - glViewport(0, 0, mResX, mResY); + glViewport(0, 0, mViewportWidth, mViewportHeight); sBoundTarget = this; } @@ -593,13 +620,30 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples ) { + if (mResX == resx + && mResY == resy + && mUseDepth == depth + && mStencil == stencil + && mUsage == usage + && (mFBO != 0) == ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) + && mColorFmt == color_fmt + && mSamples == samples) + { + // nothing to do + return; + } + stop_glerror(); mResX = resx; mResY = resy; + mViewportWidth = mResX; + mViewportHeight = mResY; mUsage = usage; mUseDepth = depth; mStencil = stencil; + mFBO = 0; + mColorFmt = color_fmt; releaseSampleBuffer(); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index b7ebfc8f7f..125747424c 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -107,6 +107,9 @@ public: //uses scissor rect if in copy-to-texture mode void clear(U32 mask = 0xFFFFFFFF); + // override default viewport to a smaller size + void setViewport(U32 width, U32 height); + //get applied viewport void getViewport(S32* viewport); @@ -150,12 +153,16 @@ protected: friend class LLMultisampleBuffer; U32 mResX; U32 mResY; + U32 mViewportWidth; + U32 mViewportHeight; std::vector<U32> mTex; U32 mFBO; + U32 mColorFmt; U32 mDepth; BOOL mStencil; BOOL mUseDepth; BOOL mRenderDepth; + LLTexUnit::eTextureType mUsage; U32 mSamples; LLMultisampleBuffer* mSampleBuffer; diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 35a854267a..045505af5b 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -256,7 +256,6 @@ void LLDockControl::on() { if (isDockVisible()) { - mDockableFloater->setCanDrag(false); mEnabled = true; mRecalculateDocablePosition = true; } @@ -264,7 +263,6 @@ void LLDockControl::on() void LLDockControl::off() { - mDockableFloater->setCanDrag(true); mEnabled = false; } diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index f2cdad8854..2a0dcaf333 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1888,41 +1888,50 @@ void LLFloaterView::reshapeFloater(S32 width, S32 height, BOOL called_from_paren // dependents use same follow flags as their "dependee" continue; } - LLRect r = floaterp->getRect(); - - // Compute absolute distance from each edge of screen - S32 left_offset = llabs(r.mLeft - 0); - S32 right_offset = llabs(old_width - r.mRight); - - S32 top_offset = llabs(old_height - r.mTop); - S32 bottom_offset = llabs(r.mBottom - 0); // Make if follow the edge it is closest to U32 follow_flags = 0x0; - if (left_offset < right_offset) + if (floaterp->isMinimized()) { - follow_flags |= FOLLOWS_LEFT; + follow_flags |= (FOLLOWS_LEFT | FOLLOWS_TOP); } else { - follow_flags |= FOLLOWS_RIGHT; - } + LLRect r = floaterp->getRect(); - // "No vertical adjustment" usually means that the bottom of the view - // has been pushed up or down. Hence we want the floaters to follow - // the top. - if (!adjust_vertical) - { - follow_flags |= FOLLOWS_TOP; - } - else if (top_offset < bottom_offset) - { - follow_flags |= FOLLOWS_TOP; - } - else - { - follow_flags |= FOLLOWS_BOTTOM; + // Compute absolute distance from each edge of screen + S32 left_offset = llabs(r.mLeft - 0); + S32 right_offset = llabs(old_width - r.mRight); + + S32 top_offset = llabs(old_height - r.mTop); + S32 bottom_offset = llabs(r.mBottom - 0); + + + if (left_offset < right_offset) + { + follow_flags |= FOLLOWS_LEFT; + } + else + { + follow_flags |= FOLLOWS_RIGHT; + } + + // "No vertical adjustment" usually means that the bottom of the view + // has been pushed up or down. Hence we want the floaters to follow + // the top. + if (!adjust_vertical) + { + follow_flags |= FOLLOWS_TOP; + } + else if (top_offset < bottom_offset) + { + follow_flags |= FOLLOWS_TOP; + } + else + { + follow_flags |= FOLLOWS_BOTTOM; + } } floaterp->setFollows(follow_flags); @@ -2172,16 +2181,16 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) const LLFloater::Params& default_params = LLFloater::getDefaultParams(); S32 floater_header_size = default_params.header_height; static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0); - S32 col = 0; LLRect snap_rect_local = getLocalSnapRect(); - for(S32 row = snap_rect_local.mBottom; - row < snap_rect_local.getHeight() - floater_header_size; - row += floater_header_size ) //loop rows - { - for(col = snap_rect_local.mLeft; - col < snap_rect_local.getWidth() - minimized_width; - col += minimized_width) + for(S32 col = snap_rect_local.mLeft; + col < snap_rect_local.getWidth() - minimized_width; + col += minimized_width) + { + for(S32 row = snap_rect_local.mTop - floater_header_size; + row > floater_header_size; + row -= floater_header_size ) //loop rows { + bool foundGap = TRUE; for(child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 03925f922c..eb67e3a561 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -46,7 +46,7 @@ LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap; LLFloaterReg::build_map_t LLFloaterReg::sBuildMap; std::map<std::string,std::string> LLFloaterReg::sGroupMap; -static LLFloaterRegListener sFloaterRegListener("LLFloaterReg"); +static LLFloaterRegListener sFloaterRegListener; //******************************************************* diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp index 57d148b5af..029d3b6810 100644 --- a/indra/llui/llfloaterreglistener.cpp +++ b/indra/llui/llfloaterreglistener.cpp @@ -21,19 +21,35 @@ #include "llfloater.h" #include "llbutton.h" -LLFloaterRegListener::LLFloaterRegListener(const std::string& pumpName): - LLDispatchListener(pumpName, "op") +LLFloaterRegListener::LLFloaterRegListener(): + LLEventAPI("LLFloaterReg", + "LLFloaterReg listener to (e.g.) show/hide LLFloater instances") { - add("getBuildMap", &LLFloaterRegListener::getBuildMap, LLSD().insert("reply", LLSD())); + add("getBuildMap", + "Return on [\"reply\"] data about all registered LLFloaterReg floater names", + &LLFloaterRegListener::getBuildMap, + LLSD().insert("reply", LLSD())); LLSD requiredName; requiredName["name"] = LLSD(); - add("showInstance", &LLFloaterRegListener::showInstance, requiredName); - add("hideInstance", &LLFloaterRegListener::hideInstance, requiredName); - add("toggleInstance", &LLFloaterRegListener::toggleInstance, requiredName); + add("showInstance", + "Ask to display the floater specified in [\"name\"]", + &LLFloaterRegListener::showInstance, + requiredName); + add("hideInstance", + "Ask to hide the floater specified in [\"name\"]", + &LLFloaterRegListener::hideInstance, + requiredName); + add("toggleInstance", + "Ask to toggle the state of the floater specified in [\"name\"]", + &LLFloaterRegListener::toggleInstance, + requiredName); LLSD requiredNameButton; requiredNameButton["name"] = LLSD(); requiredNameButton["button"] = LLSD(); - add("clickButton", &LLFloaterRegListener::clickButton, requiredNameButton); + add("clickButton", + "Simulate clicking the named [\"button\"] in the visible floater named in [\"name\"]", + &LLFloaterRegListener::clickButton, + requiredNameButton); } void LLFloaterRegListener::getBuildMap(const LLSD& event) const diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h index 304ecd1090..a38117f6b0 100644 --- a/indra/llui/llfloaterreglistener.h +++ b/indra/llui/llfloaterreglistener.h @@ -12,18 +12,18 @@ #if ! defined(LL_LLFLOATERREGLISTENER_H) #define LL_LLFLOATERREGLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" #include <string> class LLSD; /// Event API wrapper for LLFloaterReg -class LLFloaterRegListener: public LLDispatchListener +class LLFloaterRegListener: public LLEventAPI { public: /// As all public LLFloaterReg methods are static, there's no point in /// binding an LLFloaterReg instance. - LLFloaterRegListener(const std::string& pumpName); + LLFloaterRegListener(); private: void getBuildMap(const LLSD& event) const; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 9399ace1f7..14a6ddb7e0 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -792,8 +792,8 @@ void LLLayoutStack::calcMinExtents() //static void LLLayoutStack::updateClass() { - for (LLInstanceTracker<LLLayoutStack>::instance_iter it = beginInstances(); it != endInstances(); ++it) + for (LLLayoutStack::instance_iter it = beginInstances(); it != endInstances(); ++it) { - (*it)->updateLayout(); + it->updateLayout(); } } diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 75f4d6177d..fe4fbe7510 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -16,10 +16,14 @@ #include "llnotifications.h" LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) : - LLDispatchListener("LLNotifications", "op"), + LLEventAPI("LLNotifications", + "LLNotifications listener to (e.g.) pop up a notification"), mNotifications(notifications) { - add("requestAdd", &LLNotificationsListener::requestAdd); + add("requestAdd", + "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n" + "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.", + &LLNotificationsListener::requestAdd); } void LLNotificationsListener::requestAdd(const LLSD& event_data) const diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index 6f71a7c781..9b405d7b4b 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -12,12 +12,12 @@ #ifndef LL_LLNOTIFICATIONSLISTENER_H #define LL_LLNOTIFICATIONSLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" class LLNotifications; class LLSD; -class LLNotificationsListener : public LLDispatchListener +class LLNotificationsListener : public LLEventAPI { public: LLNotificationsListener(LLNotifications & notifications); diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 07c0f3ce84..89c4656297 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -512,6 +512,8 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu // add children using dimensions from referenced xml for consistent layout setShape(params.rect); LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance()); + + setXMLFilename(xml_filename); } // ask LLUICtrlFactory for filename, since xml_filename might be empty diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index a7c268758a..544352176a 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -71,7 +71,8 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_ LLScrollListCell::LLScrollListCell(const LLScrollListCell::Params& p) -: mWidth(p.width) +: mWidth(p.width), + mToolTip(p.tool_tip) {} // virtual @@ -204,13 +205,28 @@ BOOL LLScrollListText::isText() const return TRUE; } +// virtual +const std::string &LLScrollListText::getToolTip() const +{ + // If base class has a tooltip, return that + if (! LLScrollListCell::getToolTip().empty()) + return LLScrollListCell::getToolTip(); + + // ...otherwise, return the value itself as the tooltip + return mText.getString(); +} + +// virtual BOOL LLScrollListText::needsToolTip() const { - // show tooltips for truncated text + // If base class has a tooltip, return that + if (LLScrollListCell::needsToolTip()) + return LLScrollListCell::needsToolTip(); + + // ...otherwise, show tooltips for truncated text return mFont->getWidth(mText.getString()) > getWidth(); } - //virtual BOOL LLScrollListText::getVisible() const { diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 758623f121..5fecf5aade 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -66,6 +66,7 @@ public: Optional<void*> userdata; Optional<LLSD> value; + Optional<std::string> tool_tip; Optional<const LLFontGL*> font; Optional<LLColor4> font_color; @@ -80,6 +81,7 @@ public: enabled("enabled", true), visible("visible", true), value("value"), + tool_tip("tool_tip", ""), font("font", LLFontGL::getFontSansSerifSmall()), font_color("font_color", LLColor4::black), color("color", LLColor4::white), @@ -101,11 +103,13 @@ public: virtual S32 getHeight() const { return 0; } virtual const LLSD getValue() const; virtual void setValue(const LLSD& value) { } + virtual const std::string &getToolTip() const { return mToolTip; } + virtual void setToolTip(const std::string &str) { mToolTip = str; } virtual BOOL getVisible() const { return TRUE; } virtual void setWidth(S32 width) { mWidth = width; } virtual void highlightText(S32 offset, S32 num_chars) {} virtual BOOL isText() const { return FALSE; } - virtual BOOL needsToolTip() const { return FALSE; } + virtual BOOL needsToolTip() const { return ! mToolTip.empty(); } virtual void setColor(const LLColor4&) {} virtual void onCommit() {}; @@ -114,6 +118,7 @@ public: private: S32 mWidth; + std::string mToolTip; }; class LLScrollListSpacer : public LLScrollListCell @@ -143,6 +148,7 @@ public: /*virtual*/ void setColor(const LLColor4&); /*virtual*/ BOOL isText() const; + /*virtual*/ const std::string & getToolTip() const; /*virtual*/ BOOL needsToolTip() const; void setText(const LLStringExplicit& text); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 1c2c02e1cc..a53a30b501 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1565,7 +1565,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask) // display tooltip exactly over original cell, in same font LLToolTipMgr::instance().show(LLToolTip::Params() - .message(hit_cell->getValue().asString()) + .message(hit_cell->getToolTip()) .font(LLFontGL::getFontSansSerifSmall()) .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6)) .delay_time(0.2f) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 8d36c9c616..9706878a57 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -994,6 +994,12 @@ void LLTextBase::setColor( const LLColor4& c ) mFgColor = c; } +//virtual +void LLTextBase::setReadOnlyColor(const LLColor4 &c) +{ + mReadOnlyFgColor = c; +} + //virtual void LLTextBase::setValue(const LLSD& value ) { @@ -2369,7 +2375,9 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt height = mFontHeight; width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); - return num_chars >= 1 && text[mStart + num_chars - 1] == '\n'; + // if last character is a newline, then return true, forcing line break + llwchar last_char = text[mStart + first_char + num_chars - 1]; + return num_chars >= 1 && last_char == '\n'; } S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 8cae8fde22..fb01cd1e7c 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -118,6 +118,8 @@ public: // LLUICtrl interface /*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; } /*virtual*/ void setColor( const LLColor4& c ); + virtual void setReadOnlyColor(const LLColor4 &c); + /*virtual*/ void setValue(const LLSD& value ); /*virtual*/ LLTextViewModel* getViewModel() const; diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 984a534da6..bb85177811 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -172,7 +172,6 @@ LLToolTip::Params::Params() LLToolTip::LLToolTip(const LLToolTip::Params& p) : LLPanel(p), - mMaxWidth(p.max_width), mHasClickCallback(p.click_callback.isProvided()), mPadding(p.padding), mTextBox(NULL), @@ -181,11 +180,9 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) mHomePageButton(NULL) { LLTextBox::Params params; - params.initial_value = "tip_text"; params.name = params.initial_value().asString(); // bake textbox padding into initial rect params.rect = LLRect (mPadding, mPadding + 1, mPadding + 1, mPadding); - params.follows.flags = FOLLOWS_ALL; params.h_pad = 0; params.v_pad = 0; params.mouse_opaque = false; @@ -210,7 +207,6 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16); icon_rect.setOriginAndSize(mPadding, mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE); icon_params.rect = icon_rect; - //icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM; icon_params.image_unselected(imagep); icon_params.image_selected(imagep); @@ -281,15 +277,30 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) } } -void LLToolTip::setValue(const LLSD& value) +void LLToolTip::initFromParams(const LLToolTip::Params& p) { + LLPanel::initFromParams(p); + + // do this *after* we've had our size set in LLPanel::initFromParams(); const S32 REALLY_LARGE_HEIGHT = 10000; - reshape(mMaxWidth, REALLY_LARGE_HEIGHT); + mTextBox->reshape(p.max_width, REALLY_LARGE_HEIGHT); - mTextBox->setValue(value); + if (p.styled_message.isProvided()) + { + for (LLInitParam::ParamIterator<LLToolTip::StyledText>::const_iterator text_it = p.styled_message().begin(); + text_it != p.styled_message().end(); + ++text_it) + { + mTextBox->appendText(text_it->text(), false, text_it->style); + } + } + else + { + mTextBox->setText(p.message()); + } LLRect text_contents_rect = mTextBox->getContentsRect(); - S32 text_width = llmin(mMaxWidth, text_contents_rect.getWidth()); + S32 text_width = llmin(p.max_width(), text_contents_rect.getWidth()); S32 text_height = text_contents_rect.getHeight(); mTextBox->reshape(text_width, text_height); @@ -300,7 +311,7 @@ void LLToolTip::setValue(const LLSD& value) tooltip_rect.mBottom = 0; tooltip_rect.mLeft = 0; - setRect(tooltip_rect); + setShape(tooltip_rect); } void LLToolTip::setVisible(BOOL visible) @@ -411,9 +422,8 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) } tooltip_params.rect = LLRect (0, 1, 1, 0); - mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params); - mToolTip->setValue(params.message()); + gToolTipView->addChild(mToolTip); if (params.pos.isProvided()) diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 774ca507c1..8c8fdf0a4c 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -37,6 +37,7 @@ #include "llsingleton.h" #include "llinitparam.h" #include "llpanel.h" +#include "llstyle.h" // // Classes @@ -65,11 +66,19 @@ public: class LLToolTip : public LLPanel { public: + + struct StyledText : public LLInitParam::Block<StyledText> + { + Mandatory<std::string> text; + Optional<LLStyle::Params> style; + }; + struct Params : public LLInitParam::Block<Params, LLPanel::Params> { typedef boost::function<void(void)> click_callback_t; - Mandatory<std::string> message; + Optional<std::string> message; + Multiple<StyledText> styled_message; Optional<LLCoordGL> pos; Optional<F32> delay_time, @@ -85,8 +94,8 @@ public: Optional<click_callback_t> click_callback, click_playmedia_callback, click_homepage_callback; - Optional<S32> max_width; - Optional<S32> padding; + Optional<S32> max_width, + padding; Optional<bool> wrap; Params(); @@ -94,7 +103,6 @@ public: /*virtual*/ void draw(); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ void setValue(const LLSD& value); /*virtual*/ void setVisible(BOOL visible); bool isFading(); @@ -102,6 +110,7 @@ public: bool hasClickCallback(); LLToolTip(const Params& p); + void initFromParams(const LLToolTip::Params& params); private: class LLTextBox* mTextBox; @@ -111,7 +120,6 @@ private: LLFrameTimer mFadeTimer; LLFrameTimer mVisibleTimer; - S32 mMaxWidth; bool mHasClickCallback; S32 mPadding; // pixels }; diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index 851091f0ca..f1e3000547 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -69,7 +69,14 @@ void LLUIColorTable::insertFromParams(const Params& p) ColorEntryParams color_entry = *it; if(color_entry.color.value.isChosen()) { - setColor(color_entry.name, color_entry.color.value, mLoadedColors); + if(mUserSetColors.find(color_entry.name)!=mUserSetColors.end()) + { + setColor(color_entry.name, color_entry.color.value); + } + else + { + setColor(color_entry.name, color_entry.color.value, mLoadedColors); + } } else { @@ -213,7 +220,7 @@ bool LLUIColorTable::loadFromSettings() result |= loadFromFilename(current_filename); } - std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SKIN, "colors.xml"); + std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml"); loadFromFilename(user_filename); return result; @@ -239,7 +246,7 @@ void LLUIColorTable::saveUserSettings() const if(!output_node->isNull()) { - const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SKIN, "colors.xml"); + const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml"); LLFILE *fp = LLFile::fopen(filename, "w"); if(fp != NULL) diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 08fc8fb784..aaadc1b58d 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -38,6 +38,10 @@ #include "llpanel.h" #include "lluictrlfactory.h" +// This breaks the ability to construct dummy LLUICtrls for calls like +// getChild<LLUICtrl>("not-there") +//static LLWidgetNameRegistry::StaticRegistrar r(&typeid(LLUICtrl::Params), "ui_ctrl"); +// This doesn't appear to read/apply ui_ctrl.xml static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl"); LLUICtrl::Params::Params() diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index dae4b512d1..219fae84be 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -512,50 +512,6 @@ std::string LLUrlEntryTeleport::getLocation(const std::string &url) const return ::getStringAfterToken(url, "app/teleport/"); } -/// -/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g., -/// secondlife:///app/objectim/<sessionid> -/// -LLUrlEntryObjectIM::LLUrlEntryObjectIM() -{ - mPattern = boost::regex("secondlife:///app/objectim/[\\da-f-]+\\??\\S*", - boost::regex::perl|boost::regex::icase); - mMenuName = "menu_url_objectim.xml"; - mTooltip = LLTrans::getString("TooltipObjectIMUrl"); -} - -std::string LLUrlEntryObjectIM::getLabel(const std::string &url, const LLUrlLabelCallback &cb) -{ - LLURI uri(url); - LLSD params = uri.queryMap(); - if (params.has("name")) - { - // look for a ?name=<obj-name> param in the url - // and use that as the label if present. - std::string name = params.get("name"); - LLStringUtil::trim(name); - if (name.empty()) - { - name = LLTrans::getString("Unnamed"); - } - return name; - } - - return unescapeUrl(url); -} - -std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const -{ - LLURI uri(url); - LLSD params = uri.queryMap(); - if (params.has("slurl")) - { - return params.get("slurl"); - } - - return ""; -} - // // LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts // with secondlife:// (used as a catch-all for cases not matched above) diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h index 4507572b1e..7970b48eb5 100644 --- a/indra/llui/llurlentry.h +++ b/indra/llui/llurlentry.h @@ -209,18 +209,6 @@ public: }; /// -/// LLUrlEntryObjectIM Describes a Second Life object instant msg Url, e.g., -/// secondlife:///app/objectim/<sessionid>?name=Foo -/// -class LLUrlEntryObjectIM : public LLUrlEntryBase -{ -public: - LLUrlEntryObjectIM(); - /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb); - /*virtual*/ std::string getLocation(const std::string &url) const; -}; - -/// /// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts /// with secondlife:// (used as a catch-all for cases not matched above) /// diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index 60275b60bc..a6922b019b 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -52,7 +52,6 @@ LLUrlRegistry::LLUrlRegistry() registerUrl(new LLUrlEntryParcel()); registerUrl(new LLUrlEntryTeleport()); registerUrl(new LLUrlEntryWorldMap()); - registerUrl(new LLUrlEntryObjectIM()); registerUrl(new LLUrlEntryPlace()); registerUrl(new LLUrlEntrySL()); registerUrl(new LLUrlEntrySLLabel()); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 13c381edae..9d44f34ea8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -246,11 +246,13 @@ set(viewer_SOURCE_FILES llinspectavatar.cpp llinspectgroup.cpp llinspectobject.cpp + llinspectremoteobject.cpp llinventorybridge.cpp llinventoryclipboard.cpp llinventoryfilter.cpp llinventoryfunctions.cpp llinventorymodel.cpp + llinventoryobserver.cpp llinventorypanel.cpp llinventorysubtreepanel.cpp lljoystickbutton.cpp @@ -741,11 +743,13 @@ set(viewer_HEADER_FILES llinspectavatar.h llinspectgroup.h llinspectobject.h + llinspectremoteobject.h llinventorybridge.h llinventoryclipboard.h llinventoryfilter.h llinventoryfunctions.h llinventorymodel.h + llinventoryobserver.h llinventorypanel.h llinventorysubtreepanel.h lljoystickbutton.h @@ -1379,7 +1383,7 @@ if (WINDOWS) ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln --workingdir ${VIEWER_BINARY_NAME} - "./${CMAKE_CFG_INTDIR}" + "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging." ) endif (NOT UNATTENDED) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index d7bb64ce8a..ec80d2d014 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -34,6 +34,7 @@ </array> <key>classes</key> <array> + <string>LLBottomTray</string> </array> <key>files</key> <array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 15c9499bbc..eb4148f92f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4259,7 +4259,29 @@ <key>Value</key> <integer>0</integer> </map> - <key>LogMessages</key> + <key>LoginSRVTimeout</key> + <map> + <key>Comment</key> + <string>Duration in seconds of the login SRV request timeout</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>10.0</real> + </map> + <key>LoginSRVPump</key> + <map> + <key>Comment</key> + <string>Name of the message pump that handles SRV request</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>LLAres</string> + </map> + <key>LogMessages</key> <map> <key>Comment</key> <string>Log network traffic</string> @@ -5501,7 +5523,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>QAMode</key> <map> diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 0f00078b33..b3ed7c353e 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -22,12 +22,20 @@ #include "llviewerregion.h" LLAgentListener::LLAgentListener(LLAgent &agent) - : LLDispatchListener("LLAgent", "op"), + : LLEventAPI("LLAgent", + "LLAgent listener to (e.g.) teleport, sit, stand, etc."), mAgent(agent) { - add("requestTeleport", &LLAgentListener::requestTeleport); - add("requestSit", &LLAgentListener::requestSit); - add("requestStand", &LLAgentListener::requestStand); + add("requestTeleport", + "Teleport: [\"regionname\"], [\"x\"], [\"y\"], [\"z\"]\n" + "If [\"skip_confirmation\"] is true, use LLURLDispatcher rather than LLCommandDispatcher.", + &LLAgentListener::requestTeleport); + add("requestSit", + "Ask to sit on the object specified in [\"obj_uuid\"]", + &LLAgentListener::requestSit); + add("requestStand", + "Ask to stand up", + &LLAgentListener::requestStand); } void LLAgentListener::requestTeleport(LLSD const & event_data) const @@ -40,7 +48,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const params.append(event_data["y"]); params.append(event_data["z"]); LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true); - // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "objectim", "parcel", "login", login_refresh", "balance", "chat" + // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat" // should we just compose LLCommandHandler and LLDispatchListener? } else diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index 6f0b5a54c5..eed6922b3e 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -13,12 +13,12 @@ #ifndef LL_LLAGENTLISTENER_H #define LL_LLAGENTLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" class LLAgent; class LLSD; -class LLAgentListener : public LLDispatchListener +class LLAgentListener : public LLEventAPI { public: LLAgentListener(LLAgent &agent); diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp index 2911a35581..568ac4164a 100644 --- a/indra/newview/llagentui.cpp +++ b/indra/newview/llagentui.cpp @@ -159,19 +159,19 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const buffer = llformat("%.100s", parcel_name.c_str()); break; case LOCATION_FORMAT_NORMAL: - buffer = llformat("%s, %s", region_name.c_str(), parcel_name.c_str()); + buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str()); break; case LOCATION_FORMAT_WITHOUT_SIM: buffer = llformat("%s, %s (%d, %d, %d)", - region_name.c_str(), parcel_name.c_str(), + region_name.c_str(), pos_x, pos_y, pos_z); break; case LOCATION_FORMAT_FULL: std::string sim_access_string = region->getSimAccessString(); buffer = llformat("%s, %s (%d, %d, %d)%s%s", - region_name.c_str(), parcel_name.c_str(), + region_name.c_str(), pos_x, pos_y, pos_z, sim_access_string.empty() ? "" : " - ", sim_access_string.c_str()); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 3fc1055acd..9b4986247f 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -887,9 +887,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs lldebugs << " " << LLWearableDictionary::getTypeLabel(type) << llendl; } - // What we do here is get the complete information on the items in - // the inventory, and set up an observer that will wait for that to - // happen. + // Get the complete information on the items in the inventory and set up an observer + // that will trigger when the complete information is fetched. LLInventoryFetchDescendentsObserver::folder_ref_t folders; folders.push_back(current_outfit_id); outfit->fetchDescendents(folders); @@ -1985,14 +1984,14 @@ bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const return !(((type == WT_SHAPE) || (type == WT_SKIN) || (type == WT_HAIR) || (type == WT_EYES)) && (getWearableCount(type) <= 1) ); } -void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL set_by_user) +void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake) { for( S32 type = 0; type < WT_COUNT; ++type ) { for (S32 count = 0; count < (S32)getWearableCount((EWearableType)type); ++count) { LLWearable *wearable = getWearable((EWearableType)type,count); - wearable->animateParams(delta, set_by_user); + wearable->animateParams(delta, upload_bake); } } } @@ -2023,6 +2022,8 @@ void LLInitialWearablesFetch::done() else { processWearablesMessage(); + // Create links for attachments that may have arrived before the COF existed. + LLAppearanceManager::linkRegisteredAttachments(); } delete this; } diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 317f4a7e4f..9017c25fc6 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -80,7 +80,7 @@ public: // Note: False for shape, skin, eyes, and hair, unless you have MORE than 1. bool canWearableBeRemoved(const LLWearable* wearable) const; - void animateAllWearableParams(F32 delta, BOOL set_by_user); + void animateAllWearableParams(F32 delta, BOOL upload_bake); //-------------------------------------------------------------------- // Accessors diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d14de1c301..0901289dac 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1123,6 +1123,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) { if (do_update) LLAppearanceManager::updateAppearanceFromCOF(); + return; } else { @@ -1134,6 +1135,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) LLAssetType::AT_LINK, cb); } + return; } /* static */ @@ -1281,3 +1283,22 @@ void LLAppearanceManager::unregisterAttachment(const LLUUID& item_id) //llinfos << "no link changes, inv link not enabled" << llendl; } } + +/* static */ +void LLAppearanceManager::linkRegisteredAttachments() +{ + for (std::set<LLUUID>::iterator it = sRegisteredAttachments.begin(); + it != sRegisteredAttachments.end(); + ++it) + { + LLUUID item_id = *it; + LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + { + wearItem(item, false); + gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); + gInventory.notifyObservers(); + } + } + sRegisteredAttachments.clear(); +} diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 56f54dfc23..7dea16b6cf 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -71,6 +71,7 @@ public: static void unregisterAttachment(const LLUUID& item_id); static void registerAttachment(const LLUUID& item_id); static void setAttachmentInvLinkEnable(bool val); + static void linkRegisteredAttachments(); private: static void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ddb6589b49..845a264327 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -207,7 +207,7 @@ #pragma warning (disable:4702) #endif -static LLAppViewerListener sAppViewerListener("LLAppViewer", LLAppViewer::instance); +static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp index 3259309eee..adb5f43c1a 100644 --- a/indra/newview/llappviewerlistener.cpp +++ b/indra/newview/llappviewerlistener.cpp @@ -19,14 +19,18 @@ // other Linden headers #include "llappviewer.h" -LLAppViewerListener::LLAppViewerListener(const std::string& pumpname, - const LLAppViewerGetter& getter): - LLDispatchListener(pumpname, "op"), +LLAppViewerListener::LLAppViewerListener(const LLAppViewerGetter& getter): + LLEventAPI("LLAppViewer", + "LLAppViewer listener to (e.g.) request shutdown"), mAppViewerGetter(getter) { // add() every method we want to be able to invoke via this event API. - add("requestQuit", &LLAppViewerListener::requestQuit); - add("forceQuit", &LLAppViewerListener::forceQuit); + add("requestQuit", + "Ask to quit nicely", + &LLAppViewerListener::requestQuit); + add("forceQuit", + "Quit abruptly", + &LLAppViewerListener::forceQuit); } void LLAppViewerListener::requestQuit(const LLSD& event) diff --git a/indra/newview/llappviewerlistener.h b/indra/newview/llappviewerlistener.h index 73227cb95a..deedcbc179 100644 --- a/indra/newview/llappviewerlistener.h +++ b/indra/newview/llappviewerlistener.h @@ -12,20 +12,19 @@ #if ! defined(LL_LLAPPVIEWERLISTENER_H) #define LL_LLAPPVIEWERLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" #include <boost/function.hpp> class LLAppViewer; class LLSD; /// Listen on an LLEventPump with specified name for LLAppViewer request events. -class LLAppViewerListener: public LLDispatchListener +class LLAppViewerListener: public LLEventAPI { public: typedef boost::function<LLAppViewer*(void)> LLAppViewerGetter; - /// Specify the pump name on which to listen, and bind the LLAppViewer - /// instance to use (e.g. LLAppViewer::instance()). - LLAppViewerListener(const std::string& pumpname, const LLAppViewerGetter& getter); + /// Bind the LLAppViewer instance to use (e.g. LLAppViewer::instance()). + LLAppViewerListener(const LLAppViewerGetter& getter); private: void requestQuit(const LLSD& event); diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index dae4296a82..ee4a9df15f 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -54,11 +54,15 @@ #include "llmutelist.h" #include "llrecentpeople.h" #include "llsidetray.h" +#include "lltrans.h" #include "llviewerobjectlist.h" #include "llviewermessage.h" // for handle_lure #include "llviewerregion.h" #include "llimfloater.h" +#include "lltrans.h" +// callback connection to auto-call when the IM floater initializes +boost::signals2::connection gAdhocAutoCall; // static void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name) @@ -188,7 +192,7 @@ void LLAvatarActions::startIM(const LLUUID& id) // static void LLAvatarActions::startCall(const LLUUID& id) { - if (id.isNull() || isCalling(id)) + if (id.isNull()) { return; } @@ -206,6 +210,39 @@ void LLAvatarActions::startCall(const LLUUID& id) } // static +void LLAvatarActions::startAdhocCall(const std::vector<LLUUID>& ids) +{ + if (ids.size() == 0) + { + return; + } + + // convert vector into LLDynamicArray for addSession + LLDynamicArray<LLUUID> id_array; + for (std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + id_array.push_back(*it); + } + + // create the new ad hoc voice session + const std::string title = LLTrans::getString("conference-title"); + LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, + ids[0], id_array); + if (session_id == LLUUID::null) + { + return; + } + + // always open IM window when connecting to voice + LLIMFloater::show(session_id); + + // start the call once the floater has fully initialized + gAdhocAutoCall = LLIMModel::getInstance()->addSessionInitializedCallback(callbackAutoStartCall); + + make_ui_sound("UISndStartIM"); +} + +// static bool LLAvatarActions::isCalling(const LLUUID &id) { if (id.isNull()) @@ -226,7 +263,8 @@ void LLAvatarActions::startConference(const std::vector<LLUUID>& ids) { id_array.push_back(*it); } - LLUUID session_id = gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array); + const std::string title = LLTrans::getString("conference-title"); + LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array); if (session_id != LLUUID::null) { LLIMFloater::show(session_id); @@ -394,6 +432,17 @@ bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& re } // static +void LLAvatarActions::callbackAutoStartCall(const LLSD& data) +{ + // start the adhoc voice call now the IM panel has initialized + LLUUID session_id = data["session_id"].asUUID(); + gIMMgr->startCall(session_id); + + // and deschedule this callback as its work is done now + gAdhocAutoCall.disconnect(); +} + +// static void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message) { const LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 0ec20ae357..66ea6880db 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -33,6 +33,13 @@ #ifndef LL_LLAVATARACTIONS_H #define LL_LLAVATARACTIONS_H +#include "lldarray.h" +#include "llsd.h" +#include "lluuid.h" + +#include <string> +#include <vector> + /** * Friend-related actions (add, remove, offer teleport, etc) */ @@ -72,6 +79,11 @@ public: static void startCall(const LLUUID& id); /** + * Start an ad-hoc conference voice call with multiple users + */ + static void startAdhocCall(const std::vector<LLUUID>& ids); + + /** * Start conference chat with the given avatars. */ static void startConference(const std::vector<LLUUID>& ids); @@ -117,6 +129,7 @@ private: static bool handleRemove(const LLSD& notification, const LLSD& response); static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id); static void callback_invite_to_group(LLUUID group_id, LLUUID id); + static void callbackAutoStartCall(const LLSD& data); // Just request friendship, no dialog. static void requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message); diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 0ee3e78409..327d80ba34 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -143,7 +143,8 @@ void LLAvatarIconIDCache::remove (const LLUUID& avatar_id) LLAvatarIconCtrl::Params::Params() : avatar_id("avatar_id"), - draw_tooltip("draw_tooltip", true) + draw_tooltip("draw_tooltip", true), + default_icon_name("default_icon_name") { name = "avatar_icon"; } @@ -151,7 +152,8 @@ LLAvatarIconCtrl::Params::Params() LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) : LLIconCtrl(p), - mDrawTooltip(p.draw_tooltip) + mDrawTooltip(p.draw_tooltip), + mDefaultIconName(p.default_icon_name) { mPriority = LLViewerFetchedTexture::BOOST_ICON; @@ -193,16 +195,8 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) } else { - LLIconCtrl::setValue("default_profile_picture.j2c"); + LLIconCtrl::setValue(mDefaultIconName); } - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - - registrar.add("AvatarIcon.Action", boost::bind(&LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked, this, _2)); - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - - mPopupMenuHandle = menu->getHandle(); } LLAvatarIconCtrl::~LLAvatarIconCtrl() @@ -212,8 +206,6 @@ LLAvatarIconCtrl::~LLAvatarIconCtrl() LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this); // Name callbacks will be automatically disconnected since LLUICtrl is trackable } - - LLView::deleteViewByHandle(mPopupMenuHandle); } //virtual @@ -270,7 +262,7 @@ bool LLAvatarIconCtrl::updateFromCache() } else { - LLIconCtrl::setValue("default_profile_picture.j2c"); + LLIconCtrl::setValue(mDefaultIconName); } return true; @@ -295,32 +287,6 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type) } } -BOOL LLAvatarIconCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); - - if(menu) - { - bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarId) != NULL; - - menu->setItemEnabled("Add Friend", !is_friend); - menu->setItemEnabled("Remove Friend", is_friend); - - if(gAgentID == mAvatarId) - { - menu->setItemEnabled("Add Friend", false); - menu->setItemEnabled("Send IM", false); - menu->setItemEnabled("Remove Friend", false); - } - - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, x, y); - } - - return TRUE; -} - void LLAvatarIconCtrl::nameUpdatedCallback( const LLUUID& id, const std::string& first, @@ -338,40 +304,3 @@ void LLAvatarIconCtrl::nameUpdatedCallback( } } } - -void LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked(const LLSD& userdata) -{ - std::string level = userdata.asString(); - LLUUID id = getAvatarId(); - - if (level == "profile") - { - LLAvatarActions::showProfile(id); - } - else if (level == "im") - { - std::string name; - name.assign(getFirstName()); - name.append(" "); - name.append(getLastName()); - - LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); - if (session_id != LLUUID::null) - { - LLIMFloater::show(session_id); - } - } - else if (level == "add") - { - std::string name; - name.assign(getFirstName()); - name.append(" "); - name.append(getLastName()); - - LLAvatarActions::requestFriendshipDialog(id, name); - } - else if (level == "remove") - { - LLAvatarActions::removeFriendDialog(id); - } -} diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index 65b5c86ed5..38616b7852 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -74,6 +74,7 @@ public: { Optional <LLUUID> avatar_id; Optional <bool> draw_tooltip; + Optional <std::string> default_icon_name; Params(); }; @@ -81,8 +82,6 @@ protected: LLAvatarIconCtrl(const Params&); friend class LLUICtrlFactory; - void onAvatarIconContextMenuItemClicked(const LLSD& userdata); - public: virtual ~LLAvatarIconCtrl(); @@ -91,8 +90,6 @@ public: // LLAvatarPropertiesProcessor observer trigger virtual void processProperties(void* data, EAvatarProcessorType type); - BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - void nameUpdatedCallback( const LLUUID& id, const std::string& first, @@ -109,9 +106,8 @@ protected: LLUUID mAvatarId; std::string mFirstName; std::string mLastName; - LLHandle<LLView> mPopupMenuHandle; bool mDrawTooltip; - + std::string mDefaultIconName; bool updateFromCache(); }; diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 73e24ca8e7..7cda2d31e6 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -158,6 +158,11 @@ void LLAvatarPropertiesProcessor::sendAvatarTexturesRequest(const LLUUID& avatar removePendingRequest(avatar_id, APT_TEXTURES); } +void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& avatar_id) +{ + sendGenericRequest(avatar_id, APT_CLASSIFIEDS, "avatarclassifiedsrequest"); +} + void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props) { llinfos << "Sending avatarinfo update" << llendl; @@ -284,12 +289,60 @@ void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* m */ } -void LLAvatarPropertiesProcessor::processAvatarClassifiedReply(LLMessageSystem* msg, void**) +void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**) { - // avatarclassifiedsrequest is not sent according to new UI design but - // keep this method according to resolved issues. + LLAvatarClassifieds classifieds; + + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, classifieds.agent_id); + msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, classifieds.target_id); + + S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data); + + for(int n = 0; n < block_count; ++n) + { + LLAvatarClassifieds::classified_data data; + + msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n); + msg->getString(_PREHASH_Data, _PREHASH_Name, data.name, n); + + classifieds.classifieds_list.push_back(data); + } + + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(classifieds.target_id, APT_CLASSIFIEDS); + self->notifyObservers(classifieds.target_id,&classifieds,APT_CLASSIFIEDS); } +void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* msg, void**) +{ + LLAvatarClassifiedInfo c_info; + + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, c_info.agent_id); + + msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, c_info.classified_id); + msg->getUUID(_PREHASH_Data, _PREHASH_CreatorID, c_info.creator_id); + msg->getU32(_PREHASH_Data, _PREHASH_CreationDate, c_info.creation_date); + msg->getU32(_PREHASH_Data, _PREHASH_ExpirationDate, c_info.expiration_date); + msg->getU32(_PREHASH_Data, _PREHASH_Category, c_info.category); + msg->getString(_PREHASH_Data, _PREHASH_Name, c_info.name); + msg->getString(_PREHASH_Data, _PREHASH_Desc, c_info.description); + msg->getUUID(_PREHASH_Data, _PREHASH_ParcelID, c_info.parcel_id); + msg->getU32(_PREHASH_Data, _PREHASH_ParentEstate, c_info.parent_estate); + msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, c_info.snapshot_id); + msg->getString(_PREHASH_Data, _PREHASH_SimName, c_info.sim_name); + msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, c_info.pos_global); + msg->getString(_PREHASH_Data, _PREHASH_ParcelName, c_info.parcel_name); + msg->getU8(_PREHASH_Data, _PREHASH_ClassifiedFlags, c_info.flags); + msg->getS32(_PREHASH_Data, _PREHASH_PriceForListing, c_info.price_for_listing); + + LLAvatarPropertiesProcessor* self = getInstance(); + // Request processed, no longer pending + self->removePendingRequest(c_info.creator_id, APT_CLASSIFIED_INFO); + self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO); +} + + void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**) { LLAvatarNotes avatar_notes; @@ -451,6 +504,22 @@ void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id ) LLAgentPicksInfo::getInstance()->decrementNumberOfPicks(); } +void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_id) +{ + LLMessageSystem* msg = gMessageSystem; + + msg->newMessage(_PREHASH_ClassifiedDelete); + + msg->nextBlock(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgent.getID()); + msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_ClassifiedID, classified_id); + + gAgent.sendReliableMessage(); +} + void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) { if (!new_pick) return; @@ -485,6 +554,36 @@ void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); } +void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data) +{ + if(!c_data) + { + return; + } + + LLMessageSystem* msg = gMessageSystem; + + msg->newMessage(_PREHASH_ClassifiedInfoUpdate); + + msg->nextBlock(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgent.getID()); + msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_ClassifiedID, c_data->classified_id); + msg->addU32(_PREHASH_Category, c_data->category); + msg->addString(_PREHASH_Name, c_data->name); + msg->addString(_PREHASH_Desc, c_data->description); + msg->addUUID(_PREHASH_ParcelID, c_data->parcel_id); + msg->addU32(_PREHASH_ParentEstate, 0); + msg->addUUID(_PREHASH_SnapshotID, c_data->snapshot_id); + msg->addVector3d(_PREHASH_PosGlobal, c_data->pos_global); + msg->addU8(_PREHASH_ClassifiedFlags, c_data->flags); + msg->addS32(_PREHASH_PriceForListing, c_data->price_for_listing); + + gAgent.sendReliableMessage(); +} + void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id) { // Must ask for a pick based on the creator id because @@ -495,6 +594,21 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, send_generic_message("pickinforequest", request_params); } +void LLAvatarPropertiesProcessor::sendClassifiedInfoRequest(const LLUUID& classified_id) +{ + LLMessageSystem* msg = gMessageSystem; + + msg->newMessage(_PREHASH_ClassifiedInfoRequest); + msg->nextBlock(_PREHASH_AgentData); + + msg->addUUID(_PREHASH_AgentID, gAgent.getID()); + msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_ClassifiedID, classified_id); + + gAgent.sendReliableMessage(); +} bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) { diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index e6563024b2..716c1b8065 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -53,7 +53,9 @@ enum EAvatarProcessorType APT_GROUPS, APT_PICKS, APT_PICK_INFO, - APT_TEXTURES + APT_TEXTURES, + APT_CLASSIFIEDS, + APT_CLASSIFIED_INFO }; struct LLAvatarData @@ -136,6 +138,43 @@ struct LLAvatarGroups }; }; +struct LLAvatarClassifieds +{ + LLUUID agent_id; + LLUUID target_id; + + struct classified_data; + typedef std::list<classified_data> classifieds_list_t; + + classifieds_list_t classifieds_list; + + struct classified_data + { + LLUUID classified_id; + std::string name; + }; +}; + +struct LLAvatarClassifiedInfo +{ + LLUUID agent_id; + LLUUID classified_id; + LLUUID creator_id; + U32 creation_date; + U32 expiration_date; + U32 category; + std::string name; + std::string description; + LLUUID parcel_id; + U32 parent_estate; + LLUUID snapshot_id; + std::string sim_name; + LLVector3d pos_global; + std::string parcel_name; + U8 flags; + S32 price_for_listing; +}; + class LLAvatarPropertiesObserver { public: @@ -162,20 +201,27 @@ public: void sendAvatarNotesRequest(const LLUUID& avatar_id); void sendAvatarGroupsRequest(const LLUUID& avatar_id); void sendAvatarTexturesRequest(const LLUUID& avatar_id); + void sendAvatarClassifiedsRequest(const LLUUID& avatar_id); // Duplicate pick info requests are not suppressed. void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id); + void sendClassifiedInfoRequest(const LLUUID& classified_id); + void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props); void sendPickInfoUpdate(const LLPickData* new_pick); + void sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data); + void sendFriendRights(const LLUUID& avatar_id, S32 rights); void sendNotes(const LLUUID& avatar_id, const std::string notes); void sendPickDelete(const LLUUID& pick_id); + void sendClassifiedDelete(const LLUUID& classified_id); + // Returns translated, human readable string for account type, such // as "Resident" or "Linden Employee". Used for profiles, inspectors. static std::string accountType(const LLAvatarData* avatar_data); @@ -189,7 +235,9 @@ public: static void processAvatarInterestsReply(LLMessageSystem* msg, void**); - static void processAvatarClassifiedReply(LLMessageSystem* msg, void**); + static void processAvatarClassifiedsReply(LLMessageSystem* msg, void**); + + static void processClassifiedInfoReply(LLMessageSystem* msg, void**); static void processAvatarGroupsReply(LLMessageSystem* msg, void**); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 832694873f..ab685b69ad 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -40,6 +40,7 @@ #include "llimfloater.h" // for LLIMFloater #include "lllayoutstack.h" #include "llnearbychatbar.h" +#include "llspeakbutton.h" #include "llsplitbutton.h" #include "llsyswellwindow.h" #include "llfloatercamera.h" @@ -50,6 +51,8 @@ LLBottomTray::LLBottomTray(const LLSD&) mSpeakBtn(NULL), mNearbyChatBar(NULL), mToolbarStack(NULL) +, mMovementButton(NULL) +// Add more members { mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL); @@ -72,6 +75,8 @@ LLBottomTray::LLBottomTray(const LLSD&) //destroyed LLBottomTray requires some subsystems that are long gone //LLUI::getRootView()->addChild(this); + initStateProcessedObjectMap(); + // Necessary for focus movement among child controls setFocusRoot(TRUE); } @@ -181,6 +186,28 @@ void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& } } +// virtual +void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + // Time it takes to connect to voice channel might be pretty long, + // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED. + BOOL enable = FALSE; + + switch (status) + { + // Do not add STATUS_VOICE_ENABLED because voice chat is + // inactive until STATUS_JOINED + case STATUS_JOINED: + enable = TRUE; + break; + default: + enable = FALSE; + break; + } + + mSpeakBtn->setEnabled(enable); +} + //virtual void LLBottomTray::onFocusLost() { @@ -254,10 +281,11 @@ void LLBottomTray::showSnapshotButton(BOOL visible) namespace { - const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; - const std::string& PANEL_CHATBAR_NAME = "chat_bar"; - const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; - const std::string& PANEL_CAMERA_NAME = "cam_panel"; + const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; + const std::string& PANEL_CHATBAR_NAME = "chat_bar"; + const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; + const std::string& PANEL_CAMERA_NAME = "cam_panel"; + const std::string& PANEL_GESTURE_NAME = "gesture_panel"; } BOOL LLBottomTray::postBuild() @@ -275,6 +303,19 @@ BOOL LLBottomTray::postBuild() mSnapshotPanel = getChild<LLPanel>("snapshot_panel"); setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4)); + mSpeakBtn = getChild<LLSpeakButton>("talk"); + + // Speak button should be initially disabled because + // it takes some time between logging in to world and connecting to voice channel. + mSpeakBtn->setEnabled(FALSE); + + // Localization tool doesn't understand custom buttons like <talk_button> + mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") ); + mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") ); + + // Registering Chat Bar to receive Voice client status change notifications. + gVoiceClient->addObserver(this); + if (mChicletPanel && mToolbarStack && mNearbyChatBar) { verifyChildControlsSizes(); @@ -283,159 +324,393 @@ BOOL LLBottomTray::postBuild() return TRUE; } +void LLBottomTray::log(LLView* panel, const std::string& descr) +{ + if (NULL == panel) return; + LLView* layout = panel->getParent(); + lldebugs << descr << ": " + << "panel: " << panel->getName() + << ", rect: " << panel->getRect() + + + << "layout: " << layout->getName() + << ", rect: " << layout->getRect() + << llendl + ; +} + void LLBottomTray::verifyChildControlsSizes() { LLRect rect = mChicletPanel->getRect(); + /* if (rect.getWidth() < mChicletPanel->getMinWidth()) { + llwarns << "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ: chiclet panel less then min" << llendl; mChicletPanel->reshape(mChicletPanel->getMinWidth(), rect.getHeight()); } - +*/ rect = mNearbyChatBar->getRect(); +/* if (rect.getWidth() < mNearbyChatBar->getMinWidth()) { + llwarns << "WWWWWWWWWWWWWWWWWWWWWWWWWWWWW: near chat panel less then min" << llendl; mNearbyChatBar->reshape(mNearbyChatBar->getMinWidth(), rect.getHeight()); } - else if (rect.getWidth() > mNearbyChatBar->getMaxWidth()) + else +*/ + if (rect.getWidth() > mNearbyChatBar->getMaxWidth()) { + llerrs << "WWWWWWWWWWWWWWWWWWWWWWWWWWWWW: near chat panel more then max width" << llendl; + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, mNearbyChatBar->getMaxWidth(), rect.getHeight()); mNearbyChatBar->reshape(mNearbyChatBar->getMaxWidth(), rect.getHeight()); mNearbyChatBar->setRect(rect); } } - +#define __FEATURE_EXT_991 void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) { + lldebugs << "****************************************" << llendl; + + S32 current_width = getRect().getWidth(); + lldebugs << "Reshaping: " + << ", width: " << width + << ", height: " << height + << ", called_from_parent: " << called_from_parent + << ", cur width: " << current_width + << ", cur height: " << getRect().getHeight() + << llendl; + + if (mNearbyChatBar) log(mNearbyChatBar, "before"); + if (mChicletPanel) log(mChicletPanel, "before"); if (mChicletPanel && mToolbarStack && mNearbyChatBar) { -#ifdef __FEATURE_EXT_991__ - BOOL shrink = width < getRect().getWidth(); - const S32 MIN_RENDERED_CHARS = 3; -#endif + mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); + verifyChildControlsSizes(); + updateResizeState(width, current_width); + } - verifyChildControlsSizes(); - updateResizeState(width, height); + LLPanel::reshape(width, height, called_from_parent); + + + if (mNearbyChatBar) log(mNearbyChatBar, "after"); + if (mChicletPanel) log(mChicletPanel, "after"); +} + +void LLBottomTray::updateResizeState(S32 new_width, S32 cur_width) +{ + mResizeState = RS_NORESIZE; + MASK compensative_view_item_mask = RS_CHATBAR_INPUT; + LLPanel* compansative_view = mNearbyChatBar; + + S32 delta_width = new_width - cur_width; +// if (delta_width == 0) return; + bool shrink = new_width < cur_width; + + const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); + const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); - switch (mResizeState) + const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); + const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); + const S32 chatbar_panel_max_width = mNearbyChatBar->getMaxWidth(); + + lldebugs << "chatbar_panel_width: " << chatbar_panel_width + << ", chatbar_panel_min_width: " << chatbar_panel_min_width + << ", chatbar_panel_max_width: " << chatbar_panel_max_width + << ", chiclet_panel_width: " << chiclet_panel_width + << ", chiclet_panel_min_width: " << chiclet_panel_min_width + << llendl; + + bool still_should_be_processed = true; + // bottom tray is narrowed + if (shrink) + { + S32 compensative_delta_width = 0; + if (chiclet_panel_width > chiclet_panel_min_width) + { + // we have some space to decrease chiclet panel + S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width; + mResizeState |= RS_CHICLET_PANEL; + + S32 delta_panel = llmin(-delta_width, panel_delta_min); + + lldebugs << "delta_width: " << delta_width + << ", panel_delta_min: " << panel_delta_min + << ", delta_panel: " << delta_panel + << llendl; + + // is chiclet panel width enough to process resizing? + delta_width += panel_delta_min; + + still_should_be_processed = delta_width < 0; + + mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight()); + log(mChicletPanel, "after processing panel decreasing via chiclet panel"); + + lldebugs << "RS_CHICLET_PANEL" + << ", delta_width: " << delta_width + << llendl; + } + + if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width) { - case STATE_CHICLET_PANEL: - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); + // we have some space to decrease chatbar panel + S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width; + mResizeState |= RS_CHATBAR_INPUT; - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, FALSE); + S32 delta_panel = llmin(-delta_width, panel_delta_min); - break; - case STATE_CHATBAR_INPUT: - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE); + // is chatbar panel width enough to process resizing? + delta_width += panel_delta_min; + - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, FALSE); + still_should_be_processed = delta_width < 0; - break; + mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mNearbyChatBar->getRect().getHeight()); -#ifdef __FEATURE_EXT_991__ + lldebugs << "RS_CHATBAR_INPUT" + << ", delta_panel: " << delta_panel + << ", delta_width: " << delta_width + << llendl; - case STATE_BUTTONS: - mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, TRUE); - mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, TRUE); + log(mChicletPanel, "after nearby was processed"); - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); + } + if (still_should_be_processed) + { + mResizeState |= compensative_view_item_mask; - if (shrink) + if (mSnapshotPanel->getVisible()) { + mResizeState |= RS_BUTTON_SNAPSHOT; + delta_width += mSnapshotPanel->getRect().getWidth(); - if (mSnapshotPanel->getVisible()) + if (delta_width > 0) { - showSnapshotButton(FALSE); + compensative_delta_width += delta_width; } + lldebugs << "RS_BUTTON_SNAPSHOT" + << ", compensative_delta_width: " << compensative_delta_width + << ", delta_width: " << delta_width + << llendl; + showSnapshotButton(false); + } - if (mCamPanel->getVisible() && mCamButton->getLastDrawCharsCount() < MIN_RENDERED_CHARS) + if (delta_width < 0 && mCamPanel->getVisible()) + { + mResizeState |= RS_BUTTON_CAMERA; + delta_width += mCamPanel->getRect().getWidth(); + if (delta_width > 0) { - showCameraButton(FALSE); + compensative_delta_width += delta_width; } + lldebugs << "RS_BUTTON_CAMERA" + << ", compensative_delta_width: " << compensative_delta_width + << ", delta_width: " << delta_width + << llendl; + showCameraButton(false); + } - if (mMovementPanel->getVisible() && mMovementButton->getLastDrawCharsCount() < MIN_RENDERED_CHARS) + if (delta_width < 0 && mMovementPanel->getVisible()) + { + mResizeState |= RS_BUTTON_MOVEMENT; + delta_width += mMovementPanel->getRect().getWidth(); + if (delta_width > 0) { - showMoveButton(FALSE); + compensative_delta_width += delta_width; } - + lldebugs << "RS_BUTTON_MOVEMENT" + << ", compensative_delta_width: " << compensative_delta_width + << ", delta_width: " << delta_width + << llendl; + showMoveButton(false); } - else - { - showMoveButton(TRUE); - mMovementPanel->draw(); - if (mMovementButton->getLastDrawCharsCount() >= MIN_RENDERED_CHARS) - { - showMoveButton(TRUE); - } - else + if (delta_width < 0 && mGesturePanel->getVisible()) + { + mResizeState |= RS_BUTTON_GESTURES; + delta_width += mGesturePanel->getRect().getWidth(); + if (delta_width > 0) { - showMoveButton(FALSE); + compensative_delta_width += delta_width; } + lldebugs << "RS_BUTTON_GESTURES" + << ", compensative_delta_width: " << compensative_delta_width + << ", delta_width: " << delta_width + << llendl; + showGestureButton(false); } - break; -#endif - default: - break; + if (delta_width < 0) + { + llwarns << "WARNING: there is no enough room for bottom tray, resizing still should be processed" << llendl; + } + + if (compensative_delta_width != 0) + { + if (compansative_view) log(compansative_view, "before applying compensative width: "); + compansative_view->reshape(compansative_view->getRect().getWidth() + compensative_delta_width, compansative_view->getRect().getHeight() ); + if (compansative_view) log(compansative_view, "after applying compensative width: "); + lldebugs << compensative_delta_width << llendl; + + } } } + // bottom tray is widen + else + { + processWidthIncreased(delta_width); + } - LLPanel::reshape(width, height, called_from_parent); + lldebugs << "New resize state: " << mResizeState << llendl; } -void LLBottomTray::updateResizeState(S32 width, S32 height) +void LLBottomTray::processWidthDecreased(S32 delta_width) { - mResizeState = STATE_BUTTONS; - const S32 chiclet_panel_width = mChicletPanel->getRect().getWidth(); +} + +void LLBottomTray::processWidthIncreased(S32 delta_width) +{ + const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); const S32 chatbar_panel_max_width = mNearbyChatBar->getMaxWidth(); - // bottom tray is narrowed - if (width < getRect().getWidth()) + const S32 chatbar_available_shrink_width = chatbar_panel_width - chatbar_panel_min_width; + const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width; + + // how many room we have to show hidden buttons + S32 available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet; + S32 buttons_required_width = 0; //How many room will take shown buttons + + if (available_width > 0) { - if (chiclet_panel_width > chiclet_panel_min_width) - { - mResizeState = STATE_CHICLET_PANEL; - } - else if (chatbar_panel_width > chatbar_panel_min_width) - { - mResizeState = STATE_CHATBAR_INPUT; - } - else - { - mResizeState = STATE_BUTTONS; - } + lldebugs << "Trying to process: RS_BUTTON_GESTURES" << llendl; + processShowButton(RS_BUTTON_GESTURES, &available_width, &buttons_required_width); } - // bottom tray is widen - else + + if (available_width > 0) + { + lldebugs << "Trying to process: RS_BUTTON_MOVEMENT" << llendl; + processShowButton(RS_BUTTON_MOVEMENT, &available_width, &buttons_required_width); + } + + if (available_width > 0) + { + lldebugs << "Trying to process: RS_BUTTON_CAMERA" << llendl; + processShowButton(RS_BUTTON_CAMERA, &available_width, &buttons_required_width); + } + + if (available_width > 0) { -#ifdef __FEATURE_EXT_991__ - if (!mMovementPanel->getVisible()) + lldebugs << "Trying to process: RS_BUTTON_SNAPSHOT" << llendl; + processShowButton(RS_BUTTON_SNAPSHOT, &available_width, &buttons_required_width); + } + + // if we have to show some buttons but whidth increasing is not enough... + if (buttons_required_width > 0 && delta_width < buttons_required_width) + { + // ... let's shrink nearby chat & chiclet panels + S32 required_to_process_width = buttons_required_width; + + // 1. use delta width of resizing + required_to_process_width -= delta_width; + + // 2. use width available via decreasing of nearby chat panel + S32 chatbar_shrink_width = required_to_process_width; + if (chatbar_available_shrink_width < chatbar_shrink_width) { - mResizeState = STATE_BUTTONS; + chatbar_shrink_width = chatbar_available_shrink_width; } - else -#endif - if (chatbar_panel_width < chatbar_panel_max_width) + + log(mNearbyChatBar, "increase width: before applying compensative width: "); + mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - chatbar_shrink_width, mNearbyChatBar->getRect().getHeight() ); + if (mNearbyChatBar) log(mNearbyChatBar, "after applying compensative width: "); + lldebugs << chatbar_shrink_width << llendl; + + // 3. use width available via decreasing of chiclet panel + required_to_process_width -= chatbar_shrink_width; + + if (required_to_process_width > 0) { - mResizeState = STATE_CHATBAR_INPUT; + mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight()); + log(mChicletPanel, "after applying compensative width for chiclets: "); + lldebugs << required_to_process_width << llendl; } - else + + } + + // shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels + delta_width -= buttons_required_width; + + // how many space can nearby chatbar take? + S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth(); + if (delta_width > 0 && chatbar_panel_width_ < chatbar_panel_max_width) + { + mResizeState |= RS_CHATBAR_INPUT; + S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_; + S32 delta_panel = llmin(delta_width, delta_panel_max); + delta_width -= delta_panel_max; + mNearbyChatBar->reshape(chatbar_panel_width_ + delta_panel, mNearbyChatBar->getRect().getHeight()); + } +} + +bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width) +{ + LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; + if (NULL == panel) + { + lldebugs << "There is no object to process for state: " << shown_object_type << llendl; + return false; + } + bool can_be_shown = canButtonBeShown(panel); + if (can_be_shown) + { + //validate if we have enough room to show this button + const S32 required_width = panel->getRect().getWidth(); + can_be_shown = *available_width >= required_width; + if (can_be_shown) { - mResizeState = STATE_CHICLET_PANEL; + *available_width -= required_width; + *buttons_required_width += required_width; + + switch (shown_object_type) + { + case RS_BUTTON_GESTURES: showGestureButton(true); break; + case RS_BUTTON_MOVEMENT: showMoveButton(true); break; + case RS_BUTTON_CAMERA: showCameraButton(true); break; + case RS_BUTTON_SNAPSHOT: showSnapshotButton(true); break; + default: + llwarns << "Unexpected type of button to be shown: " << shown_object_type << llendl; + } + + lldebugs << "processing object type: " << shown_object_type + << ", buttons_required_width: " << buttons_required_width + << llendl; } } + return can_be_shown; +} +bool LLBottomTray::canButtonBeShown(LLPanel* panel) const +{ + bool can_be_shown = !panel->getVisible(); + if (can_be_shown) + { + // *TODO: mantipov: synchronize with situation when button was hidden via context menu; + } + return can_be_shown; +} - // TODO: finish implementation +void LLBottomTray::initStateProcessedObjectMap() +{ + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, mGesturePanel)); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, mMovementPanel)); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, mCamPanel)); + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, mSnapshotPanel)); } +//EOF diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 02588a1975..c88bdeda1c 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -33,7 +33,7 @@ #ifndef LL_LLBOTTOMPANEL_H #define LL_LLBOTTOMPANEL_H -#include <llmenugl.h> +#include "llmenugl.h" #include "llpanel.h" #include "llimview.h" @@ -51,7 +51,9 @@ class LLBottomTray : public LLSingleton<LLBottomTray> , public LLPanel , public LLIMSessionObserver + , public LLVoiceClientStatusObserver { + LOG_CLASS(LLBottomTray); friend class LLSingleton<LLBottomTray>; public: ~LLBottomTray(); @@ -74,6 +76,10 @@ public: virtual void onFocusLost(); virtual void setVisible(BOOL visible); + // Implements LLVoiceClientStatusObserver::onChange() to enable the speak + // button when voice is available + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); + void showBottomTrayContextMenu(S32 x, S32 y, MASK mask); void showGestureButton(BOOL visible); @@ -82,18 +88,32 @@ public: void showSnapshotButton(BOOL visible); private: - - enum EResizeState + typedef enum e_resize_status_type { - STATE_CHICLET_PANEL = 1, - STATE_CHATBAR_INPUT, - STATE_BUTTONS - }; - - void updateResizeState(S32 width, S32 height); + RS_NORESIZE = 0x0000 + , RS_CHICLET_PANEL = 0x0001 + , RS_CHATBAR_INPUT = 0x0002 + , RS_BUTTON_SNAPSHOT = 0x0004 + , RS_BUTTON_CAMERA = 0x0008 + , RS_BUTTON_MOVEMENT = 0x0010 + , RS_BUTTON_GESTURES = 0x0020 + , RS_BUTTON_SPEAK = 0x0040 + , RS_RESIZABLE_BUTTONS = /*RS_BUTTON_SNAPSHOT | */RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES + }EResizeState; + + void updateResizeState(S32 new_width, S32 cur_width); void verifyChildControlsSizes(); + void processWidthDecreased(S32 delta_width); + void processWidthIncreased(S32 delta_width); + void log(LLView* panel, const std::string& descr); + bool processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width); + bool canButtonBeShown(LLPanel* panel) const; + void initStateProcessedObjectMap(); + + MASK mResizeState; - EResizeState mResizeState; + typedef std::map<EResizeState, LLPanel*> state_object_map_t; + state_object_map_t mStateProcessedObjectMap; protected: diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 2ccd6b7d35..d1922cfd6e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -47,7 +47,6 @@ #include "llmutelist.h" static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history"); -static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- "); std::string formatCurrentTime() { @@ -175,7 +174,7 @@ public: const std::string& getFirstName() const { return mFirstName; } const std::string& getLastName () const { return mLastName; } - void setup(const LLChat& chat) + void setup(const LLChat& chat,const LLStyle::Params& style_params) { mAvatarID = chat.mFromID; mSourceType = chat.mSourceType; @@ -185,8 +184,11 @@ public: mSourceType = CHAT_SOURCE_SYSTEM; } - LLTextBox* userName = getChild<LLTextBox>("user_name"); + + LLUIColor color = style_params.color; + userName->setReadOnlyColor(color); + userName->setColor(color); if(!chat.mFromName.empty()) { @@ -198,6 +200,7 @@ public: std::string SL = LLTrans::getString("SECOND_LIFE"); userName->setValue(SL); } + LLTextBox* timeBox = getChild<LLTextBox>("time_box"); timeBox->setValue(formatCurrentTime()); @@ -323,17 +326,17 @@ LLView* LLChatHistory::getSeparator() return separator; } -LLView* LLChatHistory::getHeader(const LLChat& chat) +LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params) { LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename); - header->setup(chat); + header->setup(chat,style_params); return header; } void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params) { LLView* view = NULL; - std::string view_text; + std::string view_text = "\n[" + formatCurrentTime() + "] " + chat.mFromName + ": "; LLInlineViewSegment::Params p; p.force_newline = true; @@ -343,14 +346,12 @@ void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& sty if (mLastFromName == chat.mFromName) { view = getSeparator(); - view_text = "\n"; p.top_pad = mTopSeparatorPad; p.bottom_pad = mBottomSeparatorPad; } else { - view = getHeader(chat); - view_text = chat.mFromName + MESSAGE_USERNAME_DATE_SEPARATOR + formatCurrentTime() + '\n'; + view = getHeader(chat,style_params); if (getText().size() == 0) p.top_pad = 0; else @@ -370,10 +371,8 @@ void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& sty appendWidget(p, view_text, false); //Append the text message - std::string message = chat.mText + '\n'; - appendText(message, FALSE, style_params); + appendText(chat.mText, FALSE, style_params); mLastFromName = chat.mFromName; blockUndo(); - setCursorAndScrollToEnd(); } diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index 3789ebff4e..f0944042af 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -94,11 +94,9 @@ class LLChatHistory : public LLTextEditor LLView* getSeparator(); /** * Builds a message header. - * @param from owner of a message. - * @param time time of a message. * @return pointer to LLView header object. */ - LLView* getHeader(const LLChat& chat); + LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params); public: ~LLChatHistory(); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index c200a97058..b919195fb2 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -55,6 +55,13 @@ static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notif static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p"); static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group"); +static const LLRect CHICLET_RECT(0, 25, 25, 0); +static const LLRect CHICLET_ICON_RECT(0, 24, 24, 0); +static const LLRect VOICE_INDICATOR_RECT(25, 25, 45, 0); + +// static +const S32 LLChicletPanel::s_scroll_ratio = 10; + S32 LLNotificationChiclet::mUreadSystemNotifications = 0; boost::signals2::signal<LLChiclet* (const LLUUID&), @@ -96,6 +103,7 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) // connect counter handlers to the signals connectCounterUpdatersToSignal("notify"); connectCounterUpdatersToSignal("groupnotify"); + connectCounterUpdatersToSignal("offer"); } LLNotificationChiclet::~LLNotificationChiclet() @@ -199,7 +207,9 @@ void LLChiclet::setValue(const LLSD& value) LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) : LLChiclet(p) +, mShowSpeaker(false) , mNewMessagesIcon(NULL) +, mSpeakerCtrl(NULL) , mCounterCtrl(NULL) { // initialize an overlay icon for new messages @@ -218,6 +228,40 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) setShowCounter(false); } +void LLIMChiclet::setShowSpeaker(bool show) +{ + bool needs_resize = getShowSpeaker() != show; + if(needs_resize) + { + mShowSpeaker = show; + toggleSpeakerControl(); + onChicletSizeChanged(); + } +} +void LLIMChiclet::initSpeakerControl() +{ + // virtual +} + +void LLIMChiclet::toggleSpeakerControl() +{ + LLRect speaker_rect = mSpeakerCtrl->getRect(); + S32 required_width = getRect().getWidth(); + + if(getShowSpeaker()) + { + required_width = required_width + speaker_rect.getWidth(); + initSpeakerControl(); + } + else + { + required_width = required_width - speaker_rect.getWidth(); + } + + reshape(required_width, getRect().getHeight()); + mSpeakerCtrl->setVisible(getShowSpeaker()); +} + void LLIMChiclet::setShowNewMessagesIcon(bool show) { if(mNewMessagesIcon) @@ -300,7 +344,7 @@ LLIMP2PChiclet::Params::Params() , show_speaker("show_speaker") { // *TODO Vadim: Get rid of hardcoded values. - rect(LLRect(0, 25, 25, 0)); + rect(CHICLET_RECT); avatar_icon.name("avatar_icon"); avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); @@ -309,11 +353,10 @@ LLIMP2PChiclet::Params::Params() // Changed icon height from 25 to 24 to fix ticket EXT-794. // In some cases(after changing UI scale) 25 pixel height icon was // drawn incorrectly, i'm not sure why. - avatar_icon.rect(LLRect(0, 24, 25, 0)); + avatar_icon.rect(CHICLET_ICON_RECT); avatar_icon.mouse_opaque(false); unread_notifications.name("unread"); - unread_notifications.rect(LLRect(25, 25, 45, 0)); unread_notifications.font(LLFontGL::getFontSansSerif()); unread_notifications.font_halign(LLFontGL::HCENTER); unread_notifications.v_pad(5); @@ -322,7 +365,9 @@ LLIMP2PChiclet::Params::Params() unread_notifications.visible(false); speaker.name("speaker"); - speaker.rect(LLRect(45, 25, 65, 0)); + speaker.rect(VOICE_INDICATOR_RECT); + speaker.auto_update(true); + speaker.draw_border(false); show_speaker = false; } @@ -330,7 +375,6 @@ LLIMP2PChiclet::Params::Params() LLIMP2PChiclet::LLIMP2PChiclet(const Params& p) : LLIMChiclet(p) , mChicletIconCtrl(NULL) -, mSpeakerCtrl(NULL) , mPopupMenu(NULL) { LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; @@ -358,18 +402,9 @@ void LLIMP2PChiclet::setCounter(S32 counter) setShowNewMessagesIcon(counter); } -LLRect LLIMP2PChiclet::getRequiredRect() +void LLIMP2PChiclet::initSpeakerControl() { - LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0); - if(getShowCounter()) - { - rect.mRight += mCounterCtrl->getRequiredRect().getWidth(); - } - if(getShowSpeaker()) - { - rect.mRight += mSpeakerCtrl->getRect().getWidth(); - } - return rect; + mSpeakerCtrl->setSpeakerId(getOtherParticipantId()); } void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id) @@ -446,18 +481,6 @@ void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data) } } -void LLIMP2PChiclet::setShowSpeaker(bool show) -{ - LLIMChiclet::setShowSpeaker(show); - - bool needs_resize = getShowSpeaker() != show; - mSpeakerCtrl->setVisible(getShowSpeaker()); - if(needs_resize) - { - onChicletSizeChanged(); - } -} - ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -470,7 +493,7 @@ LLAdHocChiclet::Params::Params() , avatar_icon_color("avatar_icon_color", LLColor4::green) { // *TODO Vadim: Get rid of hardcoded values. - rect(LLRect(0, 25, 25, 0)); + rect(CHICLET_RECT); avatar_icon.name("avatar_icon"); avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); @@ -479,11 +502,10 @@ LLAdHocChiclet::Params::Params() // Changed icon height from 25 to 24 to fix ticket EXT-794. // In some cases(after changing UI scale) 25 pixel height icon was // drawn incorrectly, i'm not sure why. - avatar_icon.rect(LLRect(0, 24, 25, 0)); + avatar_icon.rect(CHICLET_ICON_RECT); avatar_icon.mouse_opaque(false); unread_notifications.name("unread"); - unread_notifications.rect(LLRect(25, 25, 45, 0)); unread_notifications.font(LLFontGL::getFontSansSerif()); unread_notifications.font_halign(LLFontGL::HCENTER); unread_notifications.v_pad(5); @@ -493,7 +515,9 @@ LLAdHocChiclet::Params::Params() speaker.name("speaker"); - speaker.rect(LLRect(45, 25, 65, 0)); + speaker.rect(VOICE_INDICATOR_RECT); + speaker.auto_update(true); + speaker.draw_border(false); show_speaker = false; } @@ -501,7 +525,6 @@ LLAdHocChiclet::Params::Params() LLAdHocChiclet::LLAdHocChiclet(const Params& p) : LLIMChiclet(p) , mChicletIconCtrl(NULL) -, mSpeakerCtrl(NULL) , mPopupMenu(NULL) { LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon; @@ -532,24 +555,40 @@ void LLAdHocChiclet::setSessionId(const LLUUID& session_id) mChicletIconCtrl->setValue(im_session->mOtherParticipantID); } -void LLAdHocChiclet::setCounter(S32 counter) +void LLAdHocChiclet::draw() { - mCounterCtrl->setCounter(counter); - setShowNewMessagesIcon(counter); + switchToCurrentSpeaker(); + LLIMChiclet::draw(); } -LLRect LLAdHocChiclet::getRequiredRect() +void LLAdHocChiclet::initSpeakerControl() { - LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0); - if(getShowCounter()) - { - rect.mRight += mCounterCtrl->getRequiredRect().getWidth(); - } - if(getShowSpeaker()) + switchToCurrentSpeaker(); +} + +void LLAdHocChiclet::switchToCurrentSpeaker() +{ + LLUUID speaker_id; + LLSpeakerMgr::speaker_list_t speaker_list; + + LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE); + for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) { - rect.mRight += mSpeakerCtrl->getRect().getWidth(); + LLPointer<LLSpeaker> s = *i; + if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) + { + speaker_id = s->mID; + break; + } } - return rect; + + mSpeakerCtrl->setSpeakerId(speaker_id); +} + +void LLAdHocChiclet::setCounter(S32 counter) +{ + mCounterCtrl->setCounter(counter); + setShowNewMessagesIcon(counter); } BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) @@ -564,7 +603,7 @@ BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) LLIMGroupChiclet::Params::Params() : group_icon("group_icon") { - rect(LLRect(0, 25, 25, 0)); + rect(CHICLET_RECT); group_icon.name("group_icon"); @@ -572,10 +611,9 @@ LLIMGroupChiclet::Params::Params() // Changed icon height from 25 to 24 to fix ticket EXT-794. // In some cases(after changing UI scale) 25 pixel height icon was // drawn incorrectly, i'm not sure why. - group_icon.rect(LLRect(0, 24, 25, 0)); + group_icon.rect(CHICLET_ICON_RECT); unread_notifications.name("unread"); - unread_notifications.rect(LLRect(25, 25, 45, 0)); unread_notifications.font(LLFontGL::getFontSansSerif()); unread_notifications.font_halign(LLFontGL::HCENTER); unread_notifications.v_pad(5); @@ -583,7 +621,9 @@ LLIMGroupChiclet::Params::Params() unread_notifications.visible(false); speaker.name("speaker"); - speaker.rect(LLRect(45, 25, 65, 0)); + speaker.rect(VOICE_INDICATOR_RECT); + speaker.auto_update(true); + speaker.draw_border(false); show_speaker = false; } @@ -592,7 +632,6 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p) : LLIMChiclet(p) , LLGroupMgrObserver(LLUUID::null) , mChicletIconCtrl(NULL) -, mSpeakerCtrl(NULL) , mPopupMenu(NULL) { LLChicletGroupIconCtrl::Params avatar_params = p.group_icon; @@ -625,18 +664,34 @@ void LLIMGroupChiclet::setCounter(S32 counter) setShowNewMessagesIcon(counter); } -LLRect LLIMGroupChiclet::getRequiredRect() +void LLIMGroupChiclet::draw() { - LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0); - if(getShowCounter()) - { - rect.mRight += mCounterCtrl->getRequiredRect().getWidth(); - } - if(getShowSpeaker()) + switchToCurrentSpeaker(); + LLIMChiclet::draw(); +} + +void LLIMGroupChiclet::initSpeakerControl() +{ + switchToCurrentSpeaker(); +} + +void LLIMGroupChiclet::switchToCurrentSpeaker() +{ + LLUUID speaker_id; + LLSpeakerMgr::speaker_list_t speaker_list; + + LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE); + for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) { - rect.mRight += mSpeakerCtrl->getRect().getWidth(); + LLPointer<LLSpeaker> s = *i; + if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) + { + speaker_id = s->mID; + break; + } } - return rect; + + mSpeakerCtrl->setSpeakerId(speaker_id); } void LLIMGroupChiclet::setSessionId(const LLUUID& session_id) @@ -723,17 +778,6 @@ void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data) } } -void LLIMGroupChiclet::setShowSpeaker(bool show) -{ - LLIMChiclet::setShowSpeaker(show); - - bool needs_resize = getShowSpeaker() != show; - mSpeakerCtrl->setVisible(getShowSpeaker()); - if(needs_resize) - { - onChicletSizeChanged(); - } -} ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -742,36 +786,18 @@ void LLIMGroupChiclet::setShowSpeaker(bool show) LLChicletPanel::Params::Params() : chiclet_padding("chiclet_padding") , scrolling_offset("scrolling_offset") -, left_scroll_button("left_scroll_button") -, right_scroll_button("right_scroll_button") , min_width("min_width") { chiclet_padding = 3; scrolling_offset = 40; +/* if (!min_width.isProvided()) { // min_width = 4 chiclets + 3 paddings - min_width = 179 + 3*chiclet_padding; + min_width = 180 + 3*chiclet_padding; } - - LLRect scroll_button_rect(0, 25, 19, 5); - - left_scroll_button.name("left_scroll"); - left_scroll_button.label(LLStringUtil::null); - left_scroll_button.rect(scroll_button_rect); - left_scroll_button.tab_stop(false); - left_scroll_button.image_selected(LLUI::getUIImage("bottom_tray_scroll_left.tga")); - left_scroll_button.image_unselected(LLUI::getUIImage("bottom_tray_scroll_left.tga")); - left_scroll_button.image_hover_selected(LLUI::getUIImage("bottom_tray_scroll_left.tga")); - - right_scroll_button.name("right_scroll"); - right_scroll_button.label(LLStringUtil::null); - right_scroll_button.rect(scroll_button_rect); - right_scroll_button.tab_stop(false); - right_scroll_button.image_selected(LLUI::getUIImage("bottom_tray_scroll_right.tga")); - right_scroll_button.image_unselected(LLUI::getUIImage("bottom_tray_scroll_right.tga")); - right_scroll_button.image_hover_selected(LLUI::getUIImage("bottom_tray_scroll_right.tga")); +*/ }; LLChicletPanel::LLChicletPanel(const Params&p) @@ -784,24 +810,8 @@ LLChicletPanel::LLChicletPanel(const Params&p) , mMinWidth(p.min_width) , mShowControls(true) { - LLButton::Params scroll_button_params = p.left_scroll_button; - - mLeftScrollButton = LLUICtrlFactory::create<LLButton>(scroll_button_params); - addChild(mLeftScrollButton); - LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton); - - mLeftScrollButton->setClickedCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this)); - mLeftScrollButton->setEnabled(false); - - scroll_button_params = p.right_scroll_button; - mRightScrollButton = LLUICtrlFactory::create<LLButton>(scroll_button_params); - addChild(mRightScrollButton); - LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton); - - mRightScrollButton->setClickedCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this)); - mRightScrollButton->setEnabled(false); - LLPanel::Params panel_params; + panel_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT); mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this); // important for Show/Hide Camera and Move controls menu in bottom tray to work properly @@ -851,10 +861,40 @@ BOOL LLChicletPanel::postBuild() LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1)); LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1)); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1)); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1)); + + mLeftScrollButton=getChild<LLButton>("chicklet_left_scroll_button"); + LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton); + mLeftScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this)); + mLeftScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onLeftScrollHeldDown,this)); + mLeftScrollButton->setEnabled(false); + + mRightScrollButton=getChild<LLButton>("chicklet_right_scroll_button"); + LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton); + mRightScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this)); + mRightScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onRightScrollHeldDown,this)); + mRightScrollButton->setEnabled(false); return TRUE; } +void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id) +{ + for(chiclet_list_t::iterator it = mChicletList.begin(); it != mChicletList.end(); ++it) + { + LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it); + if(chiclet) + { + if(chiclet->getSessionId() == session_id) + { + chiclet->setShowSpeaker(true); + continue; + } + chiclet->setShowSpeaker(false); + } + } +} + S32 LLChicletPanel::calcChickletPanleWidth() { S32 res = 0; @@ -898,23 +938,7 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param) { - S32 chiclet_width = ctrl->getRect().getWidth(); - S32 chiclet_new_width = ctrl->getRequiredRect().getWidth(); - - if(chiclet_new_width == chiclet_width) - { - return; - } - - LLRect chiclet_rect = ctrl->getRect(); - chiclet_rect.mRight = chiclet_rect.mLeft + chiclet_new_width; - - ctrl->setRect(chiclet_rect); - - S32 offset = chiclet_new_width - chiclet_width; - S32 index = getChicletIndex(ctrl); - - shiftChiclets(offset, index + 1); + arrange(); trimChiclets(); showScrollButtonsIfNeeded(); } @@ -1026,23 +1050,24 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) static const S32 SCROLL_BUTTON_PAD = 5; + //Needed once- to avoid error at first call of reshape() before postBuild() + if(!mLeftScrollButton||!mRightScrollButton) + return; + LLRect scroll_button_rect = mLeftScrollButton->getRect(); - mLeftScrollButton->setRect(LLRect(0,height,scroll_button_rect.getWidth(), - height - scroll_button_rect.getHeight())); - + mLeftScrollButton->setRect(LLRect(0,scroll_button_rect.mTop,scroll_button_rect.getWidth(), + scroll_button_rect.mBottom)); scroll_button_rect = mRightScrollButton->getRect(); - mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),height, - width, height - scroll_button_rect.getHeight())); - + mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop, + width, scroll_button_rect.mBottom)); mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); - - mShowControls = width > mMinWidth; + mShowControls = width >= mMinWidth; mScrollArea->setVisible(mShowControls); trimChiclets(); - showScrollButtonsIfNeeded(); + } void LLChicletPanel::arrange() @@ -1206,6 +1231,22 @@ void LLChicletPanel::onRightScrollClick() scrollRight(); } +void LLChicletPanel::onLeftScrollHeldDown() +{ + S32 offset = mScrollingOffset; + mScrollingOffset = mScrollingOffset / s_scroll_ratio; + scrollLeft(); + mScrollingOffset = offset; +} + +void LLChicletPanel::onRightScrollHeldDown() +{ + S32 offset = mScrollingOffset; + mScrollingOffset = mScrollingOffset / s_scroll_ratio; + scrollRight(); + mScrollingOffset = offset; +} + boost::signals2::connection LLChicletPanel::setChicletClickedCallback( const commit_callback_t& cb) { @@ -1329,6 +1370,6 @@ void LLChicletGroupIconCtrl::setValue(const LLSD& value ) ////////////////////////////////////////////////////////////////////////// LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) - : LLIconCtrl(p) + : LLOutputMonitorCtrl(p) { } diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index b50702205c..eab4a282f5 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -107,6 +107,7 @@ public: { draw_tooltip(FALSE); mouse_opaque(FALSE); + default_icon_name("Generic_Person"); }; }; @@ -128,7 +129,7 @@ public: Optional<std::string> default_icon; Params() - : default_icon("default_icon", "default_land_picture.j2c") + : default_icon("default_icon", "Generic_Group") { }; }; @@ -147,13 +148,13 @@ protected: }; /* - * Class for displaying status of Voice Chat + * Class for displaying of speaker's voice indicator */ -class LLChicletSpeakerCtrl : public LLIconCtrl +class LLChicletSpeakerCtrl : public LLOutputMonitorCtrl { public: - struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params> + struct Params : public LLInitParam::Block<Params, LLOutputMonitorCtrl::Params> { Params(){}; }; @@ -266,8 +267,6 @@ private: * Base class for Instant Message chiclets. * IMChiclet displays icon, number of unread messages(optional) * and voice chat status(optional). -* Every chiclet should override LLUICtrl::getRequiredRect and return -* desired width. */ class LLIMChiclet : public LLChiclet { @@ -306,9 +305,14 @@ public: virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; } /* - * Shows/hides voice chat status control. + * Init Speaker Control with speaker's ID */ - virtual void setShowSpeaker(bool show) { mShowSpeaker = show; } + virtual void initSpeakerControl(); + + /* + * set status (Shows/Hide) for voice control. + */ + virtual void setShowSpeaker(bool show); /* * Returns voice chat status control visibility. @@ -316,6 +320,11 @@ public: virtual bool getShowSpeaker() {return mShowSpeaker;}; /* + * Shows/Hides for voice control for a chiclet. + */ + virtual void toggleSpeakerControl(); + + /* * Shows/hides overlay icon concerning new unread messages. */ virtual void setShowNewMessagesIcon(bool show); @@ -325,10 +334,7 @@ public: */ virtual bool getShowNewMessagesIcon(); - /* - * Draws border around chiclet. - */ - /*virtual*/ void draw(); + virtual void draw(); /** * Determine whether given ID refers to a group or an IM chat session. @@ -363,6 +369,8 @@ protected: LLIconCtrl* mNewMessagesIcon; LLChicletNotificationCounterCtrl* mCounterCtrl; + LLChicletSpeakerCtrl* mSpeakerCtrl; + /** the id of another participant, either an avatar id or a group id*/ LLUUID mOtherParticipantId; @@ -410,8 +418,6 @@ public: /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id); - /*virtual*/ void setShowSpeaker(bool show); - /* * Sets number of unread messages. Will update chiclet's width if number text * exceeds size of counter and notify it's parent about size change. @@ -419,15 +425,14 @@ public: /*virtual*/ void setCounter(S32); /* - * Returns number of unread messages. + * Init Speaker Control with speaker's ID */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } + /*virtual*/ void initSpeakerControl(); /* - * Returns rect, required to display chiclet. - * Width is the only valid value. + * Returns number of unread messages. */ - /*virtual*/ LLRect getRequiredRect(); + /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } protected: LLIMP2PChiclet(const Params& p); @@ -457,7 +462,6 @@ protected: private: LLChicletAvatarIconCtrl* mChicletIconCtrl; - LLChicletSpeakerCtrl* mSpeakerCtrl; LLMenuGL* mPopupMenu; }; @@ -495,15 +499,19 @@ public: /*virtual*/ void setCounter(S32); /* - * Returns number of unread messages. + * Keep Speaker Control with actual speaker's ID */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } + /*virtual*/ void draw(); /* - * Returns rect, required to display chiclet. - * Width is the only valid value. + * Init Speaker Control with speaker's ID */ - /*virtual*/ LLRect getRequiredRect(); + /*virtual*/ void initSpeakerControl(); + + /* + * Returns number of unread messages. + */ + /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } protected: LLAdHocChiclet(const Params& p); @@ -514,10 +522,14 @@ protected: */ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /* + * Finds a current speaker and resets the SpeakerControl with speaker's ID + */ + /*virtual*/ void switchToCurrentSpeaker(); + private: LLChicletAvatarIconCtrl* mChicletIconCtrl; - LLChicletSpeakerCtrl* mSpeakerCtrl; LLMenuGL* mPopupMenu; }; @@ -547,14 +559,17 @@ public: */ /*virtual*/ void setSessionId(const LLUUID& session_id); + /* + * Keep Speaker Control with actual speaker's ID + */ + /*virtual*/ void draw(); + /** * Callback for LLGroupMgrObserver, we get this when group data is available or changed. * Sets group icon. */ /*virtual*/ void changed(LLGroupChange gc); - /*virtual*/ void setShowSpeaker(bool show); - /* * Sets number of unread messages. Will update chiclet's width if number text * exceeds size of counter and notify it's parent about size change. @@ -562,15 +577,14 @@ public: /*virtual*/ void setCounter(S32); /* - * Returns number of unread messages. + * Init Speaker Control with speaker's ID */ - /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } + /*virtual*/ void initSpeakerControl(); /* - * Returns rect, required to display chiclet. - * Width is the only valid value. + * Returns number of unread messages. */ - /*virtual*/ LLRect getRequiredRect(); + /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } ~LLIMGroupChiclet(); @@ -579,6 +593,11 @@ protected: friend class LLUICtrlFactory; /* + * Finds a current speaker and resets the SpeakerControl with speaker's ID + */ + /*virtual*/ void switchToCurrentSpeaker(); + + /* * Creates chiclet popup menu. Will create P2P or Group IM Chat menu * based on other participant's id. */ @@ -597,7 +616,6 @@ protected: private: LLChicletGroupIconCtrl* mChicletIconCtrl; - LLChicletSpeakerCtrl* mSpeakerCtrl; LLMenuGL* mPopupMenu; }; @@ -660,9 +678,6 @@ public: Optional<S32> chiclet_padding, scrolling_offset; - Optional<LLButton::Params> left_scroll_button, - right_scroll_button; - Optional<S32> min_width; Params(); @@ -736,6 +751,11 @@ public: /*virtual*/ BOOL postBuild(); /* + * Handler for the Voice Client's signal. Finds a corresponding chiclet and toggles its SpeakerControl + */ + void onCurrentVoiceChannelChanged(const LLUUID& session_id); + + /* * Reshapes controls and rearranges chiclets if needed. */ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE ); @@ -812,6 +832,16 @@ protected: void onRightScrollClick(); /* + * Callback for right scroll button held down event + */ + void onLeftScrollHeldDown(); + + /* + * Callback for left scroll button held down event + */ + void onRightScrollHeldDown(); + + /* * Callback for mouse wheel scrolled, calls scrollRight() or scrollLeft() */ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); @@ -851,6 +881,7 @@ protected: S32 mScrollingOffset; S32 mMinWidth; bool mShowControls; + static const S32 s_scroll_ratio; }; template<class T> diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 45f4b4fbd0..3961afe9af 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -242,7 +242,7 @@ BOOL LLDriverParam::parseData(LLXmlTreeNode* node) } #endif -void LLDriverParam::setWeight(F32 weight, BOOL set_by_user) +void LLDriverParam::setWeight(F32 weight, BOOL upload_bake) { F32 min_weight = getMinWeight(); F32 max_weight = getMaxWeight(); @@ -301,7 +301,7 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user) driven_weight = driven_min; } - setDrivenWeight(driven,driven_weight,set_by_user); + setDrivenWeight(driven,driven_weight,upload_bake); continue; } else @@ -325,13 +325,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user) driven_weight = driven_min; } - setDrivenWeight(driven,driven_weight,set_by_user); + setDrivenWeight(driven,driven_weight,upload_bake); continue; } } driven_weight = getDrivenWeight(driven, mCurWeight); - setDrivenWeight(driven,driven_weight,set_by_user); + setDrivenWeight(driven,driven_weight,upload_bake); } } @@ -455,9 +455,9 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ //----------------------------------------------------------------------------- // setAnimationTarget() //----------------------------------------------------------------------------- -void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user ) +void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake ) { - LLVisualParam::setAnimationTarget(target_value, set_by_user); + LLVisualParam::setAnimationTarget(target_value, upload_bake); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { @@ -466,16 +466,16 @@ void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user ) // this isn't normally necessary, as driver params handle interpolation of their driven params // but texture params need to know to assume their final value at beginning of interpolation - driven->mParam->setAnimationTarget(driven_weight, set_by_user); + driven->mParam->setAnimationTarget(driven_weight, upload_bake); } } //----------------------------------------------------------------------------- // stopAnimating() //----------------------------------------------------------------------------- -void LLDriverParam::stopAnimating(BOOL set_by_user) +void LLDriverParam::stopAnimating(BOOL upload_bake) { - LLVisualParam::stopAnimating(set_by_user); + LLVisualParam::stopAnimating(upload_bake); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { @@ -585,7 +585,7 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight return driven_weight; } -void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool set_by_user) +void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake) { LLVOAvatarSelf *avatar_self = gAgent.getAvatarObject(); if(mWearablep && @@ -593,10 +593,10 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bo mWearablep->isOnTop()) { // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values - avatar_self->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, set_by_user ); + avatar_self->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); } else { - driven->mParam->setWeight( driven_weight, set_by_user ); + driven->mParam->setWeight( driven_weight, upload_bake ); } } diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index 069e71a2cb..4e2daf5ba7 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -99,9 +99,9 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param. - /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); - /*virtual*/ void setAnimationTarget( F32 target_value, BOOL set_by_user ); - /*virtual*/ void stopAnimating(BOOL set_by_user); + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake ); + /*virtual*/ void stopAnimating(BOOL upload_bake); /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); /*virtual*/ void resetDrivenParams(); @@ -114,7 +114,7 @@ public: /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); protected: F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); - void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool set_by_user); + void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); LLVector3 mDefaultVec; // temp holder diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index b01293d17c..80b0a430e0 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -64,7 +64,7 @@ #include "llwindow.h" #include "stringize.h" #include "llsdutil_math.h" -#include "lleventdispatcher.h" +#include "lleventapi.h" #if LL_WINDOWS #include "lldxhardware.h" @@ -302,13 +302,17 @@ static std::string get_viewer_release_notes_url() return LLWeb::escapeURL(url.str()); } -class LLFloaterAboutListener: public LLDispatchListener +class LLFloaterAboutListener: public LLEventAPI { public: LLFloaterAboutListener(): - LLDispatchListener("LLFloaterAbout", "op") + LLEventAPI("LLFloaterAbout", + "LLFloaterAbout listener to retrieve About box info") { - add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD())); + add("getInfo", + "Request an LLSD::Map containing information used to populate About box", + &LLFloaterAboutListener::getInfo, + LLSD().insert("reply", LLSD())); } private: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index f07f9412a2..4434a8013d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -348,6 +348,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.AutoDetectAspect", boost::bind(&LLFloaterPreference::onCommitAutoDetectAspect, 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)); + mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); sSkin = gSavedSettings.getString("SkinCurrent"); @@ -1356,18 +1358,24 @@ void LLFloaterPreference::initWindowSizeControls(LLPanel* panelp) } +void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param) +{ + LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue())); +} + +void LLFloaterPreference::getUIColor(LLUICtrl* ctrl, const LLSD& param) +{ + LLColorSwatchCtrl* color_swatch = (LLColorSwatchCtrl*) ctrl; + color_swatch->setOriginal(LLUIColorTable::instance().getColor(param.asString())); +} + //---------------------------------------------------------------------------- static LLRegisterPanelClassWrapper<LLPanelPreference> t_places("panel_preference"); LLPanelPreference::LLPanelPreference() : LLPanel() { - mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2)); -} - -static void applyUIColor(const std::string& color_name, LLUICtrl* ctrl, const LLSD& param) -{ - LLUIColorTable::instance().setColor(color_name, LLColor4(param)); + mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2)); } //virtual @@ -1496,55 +1504,6 @@ BOOL LLPanelPreference::postBuild() refresh(); } - - if(hasChild("user") && hasChild("agent") && hasChild("im") - && hasChild("system") && hasChild("script_error") && hasChild("objects") - && hasChild("owner") && hasChild("background") && hasChild("links")) - { - LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("user"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "UserChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("UserChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("agent"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "AgentChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("AgentChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("im"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "IMChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("IMChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("system"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "SystemChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("SystemChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("script_error"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "ScriptErrorColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("ScriptErrorColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("objects"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "ObjectChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("ObjectChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("owner"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "llOwnerSayChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("llOwnerSayChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("background"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "BackgroundChatColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("BackgroundChatColor")); - - color_swatch = getChild<LLColorSwatchCtrl>("links"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "HTMLLinkColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("HTMLLinkColor")); - } - - if(hasChild("effect_color_swatch")) - { - LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("effect_color_swatch"); - color_swatch->setCommitCallback(boost::bind(&applyUIColor, "EffectColor", _1, _2)); - color_swatch->setOriginal(LLUIColorTable::instance().getColor("EffectColor")); - } - apply(); return true; } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index b1ad0348c0..10f39e46f1 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -133,7 +133,9 @@ public: void onCommitAutoDetectAspect(); void applyResolution(); void applyWindowSize(); - + void applyUIColor(LLUICtrl* ctrl, const LLSD& param); + void getUIColor(LLUICtrl* ctrl, const LLSD& param); + static void initWindowSizeControls(LLPanel* panelp); static void buildLists(void* data); @@ -159,6 +161,7 @@ public: virtual void apply(); virtual void cancel(); void setControlFalse(const LLSD& user_data); + private: typedef std::map<LLControlVariable*, LLSD> control_values_map_t; control_values_map_t mSavedValues; diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index ca2cdffcf8..e2df2ffdf7 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -124,9 +124,19 @@ void LLFloaterSearch::search(const LLSD &key) url += "&p=" + search_token.asString(); // also append the user's preferred maturity (can be changed via prefs) - std::string maturity = "pg"; - if (gAgent.prefersMature()) maturity += ",mature"; - if (gAgent.prefersAdult()) maturity += ",adult"; + std::string maturity; + if (gAgent.prefersAdult()) + { + maturity = "42"; // PG,Mature,Adult + } + else if (gAgent.prefersMature()) + { + maturity = "21"; // PG,Mature + } + else + { + maturity = "13"; // PG + } url += "&r=" + maturity; // and load the URL in the web view diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 663bd232f7..3613ac803e 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -849,6 +849,7 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) { LLUICtrlFactory::getInstance()->buildFloater(*floaterp, path, NULL); // just build it (*floaterp)->openFloater((*floaterp)->getKey()); + (*floaterp)->setCanResize((*floaterp)->isResizable()); } } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 010ed23918..cdb85f5b1c 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -181,13 +181,9 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL // item->setContextMenu(mContextMenu); item->childSetVisible("info_btn", false); + item->childSetVisible("profile_btn", false); item->setGroupIconVisible(mShowIcons); - if (id.isNull()) - { - item->childSetVisible("profile_btn", false); - } - addItem(item, id, pos); // setCommentVisible(false); @@ -254,7 +250,10 @@ void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", true); if (mGroupID.notNull()) // don't show the info button for the "none" group + { mInfoBtn->setVisible(true); + childSetVisible("profile_btn", true); + } LLPanel::onMouseEnter(x, y, mask); } @@ -263,6 +262,7 @@ void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask) { childSetVisible("hovered_icon", false); mInfoBtn->setVisible(false); + childSetVisible("profile_btn", false); LLPanel::onMouseLeave(x, y, mask); } diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 5a2331aa06..54fc6f02fb 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -479,11 +479,29 @@ void LLIMFloater::updateMessages() LLStyle::Params style_params; style_params.color(chat_color); - LLChat chat(message); + LLChat chat; chat.mFromID = from_id; chat.mFromName = from; - mChatHistory->appendWidgetMessage(chat, style_params); + //Handle IRC styled /me messages. + std::string prefix = message.substr(0, 4); + if (prefix == "/me " || prefix == "/me'") + { + if (from.size() > 0) + { + style_params.font.style = "ITALIC"; + chat.mText = from + " "; + mChatHistory->appendWidgetMessage(chat, style_params); + } + message = message.substr(3); + style_params.font.style = "UNDERLINE"; + mChatHistory->appendText(message, FALSE, style_params); + } + else + { + chat.mText = message; + mChatHistory->appendWidgetMessage(chat, style_params); + } mLastMessageIndex = msg["index"].asInteger(); } @@ -499,7 +517,7 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* LLIMModel::LLIMSession* im_session = LLIMModel::instance().findIMSession(self->mSessionID); //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) - if( im_session && im_session->mTextIMPossible && !self->mInputEditor->getEnabled()) + if( im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled()) { //in disconnected state IM input editor should be disabled self->mInputEditor->setEnabled(!gDisconnected); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 0b8b5935f8..87b801d73b 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -848,8 +848,11 @@ void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update) } - //update the speakers dropdown too - mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated); + //update the speakers dropdown too, if it's available + if (mSpeakerPanel) + { + mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated); + } } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8fb7027e82..d48aaf8461 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -46,6 +46,7 @@ #include "llagent.h" #include "llavatariconctrl.h" +#include "llbottomtray.h" #include "llcallingcard.h" #include "llchat.h" #include "llresmgr.h" @@ -73,6 +74,7 @@ #include "llvoicechannel.h" #include "lltrans.h" #include "llrecentpeople.h" +#include "llsyswellwindow.h" #include "llfirstuse.h" #include "llagentui.h" @@ -439,8 +441,11 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co addToHistory(session_id, from, from_id, utf8_text); if (log2file) logToFile(session_id, from, from_id, utf8_text); - //we do not count system messages - if (from_id.notNull()) session->mNumUnread++; + //we do not count system messages and our messages + if (from_id.notNull() && from_id != gAgentID && SYSTEM_FROM != from) + { + session->mNumUnread++; + } // notify listeners LLSD arg; @@ -651,22 +656,10 @@ void LLIMModel::sendMessage(const std::string& utf8_text, //local echo for the legacy communicate panel std::string history_echo; - std::string utf8_copy = utf8_text; LLAgentUI::buildFullname(history_echo); - // Look for IRC-style emotes here. + history_echo += ": " + utf8_text; - std::string prefix = utf8_copy.substr(0, 4); - if (prefix == "/me " || prefix == "/me'") - { - utf8_copy.replace(0,3,""); - } - else - { - history_echo += ": "; - } - history_echo += utf8_copy; - LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id); if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID()); @@ -862,7 +855,17 @@ bool LLIMModel::sendStartSession( return false; } - +// static +void LLIMModel::sendSessionInitialized(const LLUUID &session_id) +{ + LLIMSession* session = getInstance()->findIMSession(session_id); + if (session) + { + LLSD arg; + arg["session_id"] = session_id; + getInstance()->mSessionInitializedSignal(arg); + } +} // // Helper Functions @@ -1090,16 +1093,90 @@ LLIMMgr::onConfirmForceCloseError( //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLOutgoingCallDialog +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) : + LLDockableFloater(NULL, false, payload), + mPayload(payload) +{ +} + +void LLOutgoingCallDialog::getAllowedRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRectRaw(); +} + +void LLOutgoingCallDialog::onOpen(const LLSD& key) +{ + // tell the user which voice channel they are leaving + if (!mPayload["old_channel_name"].asString().empty()) + { + childSetTextArg("leaving", "[CURRENT_CHAT]", mPayload["old_channel_name"].asString()); + } + else + { + childSetTextArg("leaving", "[CURRENT_CHAT]", getString("localchat")); + } + + std::string callee_name = mPayload["session_name"].asString(); + if (callee_name == "anonymous") + { + callee_name = getString("anonymous"); + } + + setTitle(callee_name); + + LLSD callee_id = mPayload["other_user_id"]; + childSetTextArg("calling", "[CALLEE_NAME]", callee_name); + LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); + icon->setValue(callee_id); + + // dock the dialog to the sys well, where other sys messages appear + setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(), + this, getDockTongue(), LLDockControl::TOP, + boost::bind(&LLOutgoingCallDialog::getAllowedRect, this, _1))); +} + + +//static +void LLOutgoingCallDialog::onCancel(void* user_data) +{ + LLOutgoingCallDialog* self = (LLOutgoingCallDialog*)user_data; + + if (!gIMMgr) + return; + + LLUUID session_id = self->mPayload["session_id"].asUUID(); + gIMMgr->endCall(session_id); + + self->closeFloater(); +} + + +BOOL LLOutgoingCallDialog::postBuild() +{ + BOOL success = LLDockableFloater::postBuild(); + + childSetAction("Cancel", onCancel, this); + + return success; +} + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLIncomingCallDialog //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) : - LLModalDialog(payload), + LLDockableFloater(NULL, false, payload), mPayload(payload) { } BOOL LLIncomingCallDialog::postBuild() { + LLDockableFloater::postBuild(); + LLSD caller_id = mPayload["caller_id"]; EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger(); @@ -1118,6 +1195,11 @@ BOOL LLIncomingCallDialog::postBuild() call_type = getString("VoiceInviteAdHoc"); } + // check to see if this is an Avaline call + LLUUID session_id = mPayload["session_id"].asUUID(); + bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
+ childSetVisible("Start IM", is_avatar); // no IM for avaline + LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name"); caller_name_widget->setValue(caller_name + " " + call_type); LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon"); @@ -1131,6 +1213,30 @@ BOOL LLIncomingCallDialog::postBuild() return TRUE; } +void LLIncomingCallDialog::getAllowedRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRectRaw(); +} + +void LLIncomingCallDialog::onOpen(const LLSD& key) +{ + // tell the user which voice channel they would be leaving + LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel(); + if (voice && !voice->getSessionName().empty()) + { + childSetTextArg("question", "[CURRENT_CHAT]", voice->getSessionName()); + } + else + { + childSetTextArg("question", "[CURRENT_CHAT]", getString("localchat")); + } + + // dock the dialog to the sys well, where other sys messages appear + setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(), + this, getDockTongue(), LLDockControl::TOP, + boost::bind(&LLIncomingCallDialog::getAllowedRect, this, _1))); +} + //static void LLIncomingCallDialog::onAccept(void* user_data) { @@ -1157,6 +1263,9 @@ void LLIncomingCallDialog::onStartIM(void* user_data) void LLIncomingCallDialog::processCallResponse(S32 response) { + if (!gIMMgr) + return; + LLUUID session_id = mPayload["session_id"].asUUID(); EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger(); LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger(); @@ -1254,6 +1363,9 @@ void LLIncomingCallDialog::processCallResponse(S32 response) bool inviteUserResponse(const LLSD& notification, const LLSD& response) { + if (!gIMMgr) + return false; + const LLSD& payload = notification["payload"]; LLUUID session_id = payload["session_id"].asUUID(); EInstantMessage type = (EInstantMessage)payload["type"].asInteger(); @@ -2331,15 +2443,6 @@ public: BOOL is_linden = LLMuteList::getInstance()->isLinden(name); std::string separator_string(": "); - int message_offset=0; - - //Handle IRC styled /me messages. - std::string prefix = message.substr(0, 4); - if (prefix == "/me " || prefix == "/me'") - { - separator_string = ""; - message_offset = 3; - } chat.mMuted = is_muted && !is_linden; chat.mFromID = from_id; @@ -2356,7 +2459,7 @@ public: { saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } - std::string buffer = saved + message.substr(message_offset); + std::string buffer = saved + message; BOOL is_this_agent = FALSE; if(from_id == gAgentID) @@ -2375,7 +2478,7 @@ public: ll_vector3_from_sd(message_params["position"]), true); - chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); + chat.mText = std::string("IM: ") + name + separator_string + saved + message; LLFloaterChat::addChat(chat, TRUE, is_this_agent); //K now we want to accept the invitation diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index bd55bd2c30..62a54bc081 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -34,9 +34,11 @@ #define LL_LLIMVIEW_H #include "lldarray.h" +#include "lldockablefloater.h" #include "llspeakers.h" //for LLIMSpeakerMgr #include "llimpanel.h" //for voice channels #include "llmodaldialog.h" +#include "lldockablefloater.h" #include "llinstantmessage.h" #include "lluuid.h" #include "llmultifloater.h" @@ -102,6 +104,7 @@ public: typedef boost::function<void(const LLSD&)> session_callback_t; session_signal_t mNewMsgSignal; session_signal_t mNoUnreadMsgsSignal; + session_signal_t mSessionInitializedSignal; /** * Find an IM Session corresponding to session_id @@ -116,6 +119,7 @@ public: boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); } boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); } + boost::signals2::connection addSessionInitializedCallback(session_callback_t cb ) { return mSessionInitializedSignal.connect(cb); } /** * Create new session object in a model @@ -189,6 +193,7 @@ public: static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids, EInstantMessage dialog); static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing); + static void sendSessionInitialized(const LLUUID &session_id); static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id, const LLUUID& other_participant_id, EInstantMessage dialog); @@ -398,12 +403,13 @@ private: LLSD mPendingAgentListUpdates; }; -class LLIncomingCallDialog : public LLModalDialog +class LLIncomingCallDialog : public LLDockableFloater { public: LLIncomingCallDialog(const LLSD& payload); /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); static void onAccept(void* user_data); static void onReject(void* user_data); @@ -411,6 +417,23 @@ public: private: void processCallResponse(S32 response); + void getAllowedRect(LLRect& rect); + + LLSD mPayload; +}; + +class LLOutgoingCallDialog : public LLDockableFloater +{ +public: + LLOutgoingCallDialog(const LLSD& payload); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + + static void onCancel(void* user_data); + +private: + void getAllowedRect(LLRect& rect); LLSD mPayload; }; diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp new file mode 100644 index 0000000000..e4d2eec242 --- /dev/null +++ b/indra/newview/llinspectremoteobject.cpp @@ -0,0 +1,200 @@ +/** + * @file llinspectremoteobject.cpp + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinspectremoteobject.h" +#include "llinspect.h" +#include "llslurl.h" +#include "llmutelist.h" +#include "llurlaction.h" +#include "llpanelblockedlist.h" +#include "llfloaterreg.h" +#include "llui.h" +#include "lluictrl.h" + +class LLViewerObject; + +////////////////////////////////////////////////////////////////////////////// +// LLInspectRemoteObject +////////////////////////////////////////////////////////////////////////////// + +// Remote Object Inspector, a small information window used to +// display information about potentially-remote objects. Used +// to display details about objects sending messages to the user. +class LLInspectRemoteObject : public LLInspect +{ + friend class LLFloaterReg; + +public: + LLInspectRemoteObject(const LLSD& object_id); + virtual ~LLInspectRemoteObject() {}; + + /*virtual*/ BOOL postBuild(void); + /*virtual*/ void onOpen(const LLSD& avatar_id); + + void onClickMap(); + void onClickBlock(); + void onClickClose(); + +private: + void update(); + static void nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data); + +private: + LLUUID mObjectID; + LLUUID mOwnerID; + std::string mOwner; + std::string mSLurl; + std::string mName; + bool mGroupOwned; +}; + +LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) : + LLInspect(LLSD()), + mObjectID(NULL), + mOwnerID(NULL), + mOwner(""), + mSLurl(""), + mName(""), + mGroupOwned(false) +{ +} + +/*virtual*/ +BOOL LLInspectRemoteObject::postBuild(void) +{ + // hook up the inspector's buttons + getChild<LLUICtrl>("map_btn")->setCommitCallback( + boost::bind(&LLInspectRemoteObject::onClickMap, this)); + getChild<LLUICtrl>("block_btn")->setCommitCallback( + boost::bind(&LLInspectRemoteObject::onClickBlock, this)); + getChild<LLUICtrl>("close_btn")->setCommitCallback( + boost::bind(&LLInspectRemoteObject::onClickClose, this)); + + return TRUE; +} + +/*virtual*/ +void LLInspectRemoteObject::onOpen(const LLSD& data) +{ + // Start animation + LLInspect::onOpen(data); + + // Extract appropriate object information from input LLSD + // (Eventually, it might be nice to query server for details + // rather than require caller to pass in the information.) + mObjectID = data["object_id"].asUUID(); + mName = data["name"].asString(); + mOwnerID = data["owner_id"].asUUID(); + mGroupOwned = data["group_owned"].asBoolean(); + mSLurl = data["slurl"].asString(); + + // work out the owner's name + mOwner = ""; + if (gCacheName) + { + gCacheName->get(mOwnerID, mGroupOwned, nameCallback, this); + } + + // update the inspector with the current object state + update(); + + // Position the inspector relative to the mouse cursor + LLUI::positionViewNearMouse(this); +} + +void LLInspectRemoteObject::onClickMap() +{ + std::string url = "secondlife://" + mSLurl; + LLUrlAction::showLocationOnMap(url); + closeFloater(); +} + +void LLInspectRemoteObject::onClickBlock() +{ + LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT; + LLMute mute(mOwnerID, mOwner, mute_type); + LLMuteList::getInstance()->add(mute); + LLPanelBlockedList::showPanelAndSelect(mute.mID); + closeFloater(); +} + +void LLInspectRemoteObject::onClickClose() +{ + closeFloater(); +} + +//static +void LLInspectRemoteObject::nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data) +{ + LLInspectRemoteObject *self = (LLInspectRemoteObject*)data; + self->mOwner = first; + if (!last.empty()) + { + self->mOwner += " " + last; + } + self->update(); +} + +void LLInspectRemoteObject::update() +{ + // show the object name as the inspector's title + getChild<LLUICtrl>("object_name")->setValue(mName); + + // show the object's owner - click it to show profile + std::string owner = mOwner; + if (! mOwnerID.isNull()) + { + if (mGroupOwned) + { + owner = LLSLURL::buildCommand("group", mOwnerID, "about"); + } + else + { + owner = LLSLURL::buildCommand("agent", mOwnerID, "about"); + } + } + getChild<LLUICtrl>("object_owner")->setValue(owner); + + // display the object's SLurl - click it to teleport + std::string url = "secondlife:///app/teleport/" + mSLurl; + getChild<LLUICtrl>("object_slurl")->setValue(url); +} + +////////////////////////////////////////////////////////////////////////////// +// LLInspectRemoteObjectUtil +////////////////////////////////////////////////////////////////////////////// +void LLInspectRemoteObjectUtil::registerFloater() +{ + LLFloaterReg::add("inspect_remote_object", "inspect_remote_object.xml", + &LLFloaterReg::build<LLInspectRemoteObject>); +} diff --git a/indra/newview/llinspectremoteobject.h b/indra/newview/llinspectremoteobject.h new file mode 100644 index 0000000000..e756f1caf4 --- /dev/null +++ b/indra/newview/llinspectremoteobject.h @@ -0,0 +1,40 @@ +/** + * @file llinspectremoteobject.h + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 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 LLINSPECTREMOTEOBJECT_H +#define LLINSPECTREMOTEOBJECT_H + +namespace LLInspectRemoteObjectUtil +{ + void registerFloater(); +} + +#endif diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 4b7e364cf9..4b0d524906 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -176,6 +176,7 @@ LLInventoryModel::LLInventoryModel() mRootFolderID(), mLibraryRootFolderID(), mLibraryOwnerID(), + mIsNotifyObservers(FALSE), mIsAgentInvUsable(false) { } @@ -537,7 +538,10 @@ void LLInventoryModel::updateLinkedItems(const LLUUID& object_id) item_array, LLInventoryModel::INCLUDE_TRASH, is_linked_item_match); - + if (cat_array.empty() && item_array.empty()) + { + return; + } for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin(); cat_iter != cat_array.end(); cat_iter++) @@ -639,6 +643,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item) new_item = old_item; LLUUID old_parent_id = old_item->getParentUUID(); LLUUID new_parent_id = item->getParentUUID(); + if(old_parent_id != new_parent_id) { // need to update the parent-child tree @@ -1133,6 +1138,15 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const // The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328] void LLInventoryModel::notifyObservers(const std::string service_name) { + if (mIsNotifyObservers) + { + // Within notifyObservers, something called notifyObservers + // again. This type of recursion is unsafe because it causes items to be + // processed twice, and this can easily lead to infinite loops. + llwarns << "Call was made to notifyObservers within notifyObservers!" << llendl; + return; + } + mIsNotifyObservers = TRUE; for (observer_list_t::iterator iter = mObservers.begin(); iter != mObservers.end(); ) { @@ -1154,12 +1168,21 @@ void LLInventoryModel::notifyObservers(const std::string service_name) mModifyMask = LLInventoryObserver::NONE; mChangedItemIDs.clear(); + mIsNotifyObservers = FALSE; } // store flag for change // and id of object change applies to void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) { + if (mIsNotifyObservers) + { + // Something marked an item for change within a call to notifyObservers + // (which is in the process of processing the list of items marked for change). + // This means the change may fail to be processed. + llwarns << "Adding changed mask within notify observers! Change will likely be lost." << llendl; + } + mModifyMask |= mask; if (referent.notNull()) { @@ -1271,8 +1294,11 @@ void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::str bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) { - if(folder_id.isNull()) return false; - + if(folder_id.isNull()) + { + llwarns << "Calling fetch descendents on NULL folder id!" << llendl; + return false; + } LLViewerInventoryCategory* cat = getCategory(folder_id); if(!cat) { @@ -1830,13 +1856,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) { //llinfos << "LLInventoryModel::addItem()" << llendl; - - // This can happen if assettype enums change. This can be a backwards compatibility issue - // in some viewer prototypes prior to when the AT_LINK enum changed from 23 to 24. + // This can happen if assettype enums from llassettype.h ever change. + // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when + // the AT_LINK enum changed from 23 to 24. if ((item->getType() == LLAssetType::AT_NONE) || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup()) { - llwarns << "Got bad asset type for item ( name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ), ignoring." << llendl; + llwarns << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << llendl; return; } if(item) @@ -1845,7 +1871,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // The item will show up as a broken link. if (item->getIsBrokenLink()) { - llinfos << "Adding broken link ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl; + llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl; } mItemMap[item->getUUID()] = item; } @@ -2173,7 +2199,7 @@ bool LLInventoryModel::loadSkeleton( // Add all the items loaded which are parented to a // category with a correctly cached parent - count = items.count(); + S32 bad_link_count = 0; cat_map_t::iterator unparented = mCategoryMap.end(); for(item_array_t::const_iterator item_iter = items.begin(); item_iter != items.end(); @@ -2190,7 +2216,11 @@ bool LLInventoryModel::loadSkeleton( // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache. if (item->getIsBrokenLink()) { - llinfos << "Attempted to add cached link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl; + bad_link_count++; + lldebugs << "Attempted to add cached link item without baseobj present ( name: " + << item->getName() << " itemID: " << item->getUUID() + << " assetID: " << item->getAssetUUID() + << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl; invalid_categories.insert(cit->second); continue; } @@ -2200,6 +2230,12 @@ bool LLInventoryModel::loadSkeleton( } } } + if (bad_link_count > 0) + { + llinfos << "Attempted to add " << bad_link_count + << " cached link items without baseobj present. " + << "The corresponding categories were invalidated." << llendl; + } } else { @@ -3304,6 +3340,12 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) for(i = 0; i < count; ++i) { titem->unpackMessage(msg, _PREHASH_ItemData, i); + // If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added. + if (gInventory.getItem(titem->getUUID())) + { + llinfos << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl; + continue; + } gInventory.updateItem(titem); } @@ -3679,513 +3721,6 @@ bool LLNameCategoryCollector::operator()( return false; } - - -///---------------------------------------------------------------------------- -/// Observers -///---------------------------------------------------------------------------- - -void LLInventoryCompletionObserver::changed(U32 mask) -{ - // scan through the incomplete items and move or erase them as - // appropriate. - if(!mIncomplete.empty()) - { - for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) - { - it = mIncomplete.erase(it); - continue; - } - if(item->isComplete()) - { - mComplete.push_back(*it); - it = mIncomplete.erase(it); - continue; - } - ++it; - } - if(mIncomplete.empty()) - { - done(); - } - } -} - -void LLInventoryCompletionObserver::watchItem(const LLUUID& id) -{ - if(id.notNull()) - { - mIncomplete.push_back(id); - } -} - - -void LLInventoryFetchObserver::changed(U32 mask) -{ - // scan through the incomplete items and move or erase them as - // appropriate. - if(!mIncomplete.empty()) - { - for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) - { - // BUG: This can cause done() to get called prematurely below. - // This happens with the LLGestureInventoryFetchObserver that - // loads gestures at startup. JC - it = mIncomplete.erase(it); - continue; - } - if(item->isComplete()) - { - mComplete.push_back(*it); - it = mIncomplete.erase(it); - continue; - } - ++it; - } - if(mIncomplete.empty()) - { - done(); - } - } - //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl; - //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl; -} - -bool LLInventoryFetchObserver::isEverythingComplete() const -{ - return mIncomplete.empty(); -} - -void fetch_items_from_llsd(const LLSD& items_llsd) -{ - if (!items_llsd.size()) return; - LLSD body; - body[0]["cap_name"] = "FetchInventory"; - body[1]["cap_name"] = "FetchLib"; - for (S32 i=0; i<items_llsd.size();i++) - { - if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString()) - { - body[0]["items"].append(items_llsd[i]); - continue; - } - if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString()) - { - body[1]["items"].append(items_llsd[i]); - continue; - } - } - - for (S32 i=0; i<body.size(); i++) - { - if (0 >= body[i].size()) continue; - std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString()); - - if (!url.empty()) - { - body[i]["agent_id"] = gAgent.getID(); - LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i])); - break; - } - - LLMessageSystem* msg = gMessageSystem; - BOOL start_new_message = TRUE; - for (S32 j=0; j<body[i]["items"].size(); j++) - { - LLSD item_entry = body[i]["items"][j]; - if(start_new_message) - { - start_new_message = FALSE; - msg->newMessageFast(_PREHASH_FetchInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID()); - msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID()); - if(msg->isSendFull(NULL)) - { - start_new_message = TRUE; - gAgent.sendReliableMessage(); - } - } - if(!start_new_message) - { - gAgent.sendReliableMessage(); - } - } -} - -void LLInventoryFetchObserver::fetchItems( - const LLInventoryFetchObserver::item_ref_t& ids) -{ - LLUUID owner_id; - LLSD items_llsd; - for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(item) - { - if(item->isComplete()) - { - // It's complete, so put it on the complete container. - mComplete.push_back(*it); - continue; - } - else - { - owner_id = item->getPermissions().getOwner(); - } - } - else - { - // assume it's agent inventory. - owner_id = gAgent.getID(); - } - - // It's incomplete, so put it on the incomplete container, and - // pack this on the message. - mIncomplete.push_back(*it); - - // Prepare the data to fetch - LLSD item_entry; - item_entry["owner_id"] = owner_id; - item_entry["item_id"] = (*it); - items_llsd.append(item_entry); - } - fetch_items_from_llsd(items_llsd); -} - -// virtual -void LLInventoryFetchDescendentsObserver::changed(U32 mask) -{ - for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if(!cat) - { - it = mIncompleteFolders.erase(it); - continue; - } - if(isComplete(cat)) - { - mCompleteFolders.push_back(*it); - it = mIncompleteFolders.erase(it); - continue; - } - ++it; - } - if(mIncompleteFolders.empty()) - { - done(); - } -} - -void LLInventoryFetchDescendentsObserver::fetchDescendents( - const folder_ref_t& ids) -{ - for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if(!cat) continue; - if(!isComplete(cat)) - { - cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it. - mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer. - } - else - { - mCompleteFolders.push_back(*it); - } - } -} - -bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const -{ - return mIncompleteFolders.empty(); -} - -bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat) -{ - S32 version = cat->getVersion(); - S32 descendents = cat->getDescendentCount(); - if((LLViewerInventoryCategory::VERSION_UNKNOWN == version) - || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents)) - { - return false; - } - // it might be complete - check known descendents against - // currently available. - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items); - if(!cats || !items) - { - // bit of a hack - pretend we're done if they are gone or - // incomplete. should never know, but it would suck if this - // kept tight looping because of a corrupt memory state. - return true; - } - S32 known = cats->count() + items->count(); - if(descendents == known) - { - // hey - we're done. - return true; - } - return false; -} - -void LLInventoryFetchComboObserver::changed(U32 mask) -{ - if(!mIncompleteItems.empty()) - { - for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); ) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) - { - it = mIncompleteItems.erase(it); - continue; - } - if(item->isComplete()) - { - mCompleteItems.push_back(*it); - it = mIncompleteItems.erase(it); - continue; - } - ++it; - } - } - if(!mIncompleteFolders.empty()) - { - for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if(!cat) - { - it = mIncompleteFolders.erase(it); - continue; - } - if(gInventory.isCategoryComplete(*it)) - { - mCompleteFolders.push_back(*it); - it = mIncompleteFolders.erase(it); - continue; - } - ++it; - } - } - if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty()) - { - mDone = true; - done(); - } -} - -void LLInventoryFetchComboObserver::fetch( - const folder_ref_t& folder_ids, - const item_ref_t& item_ids) -{ - lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl; - for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(*fit); - if(!cat) continue; - if(!gInventory.isCategoryComplete(*fit)) - { - cat->fetchDescendents(); - lldebugs << "fetching folder " << *fit <<llendl; - mIncompleteFolders.push_back(*fit); - } - else - { - mCompleteFolders.push_back(*fit); - lldebugs << "completing folder " << *fit <<llendl; - } - } - - // Now for the items - we fetch everything which is not a direct - // descendent of an incomplete folder because the item will show - // up in an inventory descendents message soon enough so we do not - // have to fetch it individually. - LLSD items_llsd; - LLUUID owner_id; - for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit) - { - LLViewerInventoryItem* item = gInventory.getItem(*iit); - if(!item) - { - lldebugs << "uanble to find item " << *iit << llendl; - continue; - } - if(item->isComplete()) - { - // It's complete, so put it on the complete container. - mCompleteItems.push_back(*iit); - lldebugs << "completing item " << *iit << llendl; - continue; - } - else - { - mIncompleteItems.push_back(*iit); - owner_id = item->getPermissions().getOwner(); - } - if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) - { - LLSD item_entry; - item_entry["owner_id"] = owner_id; - item_entry["item_id"] = (*iit); - items_llsd.append(item_entry); - } - else - { - lldebugs << "not worrying about " << *iit << llendl; - } - } - fetch_items_from_llsd(items_llsd); -} - -void LLInventoryExistenceObserver::watchItem(const LLUUID& id) -{ - if(id.notNull()) - { - mMIA.push_back(id); - } -} - -void LLInventoryExistenceObserver::changed(U32 mask) -{ - // scan through the incomplete items and move or erase them as - // appropriate. - if(!mMIA.empty()) - { - for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); ) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) - { - ++it; - continue; - } - mExist.push_back(*it); - it = mMIA.erase(it); - } - if(mMIA.empty()) - { - done(); - } - } -} - -void LLInventoryAddedObserver::changed(U32 mask) -{ - if(!(mask & LLInventoryObserver::ADD)) - { - return; - } - - // *HACK: If this was in response to a packet off - // the network, figure out which item was updated. - LLMessageSystem* msg = gMessageSystem; - - std::string msg_name; - if (mMessageName.empty()) - { - msg_name = msg->getMessageName(); - } - else - { - msg_name = mMessageName; - } - - if (msg_name.empty()) - { - return; - } - - // We only want newly created inventory items. JC - if ( msg_name != "UpdateCreateInventoryItem") - { - return; - } - - LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; - S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); - for(S32 i = 0; i < num_blocks; ++i) - { - titem->unpackMessage(msg, _PREHASH_InventoryData, i); - if (!(titem->getUUID().isNull())) - { - //we don't do anything with null keys - mAdded.push_back(titem->getUUID()); - } - } - if (!mAdded.empty()) - { - done(); - } -} - -LLInventoryTransactionObserver::LLInventoryTransactionObserver( - const LLTransactionID& transaction_id) : - mTransactionID(transaction_id) -{ -} - -void LLInventoryTransactionObserver::changed(U32 mask) -{ - if(mask & LLInventoryObserver::ADD) - { - // This could be it - see if we are processing a bulk update - LLMessageSystem* msg = gMessageSystem; - if(msg->getMessageName() - && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory"))) - { - // we have a match for the message - now check the - // transaction id. - LLUUID id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id); - if(id == mTransactionID) - { - // woo hoo, we found it - folder_ref_t folders; - item_ref_t items; - S32 count; - count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); - S32 i; - for(i = 0; i < count; ++i) - { - msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i); - if(id.notNull()) - { - folders.push_back(id); - } - } - count = msg->getNumberOfBlocksFast(_PREHASH_ItemData); - for(i = 0; i < count; ++i) - { - msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i); - if(id.notNull()) - { - items.push_back(id); - } - } - - // call the derived class the implements this method. - done(folders, items); - } - } - } -} - - ///---------------------------------------------------------------------------- /// LLAssetIDMatches ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index faf026887a..bd64591194 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -41,40 +41,27 @@ #include "lluuid.h" #include "llpermissionsflags.h" #include "llstring.h" - #include <map> #include <set> #include <string> #include <vector> -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryObserver -// -// This class is designed to be a simple abstract base class which can -// relay messages when the inventory changes. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ! REFACTOR ! Remove llinventoryobservers.h and have other files that need it explicitly +// include llinventoryobservers.h instead of llinventorymodel.h . This will reduce dependency on +// llinventorymodel.h. +#include "llinventoryobserver.h" + +class LLInventoryObserver; +class LLInventoryObject; +class LLInventoryItem; +class LLInventoryCategory; +class LLViewerInventoryItem; +class LLViewerInventoryCategory; +class LLViewerInventoryItem; +class LLViewerInventoryCategory; +class LLMessageSystem; +class LLInventoryCollectFunctor; -class LLInventoryObserver -{ -public: - // This enumeration is a way to refer to what changed in a more - // human readable format. You can mask the value provided by - // chaged() to see if the observer is interested in the change. - enum - { - NONE = 0, - LABEL = 1, // name changed - INTERNAL = 2, // internal change, eg, asset uuid different - ADD = 4, // something added - REMOVE = 8, // something deleted - STRUCTURE = 16, // structural change, eg, item or folder moved - CALLING_CARD = 32, // online, grant status, cancel, etc change - ALL = 0xffffffff - }; - virtual ~LLInventoryObserver() {}; - virtual void changed(U32 mask) = 0; - std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328] -}; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryModel @@ -87,16 +74,6 @@ public: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryObject; -class LLInventoryItem; -class LLInventoryCategory; -class LLViewerInventoryItem; -class LLViewerInventoryCategory; -class LLViewerInventoryItem; -class LLViewerInventoryCategory; -class LLMessageSystem; -class LLInventoryCollectFunctor; - class LLInventoryModel { public: @@ -473,23 +450,12 @@ protected: cat_array_t* getUnlockedCatArray(const LLUUID& id); item_array_t* getUnlockedItemArray(const LLUUID& id); -protected: +private: // Variables used to track what has changed since the last notify. U32 mModifyMask; typedef std::set<LLUUID> changed_items_t; changed_items_t mChangedItemIDs; - // Information for tracking the actual inventory. We index this - // information in a lot of different ways so we can access - // the inventory using several different identifiers. - // mInventory member data is the 'master' list of inventory, and - // mCategoryMap and mItemMap store uuid->object mappings. - typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t; - typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t; - //inv_map_t mInventory; - cat_map_t mCategoryMap; - item_map_t mItemMap; - std::map<LLUUID, bool> mCategoryLock; std::map<LLUUID, bool> mItemLock; @@ -525,6 +491,21 @@ protected: // This flag is used to handle an invalid inventory state. bool mIsAgentInvUsable; +private: + // Information for tracking the actual inventory. We index this + // information in a lot of different ways so we can access + // the inventory using several different identifiers. + // mInventory member data is the 'master' list of inventory, and + // mCategoryMap and mItemMap store uuid->object mappings. + typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t; + typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t; + //inv_map_t mInventory; + cat_map_t mCategoryMap; + item_map_t mItemMap; + + // Flag set when notifyObservers is being called, to look for bugs + // where it's called recursively. + BOOL mIsNotifyObservers; public: // *NOTE: DEBUG functionality void dumpInventory() const; @@ -767,183 +748,5 @@ public: LLInventoryItem* item); }; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryCompletionObserver -// -// Class which can be used as a base class for doing something when -// when all observed items are locally complete. This class implements -// the changed() method of LLInventoryObserver and declares a new -// method named done() which is called when all watched items have -// complete information in the inventory model. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryCompletionObserver : public LLInventoryObserver -{ -public: - LLInventoryCompletionObserver() {} - virtual void changed(U32 mask); - - void watchItem(const LLUUID& id); - -protected: - virtual void done() = 0; - - typedef std::vector<LLUUID> item_ref_t; - item_ref_t mComplete; - item_ref_t mIncomplete; -}; - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryFetchObserver -// -// This class is much like the LLInventoryCompletionObserver, except -// that it handles all the the fetching necessary. Override the done() -// method to do the thing you want. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryFetchObserver : public LLInventoryObserver -{ -public: - LLInventoryFetchObserver() {} - virtual void changed(U32 mask); - - typedef std::vector<LLUUID> item_ref_t; - - bool isEverythingComplete() const; - void fetchItems(const item_ref_t& ids); - virtual void done() = 0; - -protected: - item_ref_t mComplete; - item_ref_t mIncomplete; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryFetchDescendentsObserver -// -// This class is much like the LLInventoryCompletionObserver, except -// that it handles fetching based on category. Override the done() -// method to do the thing you want. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFetchDescendentsObserver : public LLInventoryObserver -{ -public: - LLInventoryFetchDescendentsObserver() {} - virtual void changed(U32 mask); - - typedef std::vector<LLUUID> folder_ref_t; - void fetchDescendents(const folder_ref_t& ids); - bool isEverythingComplete() const; - virtual void done() = 0; - -protected: - bool isComplete(LLViewerInventoryCategory* cat); - folder_ref_t mIncompleteFolders; - folder_ref_t mCompleteFolders; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryFetchComboObserver -// -// This class does an appropriate combination of fetch descendents and -// item fetches based on completion of categories and items. Much like -// the fetch and fetch descendents, this will call done() when everything -// has arrived. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFetchComboObserver : public LLInventoryObserver -{ -public: - LLInventoryFetchComboObserver() : mDone(false) {} - virtual void changed(U32 mask); - - typedef std::vector<LLUUID> folder_ref_t; - typedef std::vector<LLUUID> item_ref_t; - void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids); - - virtual void done() = 0; - -protected: - bool mDone; - folder_ref_t mCompleteFolders; - folder_ref_t mIncompleteFolders; - item_ref_t mCompleteItems; - item_ref_t mIncompleteItems; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryExistenceObserver -// -// This class is used as a base class for doing somethign when all the -// observed item ids exist in the inventory somewhere. You can derive -// a class from this class and implement the done() method to do -// something useful. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryExistenceObserver : public LLInventoryObserver -{ -public: - LLInventoryExistenceObserver() {} - virtual void changed(U32 mask); - - void watchItem(const LLUUID& id); - -protected: - virtual void done() = 0; - - typedef std::vector<LLUUID> item_ref_t; - item_ref_t mExist; - item_ref_t mMIA; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryAddedObserver -// -// This class is used as a base class for doing something when -// a new item arrives in inventory. -// It does not watch for a certain UUID, rather it acts when anything is added -// Derive a class from this class and implement the done() method to do -// something useful. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryAddedObserver : public LLInventoryObserver -{ -public: - LLInventoryAddedObserver() : mAdded() {} - virtual void changed(U32 mask); - -protected: - virtual void done() = 0; - - typedef std::vector<LLUUID> item_ref_t; - item_ref_t mAdded; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryTransactionObserver -// -// Class which can be used as a base class for doing something when an -// inventory transaction completes. -// -// *NOTE: This class is not quite complete. Avoid using unless you fix up it's -// functionality gaps. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLInventoryTransactionObserver : public LLInventoryObserver -{ -public: - LLInventoryTransactionObserver(const LLTransactionID& transaction_id); - virtual void changed(U32 mask); - -protected: - typedef std::vector<LLUUID> folder_ref_t; - typedef std::vector<LLUUID> item_ref_t; - virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0; - - LLTransactionID mTransactionID; -}; - - #endif // LL_LLINVENTORYMODEL_H diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp new file mode 100644 index 0000000000..3ccf593d27 --- /dev/null +++ b/indra/newview/llinventoryobserver.cpp @@ -0,0 +1,564 @@ +/** + * @file llinventoryobserver.cpp + * @brief Implementation of the inventory observers used to track agent inventory. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinventoryobserver.h" + +#include "llassetstorage.h" +#include "llcrc.h" +#include "lldir.h" +#include "llsys.h" +#include "llxfermanager.h" +#include "message.h" + +#include "llagent.h" +#include "llagentwearables.h" +#include "llfloater.h" +#include "llfocusmgr.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llviewermessage.h" +#include "llviewerwindow.h" +#include "llviewerregion.h" +#include "llappviewer.h" +#include "lldbstrings.h" +#include "llviewerstats.h" +#include "llmutelist.h" +#include "llnotifications.h" +#include "llcallbacklist.h" +#include "llpreview.h" +#include "llviewercontrol.h" +#include "llvoavatarself.h" +#include "llsdutil.h" +#include <deque> + +void LLInventoryCompletionObserver::changed(U32 mask) +{ + // scan through the incomplete items and move or erase them as + // appropriate. + if(!mIncomplete.empty()) + { + for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if(!item) + { + it = mIncomplete.erase(it); + continue; + } + if(item->isComplete()) + { + mComplete.push_back(*it); + it = mIncomplete.erase(it); + continue; + } + ++it; + } + if(mIncomplete.empty()) + { + done(); + } + } +} + +void LLInventoryCompletionObserver::watchItem(const LLUUID& id) +{ + if(id.notNull()) + { + mIncomplete.push_back(id); + } +} + + +void LLInventoryFetchObserver::changed(U32 mask) +{ + // scan through the incomplete items and move or erase them as + // appropriate. + if(!mIncomplete.empty()) + { + for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if(!item) + { + // BUG: This can cause done() to get called prematurely below. + // This happens with the LLGestureInventoryFetchObserver that + // loads gestures at startup. JC + it = mIncomplete.erase(it); + continue; + } + if(item->isComplete()) + { + mComplete.push_back(*it); + it = mIncomplete.erase(it); + continue; + } + ++it; + } + if(mIncomplete.empty()) + { + done(); + } + } + //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl; + //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl; +} + +bool LLInventoryFetchObserver::isEverythingComplete() const +{ + return mIncomplete.empty(); +} + +void fetch_items_from_llsd(const LLSD& items_llsd) +{ + if (!items_llsd.size()) return; + LLSD body; + body[0]["cap_name"] = "FetchInventory"; + body[1]["cap_name"] = "FetchLib"; + for (S32 i=0; i<items_llsd.size();i++) + { + if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString()) + { + body[0]["items"].append(items_llsd[i]); + continue; + } + if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString()) + { + body[1]["items"].append(items_llsd[i]); + continue; + } + } + + for (S32 i=0; i<body.size(); i++) + { + if (0 >= body[i].size()) continue; + std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString()); + + if (!url.empty()) + { + body[i]["agent_id"] = gAgent.getID(); + LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i])); + break; + } + + LLMessageSystem* msg = gMessageSystem; + BOOL start_new_message = TRUE; + for (S32 j=0; j<body[i]["items"].size(); j++) + { + LLSD item_entry = body[i]["items"][j]; + if(start_new_message) + { + start_new_message = FALSE; + msg->newMessageFast(_PREHASH_FetchInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + } + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID()); + msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID()); + if(msg->isSendFull(NULL)) + { + start_new_message = TRUE; + gAgent.sendReliableMessage(); + } + } + if(!start_new_message) + { + gAgent.sendReliableMessage(); + } + } +} + +void LLInventoryFetchObserver::fetchItems( + const LLInventoryFetchObserver::item_ref_t& ids) +{ + LLUUID owner_id; + LLSD items_llsd; + for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if(item) + { + if(item->isComplete()) + { + // It's complete, so put it on the complete container. + mComplete.push_back(*it); + continue; + } + else + { + owner_id = item->getPermissions().getOwner(); + } + } + else + { + // assume it's agent inventory. + owner_id = gAgent.getID(); + } + + // It's incomplete, so put it on the incomplete container, and + // pack this on the message. + mIncomplete.push_back(*it); + + // Prepare the data to fetch + LLSD item_entry; + item_entry["owner_id"] = owner_id; + item_entry["item_id"] = (*it); + items_llsd.append(item_entry); + } + fetch_items_from_llsd(items_llsd); +} + +// virtual +void LLInventoryFetchDescendentsObserver::changed(U32 mask) +{ + for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + if(!cat) + { + it = mIncompleteFolders.erase(it); + continue; + } + if(isComplete(cat)) + { + mCompleteFolders.push_back(*it); + it = mIncompleteFolders.erase(it); + continue; + } + ++it; + } + if(mIncompleteFolders.empty()) + { + done(); + } +} + +void LLInventoryFetchDescendentsObserver::fetchDescendents( + const folder_ref_t& ids) +{ + for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + if(!cat) continue; + if(!isComplete(cat)) + { + cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it. + mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer. + } + else + { + mCompleteFolders.push_back(*it); + } + } +} + +bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const +{ + return mIncompleteFolders.empty(); +} + +bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat) +{ + S32 version = cat->getVersion(); + S32 descendents = cat->getDescendentCount(); + if((LLViewerInventoryCategory::VERSION_UNKNOWN == version) + || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents)) + { + return false; + } + // it might be complete - check known descendents against + // currently available. + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items); + if(!cats || !items) + { + // bit of a hack - pretend we're done if they are gone or + // incomplete. should never know, but it would suck if this + // kept tight looping because of a corrupt memory state. + return true; + } + S32 known = cats->count() + items->count(); + if(descendents == known) + { + // hey - we're done. + return true; + } + return false; +} + +void LLInventoryFetchComboObserver::changed(U32 mask) +{ + if(!mIncompleteItems.empty()) + { + for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); ) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if(!item) + { + it = mIncompleteItems.erase(it); + continue; + } + if(item->isComplete()) + { + mCompleteItems.push_back(*it); + it = mIncompleteItems.erase(it); + continue; + } + ++it; + } + } + if(!mIncompleteFolders.empty()) + { + for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + if(!cat) + { + it = mIncompleteFolders.erase(it); + continue; + } + if(gInventory.isCategoryComplete(*it)) + { + mCompleteFolders.push_back(*it); + it = mIncompleteFolders.erase(it); + continue; + } + ++it; + } + } + if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty()) + { + mDone = true; + done(); + } +} + +void LLInventoryFetchComboObserver::fetch( + const folder_ref_t& folder_ids, + const item_ref_t& item_ids) +{ + lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl; + for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*fit); + if(!cat) continue; + if(!gInventory.isCategoryComplete(*fit)) + { + cat->fetchDescendents(); + lldebugs << "fetching folder " << *fit <<llendl; + mIncompleteFolders.push_back(*fit); + } + else + { + mCompleteFolders.push_back(*fit); + lldebugs << "completing folder " << *fit <<llendl; + } + } + + // Now for the items - we fetch everything which is not a direct + // descendent of an incomplete folder because the item will show + // up in an inventory descendents message soon enough so we do not + // have to fetch it individually. + LLSD items_llsd; + LLUUID owner_id; + for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit) + { + LLViewerInventoryItem* item = gInventory.getItem(*iit); + if(!item) + { + lldebugs << "uanble to find item " << *iit << llendl; + continue; + } + if(item->isComplete()) + { + // It's complete, so put it on the complete container. + mCompleteItems.push_back(*iit); + lldebugs << "completing item " << *iit << llendl; + continue; + } + else + { + mIncompleteItems.push_back(*iit); + owner_id = item->getPermissions().getOwner(); + } + if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) + { + LLSD item_entry; + item_entry["owner_id"] = owner_id; + item_entry["item_id"] = (*iit); + items_llsd.append(item_entry); + } + else + { + lldebugs << "not worrying about " << *iit << llendl; + } + } + fetch_items_from_llsd(items_llsd); +} + +void LLInventoryExistenceObserver::watchItem(const LLUUID& id) +{ + if(id.notNull()) + { + mMIA.push_back(id); + } +} + +void LLInventoryExistenceObserver::changed(U32 mask) +{ + // scan through the incomplete items and move or erase them as + // appropriate. + if(!mMIA.empty()) + { + for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); ) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if(!item) + { + ++it; + continue; + } + mExist.push_back(*it); + it = mMIA.erase(it); + } + if(mMIA.empty()) + { + done(); + } + } +} + +void LLInventoryAddedObserver::changed(U32 mask) +{ + if(!(mask & LLInventoryObserver::ADD)) + { + return; + } + + // *HACK: If this was in response to a packet off + // the network, figure out which item was updated. + LLMessageSystem* msg = gMessageSystem; + + std::string msg_name; + if (mMessageName.empty()) + { + msg_name = msg->getMessageName(); + } + else + { + msg_name = mMessageName; + } + + if (msg_name.empty()) + { + return; + } + + // We only want newly created inventory items. JC + if ( msg_name != "UpdateCreateInventoryItem") + { + return; + } + + LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; + S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); + for(S32 i = 0; i < num_blocks; ++i) + { + titem->unpackMessage(msg, _PREHASH_InventoryData, i); + if (!(titem->getUUID().isNull())) + { + //we don't do anything with null keys + mAdded.push_back(titem->getUUID()); + } + } + if (!mAdded.empty()) + { + done(); + } +} + +LLInventoryTransactionObserver::LLInventoryTransactionObserver( + const LLTransactionID& transaction_id) : + mTransactionID(transaction_id) +{ +} + +void LLInventoryTransactionObserver::changed(U32 mask) +{ + if(mask & LLInventoryObserver::ADD) + { + // This could be it - see if we are processing a bulk update + LLMessageSystem* msg = gMessageSystem; + if(msg->getMessageName() + && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory"))) + { + // we have a match for the message - now check the + // transaction id. + LLUUID id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id); + if(id == mTransactionID) + { + // woo hoo, we found it + folder_ref_t folders; + item_ref_t items; + S32 count; + count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); + S32 i; + for(i = 0; i < count; ++i) + { + msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i); + if(id.notNull()) + { + folders.push_back(id); + } + } + count = msg->getNumberOfBlocksFast(_PREHASH_ItemData); + for(i = 0; i < count; ++i) + { + msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i); + if(id.notNull()) + { + items.push_back(id); + } + } + + // call the derived class the implements this method. + done(folders, items); + } + } + } +} diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h new file mode 100644 index 0000000000..384e6292e8 --- /dev/null +++ b/indra/newview/llinventoryobserver.h @@ -0,0 +1,249 @@ +/** + * @file llinventoryobserver.h + * @brief LLInventoryObserver class header file + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINVENTORYOBSERVERS_H +#define LL_LLINVENTORYOBSERVERS_H + +#include "lluuid.h" +#include <string> +#include <vector> + +class LLViewerInventoryCategory; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryObserver +// +// This class is designed to be a simple abstract base class which can +// relay messages when the inventory changes. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryObserver +{ +public: + // This enumeration is a way to refer to what changed in a more + // human readable format. You can mask the value provided by + // chaged() to see if the observer is interested in the change. + enum + { + NONE = 0, + LABEL = 1, // name changed + INTERNAL = 2, // internal change, eg, asset uuid different + ADD = 4, // something added + REMOVE = 8, // something deleted + STRUCTURE = 16, // structural change, eg, item or folder moved + CALLING_CARD = 32, // online, grant status, cancel, etc change + ALL = 0xffffffff + }; + virtual ~LLInventoryObserver() {}; + virtual void changed(U32 mask) = 0; + std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328] +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryCompletionObserver +// +// Class which can be used as a base class for doing something when +// when all observed items are locally complete. This class implements +// the changed() method of LLInventoryObserver and declares a new +// method named done() which is called when all watched items have +// complete information in the inventory model. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryCompletionObserver : public LLInventoryObserver +{ +public: + LLInventoryCompletionObserver() {} + virtual void changed(U32 mask); + + void watchItem(const LLUUID& id); + +protected: + virtual void done() = 0; + + typedef std::vector<LLUUID> item_ref_t; + item_ref_t mComplete; + item_ref_t mIncomplete; +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryFetchObserver +// +// This class is much like the LLInventoryCompletionObserver, except +// that it handles all the the fetching necessary. Override the done() +// method to do the thing you want. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryFetchObserver : public LLInventoryObserver +{ +public: + LLInventoryFetchObserver() {} + virtual void changed(U32 mask); + + typedef std::vector<LLUUID> item_ref_t; + + bool isEverythingComplete() const; + void fetchItems(const item_ref_t& ids); + virtual void done() = 0; + +protected: + item_ref_t mComplete; + item_ref_t mIncomplete; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryFetchDescendentsObserver +// +// This class is much like the LLInventoryCompletionObserver, except +// that it handles fetching based on category. Override the done() +// method to do the thing you want. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryFetchDescendentsObserver : public LLInventoryObserver +{ +public: + LLInventoryFetchDescendentsObserver() {} + virtual void changed(U32 mask); + + typedef std::vector<LLUUID> folder_ref_t; + void fetchDescendents(const folder_ref_t& ids); + bool isEverythingComplete() const; + virtual void done() = 0; + +protected: + bool isComplete(LLViewerInventoryCategory* cat); + folder_ref_t mIncompleteFolders; + folder_ref_t mCompleteFolders; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryFetchComboObserver +// +// This class does an appropriate combination of fetch descendents and +// item fetches based on completion of categories and items. Much like +// the fetch and fetch descendents, this will call done() when everything +// has arrived. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryFetchComboObserver : public LLInventoryObserver +{ +public: + LLInventoryFetchComboObserver() : mDone(false) {} + virtual void changed(U32 mask); + + typedef std::vector<LLUUID> folder_ref_t; + typedef std::vector<LLUUID> item_ref_t; + void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids); + + virtual void done() = 0; + +protected: + bool mDone; + folder_ref_t mCompleteFolders; + folder_ref_t mIncompleteFolders; + item_ref_t mCompleteItems; + item_ref_t mIncompleteItems; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryExistenceObserver +// +// This class is used as a base class for doing somethign when all the +// observed item ids exist in the inventory somewhere. You can derive +// a class from this class and implement the done() method to do +// something useful. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryExistenceObserver : public LLInventoryObserver +{ +public: + LLInventoryExistenceObserver() {} + virtual void changed(U32 mask); + + void watchItem(const LLUUID& id); + +protected: + virtual void done() = 0; + + typedef std::vector<LLUUID> item_ref_t; + item_ref_t mExist; + item_ref_t mMIA; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryAddedObserver +// +// This class is used as a base class for doing something when +// a new item arrives in inventory. +// It does not watch for a certain UUID, rather it acts when anything is added +// Derive a class from this class and implement the done() method to do +// something useful. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryAddedObserver : public LLInventoryObserver +{ +public: + LLInventoryAddedObserver() : mAdded() {} + virtual void changed(U32 mask); + +protected: + virtual void done() = 0; + + typedef std::vector<LLUUID> item_ref_t; + item_ref_t mAdded; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryTransactionObserver +// +// Class which can be used as a base class for doing something when an +// inventory transaction completes. +// +// *NOTE: This class is not quite complete. Avoid using unless you fix up it's +// functionality gaps. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryTransactionObserver : public LLInventoryObserver +{ +public: + LLInventoryTransactionObserver(const LLTransactionID& transaction_id); + virtual void changed(U32 mask); + +protected: + typedef std::vector<LLUUID> folder_ref_t; + typedef std::vector<LLUUID> item_ref_t; + virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0; + + LLTransactionID mTransactionID; +}; + + +#endif // LL_LLINVENTORYOBSERVERS_H + diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 9a71e53441..dfd4af5c28 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -191,11 +191,9 @@ BOOL LLInventoryPanel::postBuild() {
rebuildViewsFor(mStartFolderID);
mHasInventoryConnection = true;
+ defaultOpenInventory();
}
- // bit of a hack to make sure the inventory is open.
- mFolders->openFolder(preferred_type != LLFolderType::FT_NONE ? LLViewerFolderType::lookupNewCategoryName(preferred_type) : "My Inventory");
-
if (mSortOrderSetting != INHERIT_SORT_ORDER)
{
setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
@@ -300,6 +298,7 @@ void LLInventoryPanel::modelChanged(U32 mask) {
rebuildViewsFor(mStartFolderID);
mHasInventoryConnection = true;
+ defaultOpenInventory();
return;
}
@@ -561,6 +560,25 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id) }
}
+// bit of a hack to make sure the inventory is open.
+void LLInventoryPanel::defaultOpenInventory()
+{
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+ if (preferred_type != LLFolderType::FT_NONE)
+ {
+ const std::string& top_level_folder_name = LLViewerFolderType::lookupNewCategoryName(preferred_type);
+ mFolders->openFolder(top_level_folder_name);
+ }
+ else
+ {
+ // Get the first child (it should be "My Inventory") and
+ // open it up by name (just to make sure the first child is actually a folder).
+ LLView* first_child = mFolders->getFirstChild();
+ const std::string& first_child_name = first_child->getName();
+ mFolders->openFolder(first_child_name);
+ }
+}
+
struct LLConfirmPurgeData
{
LLUUID mID;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 9f74fad5c1..e398c44105 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -165,7 +165,7 @@ protected: // Given the id and the parent, build all of the folder views. void rebuildViewsFor(const LLUUID& id); virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719 - + void defaultOpenInventory(); // open the first level of inventory protected: LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index e5f347ddc4..a01426ea87 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -73,9 +73,9 @@ LLLoginInstance::LLLoginInstance() : { mLoginModule->getEventPump().listen("lllogininstance", boost::bind(&LLLoginInstance::handleLoginEvent, this, _1)); - mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1)); - mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1)); - mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1)); + mDispatcher.add("fail.login", "", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1)); + mDispatcher.add("connect", "", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1)); + mDispatcher.add("disconnect", "", boost::bind(&LLLoginInstance::handleDisconnect, this, _1)); } LLLoginInstance::~LLLoginInstance() @@ -182,6 +182,9 @@ void LLLoginInstance::constructAuthParams(const LLSD& credentials) mRequestData["method"] = "login_to_simulator"; mRequestData["params"] = request_params; mRequestData["options"] = requested_options; + + mRequestData["cfg_srv_timeout"] = gSavedSettings.getF32("LoginSRVTimeout"); + mRequestData["cfg_srv_pump"] = gSavedSettings.getString("LoginSRVPump"); } bool LLLoginInstance::handleLoginEvent(const LLSD& event) diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 541db0ca6e..9439717fb8 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -323,8 +323,8 @@ void LLNameListCtrl::refreshAll(const LLUUID& id, const std::string& first, LLInstanceTracker<LLNameListCtrl>::instance_iter it; for (it = beginInstances(); it != endInstances(); ++it) { - LLNameListCtrl* ctrl = *it; - ctrl->refresh(id, first, last, is_group); + LLNameListCtrl& ctrl = *it; + ctrl.refresh(id, first, last, is_group); } } diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 17b712bc5e..794d73a5ad 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -480,7 +480,7 @@ void LLNavigationBar::rebuildTeleportHistoryMenu() type = LLTeleportHistoryMenuItem::TYPE_CURRENT; LLTeleportHistoryMenuItem::Params item_params; - item_params.label = item_params.name = hist_items[i].getTitle(); + item_params.label = item_params.name = hist_items[i].mTitle; item_params.item_type = type; item_params.on_click.function(boost::bind(&LLNavigationBar::onTeleportHistoryMenuItemClicked, this, i)); LLTeleportHistoryMenuItem* new_itemp = LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params); diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index d54545971b..94b8791147 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -36,7 +36,6 @@ #include "lltrans.h" #include "llnearbychatbar.h" -#include "llspeakbutton.h" #include "llbottomtray.h" #include "llagent.h" #include "llgesturemgr.h" @@ -234,14 +233,6 @@ BOOL LLNearbyChatBar::postBuild() mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); mOutputMonitor->setVisible(FALSE); - mSpeakBtn = getParent()->getChild<LLSpeakButton>("talk"); - - // Speak button should be initially disabled because - // it takes some time between logging in to world and connecting to voice channel. - mSpeakBtn->setEnabled(FALSE); - - // Registering Chat Bar to receive Voice client status change notifications. - gVoiceClient->addObserver(this); return TRUE; } @@ -260,6 +251,8 @@ bool LLNearbyChatBar::instanceExists() void LLNearbyChatBar::draw() { +// TODO: mantipov: remove +/* LLRect rect = getRect(); S32 max_width = getMaxWidth(); @@ -269,6 +262,7 @@ void LLNearbyChatBar::draw() reshape(rect.getWidth(), rect.getHeight(), FALSE); setRect(rect); } +*/ displaySpeakingIndicator(); LLPanel::draw(); @@ -730,27 +724,6 @@ public: } }; -void LLNearbyChatBar::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - // Time it takes to connect to voice channel might be pretty long, - // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED. - BOOL enable = FALSE; - - switch (status) - { - // Do not add STATUS_VOICE_ENABLED because voice chat is - // inactive until STATUS_JOINED - case STATUS_JOINED: - enable = TRUE; - break; - default: - enable = FALSE; - break; - } - - mSpeakBtn->setEnabled(enable); -} - // Creating the object registers with the dispatcher. LLChatHandler gChatHandler; diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index 56ee706a97..224118e088 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -42,9 +42,6 @@ #include "llspeakers.h" -class LLSpeakButton; - - class LLGestureComboBox : public LLComboBox , public LLGestureManagerObserver @@ -76,7 +73,6 @@ protected: class LLNearbyChatBar : public LLPanel -, public LLVoiceClientStatusObserver { public: // constructor for inline chat-bars (e.g. hosted in chat history window) @@ -105,11 +101,6 @@ public: S32 getMinWidth() const; S32 getMaxWidth() const; - /** - * Implements LLVoiceClientStatusObserver::onChange() - */ - /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - protected: static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); @@ -127,7 +118,6 @@ protected: static S32 sLastSpecialChatChannel; LLLineEditor* mChatBox; - LLSpeakButton* mSpeakBtn; LLOutputMonitorCtrl* mOutputMonitor; LLLocalSpeakerMgr* mSpeakerMgr; }; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 4286582cdc..6145588df2 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -155,11 +155,9 @@ void LLNetMap::draw() F32 rotation = 0; { - LLGLEnable scissor(GL_SCISSOR_TEST); - + LLLocalClipRect clip(getLocalRect()); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLLocalClipRect clip(getLocalRect()); glMatrixMode(GL_MODELVIEW); diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 1bf7be1c4e..471dd28426 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -95,14 +95,9 @@ bool LLOfferHandler::processNotification(const LLSD& notify) LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, notification->getPayload()["from_id"]); if (!LLIMMgr::instance().hasSession(session_id)) { - // create session with faked type to avoid creating chicklets session_id = LLIMMgr::instance().addSession( notification->getSubstitutions()["NAME"], IM_NOTHING_SPECIAL, notification->getPayload()["from_id"]); - if (session_id != LLUUID::null) - { - LLIMFloater::show(session_id); - } } LLIMMgr::instance().addMessage(session_id, LLUUID(), notification->getSubstitutions()["NAME"], diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index a29c9752e6..67a2704501 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1142,3 +1142,552 @@ void LLPanelClassified::setDefaultAccessCombo() break; } } + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelClassifiedInfo::LLPanelClassifiedInfo() + : LLPanel() + , mInfoLoaded(false) +{ +} + +LLPanelClassifiedInfo::~LLPanelClassifiedInfo() +{ +} + +// static +LLPanelClassifiedInfo* LLPanelClassifiedInfo::create() +{ + LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo(); + LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_classified_info.xml"); + return panel; +} + +BOOL LLPanelClassifiedInfo::postBuild() +{ + childSetAction("back_btn", boost::bind(&LLPanelClassifiedInfo::onExit, this)); + childSetAction("show_on_map_btn", boost::bind(&LLPanelClassifiedInfo::onMapClick, this)); + childSetAction("teleport_btn", boost::bind(&LLPanelClassifiedInfo::onTeleportClick, this)); + + return TRUE; +} + +void LLPanelClassifiedInfo::setExitCallback(const commit_callback_t& cb) +{ + getChild<LLButton>("back_btn")->setClickedCallback(cb); +} + +void LLPanelClassifiedInfo::setEditClassifiedCallback(const commit_callback_t& cb) +{ + getChild<LLButton>("edit_btn")->setClickedCallback(cb); +} + +void LLPanelClassifiedInfo::onOpen(const LLSD& key) +{ + LLUUID avatar_id = key["avatar_id"]; + if(avatar_id.isNull()) + { + return; + } + + if(getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); + } + + setAvatarId(avatar_id); + + resetData(); + resetControls(); + + setClassifiedId(key["classified_id"]); + setClassifiedName(key["name"]); + setDescription(key["desc"]); + setSnapshotId(key["snapshot_id"]); + + LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); + setInfoLoaded(false); +} + +void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType type) +{ + if(APT_CLASSIFIED_INFO == type) + { + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if(c_info && getClassifiedId() == c_info->classified_id) + { + setClassifiedName(c_info->name); + setDescription(c_info->description); + setSnapshotId(c_info->snapshot_id); + setParcelId(c_info->parcel_id); + setPosGlobal(c_info->pos_global); + setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); + childSetValue("category", LLClassifiedInfo::sCategories[c_info->category]); + + static std::string mature_str = getString("type_mature"); + static std::string pg_str = getString("type_pg"); + + bool mature = is_cf_mature(c_info->flags); + childSetValue("content_type", mature ? mature_str : pg_str); + childSetValue("auto_renew", is_cf_auto_renew(c_info->flags)); + + childSetTextArg("price_for_listing", "[PRICE]", llformat("%d", c_info->price_for_listing)); + + setInfoLoaded(true); + } + } +} + +void LLPanelClassifiedInfo::resetData() +{ + setClassifiedName(LLStringUtil::null); + setDescription(LLStringUtil::null); + setClassifiedLocation(LLStringUtil::null); + setClassifiedId(LLUUID::null); + setSnapshotId(LLUUID::null); + mPosGlobal.clearVec(); + childSetValue("category", LLStringUtil::null); + childSetValue("content_type", LLStringUtil::null); +} + +void LLPanelClassifiedInfo::resetControls() +{ + if(getAvatarId() == gAgent.getID()) + { + childSetEnabled("edit_btn", TRUE); + childSetVisible("edit_btn", TRUE); + } + else + { + childSetEnabled("edit_btn", FALSE); + childSetVisible("edit_btn", FALSE); + } +} + +void LLPanelClassifiedInfo::setClassifiedName(const std::string& name) +{ + childSetValue("classified_name", name); +} + +std::string LLPanelClassifiedInfo::getClassifiedName() +{ + return childGetValue("classified_name").asString(); +} + +void LLPanelClassifiedInfo::setDescription(const std::string& desc) +{ + childSetValue("classified_desc", desc); +} + +std::string LLPanelClassifiedInfo::getDescription() +{ + return childGetValue("classified_desc").asString(); +} + +void LLPanelClassifiedInfo::setClassifiedLocation(const std::string& location) +{ + childSetValue("classified_location", location); +} + +void LLPanelClassifiedInfo::setSnapshotId(const LLUUID& id) +{ + childSetValue("classified_snapshot", id); +} + +LLUUID LLPanelClassifiedInfo::getSnapshotId() +{ + return childGetValue("classified_snapshot").asUUID(); +} + +// static +std::string LLPanelClassifiedInfo::createLocationText( + const std::string& original_name, + const std::string& sim_name, + const LLVector3d& pos_global) +{ + std::string location_text; + + location_text.append(original_name); + + if (!sim_name.empty()) + { + if (!location_text.empty()) + location_text.append(", "); + location_text.append(sim_name); + } + + if (!location_text.empty()) + location_text.append(" "); + + if (!pos_global.isNull()) + { + S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; + S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; + S32 region_z = llround((F32)pos_global.mdV[VZ]); + location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); + } + + return location_text; +} + +void LLPanelClassifiedInfo::onMapClick() +{ + LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); + LLFloaterReg::showInstance("world_map", "center"); +} + +void LLPanelClassifiedInfo::onTeleportClick() +{ + if (!getPosGlobal().isExactlyZero()) + { + gAgent.teleportViaLocation(getPosGlobal()); + LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal()); + } +} + +void LLPanelClassifiedInfo::onExit() +{ + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +static const S32 CB_ITEM_MATURE = 0; +static const S32 CB_ITEM_PG = 1; + +LLPanelClassifiedEdit::LLPanelClassifiedEdit() + : LLPanelClassifiedInfo() + , mIsNew(false) +{ +} + +LLPanelClassifiedEdit::~LLPanelClassifiedEdit() +{ +} + +//static +LLPanelClassifiedEdit* LLPanelClassifiedEdit::create() +{ + LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit(); + LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_edit_classified.xml"); + return panel; +} + +BOOL LLPanelClassifiedEdit::postBuild() +{ + LLPanelClassifiedInfo::postBuild(); + + LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("classified_snapshot"); + snapshot->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); + + LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon"); + snapshot->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon)); + snapshot->setMouseLeaveCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseLeave, this, edit_icon)); + edit_icon->setVisible(false); + + LLLineEditor* line_edit = getChild<LLLineEditor>("classified_name"); + line_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); + + LLTextEditor* text_edit = getChild<LLTextEditor>("classified_desc"); + text_edit->setKeystrokeCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); + + LLComboBox* combobox = getChild<LLComboBox>( "category"); + LLClassifiedInfo::cat_map::iterator iter; + for (iter = LLClassifiedInfo::sCategories.begin(); + iter != LLClassifiedInfo::sCategories.end(); + iter++) + { + combobox->add(LLTrans::getString(iter->second)); + } + + combobox->setCommitCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this)); + + childSetCommitCallback("content_type", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); + childSetCommitCallback("price_for_listing", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); + childSetCommitCallback("auto_renew", boost::bind(&LLPanelClassifiedEdit::onChange, this), NULL); + + childSetAction("save_changes_btn", boost::bind(&LLPanelClassifiedEdit::onSaveClick, this)); + childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelClassifiedEdit::onSetLocationClick, this)); + + return TRUE; +} + +void LLPanelClassifiedEdit::onOpen(const LLSD& key) +{ + LLUUID classified_id = key["classified_id"]; + + mIsNew = classified_id.isNull(); + + if(mIsNew) + { + setAvatarId(gAgent.getID()); + + resetData(); + resetControls(); + + setPosGlobal(gAgent.getPositionGlobal()); + + LLUUID snapshot_id = LLUUID::null; + std::string desc; + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + if(parcel) + { + desc = parcel->getDesc(); + snapshot_id = parcel->getSnapshotID(); + } + + std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + region_name = region->getName(); + } + + childSetValue("classified_name", makeClassifiedName()); + childSetValue("classified_desc", desc); + setSnapshotId(snapshot_id); + + setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); + + // server will set valid parcel id + setParcelId(LLUUID::null); + + enableVerbs(true); + enableEditing(true); + } + else + { + LLPanelClassifiedInfo::onOpen(key); + enableVerbs(false); + enableEditing(false); + } + + resetDirty(); + setInfoLoaded(false); +} + +void LLPanelClassifiedEdit::processProperties(void* data, EAvatarProcessorType type) +{ + if(APT_CLASSIFIED_INFO == type) + { + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if(c_info && getClassifiedId() == c_info->classified_id) + { + enableEditing(true); + + setClassifiedName(c_info->name); + setDescription(c_info->description); + setSnapshotId(c_info->snapshot_id); + setPosGlobal(c_info->pos_global); + + setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global)); + getChild<LLComboBox>("category")->setCurrentByIndex(c_info->category + 1); + getChild<LLComboBox>("category")->resetDirty(); + + bool mature = is_cf_mature(c_info->flags); + bool auto_renew = is_cf_auto_renew(c_info->flags); + + getChild<LLComboBox>("content_type")->setCurrentByIndex(mature ? CB_ITEM_MATURE : CB_ITEM_PG); + childSetValue("auto_renew", auto_renew); + childSetValue("price_for_listing", c_info->price_for_listing); + + resetDirty(); + setInfoLoaded(true); + } + } +} + +BOOL LLPanelClassifiedEdit::isDirty() const +{ + if(mIsNew) + { + return TRUE; + } + + BOOL dirty = false; + + dirty |= LLPanelClassifiedInfo::isDirty(); + dirty |= getChild<LLUICtrl>("classified_snapshot")->isDirty(); + dirty |= getChild<LLUICtrl>("classified_name")->isDirty(); + dirty |= getChild<LLUICtrl>("classified_desc")->isDirty(); + dirty |= getChild<LLUICtrl>("category")->isDirty(); + dirty |= getChild<LLUICtrl>("content_type")->isDirty(); + dirty |= getChild<LLUICtrl>("auto_renew")->isDirty(); + dirty |= getChild<LLUICtrl>("price_for_listing")->isDirty(); + + return dirty; +} + +void LLPanelClassifiedEdit::resetDirty() +{ + LLPanelClassifiedInfo::resetDirty(); + getChild<LLUICtrl>("classified_snapshot")->resetDirty(); + getChild<LLUICtrl>("classified_name")->resetDirty(); + getChild<LLUICtrl>("classified_desc")->resetDirty(); + getChild<LLUICtrl>("category")->resetDirty(); + getChild<LLUICtrl>("content_type")->resetDirty(); + getChild<LLUICtrl>("auto_renew")->resetDirty(); + getChild<LLUICtrl>("price_for_listing")->resetDirty(); +} + +void LLPanelClassifiedEdit::setSaveCallback(const commit_callback_t& cb) +{ + getChild<LLButton>("save_changes_btn")->setClickedCallback(cb); +} + +void LLPanelClassifiedEdit::setCancelCallback(const commit_callback_t& cb) +{ + getChild<LLButton>("cancel_btn")->setClickedCallback(cb); +} + +void LLPanelClassifiedEdit::resetControls() +{ + LLPanelClassifiedInfo::resetControls(); + + getChild<LLComboBox>("category")->setCurrentByIndex(0); + getChild<LLComboBox>("content_type")->setCurrentByIndex(0); + childSetValue("auto_renew", false); + childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING); +} + +void LLPanelClassifiedEdit::sendUpdate() +{ + LLAvatarClassifiedInfo c_data; + + if(getClassifiedId().isNull()) + { + LLUUID id; + id.generate(); + setClassifiedId(id); + } + + c_data.agent_id = gAgent.getID(); + c_data.classified_id = getClassifiedId(); + c_data.category = getCategory(); + c_data.name = getClassifiedName(); + c_data.description = getDescription(); + c_data.parcel_id = getParcelId(); + c_data.snapshot_id = getSnapshotId(); + c_data.pos_global = getPosGlobal(); + c_data.flags = getFlags(); + c_data.price_for_listing = getPriceForListing(); + + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoUpdate(&c_data); +} + +U32 LLPanelClassifiedEdit::getCategory() +{ + LLComboBox* cat_cb = getChild<LLComboBox>("category"); + return cat_cb->getCurrentIndex() + 1; +} + +U8 LLPanelClassifiedEdit::getFlags() +{ + bool auto_renew = childGetValue("auto_renew").asBoolean(); + + LLComboBox* content_cb = getChild<LLComboBox>("content_type"); + bool mature = content_cb->getCurrentIndex() == CB_ITEM_MATURE; + + return pack_classified_flags_request(auto_renew, false, mature, false); +} + +void LLPanelClassifiedEdit::enableVerbs(bool enable) +{ + childSetEnabled("save_changes_btn", enable); +} + +void LLPanelClassifiedEdit::enableEditing(bool enable) +{ + childSetEnabled("classified_snapshot", enable); + childSetEnabled("classified_name", enable); + childSetEnabled("classified_desc", enable); + childSetEnabled("set_to_curr_location_btn", enable); + childSetEnabled("category", enable); + childSetEnabled("content_type", enable); + childSetEnabled("price_for_listing", enable); + childSetEnabled("auto_renew", enable); +} + +std::string LLPanelClassifiedEdit::makeClassifiedName() +{ + std::string name; + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(parcel) + { + name = parcel->getName(); + } + + if(!name.empty()) + { + return name; + } + + LLViewerRegion* region = gAgent.getRegion(); + if(region) + { + name = region->getName(); + } + + return name; +} + +S32 LLPanelClassifiedEdit::getPriceForListing() +{ + return childGetValue("price_for_listing").asInteger(); +} + +void LLPanelClassifiedEdit::onSetLocationClick() +{ + setPosGlobal(gAgent.getPositionGlobal()); + setParcelId(LLUUID::null); + + std::string region_name = LLTrans::getString("ClassifiedUpdateAfterPublish"); + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + region_name = region->getName(); + } + + setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal())); + + // mark classified as dirty + setValue(LLSD()); + + onChange(); +} + +void LLPanelClassifiedEdit::onChange() +{ + enableVerbs(isDirty()); +} + +void LLPanelClassifiedEdit::onSaveClick() +{ + sendUpdate(); + resetDirty(); +} + +std::string LLPanelClassifiedEdit::getLocationNotice() +{ + static std::string location_notice = getString("location_notice"); + return location_notice; +} + +void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl) +{ + ctrl->setVisible(TRUE); +} + +void LLPanelClassifiedEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl) +{ + ctrl->setVisible(FALSE); +} + +//EOF diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index 417eddf460..8b32495854 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -37,6 +37,7 @@ #ifndef LL_LLPANELCLASSIFIED_H #define LL_LLPANELCLASSIFIED_H +#include "llavatarpropertiesprocessor.h" #include "llpanel.h" #include "llclassifiedinfo.h" #include "v3dmath.h" @@ -55,6 +56,8 @@ class LLTextureCtrl; class LLUICtrl; class LLMessageSystem; +// *TODO deprecated, should be removed. +// New class implemented in ticket EXT-2095 class LLPanelClassified : public LLPanel { public: @@ -198,5 +201,139 @@ private: void* mUserData; }; +class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver +{ +public: + + static LLPanelClassifiedInfo* create(); + + virtual ~LLPanelClassifiedInfo(); + + /*virtual*/ void onOpen(const LLSD& key); + + /*virtual*/ BOOL postBuild(); + + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + + void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; } + + LLUUID& getAvatarId() { return mAvatarId; } + + void setSnapshotId(const LLUUID& id); + + LLUUID getSnapshotId(); + + void setClassifiedId(const LLUUID& id) { mClassifiedId = id; } + + LLUUID& getClassifiedId() { return mClassifiedId; } + + void setClassifiedName(const std::string& name); + + std::string getClassifiedName(); + + void setDescription(const std::string& desc); + + std::string getDescription(); + + void setClassifiedLocation(const std::string& location); + + void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } + + LLVector3d& getPosGlobal() { return mPosGlobal; } + + void setParcelId(const LLUUID& id) { mParcelId = id; } + + LLUUID getParcelId() { return mParcelId; } + + bool getInfoLoaded() { return mInfoLoaded; } + + void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; } + + void setExitCallback(const commit_callback_t& cb); + + void setEditClassifiedCallback(const commit_callback_t& cb); + +protected: + + LLPanelClassifiedInfo(); + + virtual void resetData(); + + virtual void resetControls(); + + static std::string createLocationText( + const std::string& original_name, + const std::string& sim_name, + const LLVector3d& pos_global); + + void onMapClick(); + void onTeleportClick(); + void onExit(); + +private: + + LLUUID mAvatarId; + LLUUID mClassifiedId; + LLVector3d mPosGlobal; + LLUUID mParcelId; + bool mInfoLoaded; +}; + +class LLPanelClassifiedEdit : public LLPanelClassifiedInfo +{ +public: + + static LLPanelClassifiedEdit* create(); + + virtual ~LLPanelClassifiedEdit(); + + /*virtual*/ BOOL postBuild(); + + /*virtual*/ void onOpen(const LLSD& key); + + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + + /*virtual*/ BOOL isDirty() const; + + /*virtual*/ void resetDirty(); + + void setSaveCallback(const commit_callback_t& cb); + + void setCancelCallback(const commit_callback_t& cb); + + /*virtual*/ void resetControls(); + + bool isNew() { return mIsNew; } + +protected: + + LLPanelClassifiedEdit(); + + void sendUpdate(); + + U32 getCategory(); + + void enableVerbs(bool enable); + + void enableEditing(bool enable); + + std::string makeClassifiedName(); + + S32 getPriceForListing(); + + U8 getFlags(); + + std::string getLocationNotice(); + + void onSetLocationClick(); + void onChange(); + void onSaveClick(); + + void onTexturePickerMouseEnter(LLUICtrl* ctrl); + void onTexturePickerMouseLeave(LLUICtrl* ctrl); + +private: + bool mIsNew; +}; #endif // LL_LLPANELCLASSIFIED_H diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 88aad4923d..7b5b232ad2 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -2383,12 +2383,8 @@ BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root) void LLPanelGroupActionsSubTab::activate() { LLPanelGroupSubTab::activate(); - lldebugs << "LLPanelGroupActionsSubTab::activate()" << llendl; - mActionList->deselectAllItems(); - mActionMembers->deleteAllItems(); - mActionRoles->deleteAllItems(); - mActionDescription->clear(); + update(GC_ALL); } void LLPanelGroupActionsSubTab::deactivate() diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index c9168670d5..9cd949c9cc 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -86,14 +86,20 @@ void LLPanelChatControlPanel::draw() bool session_initialized = session->mSessionInitialized; bool callback_enabled = session->mCallBackEnabled; - LLViewerRegion* region = gAgent.getRegion(); - BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "") - && session_initialized + BOOL enable_connect = session_initialized && voice_enabled && callback_enabled; childSetEnabled("call_btn", enable_connect); + // send a signal when the floater is fully initialized + // this lets LLAvatarActions::startAdhocCall() start the call + if (enable_connect && !mInitialized) + { + LLIMModel::sendSessionInitialized(mSessionId); + mInitialized = true; + } + LLPanel::draw(); } @@ -168,14 +174,26 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID); - // Fetch the currect name - gCacheName->get(mAvatarID, FALSE, boost::bind(&LLPanelIMControlPanel::nameUpdatedCallback, this, _1, _2, _3, _4)); - - // Disable profile button if participant is not realy SL avatar + // Disable most profile buttons if the participant is + // not really an SL avatar (e.g., an Avaline caller). LLIMModel::LLIMSession* im_session = im_model.findIMSession(session_id); if( im_session && !im_session->mOtherParticipantIsAvatar ) + { childSetEnabled("view_profile_btn", FALSE); + childSetEnabled("add_friend_btn", FALSE); + + childSetEnabled("share_btn", FALSE); + childSetEnabled("teleport_btn", FALSE); + childSetEnabled("pay_btn", FALSE); + + getChild<LLTextBox>("avatar_name")->setValue(im_session->mName);
+ } + else + { + // If the participant is an avatar, fetch the currect name + gCacheName->get(mAvatarID, FALSE, boost::bind(&LLPanelIMControlPanel::nameUpdatedCallback, this, _1, _2, _3, _4)); + } } void LLPanelIMControlPanel::nameUpdatedCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group) @@ -190,7 +208,8 @@ void LLPanelIMControlPanel::nameUpdatedCallback(const LLUUID& id, const std::str } } -LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id) +LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): +mParticipantList(NULL) { mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id); } @@ -199,9 +218,6 @@ BOOL LLPanelGroupControlPanel::postBuild() { childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this)); - mAvatarList = getChild<LLAvatarList>("speakers_list"); - mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList); - return LLPanelChatControlPanel::postBuild(); } @@ -214,6 +230,8 @@ LLPanelGroupControlPanel::~LLPanelGroupControlPanel() // virtual void LLPanelGroupControlPanel::draw() { + //Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update() + //so we need update it to raise needed event mSpeakerManager->update(true); LLPanelChatControlPanel::draw(); } @@ -241,7 +259,7 @@ void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) { LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state); - mAvatarList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED); + mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED); } void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) @@ -249,6 +267,9 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) LLPanelChatControlPanel::setSessionId(session_id); mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id); + + if(!mParticipantList) + mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list")); } @@ -258,9 +279,7 @@ LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLP BOOL LLPanelAdHocControlPanel::postBuild() { - mAvatarList = getChild<LLAvatarList>("speakers_list"); - mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList); - + //We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat return LLPanelChatControlPanel::postBuild(); } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index ac5d86345e..923c5acbd2 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -43,7 +43,9 @@ class LLParticipantList; class LLPanelChatControlPanel : public LLPanel { public: - LLPanelChatControlPanel() {}; + LLPanelChatControlPanel() : + mSessionId(LLUUID()), + mInitialized(false) {}; ~LLPanelChatControlPanel() {}; virtual BOOL postBuild(); @@ -59,6 +61,7 @@ public: private: LLUUID mSessionId; + bool mInitialized; }; @@ -100,7 +103,7 @@ public: protected: LLUUID mGroupID; LLSpeakerMgr* mSpeakerManager; - LLAvatarList* mAvatarList; + LLParticipantList* mParticipantList; private: diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 4985663833..f94a59ecef 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -35,6 +35,7 @@ #include "llpanellandmarkinfo.h" #include "llcombobox.h" +#include "lliconctrl.h" #include "lllineeditor.h" #include "lltextbox.h" #include "lltexteditor.h" @@ -58,6 +59,11 @@ static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); static LLRegisterPanelClassWrapper<LLPanelLandmarkInfo> t_landmark_info("panel_landmark_info"); +// Statics for textures filenames +static std::string icon_pg; +static std::string icon_m; +static std::string icon_r; + LLPanelLandmarkInfo::LLPanelLandmarkInfo() : LLPanelPlaceInfo() {} @@ -79,6 +85,10 @@ BOOL LLPanelLandmarkInfo::postBuild() mNotesEditor = getChild<LLTextEditor>("notes_editor"); mFolderCombo = getChild<LLComboBox>("folder_combo"); + icon_pg = getString("icon_PG"); + icon_m = getString("icon_M"); + icon_r = getString("icon_R"); + return TRUE; } @@ -101,9 +111,8 @@ void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type) LLPanel* landmark_info_panel = getChild<LLPanel>("landmark_info_panel"); bool is_info_type_create_landmark = type == CREATE_LANDMARK; - bool is_info_type_landmark = type == LANDMARK; - landmark_info_panel->setVisible(is_info_type_landmark); + landmark_info_panel->setVisible(type == LANDMARK); getChild<LLTextBox>("folder_label")->setVisible(is_info_type_create_landmark); mFolderCombo->setVisible(is_info_type_create_landmark); @@ -136,6 +145,24 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) { LLPanelPlaceInfo::processParcelInfo(parcel_data); + // HACK: Flag 0x2 == adult region, + // Flag 0x1 == mature region, otherwise assume PG + if (parcel_data.flags & 0x2) + { + mMaturityRatingIcon->setValue(icon_r); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT)); + } + else if (parcel_data.flags & 0x1) + { + mMaturityRatingIcon->setValue(icon_m); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE)); + } + else + { + mMaturityRatingIcon->setValue(icon_pg); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); + } + S32 region_x; S32 region_y; S32 region_z; diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 15a75cb930..e3b2ab77aa 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -204,11 +204,6 @@ void LLPanelMainInventory::initListCommandsHandlers() mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
- /*
- mListCommands->getChild<LLButton>("add_btn")->setHeldDownCallback(boost::bind(&LLPanelMainInventory::onAddButtonHeldDown, this));
- static const LLSD add_landmark_command("add_landmark");
- mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddAction, this, add_landmark_command));
- */
LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index a6083a5755..2bbb2b7153 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -60,6 +60,7 @@ #include "llviewermenu.h" // for gMenuHolder #include "llvoiceclient.h" #include "llworld.h" +#include "llspeakers.h" #define FRIEND_LIST_UPDATE_TIMEOUT 0.5 #define NEARBY_LIST_UPDATE_INTERVAL 1 @@ -119,8 +120,84 @@ protected: } }; +/** Compares avatar items by distance between you and them */ +class LLAvatarItemDistanceComparator : public LLAvatarItemComparator +{ +public: + typedef std::map < LLUUID, LLVector3d > id_to_pos_map_t; + LLAvatarItemDistanceComparator() {}; + + void updateAvatarsPositions(std::vector<LLVector3d>& positions, std::vector<LLUUID>& uuids) + { + std::vector<LLVector3d>::const_iterator + pos_it = positions.begin(), + pos_end = positions.end(); + + std::vector<LLUUID>::const_iterator + id_it = uuids.begin(), + id_end = uuids.end(); + + LLAvatarItemDistanceComparator::id_to_pos_map_t pos_map; + + mAvatarsPositions.clear(); + + for (;pos_it != pos_end && id_it != id_end; ++pos_it, ++id_it ) + { + mAvatarsPositions[*id_it] = *pos_it; + } + }; + +protected: + virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const + { + const LLVector3d& me_pos = gAgent.getPositionGlobal(); + const LLVector3d& item1_pos = mAvatarsPositions.find(item1->getAvatarId())->second; + const LLVector3d& item2_pos = mAvatarsPositions.find(item2->getAvatarId())->second; + F32 dist1 = dist_vec(item1_pos, me_pos); + F32 dist2 = dist_vec(item2_pos, me_pos); + return dist1 < dist2; + } +private: + id_to_pos_map_t mAvatarsPositions; +}; + +/** Comparator for comparing nearby avatar items by last spoken time */ +class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator +{ +public: + LLAvatarItemRecentSpeakerComparator() {}; + virtual ~LLAvatarItemRecentSpeakerComparator() {}; + +protected: + virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const + { + LLPointer<LLSpeaker> lhs = LLLocalSpeakerMgr::instance().findSpeaker(item1->getAvatarId()); + LLPointer<LLSpeaker> rhs = LLLocalSpeakerMgr::instance().findSpeaker(item2->getAvatarId()); + if ( lhs.notNull() && rhs.notNull() ) + { + // Compare by last speaking time + if( lhs->mLastSpokeTime != rhs->mLastSpokeTime ) + return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime ); + } + else if ( lhs.notNull() ) + { + // True if only item1 speaker info available + return true; + } + else if ( rhs.notNull() ) + { + // False if only item2 speaker info available + return false; + } + // By default compare by name. + return LLAvatarItemNameComparator::doCompare(item1, item2); + } +}; + static const LLAvatarItemRecentComparator RECENT_COMPARATOR; static const LLAvatarItemStatusComparator STATUS_COMPARATOR; +static LLAvatarItemDistanceComparator DISTANCE_COMPARATOR; +static const LLAvatarItemRecentSpeakerComparator RECENT_SPEAKER_COMPARATOR; static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people"); @@ -432,9 +509,12 @@ BOOL LLPanelPeople::postBuild() mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false); setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false); + setSortOrder(mNearbyList, (ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"), false); LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME); groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); @@ -495,7 +575,8 @@ BOOL LLPanelPeople::postBuild() enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2)); enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2)); - + enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2)); + LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGroupPlusMenuHandle = plus_menu->getHandle(); @@ -574,8 +655,13 @@ void LLPanelPeople::updateNearbyList() if (!mNearbyList) return; - LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + std::vector<LLVector3d> positions; + + LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); mNearbyList->setDirty(); + + DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); + LLLocalSpeakerMgr::instance().update(TRUE); } void LLPanelPeople::updateRecentList() @@ -608,6 +694,12 @@ void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_si button->setClickedCallback(cb); } +bool LLPanelPeople::isFriendOnline(const LLUUID& id) +{ + LLAvatarList::uuid_vector_t ids = mOnlineFriendList->getIDs(); + return std::find(ids.begin(), ids.end(), id) != ids.end(); +} + void LLPanelPeople::updateButtons() { std::string cur_tab = getActiveTabName(); @@ -660,10 +752,10 @@ void LLPanelPeople::updateButtons() childSetEnabled("add_friend_btn", !is_friend); } - buttonSetEnabled("teleport_btn", friends_tab_active && item_selected); + 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", item_selected); + buttonSetEnabled("call_btn", multiple_selected); buttonSetEnabled("share_btn", item_selected && false); // not implemented yet bool none_group_selected = item_selected && selected_id.isNull(); @@ -758,6 +850,14 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save list->setComparator(&RECENT_COMPARATOR); list->sort(); break; + case E_SORT_BY_RECENT_SPEAKERS: + list->setComparator(&RECENT_SPEAKER_COMPARATOR); + list->sort(); + break; + case E_SORT_BY_DISTANCE: + list->setComparator(&DISTANCE_COMPARATOR); + list->sort(); + break; default: llwarns << "Unrecognized people sort order for " << list->getName() << llendl; return; @@ -772,7 +872,7 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save else if (list == mRecentList) setting = "RecentPeopleSortOrder"; else if (list == mNearbyList) - setting = "NearbyPeopleSortOrder"; // *TODO: unused by current implementation + setting = "NearbyPeopleSortOrder"; if (!setting.empty()) gSavedSettings.setU32(setting, order); @@ -1008,12 +1108,13 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) { std::string chosen_item = userdata.asString(); - if (chosen_item == "sort_recent") + if (chosen_item == "sort_by_recent_speakers") { + setSortOrder(mNearbyList, E_SORT_BY_RECENT_SPEAKERS); } else if (chosen_item == "sort_name") { - mNearbyList->sortByName(); + setSortOrder(mNearbyList, E_SORT_BY_NAME); } else if (chosen_item == "view_icons") { @@ -1021,8 +1122,25 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) } else if (chosen_item == "sort_distance") { + setSortOrder(mNearbyList, E_SORT_BY_DISTANCE); } } + +bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) +{ + std::string item = userdata.asString(); + U32 sort_order = gSavedSettings.getU32("NearbyPeopleSortOrder"); + + if (item == "sort_by_recent_speakers") + return sort_order == E_SORT_BY_RECENT_SPEAKERS; + if (item == "sort_name") + return sort_order == E_SORT_BY_NAME; + if (item == "sort_distance") + return sort_order == E_SORT_BY_DISTANCE; + + return false; +} + void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata) { std::string chosen_item = userdata.asString(); @@ -1079,7 +1197,8 @@ void LLPanelPeople::onCallButtonClicked() } else if (selected_uuids.size() > 1) { - // *NOTE: ad-hoc voice chat not implemented yet + // initiate an ad-hoc voice chat with multiple users + LLAvatarActions::startAdhocCall(selected_uuids); } } diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 9bf9befe90..a369bcd3e2 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -62,6 +62,8 @@ private: E_SORT_BY_NAME = 0, E_SORT_BY_STATUS = 1, E_SORT_BY_MOST_RECENT = 2, + E_SORT_BY_DISTANCE = 3, + E_SORT_BY_RECENT_SPEAKERS = 4, } ESortOrder; // methods indirectly called by the updaters @@ -69,6 +71,8 @@ private: void updateNearbyList(); void updateRecentList(); + bool isFriendOnline(const LLUUID& id); + void updateButtons(); std::string getActiveTabName() const; LLUUID getCurrentItemID() const; @@ -115,6 +119,7 @@ private: bool onFriendsViewSortMenuItemCheck(const LLSD& userdata); bool onRecentViewSortMenuItemCheck(const LLSD& userdata); + bool onNearbyViewSortMenuItemCheck(const LLSD& userdata); // misc callbacks static void onAvatarPicked( diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index f5c4f89702..da0c8d5020 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -440,7 +440,8 @@ void LLPanelPickEdit::resetDirty() BOOL LLPanelPickEdit::isDirty() const { - if( LLPanelPickInfo::isDirty() + if( mNewPick + || LLPanelPickInfo::isDirty() || mLocationChanged || mSnapshotCtrl->isDirty() || getChild<LLLineEditor>("pick_name")->isDirty() diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 2bf04f9681..6905c7e546 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -45,11 +45,14 @@ #include "llviewermenu.h" #include "llregistry.h" +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" #include "llpanelpicks.h" #include "llavatarpropertiesprocessor.h" #include "llpanelavatar.h" #include "llpanelprofile.h" #include "llpanelpick.h" +#include "llpanelclassified.h" static const std::string XML_BTN_NEW = "new_btn"; static const std::string XML_BTN_DELETE = "trash_btn"; @@ -62,9 +65,40 @@ static const std::string PICK_ID("pick_id"); static const std::string PICK_CREATOR_ID("pick_creator_id"); static const std::string PICK_NAME("pick_name"); +static const std::string CLASSIFIED_ID("classified_id"); +static const std::string CLASSIFIED_NAME("classified_name"); + static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks"); +////////////////////////////////////////////////////////////////////////// + +/** + * Copy&Pasted from old LLPanelClassified. This class does nothing at the moment. + * Subscribing to "classifiedclickthrough" removes a few warnings. + */ +class LLClassifiedClickThrough : public LLDispatchHandler +{ +public: + + // "classifiedclickthrough" + // strings[0] = classified_id + // strings[1] = teleport_clicks + // strings[2] = map_clicks + // strings[3] = profile_clicks + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) + { + if (strings.size() != 4) + return false; + + return true; + } +}; + //----------------------------------------------------------------------------- // LLPanelPicks //----------------------------------------------------------------------------- @@ -74,10 +108,19 @@ LLPanelPicks::LLPanelPicks() mProfilePanel(NULL), mPickPanel(NULL), mPicksList(NULL), + mClassifiedsList(NULL), mPanelPickInfo(NULL), mPanelPickEdit(NULL), - mOverflowMenu(NULL) + mOverflowMenu(NULL), + mPlusMenu(NULL), + mPicksAccTab(NULL), + mClassifiedsAccTab(NULL), + mPanelClassifiedInfo(NULL), + mPanelClassifiedEdit(NULL), + mClickThroughDisp(NULL) { + mClickThroughDisp = new LLClassifiedClickThrough(); + gGenericDispatcher.addHandler("classifiedclickthrough", mClickThroughDisp); } LLPanelPicks::~LLPanelPicks() @@ -86,6 +129,8 @@ LLPanelPicks::~LLPanelPicks() { LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); } + + delete mClickThroughDisp; } void* LLPanelPicks::create(void* data /* = NULL */) @@ -100,6 +145,9 @@ void LLPanelPicks::updateData() { mPicksList->clear(); LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); + + mClassifiedsList->clear(); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId()); } } @@ -138,13 +186,47 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) mPicksList->addItem(picture, pick_value); - picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1)); + picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickPickItem, this, _1)); picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); } + showAccordion("tab_picks", mPicksList->size()); + + resetDirty(); + updateButtons(); + } + } + else if(APT_CLASSIFIEDS == type) + { + LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data); + if(c_info && getAvatarId() == c_info->target_id) + { + mClassifiedsList->clear(); + + LLAvatarClassifieds::classifieds_list_t::const_iterator it = c_info->classifieds_list.begin(); + for(; c_info->classifieds_list.end() != it; ++it) + { + LLAvatarClassifieds::classified_data c_data = *it; + + LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), c_data.classified_id); + c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); + c_item->setClassifiedName(c_data.name); + + LLSD pick_value = LLSD(); + pick_value.insert(CLASSIFIED_ID, c_data.classified_id); + pick_value.insert(CLASSIFIED_NAME, c_data.name); + + mClassifiedsList->addItem(c_item, pick_value); + + c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); + c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); + c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); + } + + showAccordion("tab_classifieds", mClassifiedsList->size()); + resetDirty(); - LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); updateButtons(); } } @@ -158,16 +240,44 @@ LLPickItem* LLPanelPicks::getSelectedPickItem() return dynamic_cast<LLPickItem*>(selected_item); } +LLClassifiedItem* LLPanelPicks::getSelectedClassifiedItem() +{ + LLPanel* selected_item = mClassifiedsList->getSelectedItem(); + if (!selected_item) + { + return NULL; + } + return dynamic_cast<LLClassifiedItem*>(selected_item); +} + BOOL LLPanelPicks::postBuild() { mPicksList = getChild<LLFlatListView>("picks_list"); + mClassifiedsList = getChild<LLFlatListView>("classifieds_list"); + + mPicksList->setCommitOnSelectionChange(true); + mClassifiedsList->setCommitOnSelectionChange(true); + + mPicksList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mPicksList)); + mClassifiedsList->setCommitCallback(boost::bind(&LLPanelPicks::onListCommit, this, mClassifiedsList)); + + mPicksList->setNoItemsCommentText(getString("no_picks")); + mClassifiedsList->setNoItemsCommentText(getString("no_classifieds")); - childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickNew, this)); + childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickPlusBtn, this)); childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this)); childSetAction(XML_BTN_TELEPORT, boost::bind(&LLPanelPicks::onClickTeleport, this)); childSetAction(XML_BTN_SHOW_ON_MAP, boost::bind(&LLPanelPicks::onClickMap, this)); childSetAction(XML_BTN_INFO, boost::bind(&LLPanelPicks::onClickInfo, this)); childSetAction(XML_BTN_OVERFLOW, boost::bind(&LLPanelPicks::onOverflowButtonClicked, this)); + + mPicksAccTab = getChild<LLAccordionCtrlTab>("tab_picks"); + mPicksAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mPicksAccTab)); + mPicksAccTab->setDisplayChildren(true); + + mClassifiedsAccTab = getChild<LLAccordionCtrlTab>("tab_classifieds"); + mClassifiedsAccTab->setDropDownStateChangedCallback(boost::bind(&LLPanelPicks::onAccordionStateChanged, this, mClassifiedsAccTab)); + mClassifiedsAccTab->setDisplayChildren(false); LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; registar.add("Pick.Info", boost::bind(&LLPanelPicks::onClickInfo, this)); @@ -180,6 +290,10 @@ BOOL LLPanelPicks::postBuild() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar overflow_registar; overflow_registar.add("PicksList.Overflow", boost::bind(&LLPanelPicks::onOverflowMenuItemClicked, this, _2)); mOverflowMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar plus_registar; + plus_registar.add("Picks.Plus.Action", boost::bind(&LLPanelPicks::onPlusMenuItemClicked, this, _2)); + mPlusMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); return TRUE; } @@ -202,6 +316,34 @@ void LLPanelPicks::onOverflowMenuItemClicked(const LLSD& param) } } +void LLPanelPicks::onPlusMenuItemClicked(const LLSD& param) +{ + std::string value = param.asString(); + + if("new_pick" == value) + { + createNewPick(); + } + else if("new_classified" == value) + { + createNewClassified(); + } +} + +void LLPanelPicks::onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab) +{ + if(!mPicksAccTab->getDisplayChildren()) + { + mPicksList->resetSelection(true); + } + if(!mClassifiedsAccTab->getDisplayChildren()) + { + mClassifiedsList->resetSelection(true); + } + + updateButtons(); +} + void LLPanelPicks::onOverflowButtonClicked() { LLRect rect; @@ -242,6 +384,9 @@ void LLPanelPicks::onOpen(const LLSD& key) if(getAvatarId() != id) { + showAccordion("tab_picks", false); + showAccordion("tab_classifieds", false); + mPicksList->goToTop(); // Set dummy value to make panel dirty and make it reload picks setValue(LLSD()); @@ -250,21 +395,50 @@ void LLPanelPicks::onOpen(const LLSD& key) LLPanelProfileTab::onOpen(key); } +void LLPanelPicks::onListCommit(const LLFlatListView* f_list) +{ + // Make sure only one of the lists has selection. + if(f_list == mPicksList) + { + mClassifiedsList->resetSelection(true); + } + else if(f_list == mClassifiedsList) + { + mPicksList->resetSelection(true); + } + else + { + llwarns << "Unknown list" << llendl; + } + + updateButtons(); +} + //static void LLPanelPicks::onClickDelete() { - LLSD pick_value = mPicksList->getSelectedValue(); - if (pick_value.isUndefined()) return; + LLSD value = mPicksList->getSelectedValue(); + if (value.isDefined()) + { + LLSD args; + args["PICK"] = value[PICK_NAME]; + LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeletePick, this, _1, _2)); + return; + } - LLSD args; - args["PICK"] = pick_value[PICK_NAME]; - LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDelete, this, _1, _2)); + value = mClassifiedsList->getSelectedValue(); + if(value.isDefined()) + { + LLSD args; + args["NAME"] = value[CLASSIFIED_NAME]; + LLNotifications::instance().add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackDeleteClassified, this, _1, _2)); + return; + } } -bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response) +bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); - LLSD pick_value = mPicksList->getSelectedValue(); if (0 == option) @@ -276,6 +450,20 @@ bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response return false; } +bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLSD value = mClassifiedsList->getSelectedValue(); + + if (0 == option) + { + LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]); + mClassifiedsList->removeItemByValue(value); + } + updateButtons(); + return false; +} + bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& response ) { S32 option = LLNotification::getSelectedOption(notification, response); @@ -291,9 +479,14 @@ bool LLPanelPicks::callbackTeleport( const LLSD& notification, const LLSD& respo void LLPanelPicks::onClickTeleport() { LLPickItem* pick_item = getSelectedPickItem(); - if (!pick_item) return; + LLClassifiedItem* c_item = getSelectedClassifiedItem(); + + LLVector3d pos; + if(pick_item) + pos = pick_item->getPosGlobal(); + else if(c_item) + pos = c_item->getPosGlobal(); - LLVector3d pos = pick_item->getPosGlobal(); if (!pos.isExactlyZero()) { gAgent.teleportViaLocation(pos); @@ -305,9 +498,15 @@ void LLPanelPicks::onClickTeleport() void LLPanelPicks::onClickMap() { LLPickItem* pick_item = getSelectedPickItem(); - if (!pick_item) return; + LLClassifiedItem* c_item = getSelectedClassifiedItem(); + + LLVector3d pos; + if (pick_item) + pos = pick_item->getPosGlobal(); + else if(c_item) + pos = c_item->getPosGlobal(); - LLFloaterWorldMap::getInstance()->trackLocation(pick_item->getPosGlobal()); + LLFloaterWorldMap::getInstance()->trackLocation(pos); LLFloaterReg::showInstance("world_map", "center"); } @@ -325,7 +524,7 @@ void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask) } } -void LLPanelPicks::onDoubleClickItem(LLUICtrl* item) +void LLPanelPicks::onDoubleClickPickItem(LLUICtrl* item) { LLSD pick_value = mPicksList->getSelectedValue(); if (pick_value.isUndefined()) return; @@ -335,9 +534,19 @@ void LLPanelPicks::onDoubleClickItem(LLUICtrl* item) LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2)); } +void LLPanelPicks::onDoubleClickClassifiedItem(LLUICtrl* item) +{ + LLSD value = mClassifiedsList->getSelectedValue(); + if (value.isUndefined()) return; + + LLSD args; + args["CLASSIFIED"] = value[CLASSIFIED_NAME]; + LLNotifications::instance().add("TeleportToClassified", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2)); +} + void LLPanelPicks::updateButtons() { - bool has_selected = mPicksList->numSelected(); + bool has_selected = mPicksList->numSelected() > 0 || mClassifiedsList->numSelected() > 0; if (getAvatarId() == gAgentID) { @@ -366,15 +575,44 @@ void LLPanelPicks::buildPickPanel() // } } -void LLPanelPicks::onClickNew() +void LLPanelPicks::onClickPlusBtn() +{ + LLRect rect; + childGetRect(XML_BTN_NEW, rect); + + mPlusMenu->updateParent(LLMenuGL::sMenuContainer); + mPlusMenu->setButtonRect(rect, this); + LLMenuGL::showPopup(this, mPlusMenu, rect.mLeft, rect.mTop); +} + +void LLPanelPicks::createNewPick() { createPickEditPanel(); getProfilePanel()->openPanel(mPanelPickEdit, LLSD()); } +void LLPanelPicks::createNewClassified() +{ + createClassifiedEditPanel(); + + getProfilePanel()->openPanel(mPanelClassifiedEdit, LLSD()); +} + void LLPanelPicks::onClickInfo() { + if(mPicksList->numSelected() > 0) + { + openPickInfo(); + } + else if(mClassifiedsList->numSelected() > 0) + { + openClassifiedInfo(); + } +} + +void LLPanelPicks::openPickInfo() +{ LLSD selected_value = mPicksList->getSelectedValue(); if (selected_value.isUndefined()) return; @@ -392,6 +630,33 @@ void LLPanelPicks::onClickInfo() getProfilePanel()->openPanel(mPanelPickInfo, params); } +void LLPanelPicks::openClassifiedInfo() +{ + LLSD selected_value = mClassifiedsList->getSelectedValue(); + if (selected_value.isUndefined()) return; + + LLClassifiedItem* c_item = getSelectedClassifiedItem(); + + createClassifiedInfoPanel(); + + LLSD params; + params["classified_id"] = c_item->getClassifiedId(); + params["avatar_id"] = c_item->getAvatarId(); + params["snapshot_id"] = c_item->getSnapshotId(); + params["name"] = c_item->getClassifiedName(); + params["desc"] = c_item->getDescription(); + + getProfilePanel()->openPanel(mPanelClassifiedInfo, params); +} + +void LLPanelPicks::showAccordion(const std::string& name, bool show) +{ + LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name); + tab->setVisible(show); + LLAccordionCtrl* acc = getChild<LLAccordionCtrl>("accordion"); + acc->arrange(); +} + void LLPanelPicks::onPanelPickClose(LLPanel* panel) { panel->setVisible(FALSE); @@ -403,6 +668,65 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel) updateButtons(); } +void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel) +{ + if(panel->isNew()) + { + LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); + + c_item->setClassifiedName(panel->getClassifiedName()); + c_item->setDescription(panel->getDescription()); + c_item->setSnapshotId(panel->getSnapshotId()); + + LLSD c_value; + c_value.insert(CLASSIFIED_ID, c_item->getClassifiedId()); + c_value.insert(CLASSIFIED_NAME, c_item->getClassifiedName()); + mClassifiedsList->addItem(c_item, c_value, ADD_TOP); + + c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); + c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); + c_item->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); + c_item->childSetAction("info_chevron", boost::bind(&LLPanelPicks::onClickInfo, this)); + + // order does matter, showAccordion will invoke arrange for accordions. + mClassifiedsAccTab->changeOpenClose(false); + showAccordion("tab_classifieds", true); + } + else + { + onPanelClassifiedClose(panel); + return; + } + + onPanelPickClose(panel); + updateButtons(); +} + +void LLPanelPicks::onPanelClassifiedClose(LLPanelClassifiedInfo* panel) +{ + if(panel->getInfoLoaded() && !panel->isDirty()) + { + std::vector<LLSD> values; + mClassifiedsList->getValues(values); + for(size_t n = 0; n < values.size(); ++n) + { + LLUUID c_id = values[n][CLASSIFIED_ID].asUUID(); + if(panel->getClassifiedId() == c_id) + { + LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>( + mClassifiedsList->getItemByValue(values[n])); + + c_item->setClassifiedName(panel->getClassifiedName()); + c_item->setDescription(panel->getDescription()); + c_item->setSnapshotId(panel->getSnapshotId()); + } + } + } + + onPanelPickClose(panel); + updateButtons(); +} + void LLPanelPicks::createPickInfoPanel() { if(!mPanelPickInfo) @@ -414,6 +738,29 @@ void LLPanelPicks::createPickInfoPanel() } } +void LLPanelPicks::createClassifiedInfoPanel() +{ + if(!mPanelClassifiedInfo) + { + mPanelClassifiedInfo = LLPanelClassifiedInfo::create(); + mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo)); + mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelPicks::onPanelClassifiedEdit, this)); + mPanelClassifiedInfo->setVisible(FALSE); + } +} + +void LLPanelPicks::createClassifiedEditPanel() +{ + if(!mPanelClassifiedEdit) + { + mPanelClassifiedEdit = LLPanelClassifiedEdit::create(); + mPanelClassifiedEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedEdit)); + mPanelClassifiedEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, mPanelClassifiedEdit)); + mPanelClassifiedEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedEdit)); + mPanelClassifiedEdit->setVisible(FALSE); + } +} + void LLPanelPicks::createPickEditPanel() { if(!mPanelPickEdit) @@ -473,9 +820,38 @@ void LLPanelPicks::onPanelPickEdit() getProfilePanel()->openPanel(mPanelPickEdit, params); } +void LLPanelPicks::onPanelClassifiedEdit() +{ + LLSD selected_value = mClassifiedsList->getSelectedValue(); + if (selected_value.isUndefined()) + { + return; + } + + LLClassifiedItem* c_item = dynamic_cast<LLClassifiedItem*>(mClassifiedsList->getSelectedItem()); + + createClassifiedEditPanel(); + + LLSD params; + params["classified_id"] = c_item->getClassifiedId(); + params["avatar_id"] = c_item->getAvatarId(); + params["snapshot_id"] = c_item->getSnapshotId(); + params["name"] = c_item->getClassifiedName(); + params["desc"] = c_item->getDescription(); + + getProfilePanel()->openPanel(mPanelClassifiedEdit, params); +} + void LLPanelPicks::onClickMenuEdit() { - onPanelPickEdit(); + if(getSelectedPickItem()) + { + onPanelPickEdit(); + } + else if(getSelectedClassifiedItem()) + { + onPanelClassifiedEdit(); + } } inline LLPanelProfile* LLPanelPicks::getProfilePanel() @@ -610,3 +986,80 @@ void LLPickItem::setValue(const LLSD& value) if (!value.has("selected")) return; childSetVisible("selected_icon", value["selected"]); } + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id) + : LLPanel() + , mAvatarId(avatar_id) + , mClassifiedId(classified_id) +{ + LLUICtrlFactory::getInstance()->buildPanel(this,"panel_classifieds_list_item.xml"); + + LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); +} + +LLClassifiedItem::~LLClassifiedItem() +{ + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); +} + +void LLClassifiedItem::processProperties(void* data, EAvatarProcessorType type) +{ + if(APT_CLASSIFIED_INFO != type) + { + return; + } + + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if( !c_info || c_info->classified_id != getClassifiedId() ) + { + return; + } + + setClassifiedName(c_info->name); + setDescription(c_info->description); + setSnapshotId(c_info->snapshot_id); + setPosGlobal(c_info->pos_global); + + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); +} + +BOOL LLClassifiedItem::postBuild() +{ + setMouseEnterCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", true)); + setMouseLeaveCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", false)); + return TRUE; +} + +void LLClassifiedItem::setValue(const LLSD& value) +{ + if (!value.isMap()) return;; + if (!value.has("selected")) return; + childSetVisible("selected_icon", value["selected"]); +} + +void LLClassifiedItem::setClassifiedName(const std::string& name) +{ + childSetValue("name", name); +} + +void LLClassifiedItem::setDescription(const std::string& desc) +{ + childSetValue("description", desc); +} + +void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id) +{ + childSetValue("picture", snapshot_id); +} + +LLUUID LLClassifiedItem::getSnapshotId() +{ + return childGetValue("picture"); +} + +//EOF diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 5a2754ad10..4b90ea5048 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -40,6 +40,7 @@ #include "llpanelavatar.h" #include "llregistry.h" +class LLAccordionCtrlTab; class LLPanelProfile; class LLMessageSystem; class LLVector3d; @@ -47,10 +48,18 @@ class LLPanelProfileTab; class LLAgent; class LLMenuGL; class LLPickItem; +class LLClassifiedItem; class LLFlatListView; class LLPanelPickInfo; class LLPanelPickEdit; class LLToggleableMenu; +class LLPanelClassifiedInfo; +class LLPanelClassifiedEdit; +class LLClassifiedClickThrough; + +// *TODO +// Panel Picks has been consolidated with Classifieds (EXT-2095), give LLPanelPicks +// and corresponding files (cpp, h, xml) a new name. (new name is TBD at the moment) class LLPanelPicks : public LLPanelProfileTab @@ -71,6 +80,7 @@ public: // returns the selected pick item LLPickItem* getSelectedPickItem(); + LLClassifiedItem* getSelectedClassifiedItem(); //*NOTE top down approch when panel toggling is done only by // parent panels failed to work (picks related code was in me profile panel) @@ -83,41 +93,67 @@ private: void onOverflowMenuItemClicked(const LLSD& param); void onOverflowButtonClicked(); + void onPlusMenuItemClicked(const LLSD& param); + + void onListCommit(const LLFlatListView* f_list); + void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab); //------------------------------------------------ // Callbacks which require panel toggling //------------------------------------------------ - void onClickNew(); + void onClickPlusBtn(); void onClickInfo(); void onPanelPickClose(LLPanel* panel); void onPanelPickSave(LLPanel* panel); + void onPanelClassifiedSave(LLPanelClassifiedEdit* panel); + void onPanelClassifiedClose(LLPanelClassifiedInfo* panel); void onPanelPickEdit(); + void onPanelClassifiedEdit(); void onClickMenuEdit(); + void createNewPick(); + void createNewClassified(); + + void openPickInfo(); + void openClassifiedInfo(); + + void showAccordion(const std::string& name, bool show); + void buildPickPanel(); - bool callbackDelete(const LLSD& notification, const LLSD& response); + bool callbackDeletePick(const LLSD& notification, const LLSD& response); + bool callbackDeleteClassified(const LLSD& notification, const LLSD& response); bool callbackTeleport(const LLSD& notification, const LLSD& response); void updateButtons(); - virtual void onDoubleClickItem(LLUICtrl* item); + virtual void onDoubleClickPickItem(LLUICtrl* item); + virtual void onDoubleClickClassifiedItem(LLUICtrl* item); virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask); LLPanelProfile* getProfilePanel(); void createPickInfoPanel(); void createPickEditPanel(); -// void openPickEditPanel(LLPickItem* pick); -// void openPickInfoPanel(LLPickItem* pick); + void createClassifiedInfoPanel(); + void createClassifiedEditPanel(); LLMenuGL* mPopupMenu; LLPanelProfile* mProfilePanel; LLPanelPickInfo* mPickPanel; LLFlatListView* mPicksList; + LLFlatListView* mClassifiedsList; LLPanelPickInfo* mPanelPickInfo; + LLPanelClassifiedInfo* mPanelClassifiedInfo; + LLPanelClassifiedEdit* mPanelClassifiedEdit; LLPanelPickEdit* mPanelPickEdit; LLToggleableMenu* mOverflowMenu; + LLToggleableMenu* mPlusMenu; + + LLAccordionCtrlTab* mPicksAccTab; + LLAccordionCtrlTab* mClassifiedsAccTab; + + LLClassifiedClickThrough* mClickThroughDisp; }; class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver @@ -189,4 +225,48 @@ protected: std::string mSimName; }; +class LLClassifiedItem : public LLPanel, public LLAvatarPropertiesObserver +{ +public: + + LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id); + + virtual ~LLClassifiedItem(); + + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); + + /*virtual*/ BOOL postBuild(); + + /*virtual*/ void setValue(const LLSD& value); + + LLUUID getAvatarId() {return mAvatarId;} + + void setAvatarId(const LLUUID& avatar_id) {mAvatarId = avatar_id;} + + LLUUID getClassifiedId() {return mClassifiedId;} + + void setClassifiedId(const LLUUID& classified_id) {mClassifiedId = classified_id;} + + void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; } + + const LLVector3d& getPosGlobal() { return mPosGlobal; } + + void setClassifiedName (const std::string& name); + + std::string getClassifiedName() { return childGetValue("name").asString(); } + + void setDescription(const std::string& desc); + + std::string getDescription() { return childGetValue("description").asString(); } + + void setSnapshotId(const LLUUID& snapshot_id); + + LLUUID getSnapshotId(); + +private: + LLUUID mAvatarId; + LLUUID mClassifiedId; + LLVector3d mPosGlobal; +}; + #endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index c600651015..963d39de8a 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -40,7 +40,7 @@ #include "llsdutil_math.h" -#include "llscrollcontainer.h" +#include "lliconctrl.h" #include "lltextbox.h" #include "llagent.h" @@ -57,8 +57,7 @@ LLPanelPlaceInfo::LLPanelPlaceInfo() : LLPanel(), mParcelID(), mRequestedID(), - mPosRegion(), - mMinHeight(0) + mPosRegion() {} //virtual @@ -81,12 +80,9 @@ BOOL LLPanelPlaceInfo::postBuild() mParcelName = getChild<LLTextBox>("parcel_title"); mDescEditor = getChild<LLExpandableTextBox>("description"); + mMaturityRatingIcon = getChild<LLIconCtrl>("maturity_icon"); mMaturityRatingText = getChild<LLTextBox>("maturity_value"); - LLScrollContainer* scroll_container = getChild<LLScrollContainer>("place_scroll"); - scroll_container->setBorderVisible(FALSE); - mMinHeight = scroll_container->getScrolledViewRect().getHeight(); - return TRUE; } @@ -98,6 +94,7 @@ void LLPanelPlaceInfo::resetLocation() 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); @@ -204,20 +201,6 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) mDescEditor->setText(parcel_data.desc); } - // HACK: Flag 0x2 == adult region, - // Flag 0x1 == mature region, otherwise assume PG - std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG); - if (parcel_data.flags & 0x2) - { - rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT); - } - else if (parcel_data.flags & 0x1) - { - rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE); - } - - mMaturityRatingText->setValue(rating); - S32 region_x; S32 region_y; S32 region_z; diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index ec30397cff..133933a880 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -41,6 +41,7 @@ #include "llremoteparcelrequest.h" class LLExpandableTextBox; +class LLIconCtrl; class LLInventoryItem; class LLPanelPickEdit; class LLParcel; @@ -109,7 +110,6 @@ protected: LLUUID mRequestedID; LLVector3 mPosRegion; std::string mCurrentTitle; - S32 mMinHeight; INFO_TYPE mInfoType; LLTextBox* mTitle; @@ -117,6 +117,7 @@ protected: LLTextBox* mRegionName; LLTextBox* mParcelName; LLExpandableTextBox* mDescEditor; + LLIconCtrl* mMaturityRatingIcon; LLTextBox* mMaturityRatingText; }; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 2a9ba4697d..61501cc1b1 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -97,7 +97,6 @@ BOOL LLPanelPlaceProfile::postBuild() setMouseDownCallback(boost::bind(&LLPanelPlaceProfile::onForSaleBannerClick, this)); mParcelOwner = getChild<LLTextBox>("owner_value"); - mLastVisited = getChild<LLTextBox>("last_visited_value"); mParcelRatingIcon = getChild<LLIconCtrl>("rating_icon"); mParcelRatingText = getChild<LLTextBox>("rating_value"); @@ -165,7 +164,6 @@ void LLPanelPlaceProfile::resetLocation() std::string not_available = getString("not_available"); mParcelOwner->setValue(not_available); - mLastVisited->setValue(not_available); mParcelRatingIcon->setValue(not_available); mParcelRatingText->setText(not_available); @@ -209,17 +207,13 @@ void LLPanelPlaceProfile::resetLocation() void LLPanelPlaceProfile::setInfoType(INFO_TYPE type) { bool is_info_type_agent = type == AGENT; - bool is_info_type_teleport_history = type == TELEPORT_HISTORY; - getChild<LLTextBox>("maturity_label")->setVisible(!is_info_type_agent); + mMaturityRatingIcon->setVisible(!is_info_type_agent); mMaturityRatingText->setVisible(!is_info_type_agent); getChild<LLTextBox>("owner_label")->setVisible(is_info_type_agent); mParcelOwner->setVisible(is_info_type_agent); - getChild<LLTextBox>("last_visited_label")->setVisible(is_info_type_teleport_history); - mLastVisited->setVisible(is_info_type_teleport_history); - getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent); switch(type) @@ -238,6 +232,30 @@ void LLPanelPlaceProfile::setInfoType(INFO_TYPE type) LLPanelPlaceInfo::setInfoType(type); } +// virtual +void LLPanelPlaceProfile::processParcelInfo(const LLParcelData& parcel_data) +{ + LLPanelPlaceInfo::processParcelInfo(parcel_data); + + // HACK: Flag 0x2 == adult region, + // Flag 0x1 == mature region, otherwise assume PG + if (parcel_data.flags & 0x2) + { + mMaturityRatingIcon->setValue(icon_r); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT)); + } + else if (parcel_data.flags & 0x1) + { + mMaturityRatingIcon->setValue(icon_m); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE)); + } + else + { + mMaturityRatingIcon->setValue(icon_pg); + mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); + } +} + void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, LLViewerRegion* region, const LLVector3d& pos_global, @@ -521,22 +539,6 @@ void LLPanelPlaceProfile::updateCovenantText(const std::string &text) mCovenantText->setText(text); } -void LLPanelPlaceProfile::updateLastVisitedText(const LLDate &date) -{ - if (date.isNull()) - { - mLastVisited->setText(getString("unknown")); - } - else - { - std::string timeStr = getString("acquired_date"); - LLSD substitution; - substitution["datetime"] = (S32) date.secondsSinceEpoch(); - LLStringUtil::format (timeStr, substitution); - mLastVisited->setText(timeStr); - } -} - void LLPanelPlaceProfile::onForSaleBannerClick() { LLViewerParcelMgr* mgr = LLViewerParcelMgr::getInstance(); diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index b3ef4acf51..8c30ca92fb 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -50,6 +50,8 @@ public: /*virtual*/ void setInfoType(INFO_TYPE type); + /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); + // Displays information about the currently selected parcel // without sending a request to the server. // If is_current_parcel true shows "You Are Here" banner. @@ -61,7 +63,6 @@ public: void updateEstateName(const std::string& name); void updateEstateOwnerName(const std::string& name); void updateCovenantText(const std::string &text); - void updateLastVisitedText(const LLDate &date); private: void onForSaleBannerClick(); @@ -78,7 +79,6 @@ private: LLPanel* mYouAreHerePanel; LLTextBox* mParcelOwner; - LLTextBox* mLastVisited; LLIconCtrl* mParcelRatingIcon; LLTextBox* mParcelRatingText; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 8d117afcfe..3d0fba9426 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -293,7 +293,6 @@ void LLPanelPlaces::onOpen(const LLSD& key) mPosGlobal = hist_items[index].mGlobalPos; mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY); - mPlaceProfile->updateLastVisitedText(hist_items[index].mDate); mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal); } diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 5c3c260549..24de2dcdfc 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -118,21 +118,33 @@ LLPanelPrimMediaControls::~LLPanelPrimMediaControls() BOOL LLPanelPrimMediaControls::postBuild() { LLButton* scroll_up_ctrl = getChild<LLButton>("scrollup"); - scroll_up_ctrl->setClickedCallback(onScrollUp, this); - scroll_up_ctrl->setHeldDownCallback(onScrollUpHeld, this); - scroll_up_ctrl->setMouseUpCallback(onScrollStop, this); + if (scroll_up_ctrl) + { + scroll_up_ctrl->setClickedCallback(onScrollUp, this); + scroll_up_ctrl->setHeldDownCallback(onScrollUpHeld, this); + scroll_up_ctrl->setMouseUpCallback(onScrollStop, this); + } LLButton* scroll_left_ctrl = getChild<LLButton>("scrollleft"); - scroll_left_ctrl->setClickedCallback(onScrollLeft, this); - scroll_left_ctrl->setHeldDownCallback(onScrollLeftHeld, this); - scroll_left_ctrl->setMouseUpCallback(onScrollStop, this); + if (scroll_left_ctrl) + { + scroll_left_ctrl->setClickedCallback(onScrollLeft, this); + scroll_left_ctrl->setHeldDownCallback(onScrollLeftHeld, this); + scroll_left_ctrl->setMouseUpCallback(onScrollStop, this); + } LLButton* scroll_right_ctrl = getChild<LLButton>("scrollright"); - scroll_right_ctrl->setClickedCallback(onScrollRight, this); - scroll_right_ctrl->setHeldDownCallback(onScrollRightHeld, this); - scroll_right_ctrl->setMouseUpCallback(onScrollStop, this); + if (scroll_right_ctrl) + { + scroll_right_ctrl->setClickedCallback(onScrollRight, this); + scroll_right_ctrl->setHeldDownCallback(onScrollRightHeld, this); + scroll_right_ctrl->setMouseUpCallback(onScrollStop, this); + } LLButton* scroll_down_ctrl = getChild<LLButton>("scrolldown"); - scroll_down_ctrl->setClickedCallback(onScrollDown, this); - scroll_down_ctrl->setHeldDownCallback(onScrollDownHeld, this); - scroll_down_ctrl->setMouseUpCallback(onScrollStop, this); + if (scroll_down_ctrl) + { + scroll_down_ctrl->setClickedCallback(onScrollDown, this); + scroll_down_ctrl->setHeldDownCallback(onScrollDownHeld, this); + scroll_down_ctrl->setMouseUpCallback(onScrollStop, this); + } LLUICtrl* media_address = getChild<LLUICtrl>("media_address"); media_address->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this )); @@ -326,11 +338,14 @@ void LLPanelPrimMediaControls::updateShape() whitelist_icon->setVisible(false); secure_lock_icon->setVisible(false); - scroll_up_ctrl->setVisible(false); - scroll_left_ctrl->setVisible(false); - scroll_right_ctrl->setVisible(false); - scroll_down_ctrl->setVisible(false); - media_panel_scroll->setVisible(false); + if (media_panel_scroll) + { + media_panel_scroll->setVisible(false); + scroll_up_ctrl->setVisible(false); + scroll_left_ctrl->setVisible(false); + scroll_right_ctrl->setVisible(false); + scroll_down_ctrl->setVisible(false); + } F32 volume = media_impl->getVolume(); // movie's url changed @@ -422,12 +437,15 @@ void LLPanelPrimMediaControls::updateShape() volume_ctrl->setEnabled(FALSE); volume_up_ctrl->setEnabled(FALSE); volume_down_ctrl->setEnabled(FALSE); - - scroll_up_ctrl->setVisible(has_focus); - scroll_left_ctrl->setVisible(has_focus); - scroll_right_ctrl->setVisible(has_focus); - scroll_down_ctrl->setVisible(has_focus); - media_panel_scroll->setVisible(has_focus); + + if (media_panel_scroll) + { + media_panel_scroll->setVisible(has_focus); + scroll_up_ctrl->setVisible(has_focus); + scroll_left_ctrl->setVisible(has_focus); + scroll_right_ctrl->setVisible(has_focus); + scroll_down_ctrl->setVisible(has_focus); + } // TODO: get the secure lock bool from media plug in std::string prefix = std::string("https://"); std::string test_prefix = mCurrentURL.substr(0, prefix.length()); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 8147ff17f0..02f45c1b48 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -243,5 +243,6 @@ void LLPanelProfile::notifyParent(const LLSD& info) onOpen(info); return; } + LLPanel::notifyParent(info); } diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 2be0781487..f5367c0477 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -36,10 +36,12 @@ #include "lltrans.h" #include "llavataractions.h" #include "llagent.h" +#include "llimview.h" #include "llparticipantlist.h" #include "llavatarlist.h" #include "llspeakers.h" +#include "llviewermenu.h" //LLParticipantList retrieves add, clear and remove events and updates view accordingly #if LL_MSVC @@ -64,6 +66,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); + mParticipantListMenu = new LLParticipantListMenu(*this); + mAvatarList->setContextMenu(mParticipantListMenu); + //Lets fill avatarList with existing speakers LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); @@ -83,8 +88,15 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av LLParticipantList::~LLParticipantList() { + delete mParticipantListMenu; + mParticipantListMenu = NULL; } +void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible) +{ + mAvatarList->setSpeakingIndicatorsVisible(visible); +}; + void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list) { LLUUID clicked_id = list->getSelectedUUID(); @@ -265,3 +277,139 @@ bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LL { return mParent.onModeratorUpdateEvent(event, userdata); } + +LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() +{ + // set up the callbacks for all of the avatar menu items + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2)); + registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2)); + + enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem, this, _2)); + enable_registrar.add("ParticipantList.CheckItem", boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem, this, _2)); + + // create the context menu from the XUI + return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( + "menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); +} + +void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) +{ + const LLUUID speaker_id = mUUIDs.front(); + + std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); + LLSD data; + data["method"] = "mute update"; + data["session-id"] = mParent.mSpeakerMgr->getSessionID(); + data["params"] = LLSD::emptyMap(); + data["params"]["agent_id"] = speaker_id; + data["params"]["mute_info"] = LLSD::emptyMap(); + //current value represents ability to type, so invert + data["params"]["mute_info"]["text"] = !mParent.mSpeakerMgr->findSpeaker(speaker_id)->mModeratorMutedText; + + class MuteTextResponder : public LLHTTPClient::Responder + { + public: + MuteTextResponder(const LLUUID& session_id) + { + mSessionID = session_id; + } + + virtual void error(U32 status, const std::string& reason) + { + llwarns << status << ": " << reason << llendl; + + if ( gIMMgr ) + { + //403 == you're not a mod + //should be disabled if you're not a moderator + if ( 403 == status ) + { + gIMMgr->showSessionEventError( + "mute", + "not_a_moderator", + mSessionID); + } + else + { + gIMMgr->showSessionEventError( + "mute", + "generic", + mSessionID); + } + } + } + + private: + LLUUID mSessionID; + }; + + LLHTTPClient::post( + url, + data, + new MuteTextResponder(mParent.mSpeakerMgr->getSessionID())); +} + +void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata) +{ + const LLUUID speaker_id = mUUIDs.front(); + BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagTextChat); + std::string name; + + //fill in name using voice client's copy of name cache + LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id); + if (speakerp.isNull()) + { + return; + } + + name = speakerp->mDisplayName; + + LLMute mute(speaker_id, name, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT); + + if (!is_muted) + { + LLMuteList::getInstance()->add(mute, LLMute::flagTextChat); + } + else + { + LLMuteList::getInstance()->remove(mute, LLMute::flagTextChat); + } +} + +bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + if (item == "can_mute_text") + { + return mUUIDs.front() != gAgentID; + } + else + if (item == "can_allow_text_chat") + { + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mParent.mSpeakerMgr->getSessionID()); + return im_session->mType == IM_SESSION_GROUP_START && mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator; + } + return true; +} + +bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + const LLUUID& id = mUUIDs.front(); + if (item == "is_muted") + return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat); + else + if (item == "is_allowed_text_chat") + { + LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id); + + if (selected_speakerp.notNull()) + { + return !selected_speakerp->mModeratorMutedText; + } + } + return false; +} diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index fc34dd308b..5e26c39fc8 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -32,6 +32,8 @@ #include "llviewerprecompiledheaders.h" #include "llevent.h" +#include "llpanelpeoplemenus.h" +#include "llimview.h" class LLSpeakerMgr; class LLAvatarList; @@ -43,6 +45,7 @@ class LLParticipantList public: LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list); ~LLParticipantList(); + void setSpeakingIndicatorsVisible(BOOL visible); typedef enum e_participant_sort_oder { E_SORT_BY_NAME = 0, @@ -105,6 +108,25 @@ class LLParticipantList SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; + + /** + * Menu used in the participant list. + */ + class LLParticipantListMenu : public LLPanelPeopleMenus::ContextMenu + { + public: + LLParticipantListMenu(LLParticipantList& parent):mParent(parent){}; + /*virtual*/ LLContextMenu* createMenu(); + protected: + LLParticipantList& mParent; + private: + bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + + void toggleAllowTextChat(const LLSD& userdata); + void toggleMuteText(const LLSD& userdata); + + }; private: void onAvatarListDoubleClicked(LLAvatarList* list); @@ -121,5 +143,7 @@ class LLParticipantList LLPointer<SpeakerClearListener> mSpeakerClearListener; LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; + LLParticipantListMenu* mParticipantListMenu; + EParticipantSortOrder mSortOrder; }; diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp index b491c7e109..bd46b5b56a 100644 --- a/indra/newview/llrecentpeople.cpp +++ b/indra/newview/llrecentpeople.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llrecentpeople.h" +#include "llgroupmgr.h" #include "llagent.h" @@ -43,12 +44,18 @@ bool LLRecentPeople::add(const LLUUID& id) if (id == gAgent.getID()) return false; - LLDate date_added = LLDate::now(); + bool is_not_group_id = LLGroupMgr::getInstance()->getGroupData(id) == NULL; - //[] instead of insert to replace existing id->date with new date value - mPeople[id] = date_added; - mChangedSignal(); - return true; + if (is_not_group_id) + { + LLDate date_added = LLDate::now(); + + //[] instead of insert to replace existing id->date with new date value + mPeople[id] = date_added; + mChangedSignal(); + } + + return is_not_group_id; } bool LLRecentPeople::contains(const LLUUID& id) const diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 061587f11b..70dc04f575 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -101,6 +101,7 @@ LLSideTray* LLSideTray::getInstance() if (!sInstance) { sInstance = LLUICtrlFactory::createFromFile<LLSideTray>("panel_side_tray.xml",NULL, LLRootView::child_registry_t::instance()); + sInstance->setXMLFilename("panel_side_tray.xml"); } return sInstance; @@ -353,7 +354,8 @@ bool LLSideTray::selectTabByName (const std::string& name) return true; } -LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,LLUICtrl::commit_callback_t callback) +LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,const std::string& tooltip, + LLUICtrl::commit_callback_t callback) { static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>()); @@ -374,6 +376,9 @@ LLButton* LLSideTray::createButton (const std::string& name,const std::string& i LLButton* button = LLUICtrlFactory::create<LLButton> (bparams); button->setLabel(name); button->setClickedCallback(callback); + + if(tooltip!="Home") + button->setToolTip(tooltip); if(image.length()) { @@ -412,28 +417,63 @@ void LLSideTray::createButtons () // change if the home screen becomes its own tab. if (name == "sidebar_home") { - mCollapseButton = createButton("",sidebar_tab->mImage, + mCollapseButton = createButton("",sidebar_tab->mImage,sidebar_tab->getTabTitle(), boost::bind(&LLSideTray::onToggleCollapse, this)); } else { - LLButton* button = createButton("",sidebar_tab->mImage, + LLButton* button = createButton("",sidebar_tab->mImage,sidebar_tab->getTabTitle(), boost::bind(&LLSideTray::onTabButtonClick, this, name)); mTabButtons[name] = button; } } } +void LLSideTray::processTriState () +{ + if(mCollapsed) + expandSideBar(); + else + { + //!!!!!!!!!!!!!!!!! + //** HARDCODED!!!!! + //!!!!!!!!!!!!!!!!! + + //there is no common way to determine "default" panel for tab + //so default panels for now will be hardcoded + + //hardcoded for people tab and profile tab + + /*if(mActiveTab == getTab("sidebar_people")) + { + LLSideTrayPanelContainer* container = findChild<LLSideTrayPanelContainer>("panel_container"); + if(container && container->getCurrentPanelIndex()>0) + { + container->onOpen(LLSD().insert("sub_panel_name","panel_people")); + } + else + collapseSideBar(); + } + else if(mActiveTab == getTab("sidebar_me")) + { + LLTabContainer* tab_container = findChild<LLTabContainer>("tabs"); + if(tab_container && tab_container->getCurrentPanelIndex()>0) + tab_container->selectFirstTab(); + else + collapseSideBar(); + } + else*/ + collapseSideBar(); + } +} + void LLSideTray::onTabButtonClick(string name) { LLSideTrayTab* side_bar = getTab(name); if(side_bar == mActiveTab) { - if(mCollapsed) - expandSideBar(); - else - collapseSideBar(); + processTriState (); return; } selectTabByName (name); diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 4d6081e230..8b30199c45 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -134,11 +134,15 @@ public: void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); + void processTriState (); + + protected: LLSideTrayTab* getTab (const std::string& name); void createButtons (); - LLButton* createButton (const std::string& name,const std::string& image,LLUICtrl::commit_callback_t callback); + LLButton* createButton (const std::string& name,const std::string& image,const std::string& tooltip, + LLUICtrl::commit_callback_t callback); void arrange (); void reflectCollapseChange(); diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index 57ea018f25..51d53b2674 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -133,6 +133,16 @@ LLSpeakButton::~LLSpeakButton() LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn); } +void LLSpeakButton::setSpeakToolTip(const std::string& msg) +{ + mSpeakBtn->setToolTip(msg); +} + +void LLSpeakButton::setShowToolTip(const std::string& msg) +{ + mShowBtn->setToolTip(msg); +} + void LLSpeakButton::onMouseDown_SpeakBtn() { bool down = true; diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h index e213c562dd..02c8ab3890 100644 --- a/indra/newview/llspeakbutton.h +++ b/indra/newview/llspeakbutton.h @@ -62,6 +62,11 @@ public: /*virtual*/ ~LLSpeakButton(); /*virtual*/ void draw(); + // *HACK: Need to put tooltips in a translatable location, + // the panel that contains this button. + void setSpeakToolTip(const std::string& msg); + void setShowToolTip(const std::string& msg); + protected: friend class LLUICtrlFactory; LLSpeakButton(const Params& p); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 25729c91e6..2c59d62b4b 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -873,6 +873,9 @@ bool idle_startup() gViewerWindow->getWindow()->show(); display_startup(); + //DEV-10530. do cleanup. remove at some later date. jan-2009 + LLFloaterPreference::cleanupBadSetting(); + // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. #ifdef _WIN32 @@ -1900,9 +1903,6 @@ bool idle_startup() //DEV-17797. get null folder. Any items found here moved to Lost and Found LLInventoryModel::findLostItems(); - //DEV-10530. do cleanup. remove at some later date. jan-2009 - LLFloaterPreference::cleanupBadSetting(); - LLStartUp::setStartupState( STATE_PRECACHE ); timeout.reset(); return FALSE; @@ -2478,7 +2478,7 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPicksReply", &LLAvatarPropertiesProcessor::processAvatarPicksReply); msg->setHandlerFunc("AvatarClassifiedReply", - &LLAvatarPropertiesProcessor::processAvatarClassifiedReply); + &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply); msg->setHandlerFuncFast(_PREHASH_CreateGroupReply, LLGroupMgr::processCreateGroupReply); @@ -2543,7 +2543,8 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply); msg->setHandlerFunc("PickInfoReply", &LLAvatarPropertiesProcessor::processPickInfoReply); - msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply); +// msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply); + msg->setHandlerFunc("ClassifiedInfoReply", LLAvatarPropertiesProcessor::processClassifiedInfoReply); msg->setHandlerFunc("ParcelInfoReply", LLRemoteParcelInfoProcessor::processParcelInfoReply); msg->setHandlerFunc("ScriptDialog", process_script_dialog); msg->setHandlerFunc("LoadURL", process_load_url); diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp index 595b24ad47..d7840fb435 100644 --- a/indra/newview/lltexglobalcolor.cpp +++ b/indra/newview/lltexglobalcolor.cpp @@ -108,9 +108,9 @@ LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) return new_param; } -void LLTexParamGlobalColor::onGlobalColorChanged(bool set_by_user) +void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake) { - mAvatar->onGlobalColorChanged(mTexGlobalColor, set_by_user); + mAvatar->onGlobalColorChanged(mTexGlobalColor, upload_bake); } //----------------------------------------------------------------------------- diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h index 1e6754133f..829a7d645b 100644 --- a/indra/newview/lltexglobalcolor.h +++ b/indra/newview/lltexglobalcolor.h @@ -80,7 +80,7 @@ public: LLTexParamGlobalColor(LLTexGlobalColor *tex_color); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; protected: - /*virtual*/ void onGlobalColorChanged(bool set_by_user); + /*virtual*/ void onGlobalColorChanged(bool upload_bake); private: LLTexGlobalColor* mTexGlobalColor; }; diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 5d682cad3c..25e0ca46e4 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -1834,7 +1834,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) } if (layer) { - wearable->writeToAvatar(FALSE, FALSE); + wearable->writeToAvatar(); layer->setLTO(lto); success &= layer->render(x,y,width,height); } diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp index b744722f4c..0c7e61d00e 100644 --- a/indra/newview/lltexlayerparams.cpp +++ b/indra/newview/lltexlayerparams.cpp @@ -160,7 +160,7 @@ BOOL LLTexLayerParamAlpha::getMultiplyBlend() const return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; } -void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) +void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake) { if (mIsAnimating || mTexLayer == NULL) { @@ -179,37 +179,37 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) { if (gAgent.cameraCustomizeAvatar()) { - set_by_user = FALSE; + upload_bake = FALSE; } - mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), set_by_user); + mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); mTexLayer->invalidateMorphMasks(); } } } -void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user) +void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake) { // do not animate dummy parameters if (mIsDummy) { - setWeight(target_value, set_by_user); + setWeight(target_value, upload_bake); return; } mTargetWeight = target_value; - setWeight(target_value, set_by_user); + setWeight(target_value, upload_bake); mIsAnimating = TRUE; if (mNext) { - mNext->setAnimationTarget(target_value, set_by_user); + mNext->setAnimationTarget(target_value, upload_bake); } } -void LLTexLayerParamAlpha::animate(F32 delta, BOOL set_by_user) +void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake) { if (mNext) { - mNext->animate(delta, set_by_user); + mNext->animate(delta, upload_bake); } } @@ -449,7 +449,7 @@ LLColor4 LLTexLayerParamColor::getNetColor() const } } -void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user) +void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake) { if (mIsAnimating) { @@ -474,10 +474,10 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user) if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. { - onGlobalColorChanged(set_by_user); + onGlobalColorChanged(upload_bake); if (mTexLayer) { - mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), set_by_user); + mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake); } } @@ -485,23 +485,23 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user) } } -void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user) +void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake) { // set value first then set interpolating flag to ignore further updates mTargetWeight = target_value; - setWeight(target_value, set_by_user); + setWeight(target_value, upload_bake); mIsAnimating = TRUE; if (mNext) { - mNext->setAnimationTarget(target_value, set_by_user); + mNext->setAnimationTarget(target_value, upload_bake); } } -void LLTexLayerParamColor::animate(F32 delta, BOOL set_by_user) +void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake) { if (mNext) { - mNext->animate(delta, set_by_user); + mNext->animate(delta, upload_bake); } } diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 98365864f9..2b80dbdba4 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -66,9 +66,9 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); - /*virtual*/ void setAnimationTarget(F32 target_value, BOOL set_by_user); - /*virtual*/ void animate(F32 delta, BOOL set_by_user); + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); + /*virtual*/ void animate(F32 delta, BOOL upload_bake); // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } @@ -143,9 +143,9 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); - /*virtual*/ void setAnimationTarget(F32 target_value, BOOL set_by_user); - /*virtual*/ void animate(F32 delta, BOOL set_by_user); + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); + /*virtual*/ void animate(F32 delta, BOOL upload_bake); // LLViewerVisualParam Virtual functions @@ -159,7 +159,7 @@ public: // New functions LLColor4 getNetColor() const; protected: - virtual void onGlobalColorChanged(bool set_by_user) {} + virtual void onGlobalColorChanged(bool upload_bake) {} private: LLVector3 mAvgDistortionVec; }; diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 69a2d1d7a6..9be342c424 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1541,21 +1541,24 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort) { lockWorkers(); handle_map_t::iterator iter = mReaders.find(handle); - llassert_always(iter != mReaders.end() || abort); - LLTextureCacheWorker* worker = iter->second; - bool res = worker->complete(); - if (res || abort) + LLTextureCacheWorker* worker = NULL; + bool complete = false; + if (iter != mReaders.end()) + { + worker = iter->second; + complete = worker->complete(); + } + if (worker && (complete || abort)) { - mReaders.erase(handle); + mReaders.erase(iter); unlockWorkers(); worker->scheduleDelete(); - return true; } else { unlockWorkers(); - return false; } + return (complete || abort); } LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority, diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index c02fd7a5ef..9370e318cf 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -50,7 +50,19 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif mMessage = getChild<LLTextBox>("message"); mReplyBtn = getChild<LLButton>("reply"); - mMessage->setValue(p.message); + LLStyle::Params style_params; + //Handle IRC styled /me messages. + std::string prefix = p.message.substr(0, 4); + if (prefix == "/me " || prefix == "/me'") + { + mMessage->clear(); + style_params.font.style= "ITALIC"; + mMessage->appendText(p.from + " ", FALSE, style_params); + style_params.font.style= "UNDERLINE"; + mMessage->appendText(p.message.substr(3), FALSE, style_params); + } + else + mMessage->setValue(p.message); mUserName->setValue(p.from); mTime->setValue(p.time); mSessionID = p.session_id; diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp index 9c643e78de..8b4cfa7248 100644 --- a/indra/newview/lluilistener.cpp +++ b/indra/newview/lluilistener.cpp @@ -20,10 +20,16 @@ #include "lluictrl.h" #include "llerror.h" -LLUIListener::LLUIListener(const std::string& name): - LLDispatchListener(name, "op") +LLUIListener::LLUIListener(): + LLEventAPI("UI", + "LLUICtrl::CommitCallbackRegistry listener.\n" + "Capable of invoking any function (with parameter) you can specify in XUI.") { - add("call", &LLUIListener::call, LLSD().insert("function", LLSD())); + add("call", + "Invoke the operation named by [\"function\"], passing [\"parameter\"],\n" + "as if from a user gesture on a menu -- or a button click.", + &LLUIListener::call, + LLSD().insert("function", LLSD())); } void LLUIListener::call(const LLSD& event) const diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h index ea904a99ff..8605d60bd3 100644 --- a/indra/newview/lluilistener.h +++ b/indra/newview/lluilistener.h @@ -12,15 +12,15 @@ #if ! defined(LL_LLUILISTENER_H) #define LL_LLUILISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" #include <string> class LLSD; -class LLUIListener: public LLDispatchListener +class LLUIListener: public LLEventAPI { public: - LLUIListener(const std::string& name); + LLUIListener(); private: void call(const LLSD& event) const; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index a3daca6fa4..9e064d8135 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -364,9 +364,9 @@ bool LLURLDispatcher::dispatchRightClick(const std::string& url) bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url) { // *NOTE: Text editors are considered sources of trusted URLs - // in order to make objectim and avatar profile links in chat - // history work. While a malicious resident could chat an app - // SLURL, the receiving resident will see it and must affirmatively + // in order to make avatar profile links in chat history work. + // While a malicious resident could chat an app SLURL, the + // receiving resident will see it and must affirmatively // click on it. // *TODO: Make this trust model more refined. JC const bool trusted_browser = true; diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp index ecba1b8eb0..0b9db1b906 100644 --- a/indra/newview/llviewercontrollistener.cpp +++ b/indra/newview/llviewercontrollistener.cpp @@ -18,12 +18,22 @@ LLViewerControlListener gSavedSettingsListener; LLViewerControlListener::LLViewerControlListener() - : LLDispatchListener("LLViewerControl", "group") + : LLEventAPI("LLViewerControl", + "LLViewerControl listener: set, toggle or set default for various controls", + "group") { - add("Global", boost::bind(&LLViewerControlListener::set, &gSavedSettings, _1)); - add("PerAccount", boost::bind(&LLViewerControlListener::set, &gSavedPerAccountSettings, _1)); - add("Warning", boost::bind(&LLViewerControlListener::set, &gWarningSettings, _1)); - add("Crash", boost::bind(&LLViewerControlListener::set, &gCrashSettings, _1)); + add("Global", + "Set gSavedSettings control [\"key\"] to value [\"value\"]", + boost::bind(&LLViewerControlListener::set, &gSavedSettings, _1)); + add("PerAccount", + "Set gSavedPerAccountSettings control [\"key\"] to value [\"value\"]", + boost::bind(&LLViewerControlListener::set, &gSavedPerAccountSettings, _1)); + add("Warning", + "Set gWarningSettings control [\"key\"] to value [\"value\"]", + boost::bind(&LLViewerControlListener::set, &gWarningSettings, _1)); + add("Crash", + "Set gCrashSettings control [\"key\"] to value [\"value\"]", + boost::bind(&LLViewerControlListener::set, &gCrashSettings, _1)); #if 0 add(/*"toggleControl",*/ "Global", boost::bind(&LLViewerControlListener::toggleControl, &gSavedSettings, _1)); diff --git a/indra/newview/llviewercontrollistener.h b/indra/newview/llviewercontrollistener.h index cacf97e908..88afbb871d 100644 --- a/indra/newview/llviewercontrollistener.h +++ b/indra/newview/llviewercontrollistener.h @@ -12,12 +12,12 @@ #ifndef LL_LLVIEWERCONTROLLISTENER_H #define LL_LLVIEWERCONTROLLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" class LLControlGroup; class LLSD; -class LLViewerControlListener : public LLDispatchListener +class LLViewerControlListener : public LLEventAPI { public: LLViewerControlListener(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index edbac69e1b..7772f613f0 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -112,6 +112,7 @@ #include "llinspectavatar.h" #include "llinspectgroup.h" #include "llinspectobject.h" +#include "llinspectremoteobject.h" #include "llmediaremotectrl.h" #include "llmoveview.h" #include "llnearbychat.h" @@ -176,6 +177,7 @@ void LLViewerFloaterReg::registerFloaters() LLInspectAvatarUtil::registerFloater(); LLInspectGroupUtil::registerFloater(); LLInspectObjectUtil::registerFloater(); + LLInspectRemoteObjectUtil::registerFloater(); LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>); LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); @@ -195,7 +197,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>); LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); - + LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>); LLFloaterReg::add("parcel_info", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterParcelInfo>); LLFloaterPayUtil::registerFloater(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 605861f1cb..493457704b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -295,11 +295,21 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s } } - if(media_impl && needs_navigate) + if(media_impl) { std::string url = media_entry->getCurrentURL(); - - media_impl->navigateTo(url, "", true, true); + if(needs_navigate) + { + media_impl->navigateTo(url, "", true, true); + } + else if(!media_impl->mMediaURL.empty() && (media_impl->mMediaURL != url)) + { + // If we already have a non-empty media URL set and we aren't doing a navigate, update the media URL to match the media entry. + media_impl->mMediaURL = url; + + // If this causes a navigate at some point (such as after a reload), it should be considered server-driven so it isn't broadcast. + media_impl->mNavigateServerRequest = true; + } } return media_impl; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 820f709ba5..728fb7c616 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -415,7 +415,7 @@ public: static LLMenuParcelObserver* gMenuParcelObserver = NULL; -static LLUIListener sUIListener("UI"); +static LLUIListener sUIListener; LLMenuParcelObserver::LLMenuParcelObserver() { @@ -1879,7 +1879,9 @@ class LLAdvancedDebugAvatarTextures : public view_listener_t { bool handleEvent(const LLSD& userdata) { +#ifndef LL_RELEASE_FOR_DOWNLOAD handle_debug_avatar_textures(NULL); +#endif return true; } }; @@ -1893,7 +1895,9 @@ class LLAdvancedDumpAvatarLocalTextures : public view_listener_t { bool handleEvent(const LLSD& userdata) { +#ifndef LL_RELEASE_FOR_DOWNLOAD handle_dump_avatar_local_textures(NULL); +#endif return true; } }; @@ -7860,10 +7864,8 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures"); - #ifndef LL_RELEASE_FOR_DOWNLOAD view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures"); view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures"); - #endif // Advanced > Network view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog"); view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a90790c59a..4088eafe16 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1431,6 +1431,17 @@ bool goto_url_callback(const LLSD& notification, const LLSD& response) } static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback); +bool inspect_remote_object_callback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (0 == option) + { + LLFloaterReg::showInstance("inspect_remote_object", notification["payload"]); + } + return false; +} +static LLNotificationFunctorRegistration inspect_remote_object_callback_reg("ServerObjectMessage", inspect_remote_object_callback); + void process_improved_im(LLMessageSystem *msg, void **user_data) { if (gNoRender) @@ -1498,15 +1509,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } std::string separator_string(": "); - int message_offset = 0; - - //Handle IRC styled /me messages. - std::string prefix = message.substr(0, 4); - if (prefix == "/me " || prefix == "/me'") - { - separator_string = ""; - message_offset = 3; - } LLSD args; switch(dialog) @@ -1558,7 +1560,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // now store incoming IM in chat history - buffer = message.substr(message_offset); + buffer = message; LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; @@ -1576,7 +1578,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) true); // pretend this is chat generated by self, so it does not show up on screen - chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset); + chat.mText = std::string("IM: ") + name + separator_string + message; LLFloaterChat::addChat( chat, TRUE, TRUE ); } else if (from_id.isNull()) @@ -1596,7 +1598,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Treat like a system message and put in chat history. // Claim to be from a local agent so it doesn't go into // console. - chat.mText = name + separator_string + message.substr(message_offset); + chat.mText = name + separator_string + message; LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); if(nearby_chat) @@ -1612,7 +1614,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } - buffer = saved + message.substr(message_offset); + buffer = saved + message; LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; @@ -1634,7 +1636,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) region_id, position, true); - chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); + chat.mText = std::string("IM: ") + name + separator_string + saved + message; BOOL local_agent = FALSE; LLFloaterChat::addChat( chat, TRUE, local_agent ); @@ -1922,7 +1924,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } - buffer = saved + message.substr(message_offset); + buffer = saved + message; BOOL is_this_agent = FALSE; if(from_id == gAgentID) { @@ -1940,7 +1942,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) position, true); - chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset); + chat.mText = std::string("IM: ") + name + separator_string + saved + message; LLFloaterChat::addChat(chat, TRUE, is_this_agent); } break; @@ -1952,9 +1954,23 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) return; } + // Build a link to open the object IM info window. + std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1); + LLSD substitutions; - substitutions["MSG"] = message.substr(message_offset); - LLNotifications::instance().add("ServerObjectMessage", substitutions); + substitutions["NAME"] = name; + substitutions["MSG"] = message; + + LLSD payload; + payload["object_id"] = session_id; + payload["owner_id"] = from_id; + payload["slurl"] = location; + payload["name"] = name; + if (from_group) + { + payload["groupowned"] = "true"; + } + LLNotifications::instance().add("ServerObjectMessage", substitutions, payload); } break; case IM_FROM_TASK_AS_ALERT: @@ -1978,7 +1994,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) else { // TODO: after LLTrans hits release, get "busy response" into translatable file - buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.substr(message_offset).c_str()); + buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.c_str()); gIMMgr->addMessage(session_id, from_id, name, buffer); } break; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6b0f8814b9..1054223dcf 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1212,7 +1212,7 @@ LLViewerWindow::LLViewerWindow( mStatesDirty(false), mIsFullscreenChecked(false), mCurrResolutionIndex(0), - mViewerWindowListener(new LLViewerWindowListener("LLViewerWindow", this)) + mViewerWindowListener(new LLViewerWindowListener(this)) { LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); @@ -2302,13 +2302,13 @@ void LLViewerWindow::moveCursorToCenter() // Hover handlers // -void append_xui_tooltip(LLView* viewp, std::string& tool_tip_msg) +void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params) { if (viewp) { - if (!tool_tip_msg.empty()) + if (!params.styled_message().empty()) { - tool_tip_msg.append("\n---------\n"); + params.styled_message.add().text("\n---------\n"); } LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView(); // NOTE: we skip "root" since it is assumed @@ -2318,15 +2318,16 @@ void append_xui_tooltip(LLView* viewp, std::string& tool_tip_msg) { LLView* viewp = *tooltip_it; - tool_tip_msg.append(viewp->getName()); + params.styled_message.add().text(viewp->getName()); + LLPanel* panelp = dynamic_cast<LLPanel*>(viewp); if (panelp && !panelp->getXMLFilename().empty()) { - tool_tip_msg.append("("); - tool_tip_msg.append(panelp->getXMLFilename()); - tool_tip_msg.append(")"); + params.styled_message.add() + .text("(" + panelp->getXMLFilename() + ")") + .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f)); } - tool_tip_msg.append("/"); + params.styled_message.add().text("/"); } } } @@ -2567,6 +2568,8 @@ void LLViewerWindow::updateUI() if (gSavedSettings.getBOOL("DebugShowXUINames")) { + LLToolTip::Params params; + LLView* tooltip_view = mRootView; LLView::tree_iterator_t end_it = mRootView->endTreeDFS(); for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it) @@ -2599,20 +2602,20 @@ void LLViewerWindow::updateUI() // NOTE: this emulates visiting only the leaf nodes that meet our criteria if (!viewp->hasAncestor(tooltip_view)) { - append_xui_tooltip(tooltip_view, tool_tip_msg); + append_xui_tooltip(tooltip_view, params); screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); } tooltip_view = viewp; } } - append_xui_tooltip(tooltip_view, tool_tip_msg); + append_xui_tooltip(tooltip_view, params); screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tool_tip_msg) - .sticky_rect(screen_sticky_rect) - .max_width(400)); + params.sticky_rect = screen_sticky_rect; + params.max_width = 400; + + LLToolTipMgr::instance().show(params); } // if there is a mouse captor, nothing else gets a tooltip else if (mouse_captor) diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp index a890b042ae..de57788271 100644 --- a/indra/newview/llviewerwindowlistener.cpp +++ b/indra/newview/llviewerwindowlistener.cpp @@ -20,8 +20,9 @@ // other Linden headers #include "llviewerwindow.h" -LLViewerWindowListener::LLViewerWindowListener(const std::string& pumpname, LLViewerWindow* llviewerwindow): - LLDispatchListener(pumpname, "op"), +LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow): + LLEventAPI("LLViewerWindow", + "LLViewerWindow listener to (e.g.) save a screenshot"), mViewerWindow(llviewerwindow) { // add() every method we want to be able to invoke via this event API. @@ -34,8 +35,15 @@ LLViewerWindowListener::LLViewerWindowListener(const std::string& pumpname, LLVi // saveSnapshotArgs["showui"] = LLSD::Boolean(); // saveSnapshotArgs["rebuild"] = LLSD::Boolean(); // saveSnapshotArgs["type"] = LLSD::String(); - add("saveSnapshot", &LLViewerWindowListener::saveSnapshot, saveSnapshotArgs); - add("requestReshape", &LLViewerWindowListener::requestReshape); + add("saveSnapshot", + "Save screenshot: [\"filename\"], [\"width\"], [\"height\"], [\"showui\"], [\"rebuild\"], [\"type\"]\n" + "type: \"COLOR\", \"DEPTH\", \"OBJECT_ID\"\n" + "Post on [\"reply\"] an event containing [\"ok\"]", + &LLViewerWindowListener::saveSnapshot, + saveSnapshotArgs); + add("requestReshape", + "Resize the window: [\"w\"], [\"h\"]", + &LLViewerWindowListener::requestReshape); } void LLViewerWindowListener::saveSnapshot(const LLSD& event) const diff --git a/indra/newview/llviewerwindowlistener.h b/indra/newview/llviewerwindowlistener.h index 59c636ecec..699f7907af 100644 --- a/indra/newview/llviewerwindowlistener.h +++ b/indra/newview/llviewerwindowlistener.h @@ -12,18 +12,17 @@ #if ! defined(LL_LLVIEWERWINDOWLISTENER_H) #define LL_LLVIEWERWINDOWLISTENER_H -#include "lleventdispatcher.h" +#include "lleventapi.h" class LLViewerWindow; class LLSD; /// Listen on an LLEventPump with specified name for LLViewerWindow request events. -class LLViewerWindowListener: public LLDispatchListener +class LLViewerWindowListener: public LLEventAPI { public: - /// Specify the pump name on which to listen, and bind the LLViewerWindow - /// instance to use (e.g. gViewerWindow). - LLViewerWindowListener(const std::string& pumpname, LLViewerWindow* llviewerwindow); + /// Bind the LLViewerWindow instance to use (e.g. gViewerWindow). + LLViewerWindowListener(LLViewerWindow* llviewerwindow); private: void saveSnapshot(const LLSD& event) const; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 16bd74f798..62ac8adad0 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -647,7 +647,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mWindFreq(0.f), mRipplePhase( 0.f ), mBelowWater(FALSE), - mAppearanceAnimSetByUser(FALSE), mLastAppearanceBlendTime(0.f), mAppearanceAnimating(FALSE), mNameString(), @@ -2436,7 +2435,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() { if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) { - param->stopAnimating(mAppearanceAnimSetByUser); + param->stopAnimating(FALSE); } } updateVisualParams(); @@ -2459,7 +2458,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() { if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) { - param->animate(morph_amt, mAppearanceAnimSetByUser); + param->animate(morph_amt, FALSE); } } } @@ -5372,11 +5371,11 @@ void LLVOAvatar::updateShadowFaces() //----------------------------------------------------------------------------- // updateSexDependentLayerSets() //----------------------------------------------------------------------------- -void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user ) +void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake ) { - invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake ); + invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake ); + invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake ); } //----------------------------------------------------------------------------- @@ -5741,7 +5740,7 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const } // virtual -void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user ) +void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) { } @@ -5754,18 +5753,18 @@ void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b ) { } -void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL set_by_user ) +void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake ) { if (global_color == mTexSkinColor) { - invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake ); + invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake ); + invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake ); } else if (global_color == mTexHairColor) { - invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake ); + invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, upload_bake ); // ! BACKWARDS COMPATIBILITY ! // Fix for dealing with avatars from viewers that don't bake hair. @@ -5781,7 +5780,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL else if (global_color == mTexEyeColor) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; - invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, upload_bake ); } updateMeshTextures(); } @@ -6239,14 +6238,14 @@ BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name ) return TRUE; } -void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user ) +void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake ) { U32 param_name[3]; if( teToColorParams( te, param_name ) ) { - setVisualParamWeight( param_name[0], new_color.mV[VX], set_by_user ); - setVisualParamWeight( param_name[1], new_color.mV[VY], set_by_user ); - setVisualParamWeight( param_name[2], new_color.mV[VZ], set_by_user ); + setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake ); + setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake ); + setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake ); } } @@ -6592,7 +6591,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { if (interp_params) { - startAppearanceAnimation(FALSE, FALSE); + startAppearanceAnimation(); } updateVisualParams(); @@ -6977,11 +6976,10 @@ void LLVOAvatar::cullAvatarsByPixelArea() } } -void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound) +void LLVOAvatar::startAppearanceAnimation() { if(!mAppearanceAnimating) { - mAppearanceAnimSetByUser = set_by_user; mAppearanceAnimating = TRUE; mAppearanceMorphTimer.reset(); mLastAppearanceBlendTime = 0.f; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 173ad02808..2fd1a506a9 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -522,7 +522,7 @@ protected: // Composites //-------------------------------------------------------------------- public: - virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL set_by_user); + virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); virtual void invalidateAll(); virtual void setCompositeUpdatesEnabled(BOOL b); @@ -558,7 +558,7 @@ private: public: void updateMeshTextures(); - void updateSexDependentLayerSets(BOOL set_by_user); + void updateSexDependentLayerSets(BOOL upload_bake); void dirtyMesh(); // Dirty the avatar mesh void updateMeshData(); protected: @@ -591,7 +591,7 @@ protected: public: void processAvatarAppearance(LLMessageSystem* mesgsys); void hideSkirt(); - void startAppearanceAnimation(BOOL set_by_user, BOOL play_sound); + void startAppearanceAnimation(); //-------------------------------------------------------------------- // Appearance morphing @@ -600,14 +600,13 @@ public: BOOL mAppearanceAnimating; private: LLFrameTimer mAppearanceMorphTimer; - BOOL mAppearanceAnimSetByUser; F32 mLastAppearanceBlendTime; //-------------------------------------------------------------------- // Clothing colors (convenience functions to access visual parameters) //-------------------------------------------------------------------- public: - void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user); + void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name); @@ -616,7 +615,7 @@ public: //-------------------------------------------------------------------- public: LLColor4 getGlobalColor(const std::string& color_name ) const; - void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL set_by_user); + void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake); private: LLTexGlobalColor* mTexSkinColor; LLTexGlobalColor* mTexHairColor; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index a2203ba2ea..185274d40d 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -633,33 +633,33 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name) return LLVOAvatar::getJoint(name); } -/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user ) +/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake ) { if (!which_param) { return FALSE; } LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID()); - return setParamWeight(param,weight,set_by_user); + return setParamWeight(param,weight,upload_bake); } -/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user ) +/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake ) { if (!param_name) { return FALSE; } LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name); - return setParamWeight(param,weight,set_by_user); + return setParamWeight(param,weight,upload_bake); } -/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user ) +/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake ) { LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index); - return setParamWeight(param,weight,set_by_user); + return setParamWeight(param,weight,upload_bake); } -BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL set_by_user ) +BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake ) { if (!param) { @@ -675,12 +675,12 @@ BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL LLWearable *wearable = gAgentWearables.getWearable(type,count); if (wearable) { - wearable->setVisualParamWeight(param->getID(), weight, set_by_user); + wearable->setVisualParamWeight(param->getID(), weight, upload_bake); } } } - return LLCharacter::setVisualParamWeight(param,weight,set_by_user); + return LLCharacter::setVisualParamWeight(param,weight,upload_bake); } /*virtual*/ @@ -691,7 +691,7 @@ void LLVOAvatarSelf::updateVisualParams() LLWearable *wearable = gAgentWearables.getTopWearable((EWearableType)type); if (wearable) { - wearable->writeToAvatar(FALSE, FALSE); + wearable->writeToAvatar(); } } @@ -702,7 +702,7 @@ void LLVOAvatarSelf::updateVisualParams() void LLVOAvatarSelf::idleUpdateAppearanceAnimation() { // Animate all top-level wearable visual parameters - gAgentWearables.animateAllWearableParams(calcMorphAmount(), mAppearanceAnimSetByUser); + gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE); // apply wearable visual params to avatar updateVisualParams(); @@ -737,8 +737,7 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) } } -// virtual -void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, BOOL set_by_user, U32 index) +void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index) { if (te >= TEX_NUM_INDICES) { @@ -1347,7 +1346,7 @@ bool LLVOAvatarSelf::hasPendingBakedUploads() const return false; } -void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user ) +void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) { if( !layerset || !layerset->getUpdatesEnabled() ) { @@ -1358,7 +1357,7 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_u layerset->requestUpdate(); layerset->invalidateMorphMasks(); - if( set_by_user ) + if( upload_result ) { llassert(isSelf()); @@ -1945,9 +1944,7 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) if (layer_set) { llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; - // Apparently set_by_user == force upload - BOOL set_by_user = TRUE; - self->invalidateComposite(layer_set, set_by_user); + self->invalidateComposite(layer_set, TRUE); found = TRUE; LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); } @@ -1983,8 +1980,7 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) layer_set->cancelUpload(); } - BOOL set_by_user = TRUE; - invalidateComposite(layer_set, set_by_user); + invalidateComposite(layer_set, TRUE); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); } else @@ -2047,7 +2043,6 @@ void LLVOAvatarSelf::onCustomizeEnd() if (avatarp) { avatarp->invalidateAll(); - avatarp->requestLayerSetUploads(); } } @@ -2084,7 +2079,6 @@ void LLVOAvatarSelf::setInvisible(BOOL newvalue) { setCompositeUpdatesEnabled(TRUE); invalidateAll(); - requestLayerSetUploads(); gAgent.sendAgentSetAppearance(); } } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 8a66422c44..6702f030fe 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -86,15 +86,15 @@ public: /*virtual*/ void requestStopMotion(LLMotion* motion); /*virtual*/ LLJoint* getJoint(const std::string &name); - /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE ); - /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE ); - /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE ); + /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE ); /*virtual*/ void updateVisualParams(); /*virtual*/ void idleUpdateAppearanceAnimation(); private: // helper function. Passed in param is assumed to be in avatar's parameter list. - BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL set_by_user = FALSE ); + BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE ); /** Initialization @@ -186,7 +186,7 @@ public: BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const; LLViewerFetchedTexture* getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const; const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index) const; - void setLocalTextureTE(U8 te, LLViewerTexture* image, BOOL set_by_user, U32 index); + void setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index); const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index) const; BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index) const; /*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index); @@ -228,7 +228,7 @@ public: // Composites //-------------------------------------------------------------------- public: - /* virtual */ void invalidateComposite(LLTexLayerSet* layerset, BOOL set_by_user); + /* virtual */ void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result); /* virtual */ void invalidateAll(); /* virtual */ void setCompositeUpdatesEnabled(BOOL b); // only works for self void setupComposites(); diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index cefc88ebee..d93913b944 100644 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -46,6 +46,7 @@ LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap; LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap; LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL; LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL; +LLVoiceChannel::channel_changed_signal_t LLVoiceChannel::sCurrentVoiceChannelChangedSignal; BOOL LLVoiceChannel::sSuspended = FALSE; @@ -305,8 +306,10 @@ void LLVoiceChannel::activate() // activating the proximal channel between IM calls LLVoiceChannel* old_channel = sCurrentVoiceChannel; sCurrentVoiceChannel = this; + mCallDialogPayload["old_channel_name"] = ""; if (old_channel) { + mCallDialogPayload["old_channel_name"] = old_channel->getSessionName(); old_channel->deactivate(); } } @@ -320,6 +323,8 @@ void LLVoiceChannel::activate() { setState(STATE_CALL_STARTED); } + + sCurrentVoiceChannelChangedSignal(this->mSessionID); } void LLVoiceChannel::getChannelInfo() @@ -867,6 +872,19 @@ void LLVoiceChannelP2P::setState(EState state) { // HACK: Open/close the call window if needed. toggleCallWindowIfNeeded(state); + + // *HACK: open outgoing call floater if needed, might be better done elsewhere. + mCallDialogPayload["session_id"] = mSessionID; + mCallDialogPayload["session_name"] = mSessionName; + mCallDialogPayload["other_user_id"] = mOtherUserID; + if (!mReceivedCall && state == STATE_RINGING) + { + llinfos << "RINGINGGGGGGGG " << mSessionName << llendl; + if (!mSessionName.empty()) + { + LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE); + } + } // you only "answer" voice invites in p2p mode // so provide a special purpose message here diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index 8f1e9ff02d..639585de55 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -54,6 +54,13 @@ public: typedef boost::function<void(const EState& old_state, const EState& new_state)> state_changed_callback_t; + // on current channel changed signal + typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t; + typedef boost::signals2::signal<void(const LLUUID& session_id)> channel_changed_signal_t; + static channel_changed_signal_t sCurrentVoiceChannelChangedSignal; + static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb) { return sCurrentVoiceChannelChangedSignal.connect(cb); } + + LLVoiceChannel(const LLUUID& session_id, const std::string& session_name); virtual ~LLVoiceChannel(); @@ -102,6 +109,7 @@ protected: EState mState; std::string mSessionName; LLSD mNotifyArgs; + LLSD mCallDialogPayload; BOOL mIgnoreNextSessionLeave; LLHandle<LLPanel> mLoginNotificationHandle; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 39d4bb0c02..5fedfc943b 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1598,7 +1598,7 @@ void LLVoiceClient::stateMachine() } else { - LL_WARNS("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL; + LL_WARNS_ONCE("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL; } } } @@ -4273,7 +4273,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent( if(incoming) { // Send the voice chat invite to the GUI layer - // TODO: Question: Should we correlate with the mute list here? + // *TODO: Question: Should we correlate with the mute list here? session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID); session->mVoiceInvitePending = true; if(session->mName.empty()) diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 3185ee45bf..c5c97e7649 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -602,7 +602,7 @@ void LLWearable::setTexturesToDefaults() } // Updates the user's avatar's appearance -void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater ) +void LLWearable::writeToAvatar() { LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); llassert( avatar ); @@ -622,24 +622,10 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater S32 param_id = param->getID(); F32 weight = getVisualParamWeight(param_id); - // only animate with user-originated changes - if (set_by_user) - { - param->setAnimationTarget(weight, set_by_user); - } - else - { - avatar->setVisualParamWeight( param_id, weight, set_by_user ); - } + avatar->setVisualParamWeight( param_id, weight, FALSE ); } } - // only interpolate with user-originated changes - if (set_by_user) - { - avatar->startAppearanceAnimation(TRUE, TRUE); - } - // Pull texture entries for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { @@ -657,24 +643,17 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater } LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); // MULTI-WEARABLE: replace hard-coded 0 - avatar->setLocalTextureTE(te, image, set_by_user, 0); + avatar->setLocalTextureTE(te, image, 0); } } - - if( gFloaterCustomize && update_customize_floater ) - { - gFloaterCustomize->setWearable(mType, 0); - gFloaterCustomize->setCurrentWearableType( mType ); - } - ESex new_sex = avatar->getSex(); if( old_sex != new_sex ) { - avatar->updateSexDependentLayerSets( set_by_user ); + avatar->updateSexDependentLayerSets( FALSE ); } -// if( set_by_user ) +// if( upload_bake ) // { // gAgent.sendAgentSetAppearance(); // } @@ -683,7 +662,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater // Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values. // static -void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user ) +void LLWearable::removeFromAvatar( EWearableType type, BOOL upload_bake ) { LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); llassert( avatar ); @@ -707,7 +686,7 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user ) if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) ) { S32 param_id = param->getID(); - avatar->setVisualParamWeight( param_id, param->getDefaultWeight(), set_by_user ); + avatar->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake ); } } @@ -719,7 +698,7 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user ) avatar->updateVisualParams(); avatar->wearableUpdated(type); -// if( set_by_user ) +// if( upload_bake ) // { // gAgent.sendAgentSetAppearance(); // } @@ -868,12 +847,12 @@ void LLWearable::setVisualParams() } -void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL set_by_user) +void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake) { if( is_in_map(mVisualParamIndexMap, param_index ) ) { LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; - wearable_param->setWeight(value, set_by_user); + wearable_param->setWeight(value, upload_bake); } else { @@ -914,14 +893,14 @@ void LLWearable::getVisualParams(visual_param_vec_t &list) } } -void LLWearable::animateParams(F32 delta, BOOL set_by_user) +void LLWearable::animateParams(F32 delta, BOOL upload_bake) { for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) { LLVisualParam *param = (LLVisualParam*) iter->second; - param->animate(delta, set_by_user); + param->animate(delta, upload_bake); } } @@ -939,14 +918,14 @@ LLColor4 LLWearable::getClothesColor(S32 te) const return color; } -void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user ) +void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) { U32 param_name[3]; if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) ) { for( U8 index = 0; index < 3; index++ ) { - setVisualParamWeight(param_name[index], new_color.mV[index], set_by_user); + setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake); } } } diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 96631811c5..fd19a86406 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -89,9 +89,9 @@ public: BOOL isDirty() const; BOOL isOldVersion() const; - void writeToAvatar( BOOL set_by_user, BOOL update_customize_floater = TRUE ); - void removeFromAvatar( BOOL set_by_user ) { LLWearable::removeFromAvatar( mType, set_by_user ); } - static void removeFromAvatar( EWearableType type, BOOL set_by_user ); + void writeToAvatar(); + void removeFromAvatar( BOOL upload_bake ) { LLWearable::removeFromAvatar( mType, upload_bake ); } + static void removeFromAvatar( EWearableType type, BOOL upload_bake ); BOOL exportFile(LLFILE* file) const; BOOL importFile(LLFILE* file); @@ -115,14 +115,14 @@ public: void setLocalTextureObject(S32 index, LLLocalTextureObject *lto); void addVisualParam(LLVisualParam *param); void setVisualParams(); - void setVisualParamWeight(S32 index, F32 value, BOOL set_by_user); + void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake); F32 getVisualParamWeight(S32 index) const; LLVisualParam* getVisualParam(S32 index) const; void getVisualParams(visual_param_vec_t &list); - void animateParams(F32 delta, BOOL set_by_user); + void animateParams(F32 delta, BOOL upload_bake); LLColor4 getClothesColor(S32 te) const; - void setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user ); + void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ); void revertValues(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1129e9ffd1..507c726e02 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -512,16 +512,18 @@ void LLPipeline::resizeScreenTexture() LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE); if (gPipeline.canUseVertexShaders() && assertInitialized()) { - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + GLuint resX = gViewerWindow->getWindowWidthRaw(); + GLuint resY = gViewerWindow->getWindowHeightRaw(); + GLuint view_width = gViewerWindow->getWorldViewWidthRaw(); + GLuint view_height = gViewerWindow->getWorldViewHeightRaw(); - allocateScreenBuffer(resX,resY); + allocateScreenBuffer(resX, resY, view_width, view_height); llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl; } } -void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) +void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 viewport_width, U32 viewport_height) { U32 samples = gSavedSettings.getU32("RenderFSAASamples"); @@ -542,18 +544,24 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) //allocate deferred rendering color buffers mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mDeferredScreen.setViewport(viewport_width, viewport_height); + mDeferredDepth.setViewport(viewport_width, viewport_height); addDeferredAttachments(mDeferredScreen); mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mScreen.setViewport(viewport_width, viewport_height); + mEdgeMap.setViewport(viewport_width, viewport_height); for (U32 i = 0; i < 3; i++) { mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + mDeferredLight[i].setViewport(viewport_width, viewport_height); } for (U32 i = 0; i < 2; i++) { mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + mGIMapPost[i].setViewport(viewport_width, viewport_height); } F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); @@ -561,6 +569,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) for (U32 i = 0; i < 4; i++) { mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + mShadow[i].setViewport(viewport_width, viewport_height); } @@ -570,6 +579,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) for (U32 i = 4; i < 6; i++) { mShadow[i].allocate(width, height, 0, TRUE, FALSE); + mShadow[i].setViewport(viewport_width, viewport_height); } @@ -577,16 +587,19 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) width = nhpo2(resX)/2; height = nhpo2(resY)/2; mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); + mLuminanceMap.setViewport(viewport_width, viewport_height); } else { mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mScreen.setViewport(viewport_width, viewport_height); } if (gGLManager.mHasFramebufferMultisample && samples > 1) { mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + mSampleBuffer.setViewport(viewport_width, viewport_height); mScreen.setSampleBuffer(&mSampleBuffer); if (LLPipeline::sRenderDeferred) @@ -698,8 +711,10 @@ void LLPipeline::createGLBuffers() stop_glerror(); - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + GLuint resX = gViewerWindow->getWindowWidthRaw(); + GLuint resY = gViewerWindow->getWindowHeightRaw(); + GLuint viewport_width = gViewerWindow->getWorldViewWidthRaw(); + GLuint viewport_height = gViewerWindow->getWorldViewHeightRaw(); if (LLPipeline::sRenderGlow) { //screen space glow buffers @@ -711,7 +726,7 @@ void LLPipeline::createGLBuffers() mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); } - allocateScreenBuffer(resX,resY); + allocateScreenBuffer(resX,resY, viewport_width, viewport_height); } if (sRenderDeferred) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index ce50a37405..9193e19bb1 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -111,7 +111,7 @@ public: void resizeScreenTexture(); void releaseGLBuffers(); void createGLBuffers(); - void allocateScreenBuffer(U32 resX, U32 resY); + void allocateScreenBuffer(U32 resX, U32 resY, U32 viewport_width, U32 viewport_height); void resetVertexBuffers(LLDrawable* drawable); void setUseVBO(BOOL use_vbo); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 7e19a80c10..028a5844c6 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -513,7 +513,7 @@ reference="White" /> <color name="ObjectChatColor" - reference="LtGray" /> + reference="0.7 0.8 0.9 1" /> <color name="OverdrivenColor" value="1 0 0 1" /> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 48c7236796..4c4b6a3899 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -38,6 +38,8 @@ <texture name="Blank" file_name="Blank.png" preload="false" /> <texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" /> + <texture name="BottomTray_Scroll_Right" file_name="navbar/Arrow_Right_Off.png" preload="false" /> + <texture name="BottomTray_Scroll_Left" file_name="navbar/Arrow_Left_Off.png" preload="false" /> <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> @@ -529,6 +531,8 @@ <texture name="Toolbar_Right_Off" file_name="containers/Toolbar_Right_Off.png" preload="false" /> <texture name="Toolbar_Right_Press" file_name="containers/Toolbar_Right_Press.png" preload="false" /> <texture name="Toolbar_Right_Selected" file_name="containers/Toolbar_Right_Selected.png" preload="false" /> + + <texture name="Tooltip" file_name="widgets/Tooltip.png" preload="true" scale.left="2" scale.top="1" scale.right="99" scale.bottom="14" /> <texture name="TrashItem_Disabled" file_name="icons/TrashItem_Disabled.png" preload="false" /> <texture name="TrashItem_Off" file_name="icons/TrashItem_Off.png" preload="false" /> diff --git a/indra/newview/skins/default/textures/widgets/Tooltip.png b/indra/newview/skins/default/textures/widgets/Tooltip.png Binary files differnew file mode 100644 index 0000000000..f989ac9083 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Tooltip.png diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml index a0f9bb59fd..3a1499eaaa 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml @@ -16,7 +16,7 @@ </floater.string> <floater.string name="no_one_near"> - No-one near + No one near </floater.string> <floater.string name="no_results"> diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml index 16873df310..9c2898945b 100644 --- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml @@ -4,13 +4,17 @@ can_close="false" can_minimize="false" can_tear_off="false" - height="200" + height="125" layout="topleft" name="incoming call" help_topic="incoming_call" title="UNKNOWN PERSON IS CALLING" - width="240"> - <floater.string + width="410"> + <floater.string + name="localchat"> + Local Voice Chat + </floater.string> + <floater.string name="anonymous"> anonymous </floater.string> @@ -31,18 +35,26 @@ left_delta="19" top="35" width="36" /> - <text_editor - font="SansSerif" - height="64" - border_visible="false" + <text + font="SansSerifLarge" + height="20" layout="topleft" left="77" - max_length="2147483647" name="caller name" - read_only="true" - top="21" - width="163" + top="27" + width="315" word_wrap="true" /> + <text + font="SansSerif" + height="50" + layout="topleft" + left="77" + name="question" + top="52" + width="315" + word_wrap="true"> + Do you want to leave [CURRENT_CHAT] and join this voice chat? + </text> <button height="24" label="Accept" @@ -57,16 +69,14 @@ label="Reject" label_selected="Reject" layout="topleft" - left_delta="0" name="Reject" - top_pad="12" + left_pad="10" width="100" /> <button height="24" label="Start IM" layout="topleft" - left_delta="0" name="Start IM" - top_pad="12" + left_pad="10" width="100" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index 30639f955f..b48c962413 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -36,10 +36,10 @@ filename="panel_main_inventory.xml" follows="all" layout="topleft" + hide_top_panel="true" left="0" label="Inventory Panel" name="Inventory Panel" top="15" - width="467"> -</panel> + width="467" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml index 68dd2001af..8122386fae 100644 --- a/indra/newview/skins/default/xui/en/floater_media_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - bottom="-666" + bottom="666" can_close="true" can_drag_on_left="false" can_minimize="true" @@ -12,14 +12,14 @@ width="365" height="535" left="330" - min_height="430" - min_width="620" + min_height="535" + min_width="365" mouse_opaque="true" - name="Media Settings" + name="media_settings" help_topic = "media_settings" title="MEDIA SETTINGS"> <button - bottom="-525" + bottom="525" enabled="true" follows="right|bottom" font="SansSerif" @@ -61,7 +61,7 @@ scale_image="true" width="90" /> <tab_container - bottom="-500" + bottom="500" enabled="true" follows="left|top|right|bottom" height="485" diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml new file mode 100644 index 0000000000..44956f7e52 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_close="false" + can_minimize="false" + can_tear_off="false" + height="125" + layout="topleft" + name="outgoing call" + help_topic="outgoing_call" + title="CALLING" + width="410"> + <floater.string + name="localchat"> + Local Voice Chat + </floater.string> + <floater.string + name="anonymous"> + anonymous + </floater.string> + <floater.string + name="VoiceInviteP2P"> + is calling. + </floater.string> + <floater.string + name="VoiceInviteAdHoc"> + has joined a Voice Chat call with a conference chat. + </floater.string> + <avatar_icon + enabled="false" + follows="left|top" + height="36" + image_name="icon_avatar_online.tga" + layout="topleft" + left_delta="19" + top="35" + width="36" /> + <text + font="SansSerifLarge" + height="20" + layout="topleft" + left="77" + name="calling" + top="27" + width="315" + word_wrap="true"> +Calling [CALLEE_NAME] + </text> + <text + font="SansSerif" + height="50" + layout="topleft" + left="77" + name="leaving" + top="52" + width="315" + word_wrap="true"> +Leaving [CURRENT_CHAT]. + </text> + <button + height="24" + label="Cancel" + label_selected="Cancel" + left="70" + layout="topleft" + name="Cancel" + left_pad="10" + width="100" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml index b9cf456842..d9498586af 100644 --- a/indra/newview/skins/default/xui/en/floater_search.xml +++ b/indra/newview/skins/default/xui/en/floater_search.xml @@ -25,7 +25,7 @@ Done </floater.string> <layout_stack - bottom="400" + bottom="512" follows="left|right|top|bottom" layout="topleft" left="10" @@ -54,7 +54,7 @@ layout="topleft" left_delta="0" name="status_text" - top_pad="4" + top_pad="5" width="150" /> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml index 44dcb07526..a2055d8c52 100644 --- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml +++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml @@ -385,6 +385,16 @@ line to actually fit left="10" width="250" follows="top|left" + font.name="Monospace" + name="test_text10" + tool_tip="text"> + Monospace Button Flyout Checkbox + </text> + <text + top_pad="10" + left="10" + width="250" + follows="top|left" font.name="SansSerifSmall" name="test_text10" tool_tip="text"> diff --git a/indra/newview/skins/default/xui/en/inspect_remote_object.xml b/indra/newview/skins/default/xui/en/inspect_remote_object.xml new file mode 100644 index 0000000000..07c684d904 --- /dev/null +++ b/indra/newview/skins/default/xui/en/inspect_remote_object.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- + Not can_close / no title to avoid window chrome + Single instance - only have one at a time, recycle it each spawn +--> +<floater + legacy_header_height="18" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="145" + layout="topleft" + name="inspect_remote_object" + single_instance="true" + sound_flags="0" + visible="true" + width="300"> + <text + follows="all" + font="SansSerifLargeBold" + height="16" + left="8" + name="object_name" + text_color="White" + top="5" + use_ellipses="true" + width="290"> + Test Object Name That Is Really Long + </text> + <text + follows="all" + font="SansSerif" + height="20" + left="8" + name="object_owner_label" + width="55" + top_pad="20"> + Owner: + </text> + <text + follows="top|left" + font="SansSerif" + height="20" + left_pad="10" + name="object_owner" + use_ellipses="true" + width="200" + word_wrap="false"> + Longavatarname Johnsonlongstonnammer + </text> + <text + follows="top|left" + font="SansSerif" + height="20" + left="8" + name="object_slurl_label" + top_pad="10" + width="55"> + Location: + </text> + <text + follows="top|left" + height="20" + left_pad="10" + name="object_slurl" + width="240" + use_ellipses="true" + word_wrap="false"> + http://slurl.com/Ahern/50/50/50 + </text> + <button + follows="top|left" + font="SansSerif" + height="20" + label="Map" + left="10" + name="map_btn" + top="114" + width="75" /> + <button + follows="top|left" + font="SansSerif" + height="20" + label="Block" + left_pad="5" + name="block_btn" + top_delta="0" + width="75" /> + <button + follows="top|left" + font="SansSerif" + height="20" + label="Close" + right="-10" + name="close_btn" + top_delta="0" + width="75" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 5eb0560962..bd60574a95 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -185,6 +185,14 @@ <menu_item_call.on_click function="Advanced.ShowSideTray" /> </menu_item_call> + <menu_item_call + label="Widget Test" + name="Widget Test" + shortcut="control|shift|T"> + <menu_item_call.on_click + function="ShowFloater" + parameter="test_widgets" /> + </menu_item_call> <menu_item_check label="Reg In Client Test (restart)" name="Reg In Client Test (restart)"> diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml new file mode 100644 index 0000000000..c3283c6014 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<context_menu + layout="topleft" + name="Participant List Context Menu"> + <menu_item_check + label="Mute Text" + layout="topleft" + name="MuteText"> + <on_check + function="ParticipantList.CheckItem" + parameter="is_muted" /> + <on_click + function="ParticipantList.ToggleMuteText" /> + <on_enable + function="ParticipantList.EnableItem" + parameter="can_mute_text" /> + </menu_item_check> + <menu_item_check + label="Allow text chat" + layout="topleft" + name="AllowTextChat"> + <on_check + function="ParticipantList.CheckItem" + parameter="is_allowed_text_chat" /> + <on_click + function="ParticipantList.ToggleAllowTextChat" /> + <on_enable + function="ParticipantList.EnableItem" + parameter="can_allow_text_chat" /> + </menu_item_check> +</context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml index c002cd078f..39f9e48609 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml @@ -2,15 +2,36 @@ <menu name="menu_group_plus" left="0" bottom="0" visible="false" mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false"> - <menu_item_call name="sort_recent" label="Sort by Recent Speakers"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_recent" /> - </menu_item_call> - <menu_item_call name="sort_name" label="Sort by Name"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_name" /> - </menu_item_call> - <menu_item_call name="sort_distance" label="Sort by Distance"> - <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_distance" /> - </menu_item_call> + <menu_item_check + label="Sort by Recent Speakers" + name="sort_by_recent_speakers"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_by_recent_speakers"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_by_recent_speakers"/> + </menu_item_check> + <menu_item_check + label="Sort by Name" + name="sort_name"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_name"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_name"/> + </menu_item_check> + <menu_item_check + label="Sort by Distance" + name="sort_distance"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="sort_distance"/> + <menu_item_check.on_check + function="People.Nearby.ViewSort.CheckItem" + parameter="sort_distance"/> + </menu_item_check> <menu_item_separator layout="topleft" /> <menu_item_check name="view_icons" label="View People Icons"> <menu_item_check.on_click diff --git a/indra/newview/skins/default/xui/en/menu_picks_plus.xml b/indra/newview/skins/default/xui/en/menu_picks_plus.xml new file mode 100644 index 0000000000..3065239615 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_picks_plus.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + height="201" + layout="topleft" + mouse_opaque="false" + name="picks_plus_menu" + width="120"> + <menu_item_call + name="create_pick" + label="New Pick"> + <menu_item_call.on_click + function="Picks.Plus.Action" + userdata="new_pick" /> + </menu_item_call> + <menu_item_call + name="create_classified" + label="New Classified"> + <menu_item_call.on_click + function="Picks.Plus.Action" + userdata="new_classified" /> + </menu_item_call> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 1499095bcc..e98a6d57bb 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -843,18 +843,18 @@ <menu_item_call.on_click
function="Floater.Toggle"
parameter="perm_prefs" />
- <menu_item_check
- label="Show Advanced Permissions"
- layout="topleft"
- name="DebugPermissions">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugPermissions" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugPermissions" />
- </menu_item_check>
</menu_item_call>
+ <menu_item_check
+ label="Show Advanced Permissions"
+ layout="topleft"
+ name="DebugPermissions">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugPermissions" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugPermissions" />
+ </menu_item_check>
<!--menu_item_call
label="Show Script Warning/Error Window"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 989dc88851..ff0cd7ffeb 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3051,6 +3051,18 @@ Teleport to [PICK]? </notification> <notification + icon="alertmodal.tga" + name="TeleportToClassified" + type="alertmodal"> + Teleport to [CLASSIFIED]? + <usetemplate + ignoretext="Confirm that I want to teleport to a location in Classifieds" + name="okcancelignore" + notext="Cancel" + yestext="Teleport"/> + </notification> + + <notification icon="alert.tga" label="Message everyone in your Estate" name="MessageEstate" @@ -4684,7 +4696,12 @@ The objects on the selected parcel that are NOT owned by you have been returned icon="notify.tga" name="ServerObjectMessage" type="notify"> +Message from [NAME]: [MSG] + <usetemplate + name="okcancelbuttons" + notext="OK" + yestext="Inspect"/> </notification> <notification @@ -5001,6 +5018,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a name="GodMessage" type="notify"> [NAME] + [MESSAGE] </notification> 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 0c42686531..2eaa3a94ee 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 @@ -30,7 +30,7 @@ <avatar_icon follows="top|left" height="20" - image_name="smile.png" + default_icon_name="Generic_Person" layout="topleft" left="5" mouse_opaque="true" diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 3fbc8e1afd..3c16a439d9 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -13,6 +13,8 @@ chrome="true" border_visible="false" width="1000"> + <string name="SpeakBtnToolTip">Turns microphone on/off</string> + <string name="VoiceControlBtnToolTip">Shows/hides voice control panel</string> <layout_stack mouse_opaque="false" border_size="0" @@ -45,7 +47,7 @@ min_height="23" width="310" top="0" - min_width="310" + min_width="192" name="chat_bar" user_resize="false" filename="panel_nearby_chat_bar.xml" /> @@ -70,9 +72,7 @@ left="0" name="talk" top="3" - width="100" - speak_button.tool_tip="Turns microphone on/off" - show_button.tool_tip="Shows/hides voice control panel" /> + width="100" /> </layout_panel> <icon auto_resize="false" @@ -92,13 +92,13 @@ height="28" layout="topleft" min_height="28" - width="80" + width="82" top_delta="0" - min_width="76" + min_width="82" name="gesture_panel" user_resize="false"> - <button - follows="right" + <gesture_combo_box + follows="left|right" height="23" label="Gesture" layout="topleft" @@ -106,7 +106,7 @@ left="0" top="3" use_ellipses="true" - width="80" + width="82" tool_tip="Shows/hides gestures"/> </layout_panel> <icon @@ -129,8 +129,9 @@ layout="topleft" min_height="28" name="movement_panel" + user_resize="false" width="80" - min_width="76"> + min_width="80"> <button follows="left|right" height="23" @@ -166,10 +167,10 @@ height="28" layout="topleft" min_height="28" - min_width="76" + min_width="80" name="cam_panel" - top_delta="-10" - width="100"> + user_resize="false" + width="80"> <button follows="left|right" height="23" @@ -205,10 +206,11 @@ follows="left|right" height="28" layout="topleft" + min_width="40" name="snapshot_panel" width="40"> <button - follows="left|right" + follows="left|right" height="23" left="0" label="" @@ -217,9 +219,12 @@ width="36" top="3" image_overlay="Snapshot_Off" - tool_tip="Take snapshot" - /> - </layout_panel> + tool_tip="Take snapshot"> + <button.commit_callback + function="Floater.Toggle" + parameter="snapshot" /> + </button> + </layout_panel> <layout_panel mouse_opaque="false" follows="left|right" @@ -228,20 +233,48 @@ top="0" name="chiclet_list_panel" width="189" - min_width="189" + min_width="180" user_resize="false" auto_resize="true"> +<!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same +as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. EXT-991--> <chiclet_panel mouse_opaque="false" follows="left|right" height="28" layout="topleft" left="0" + min_width="180" name="chiclet_list" top="0" chiclet_padding="3" scrolling_offset="40" - width="189" /> + width="189"> + <button + auto_resize="true" + follows="right" + height="23" + image_selected="BottomTray_Scroll_Left" + image_unselected="BottomTray_Scroll_Left" + layout="topleft" + name="chicklet_left_scroll_button" + tab_stop="false" + top="3" + visible="false" + width="20" /> + <button + auto_resize="true" + follows="right" + height="23" + image_selected="BottomTray_Scroll_Right" + image_unselected="BottomTray_Scroll_Right" + layout="topleft" + name="chicklet_right_scroll_button" + tab_stop="false" + top="3" + visible="false" + width="20" /> + </chiclet_panel> </layout_panel> <icon auto_resize="false" @@ -285,9 +318,9 @@ /> <unread_notifications width="34" - height="23" - left="22" - top="23" /> + height="20" + left="0" + top="19" /> </chiclet_notification> </layout_panel> <icon diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml new file mode 100644 index 0000000000..bdca8531dc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="true" + follows="all" + height="570" + layout="topleft" + left="0" + min_height="350" + name="panel_classified_info" + top="0" + width="333"> + <panel.string + name="type_mature"> + Mature + </panel.string> + <panel.string + name="type_pg"> + PG Content + </panel.string> + <button + follows="top|right" + height="23" + image_overlay="BackArrow_Off" + layout="topleft" + name="back_btn" + picture_style="true" + left="10" + tab_stop="false" + top="2" + width="23" /> + <text + follows="top|left|right" + font="SansSerifHugeBold" + height="26" + layout="topleft" + left_pad="10" + name="title" + text_color="white" + top="0" + value="Classified Info" + use_ellipses="true" + width="275" /> + <scroll_container + color="DkGray2" + opaque="true" + follows="all" + height="500" + layout="topleft" + left="10" + top_pad="10" + name="profile_scroll" + reserve_scroll_corner="false" + width="313"> + <panel + name="scroll_content_panel" + follows="left|top" + min_height="300" + layout="topleft" + top="0" + background_visible="false" + height="500" + left="0" + width="295"> + <texture_picker + enabled="false" + follows="left|top" + height="197" + layout="topleft" + left="10" + name="classified_snapshot" + top="20" + width="290" /> + <text + follows="left|top|right" + height="35" + width="290" + layout="topleft" + font="SansSerifBig" + font.style="BOLD" + left="10" + top_pad="10" + name="classified_name" + text_color="white" + value="[name]" + use_ellipses="true" /> + <text + follows="left|top" + height="25" + layout="topleft" + left="10" + name="classified_location" + width="290" + word_wrap="true" + value="[loading...]" /> + <text + follows="left|top|right" + height="18" + layout="topleft" + left="10" + name="content_type" + width="290" + top_pad="5" + value="[content type]" /> + <text + follows="left|top|right" + height="18" + layout="topleft" + left="10" + name="category" + width="290" + top_pad="5" + value="[category]" /> + <check_box + enabled="false" + height="16" + label="Auto renew each week" + layout="topleft" + left="10" + name="auto_renew" + top_pad="5" + width="290" /> + <text + follows="left|top" + halign="left" + height="16" + layout="topleft" + left="10" + name="price_for_listing" + top_pad="5" + tool_tip="Price for listing." + width="105"> + L$[PRICE] + </text> + <text + follows="left|top|right" + height="200" + layout="topleft" + left="10" + name="classified_desc" + width="290" + value="[description]" + word_wrap="true" /> + </panel> + </scroll_container> + <panel + follows="left|right|bottom" + height="20" + layout="topleft" + top_pad="8" + left="10" + name="buttons"> + <button + follows="bottom|left" + font="SansSerifSmall" + height="19" + label="Teleport" + layout="topleft" + left="0" + name="teleport_btn" + top="0" + width="90" /> + <button + follows="bottom|left" + font="SansSerifSmall" + height="19" + label="Map" + layout="topleft" + left_pad="10" + name="show_on_map_btn" + top="0" + width="90" /> + <button + follows="bottom|left" + font="SansSerifSmall" + height="19" + label="Edit" + layout="topleft" + right="-1" + name="edit_btn" + top="0" + width="90" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml new file mode 100644 index 0000000000..ee333be0cb --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + bevel_style="none" + follows="top|left|right" + height="85" + layout="topleft" + left="0" + name="classified_item" + top="0" + width="313"> + <icon + follows="all" + height="85" + image_name="ListItem_Over" + right="-3" + mouse_opaque="false" + name="hovered_icon" + top="1" + scale_image="true" + visible="false" + width="307"/> + <icon + follows="all" + height="85" + image_name="ListItem_Select" + right="-3" + mouse_opaque="false" + name="selected_icon" + top="1" + scale_image="true" + visible="false" + width="307"/> + <texture_picker + allow_no_texture="true" + border_enabled="true" + default_image_name="TabIcon_Places_Large" + enabled="false" + follows="left|top" + height="80" + layout="topleft" + left="10" + mouse_opaque="false" + name="picture" + tab_stop="false" + top="10" + top_pad="10" + width="90" /> + <text + follows="top|left|right" + font="SansSerifSmallBold" + height="16" + layout="topleft" + left="110" + name="name" + text_color="white" + top="9" + use_ellipses="false" + width="197" + word_wrap="false" /> + <expandable_text + follows="top|left|right" + font="SansSerifSmall" + height="40" + layout="topleft" + left="110" + name="description" + top_pad="3" + width="178" + word_wrap="true" /> + <button + follows="top|right" + height="16" + image_selected="BuyArrow_Press" + image_pressed="BuyArrow_Press" + image_unselected="BuyArrow_Press" + layout="topleft" + name="info_chevron" + picture_style="true" + right="-7" + tab_stop="false" + top="27" + width="16" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml new file mode 100644 index 0000000000..2f3277804f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="true" + bevel_style="in" + follows="left|top|right|bottom" + height="570" + label="Edit Classified" + layout="topleft" + left="0" + min_height="350" + name="panel_edit_classified" + top="0" + width="333"> + <panel.string + name="location_notice"> + (will update after save) + </panel.string> + <button + follows="top|right" + height="23" + image_overlay="BackArrow_Off" + layout="topleft" + name="back_btn" + picture_style="true" + left="10" + tab_stop="false" + top="2" + width="23" /> + <text + type="string" + length="1" + follows="top" + font="SansSerifHuge" + height="15" + layout="topleft" + left_pad="10" + name="title" + text_color="white" + top="5" + width="250"> + Edit Classified + </text> + <scroll_container + color="DkGray2" + follows="all" + height="510" + layout="topleft" + left="10" + top_pad="10" + name="profile_scroll" + reserve_scroll_corner="false" + opaque="true" + width="313"> + <panel + name="scroll_content_panel" + follows="left|top" + min_height="300" + layout="topleft" + top="0" + background_visible="false" + height="600" + left="0" + width="295"> + <texture_picker + follows="left|top|right" + height="197" + width="290" + layout="topleft" + top="20" + left="10" + name="classified_snapshot" /> + <icon + height="18" + image_name="AddItem_Off" + layout="topleft" + right="-5" + name="edit_icon" + label="" + tool_tip="Click to select an image" + top="27" + width="18" /> + <text + type="string" + length="1" + follows="left|top" + height="15" + font="SansSerifSmall" + font.style="BOLD" + layout="topleft" + left="10" + top="215" + name="Name:" + text_color="white" + width="290"> + Title: + </text> + <line_editor + follows="left|top|right" + font="SansSerif" + height="20" + layout="topleft" + left="10" + top_pad="2" + max_length="63" + name="classified_name" + text_color="black" + width="290" /> + <text + type="string" + length="1" + follows="left|top" + height="15" + font="SansSerifSmall" + font.style="BOLD" + layout="topleft" + left="10" + top_pad="20" + name="description_label" + text_color="white" + width="290"> + Description: + </text> + <text_editor + follows="left|top|right" + height="100" + width="290" + hide_scrollbar="false" + layout="topleft" + left="10" + top_pad="2" + max_length="1023" + name="classified_desc" + text_color="black" + word_wrap="true" /> + <text + type="string" + length="1" + font="SansSerifSmall" + font.style="BOLD" + follows="left|top" + height="15" + layout="topleft" + left="10" + name="location_label" + text_color="white" + top_pad="20" + width="290"> + Location: + </text> + <text + type="string" + length="1" + follows="left|top" + height="50" + layout="topleft" + left="10" + name="classified_location" + right="-10" + top_pad="2" + width="290" + word_wrap="true"> + loading... + </text> + <button + follows="left|top" + height="20" + label="Set to Current Location" + layout="topleft" + left="8" + top_pad="5" + name="set_to_curr_location_btn" + width="200" /> + <combo_box + follows="left|top" + height="18" + label="" + left="10" + name="category" + top_pad="5" + width="200" /> + <combo_box + allow_text_entry="false" + follows="left|top" + height="18" + left="10" + name="content_type" + top_pad="5" + width="200"> + <combo_item + name="mature_ci" + value="Mature"> + Mature Content + </combo_item> + <combo_item + name="pg_ci" + value="PG"> + PG Content + </combo_item> + </combo_box> + <spinner + decimal_digits="0" + follows="left|top" + halign="left" + height="16" + increment="1" + label_width="20" + label="L$" + layout="topleft" + left="10" + value="50" + min_val="50" + max_val="99999" + name="price_for_listing" + top_pad="5" + tool_tip="Price for listing." + width="105" /> + <check_box + height="16" + label="Auto renew each week" + layout="topleft" + left="10" + name="auto_renew" + top_pad="5" + width="250" /> + </panel> + </scroll_container> + <panel + follows="left|right|bottom" + height="20" + label="bottom_panel" + layout="topleft" + left="10" + name="bottom_panel" + top_pad="5" + width="303"> + <button + follows="bottom|left" + height="19" + label="Save" + layout="topleft" + name="save_changes_btn" + left="0" + top="0" + width="130" /> + <button + follows="bottom|left" + height="19" + label="Cancel" + layout="topleft" + name="cancel_btn" + left_pad="5" + right="-1" + width="130" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml index f4a212ba0a..d6de5af32d 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -53,7 +53,7 @@ layout="topleft" top="0" background_visible="false" - height="470" + height="510" left="0" width="295"> <texture_picker diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 4f24c7a745..58a78a0ab8 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -8,7 +8,7 @@ left="0" top="0" name="general_tab" - width="303"> + width="310"> <panel.string name="help_text"> The General tab contains general information about this group, a list of members, general Group Preferences and member options. @@ -32,7 +32,7 @@ Hover your mouse over the options for more help. max_length="511" name="charter" top="5" - width="303" + width="305" word_wrap="true"> Group Charter </text_editor> @@ -43,10 +43,10 @@ Hover your mouse over the options for more help. heading_height="16" height="130" layout="topleft" - left_delta="0" + left="5" name="visible_members" - top_pad="0" - width="303"> + top_pad="2" + width="305"> <name_list.columns label="Member" name="name" @@ -64,7 +64,7 @@ Hover your mouse over the options for more help. left_delta="0" name="active_title_label" top_pad="5" - width="303"> + width="300"> My Title </text> <combo_box @@ -75,7 +75,7 @@ Hover your mouse over the options for more help. name="active_title" tool_tip="Sets the title that appears in your avatar's name tag when this group is active." top_pad="2" - width="303" /> + width="305" /> <check_box height="16" font="SansSerifSmall" @@ -85,7 +85,7 @@ Hover your mouse over the options for more help. name="receive_notices" tool_tip="Sets whether you want to receive Notices from this group. Uncheck this box if this group is spamming you." top_pad="5" - width="303" /> + width="300" /> <check_box height="16" label="Show in my profile" @@ -94,7 +94,7 @@ Hover your mouse over the options for more help. name="list_groups_in_profile" tool_tip="Sets whether you want to show this group in your profile" top_pad="5" - width="303" /> + width="295" /> <panel background_visible="true" bevel_style="in" @@ -106,7 +106,7 @@ Hover your mouse over the options for more help. left="5" name="preferences_container" top_pad="5" - width="303"> + width="305"> <check_box follows="right|top" height="16" diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index de1323d9cb..0082128ca4 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -9,7 +9,7 @@ background_visible="true" left="0" top="20" name="GroupInfo" - width="333"> + width="323"> <panel.string name="default_needs_apply_text"> There are unsaved changes to the current tab @@ -117,28 +117,17 @@ background_visible="true" width="120" /> <accordion follows="all" - height="425" + height="405" layout="topleft" left="0" name="groups_accordion" top_pad="15" - width="336"> + width="323"> <accordion_tab expanded="true" layout="topleft" name="group_general_tab" title="General"> - <scroll_container - color="DkGray2" - opaque="true" - height="323" - follows="all" - layout="topleft" - left="0" - top="0" - name="general_scroll" - reserve_scroll_corner="false" - width="333"> <panel border="false" class="panel_group_general" @@ -146,27 +135,15 @@ background_visible="true" layout="topleft" left="0" help_topic="group_general_tab" - name="group_general_tab_panel" + name="group_general_tab_panel" top="0" - width="303" /> - </scroll_container> + width="300" /> </accordion_tab> <accordion_tab expanded="false" layout="topleft" name="group_roles_tab" title="Roles"> - <scroll_container - color="DkGray2" - opaque="true" - height="323" - follows="all" - layout="topleft" - left="0" - top="0" - name="roles_scroll" - reserve_scroll_corner="false" - width="333"> <panel border="false" class="panel_group_roles" @@ -177,24 +154,12 @@ background_visible="true" name="group_roles_tab_panel" top="0" width="303" /> - </scroll_container> </accordion_tab> <accordion_tab expanded="false" layout="topleft" name="group_notices_tab" title="Notices"> - <scroll_container - color="DkGray2" - opaque="true" - height="323" - follows="all" - layout="topleft" - left="0" - top="0" - name="notices_scroll" - reserve_scroll_corner="false" - width="333"> <panel border="false" class="panel_group_notices" @@ -205,24 +170,12 @@ background_visible="true" name="group_notices_tab_panel" top="0" width="303" /> - </scroll_container> </accordion_tab> <accordion_tab expanded="false" layout="topleft" name="group_land_tab" title="Land/Assets"> - <scroll_container - color="DkGray2" - opaque="true" - height="323" - follows="all" - layout="topleft" - left="0" - top="0" - name="land_scroll" - reserve_scroll_corner="false" - width="333"> <panel border="false" class="panel_group_land_money" @@ -232,8 +185,7 @@ background_visible="true" help_topic="group_land_money_tab" name="group_land_tab_panel" top="0" - width="313" /> - </scroll_container> + width="300" /> </accordion_tab> </accordion> <button 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 0c6f81f8fd..2c649642c3 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 @@ -5,10 +5,10 @@ height="510" label="Land & L$" layout="topleft" - left="1" + left="0" name="land_money_tab" top="0" - width="313"> + width="310"> <panel.string name="help_text"> Parcels owned by a group are listed along with contribution details. A warning appears until the Total Land in Use is less than or = to the Total Contribution. @@ -47,10 +47,10 @@ heading_height="20" height="150" layout="topleft" - left="0" + left="2" name="group_parcel_list" top_pad="0" - width="313"> + width="305"> <scroll_list.columns label="Parcel" name="name" @@ -79,7 +79,7 @@ label_selected="Map" layout="topleft" name="map_button" - right="-10" + right="-5" top_pad="5" width="95" enabled="false" /> @@ -185,7 +185,9 @@ layout="topleft" left_pad="3" name="your_contribution_units" - top_delta="2"> + top_delta="2" + width="40" + > m² </text> <text @@ -210,17 +212,17 @@ visible="false" width="16" /> <text - follows="left|top" + follows="left|top" type="string" word_wrap="true" font="SansSerifSmall" height="35" layout="topleft" - left_pad="0" + left_pad="5" name="group_over_limit_text" text_color="EmphasisColor" top_delta="0" - width="290"> + width="260"> Group members must contribute more land credits to support land in use </text> <text @@ -241,7 +243,7 @@ height="200" halign="center" layout="topleft" - left="10" + left="5" name="group_money_tab_container" tab_position="top" tab_height="20" @@ -268,7 +270,7 @@ left="0" max_length="4096" name="group_money_planning_text" - top="0" + top="2" width="300" word_wrap="true"> Loading... @@ -293,7 +295,7 @@ left="0" max_length="4096" name="group_money_details_text" - top="0" + top="2" width="300" word_wrap="true"> Loading... @@ -305,8 +307,8 @@ layout="topleft" name="earlier_details_button" tool_tip="Back" - top_pad="3" - right="-35" + top_pad="5" + right="-45" width="31" /> <button follows="left|top" @@ -327,7 +329,7 @@ left_delta="0" help_topic="group_money_sales_tab" name="group_money_sales_tab" - top_delta="-1" + top="5" width="300"> <text_editor type="string" @@ -337,7 +339,7 @@ left="0" max_length="4096" name="group_money_sales_text" - top="0" + top="2" width="300" word_wrap="true"> Loading... @@ -349,8 +351,8 @@ layout="topleft" name="earlier_sales_button" tool_tip="Back" - top_pad="3" - right="-35" + top_pad="5" + right="-45" width="31" /> <button follows="left|top" @@ -358,7 +360,7 @@ image_overlay="Arrow_Right_Off" layout="topleft" left_pad="10" - name="later_sales_button" + name="later_sales_button" tool_tip="Next" width="31" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 24a4005a45..e56db6414f 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -7,7 +7,7 @@ left="0" name="notices_tab" top="0" - width="313"> + width="310"> <panel.string name="help_text"> Notices are a quick way to communicate across a @@ -27,7 +27,7 @@ the General tab. word_wrap="true" height="30" layout="topleft" - left="10" + left="5" name="lbl2" top="5" width="300"> @@ -41,10 +41,10 @@ Groups are limited to 200 notices/group daily heading_height="16" height="125" layout="topleft" - left="0" + left="2" name="notice_list" top_pad="0" - width="303"> + width="305"> <scroll_list.columns label="" name="icon" @@ -81,10 +81,10 @@ Groups are limited to 200 notices/group daily image_disabled="AddItem_Disabled" layout="topleft" label="Create a new notice" - left="15" + left="5" name="create_new_notice" tool_tip="Create a new notice" - top_delta="-5" + top_delta="0" width="18" /> <button follows="top|left" @@ -93,7 +93,7 @@ Groups are limited to 200 notices/group daily layout="topleft" name="refresh_notices" right="-5" - top_delta="5" + top_delta="0" width="23" /> <panel follows="left|top" @@ -219,7 +219,7 @@ Groups are limited to 200 notices/group daily label_selected="Send Notice" layout="topleft" right="-10" - top_pad="20" + top_pad="10" name="send_notice" width="100" /> <group_drop_target diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index 4129d7b448..604fb81c8e 100644 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -7,7 +7,7 @@ left="0" top="0" name="roles_tab" - width="313"> + width="310"> <panel.string name="default_needs_apply_text"> There are unsaved changes to the current tab @@ -28,9 +28,9 @@ name="roles_tab_container" tab_position="top" tab_height="20" - tab_min_width="96" + tab_min_width="75" top="3" - width="303"> + width="300"> <panel border="false" height="220" @@ -51,23 +51,13 @@ clicking on their names. <filter_editor layout="topleft" top="10" - left="4" + left="5" width="280" height="20" follows="left|top|right" max_length="250" label="Filter Members" name="filter_input" /> - <!-- <button - enabled="false" - font="SansSerifSmall" - height="20" - label="Show All" - layout="topleft" - left_pad="-90" - name="show_all_button" - top_delta="-6" - width="80" />--> <name_list column_padding="0" draw_heading="true" @@ -111,14 +101,6 @@ clicking on their names. right="-5" name="member_eject" width="100" /> - <!--What is this?--> - <icon - height="16" - image_name="Inv_FolderClosed" - layout="topleft" - name="power_folder_icon" - visible="false" - width="16" /> </panel> <panel border="false" @@ -156,7 +138,7 @@ including the Everyone and Owner Roles. <filter_editor layout="topleft" top="10" - left="4" + left="5" width="280" height="20" follows="left|top|right" @@ -179,12 +161,12 @@ including the Everyone and Owner Roles. draw_stripes="false" follows="left|top" heading_height="20" - height="150" + height="160" layout="topleft" search_column="1" left="0" name="role_list" - top_pad="4" + top_pad="2" width="300"> <scroll_list.columns label="Role" @@ -238,24 +220,13 @@ things in this group. There's a broad variety of Abilities. <filter_editor layout="topleft" top="10" - left="4" + left="5" width="280" height="20" follows="left|top|right" max_length="250" label="Filter Abilities" name="filter_input" /> - <!-- - <button - enabled="false" - font="SansSerifSmall" - height="20" - label="Show All" - layout="topleft" - left_pad="0" - name="show_all_button" - top_delta="0" - width="80" /> --> <scroll_list column_padding="0" draw_stripes="false" @@ -267,14 +238,14 @@ things in this group. There's a broad variety of Abilities. name="action_list" search_column="1" tool_tip="Select an Ability to view more details" - top_pad="6" + top_pad="2" width="300"> <scroll_list.columns label="" name="icon" width="16" /> <scroll_list.columns - label="" + label="Action" name="action" width="247" /> </scroll_list> @@ -293,9 +264,9 @@ things in this group. There's a broad variety of Abilities. follows="left|top" left="10" name="members_footer" - top_pad="10" + top="245" top_delta="0" - width="300"> + width="290"> <text type="string" height="16" @@ -304,7 +275,7 @@ things in this group. There's a broad variety of Abilities. left="0" name="static" top_pad="5" - width="295"> + width="285"> Assigned Roles </text> <scroll_list @@ -315,7 +286,7 @@ things in this group. There's a broad variety of Abilities. left="0" name="member_assigned_roles" top_pad="0" - width="295"> + width="285"> <scroll_list.columns label="" name="checkbox" @@ -323,7 +294,7 @@ things in this group. There's a broad variety of Abilities. <scroll_list.columns label="" name="role" - width="265" /> + width="255" /> </scroll_list> <text type="string" @@ -333,7 +304,7 @@ things in this group. There's a broad variety of Abilities. left="0" name="static2" top_pad="5" - width="295"> + width="285"> Allowed Abilities </text> <scroll_list @@ -345,7 +316,7 @@ things in this group. There's a broad variety of Abilities. search_column="2" tool_tip="For details of each allowed ability see the abilities tab" top_pad="0" - width="295"> + width="285"> <scroll_list.columns label="" name="icon" @@ -353,7 +324,7 @@ things in this group. There's a broad variety of Abilities. <scroll_list.columns label="" name="action" - width="275" /> + width="265" /> </scroll_list> </panel> <panel @@ -364,7 +335,7 @@ things in this group. There's a broad variety of Abilities. top_delta="0" top="245" visible="false" - width="300"> + width="290"> <text type="string" height="16" @@ -386,7 +357,7 @@ things in this group. There's a broad variety of Abilities. max_length="295" name="role_name" top_pad="0" - width="295"> + width="290"> Employees </line_editor> <text @@ -395,7 +366,7 @@ things in this group. There's a broad variety of Abilities. layout="topleft" name="static3" top_pad="5" - width="295"> + width="290"> Title </text> <line_editor @@ -408,7 +379,7 @@ things in this group. There's a broad variety of Abilities. max_length="295" name="role_title" top_pad="0" - width="295"> + width="290"> (waiting) </line_editor> <text @@ -442,7 +413,7 @@ things in this group. There's a broad variety of Abilities. left="0" name="static4" top_pad="5" - width="295"> + width="290"> Assigned Roles </text> <name_list @@ -452,7 +423,7 @@ things in this group. There's a broad variety of Abilities. left="0" name="role_assigned_members" top_pad="0" - width="295" /> + width="290" /> <check_box height="15" label="Reveal members" @@ -469,7 +440,7 @@ things in this group. There's a broad variety of Abilities. left="0" name="static5" top_pad="5" - width="295"> + width="290"> Allowed Abilities </text> <scroll_list @@ -504,7 +475,7 @@ things in this group. There's a broad variety of Abilities. top_delta="0" top="245" visible="false" - width="300"> + width="290"> <text type="string" height="16" @@ -550,7 +521,7 @@ things in this group. There's a broad variety of Abilities. layout="topleft" name="static3" top_pad="5" - width="295"> + width="290"> Members with this ability </text> <name_list @@ -558,6 +529,6 @@ things in this group. There's a broad variety of Abilities. layout="topleft" name="action_members" top_pad="0" - width="295" /> + width="290" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml index 26d8304551..be56866119 100644 --- a/indra/newview/skins/default/xui/en/panel_instant_message.xml +++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml @@ -79,7 +79,7 @@ text_color="white" top="33" use_ellipses="true" - value="MESSAGE" + value="" width="285" word_wrap="true" max_length="350" /> diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index 0c24adfad5..b01ddbf75a 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -43,6 +43,16 @@ name="acquired_date"> [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] </string> + <!-- Texture names for rating icons --> + <string + name="icon_PG" + value="parcel_drk_PG" /> + <string + name="icon_M" + value="parcel_drk_M" /> + <string + name="icon_R" + value="parcel_drk_R" /> <button follows="top|right" height="23" @@ -125,6 +135,24 @@ top_pad="10" value="Du waltz die spritz" width="300" /> + <icon + follows="top|left" + height="16" + image_name="unknown" + layout="topleft" + left="10" + name="maturity_icon" + top_pad="10" + width="18" /> + <text + follows="right|top" + height="16" + layout="topleft" + left_pad="8" + name="maturity_value" + top_delta="0" + value="unknown" + width="268" /> <panel follows="left|top|right" height="55" diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index a12797d96b..1ef845b769 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -9,7 +9,7 @@ top="21" width="310"> <string name="min_width"> - 310 + 192 </string> <string name="max_width"> 320 diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 15fdd73bdc..9fac7d34f7 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -16,7 +16,7 @@ background_visible="true" value="No people" /> <string name="no_one_near" - value="No-one near" /> + value="No one near" /> <string name="no_friends_online" value="No friends online" /> diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index ae61852f68..9cfbed432a 100644 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ b/indra/newview/skins/default/xui/en/panel_picks.xml @@ -8,16 +8,58 @@ name="panel_picks" top="0" width="313"> + <string + name="no_picks" + value="No Picks" /> + <string + name="no_classifieds" + value="No Classifieds" /> + + <accordion + follows="all" + height="465" + layout="topleft" + left="0" + name="accordion" + top="0" + single_expansion="true" + width="313"> + <accordion_tab + can_resize="false" + layout="topleft" + height="235" + min_height="150" + name="tab_picks" + title="Picks" + visible="false"> <flat_list_view color="DkGray2" follows="all" - height="465" layout="topleft" left="0" name="picks_list" opaque="true" top="0" width="313" /> + </accordion_tab> + <accordion_tab + can_resize="false" + layout="topleft" + height="235" + name="tab_classifieds" + title="Classifieds" + visible="false"> + <flat_list_view + color="DkGray2" + follows="all" + layout="topleft" + left="0" + name="classifieds_list" + opaque="true" + top="0" + width="313" /> + </accordion_tab> + </accordion> <panel background_visible="true" bevel_style="none" diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 65f150b33c..e6084202d7 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -179,7 +179,6 @@ min_height="300" name="scrolling_panel" top="0" - value=">" width="313"> <texture_picker enabled="false" @@ -296,6 +295,24 @@ top_delta="0" value="Alex Superduperlongenamenton" width="205" /> + <icon + follows="top|left" + height="16" + image_name="unknown" + layout="topleft" + left="10" + name="maturity_icon" + top_delta="0" + width="18" /> + <text + follows="right|top" + height="16" + layout="topleft" + left_pad="8" + name="maturity_value" + top_delta="0" + value="unknown" + width="268" /> <accordion follows="all" height="230" @@ -308,222 +325,211 @@ layout="topleft" name="parcel_characteristics_tab" title="Parcel"> - <scroll_container - color="DkGray2" + <panel follows="all" - height="132" + height="160" layout="topleft" left="0" - name="parcel_scroll" - opaque="true" top="0" - width="290"> - <panel - follows="all" - height="165" + width="275"> + <icon + follows="top|left" + height="16" + image_name="parcel_drk_PG" layout="topleft" - left="0" + left="10" + name="rating_icon" top="0" - width="275"> - <icon - follows="top|left" - height="16" - image_name="parcel_drk_PG" - layout="topleft" - left="20" - name="rating_icon" - top="0" - width="18" /> - <text - follows="left|top" - height="16" - layout="topleft" - left_pad="8" - name="rating_label" - value="Rating:" - width="80" /> - <text - follows="right|top" - height="16" - layout="topleft" - left_pad="0" - name="rating_value" - top_delta="0" - value="unknown" - width="120" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Voice" - layout="topleft" - left="20" - name="voice_icon" - top_pad="5" - width="22" /> - <text - follows="left|top" - height="18" - layout="topleft" - left_pad="8" - name="voice_label" - top_delta="0" - value="Voice:" - width="76" /> - <text - follows="right|top" - height="18" - layout="topleft" - left_pad="0" - name="voice_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Fly" - layout="topleft" - left="20" - name="fly_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="16" - layout="topleft" - left_pad="8" - name="fly_label" - value="Fly:" - width="76" /> - <text - follows="right|top" - height="16" - layout="topleft" - left_pad="0" - name="fly_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Push" - layout="topleft" - left="20" - name="push_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="push_label" - value="Push:" - width="76" /> - <text - follows="right|top" - height="14" - layout="topleft" - left_pad="0" - name="push_value" - top_delta="0" - value="Off" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Build" - layout="topleft" - left="20" - name="build_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="build_label" - value="Build:" - width="76" /> - <text - follows="right|top" - height="15" - layout="topleft" - left_pad="0" - name="build_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Scripts" - layout="topleft" - left="20" - name="scripts_icon" - top_pad="3" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="scripts_label" - value="Scripts:" - width="76" /> - <text - follows="right|top" - height="14" - layout="topleft" - left_pad="0" - name="scripts_value" - top_delta="0" - value="On" - width="60" /> - <icon - follows="top|left" - height="18" - image_name="parcel_drk_Damage" - layout="topleft" - left="20" - name="damage_icon" - top_pad="7" - width="22" /> - <text - follows="left|top" - height="14" - layout="topleft" - left_pad="8" - name="damage_label" - value="Damage:" - width="76" /> - <text - follows="right|top" - height="14" - layout="topleft" - left_pad="0" - name="damage_value" - top_delta="0" - value="Off" - width="60" /> - <button - follows="bottom|right" - height="19" - label="About Land" - layout="topleft" - name="about_land_btn" - right="-5" - tab_stop="false" - top="138" - width="90"> - <click_callback - function="ShowFloater" - parameter="about_land" /> - </button> - </panel> - </scroll_container> + width="18" /> + <text + follows="left|top" + height="16" + layout="topleft" + left_pad="12" + name="rating_label" + value="Rating:" + width="60" /> + <text + follows="left|right|top" + height="16" + layout="topleft" + left_pad="0" + name="rating_value" + top_delta="0" + value="unknown" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Voice" + layout="topleft" + left="10" + name="voice_icon" + top_pad="5" + width="22" /> + <text + follows="left|top" + height="18" + layout="topleft" + left_pad="8" + name="voice_label" + top_delta="0" + value="Voice:" + width="60" /> + <text + follows="left|right|top" + height="18" + layout="topleft" + left_pad="0" + name="voice_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Fly" + layout="topleft" + left="10" + name="fly_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="16" + layout="topleft" + left_pad="8" + name="fly_label" + value="Fly:" + width="60" /> + <text + follows="left|right|top" + height="16" + layout="topleft" + left_pad="0" + name="fly_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Push" + layout="topleft" + left="10" + name="push_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="push_label" + value="Push:" + width="60" /> + <text + follows="left|right|top" + height="14" + layout="topleft" + left_pad="0" + name="push_value" + top_delta="0" + value="Off" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Build" + layout="topleft" + left="10" + name="build_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="build_label" + value="Build:" + width="60" /> + <text + follows="left|right|top" + height="15" + layout="topleft" + left_pad="0" + name="build_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Scripts" + layout="topleft" + left="10" + name="scripts_icon" + top_pad="3" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="scripts_label" + value="Scripts:" + width="60" /> + <text + follows="left|right|top" + height="14" + layout="topleft" + left_pad="0" + name="scripts_value" + top_delta="0" + value="On" + width="60" /> + <icon + follows="top|left" + height="18" + image_name="parcel_drk_Damage" + layout="topleft" + left="10" + name="damage_icon" + top_pad="7" + width="22" /> + <text + follows="left|top" + height="14" + layout="topleft" + left_pad="8" + name="damage_label" + value="Damage:" + width="60" /> + <text + follows="left|right|top" + height="14" + layout="topleft" + left_pad="0" + name="damage_value" + top_delta="0" + value="Off" + width="60" /> + <button + follows="bottom|right" + height="19" + label="About Land" + layout="topleft" + name="about_land_btn" + right="-5" + tab_stop="false" + top="138" + width="90"> + <click_callback + function="ShowFloater" + parameter="about_land" /> + </button> + </panel> </accordion_tab> <accordion_tab expanded="false" @@ -545,7 +551,7 @@ name="region_name_label" top_pad="5" value="Region:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" @@ -554,7 +560,7 @@ name="region_name" top_delta="0" value="Mooseland" - width="195" /> + width="187" /> <text follows="left|top" height="15" @@ -563,7 +569,7 @@ name="region_type_label" top_pad="5" value="Type:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" @@ -572,7 +578,7 @@ name="region_type" top_delta="0" value="Moose" - width="195" /> + width="187" /> <text follows="left|top" height="15" @@ -581,7 +587,7 @@ name="region_rating_label" top_pad="7" value="Rating:" - width="80" /> + width="90" /> <icon follows="top|left" height="16" @@ -597,7 +603,7 @@ left_pad="10" name="region_rating" value="Explicit" - width="100" /> + width="159" /> <text follows="left|top" height="15" @@ -606,7 +612,7 @@ name="region_owner_label" top_pad="5" value="Owner:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" @@ -615,7 +621,7 @@ name="region_owner" top_delta="0" value="moose Van Moose" - width="195" /> + width="187" /> <text follows="left|top" height="15" @@ -624,7 +630,7 @@ name="region_group_label" top_pad="5" value="Group:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" @@ -633,7 +639,7 @@ name="region_group" top_delta="0" use_ellipses="true" - width="195"> + width="187"> The Mighty Moose of mooseville soundvillemoose </text> <button @@ -671,15 +677,15 @@ name="estate_name_label" top_pad="5" value="Estate:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="90" + left_pad="0" name="estate_name" top_delta="0" - width="160" /> + width="187" /> <text follows="left|top" height="15" @@ -688,15 +694,15 @@ name="estate_rating_label" top_pad="5" value="Rating:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="90" + left_pad="0" name="estate_rating" top_delta="0" - width="160" /> + width="187" /> <text follows="left|top" height="15" @@ -705,15 +711,15 @@ name="estate_owner_label" top_pad="5" value="Owner:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="90" + left_pad="0" name="estate_owner" top_delta="0" - width="160" /> + width="187" /> <text follows="left|top" height="15" @@ -722,7 +728,7 @@ name="covenant_label" top_pad="5" value="Covenant:" - width="220" /> + width="277" /> <text_editor bg_focus_color="DkGray2" bg_readonly_color="DkGray2" @@ -735,7 +741,8 @@ name="covenant" read_only="true" top_pad="0" - width="280" /> + width="277" + word_wrap="true" /> </panel> </accordion_tab> <accordion_tab @@ -758,15 +765,15 @@ name="sales_price_label" top_pad="5" value="Price:" - width="100" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="110" + left_pad="0" name="sales_price" top_delta="0" - width="140" /> + width="187" /> <text follows="left|top" height="15" @@ -775,15 +782,15 @@ name="area_label" top_pad="5" value="Area:" - width="100" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="110" + left_pad="0" name="area" top_delta="0" - width="140" /> + width="187" /> <text follows="left|top" height="15" @@ -792,15 +799,15 @@ name="traffic_label" top_pad="5" value="Traffic:" - width="100" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="110" + left_pad="0" name="traffic" top_delta="0" - width="140" /> + width="187" /> <text follows="left|top" height="15" @@ -809,15 +816,15 @@ name="primitives_label" top_pad="5" value="Primitives:" - width="100" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="110" + left_pad="0" name="primitives" top_delta="0" - width="140" /> + width="187" /> <text follows="left|top" height="15" @@ -826,15 +833,15 @@ name="parcel_scripts_label" top_pad="5" value="Scripts:" - width="100" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="110" + left_pad="0" name="parcel_scripts" top_delta="0" - width="140" /> + width="187" /> <text follows="left|top" height="15" @@ -843,15 +850,15 @@ name="terraform_limits_label" top_pad="5" value="Terraform limits:" - width="100" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="110" + left_pad="0" name="terraform_limits" top_delta="0" - width="140" /> + width="187" /> <text follows="left|top" height="15" @@ -860,7 +867,7 @@ name="subdivide_label" top_pad="5" value="Subdivide/Join ability:" - width="220" /> + width="277" /> <text_editor bg_focus_color="DkGray2" bg_readonly_color="DkGray2" @@ -872,7 +879,8 @@ name="subdivide" read_only="true" top_pad="5" - width="245" /> + width="277" + word_wrap="true" /> <text follows="left|top" height="15" @@ -881,7 +889,7 @@ name="resale_label" top_pad="5" value="ReSale ability:" - width="80" /> + width="277" /> <text_editor bg_focus_color="DkGray2" bg_readonly_color="DkGray2" @@ -893,7 +901,8 @@ name="resale" read_only="true" top_pad="5" - width="245" /> + width="277" + word_wrap="true" /> <text follows="left|top" height="15" @@ -902,15 +911,15 @@ name="sale_to_label" top_pad="5" value="For sale to:" - width="80" /> + width="90" /> <text follows="left|top|right" height="15" layout="topleft" - left="90" + left_pad="0" name="sale_to" top_delta="0" - width="160" /> + width="187" /> </panel> </accordion_tab> </accordion> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index cbbcfe5068..5efacb68be 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -104,7 +104,7 @@ background_visible="true" follows="bottom|right" font="SansSerifSmall" height="19" - image_disabled="ForwardArrow_Disabled" + image_disabled="ForwardArrow_Off" image_selected="ForwardArrow_Press" image_unselected="ForwardArrow_Off" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 645863e7a4..5a4b0a3892 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -45,14 +45,20 @@ <color_swatch border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" - control_name="UserChatColor" follows="left|top" height="47" layout="topleft" left="30" name="user" top_pad="10" - width="44" /> + width="44" > + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="UserChatColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="UserChatColor" /> + </color_swatch> <text type="string" length="1" @@ -69,14 +75,20 @@ <color_swatch border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" - control_name="AgentChatColor" follows="left|top" height="47" layout="topleft" left="180" name="agent" top_pad="-17" - width="44" /> + width="44" > + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="AgentChatColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="AgentChatColor" /> + </color_swatch> <text type="string" length="1" @@ -94,7 +106,6 @@ border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.6 0.6 1 1" - control_name="IMChatColor" follows="left|top" height="47" label_width="60" @@ -102,8 +113,15 @@ left="350" name="im" top_pad="-17" - width="44" /> - <text + width="44"> + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="IMChatColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="IMChatColor" /> + </color_swatch> + <text type="string" length="1" follows="left|top" @@ -120,7 +138,6 @@ border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.8 1 1 1" - control_name="SystemChatColor" follows="left|top" height="47" label_width="44" @@ -128,7 +145,14 @@ left="30" name="system" top_pad="40" - width="44" /> + width="44" > + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="SystemChatColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="SystemChatColor" /> + </color_swatch> <text type="string" length="1" @@ -146,14 +170,20 @@ border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.82 0.82 0.99 1" - control_name="ScriptErrorColor" follows="left|top" height="47" layout="topleft" left="180" name="script_error" top_pad="-17" - width="44" /> + width="44"> + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="ScriptErrorColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="ScriptErrorColor" /> + </color_swatch> <text type="string" length="1" @@ -171,14 +201,20 @@ border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.7 0.9 0.7 1" - control_name="ObjectChatColor" follows="left|top" height="47" layout="topleft" left="350" name="objects" top_pad="-17" - width="44" /> + width="44" > + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="ObjectChatColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="ObjectChatColor" /> + </color_swatch> <text type="string" length="1" @@ -196,14 +232,20 @@ border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.7 0.9 0.7 1" - control_name="llOwnerSayChatColor" follows="left|top" height="47" layout="topleft" left="30" name="owner" top_pad="40" - width="44" /> + width="44" > + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="llOwnerSayChatColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="llOwnerSayChatColor" /> + </color_swatch> <text type="string" length="1" @@ -221,14 +263,20 @@ border_color="0.45098 0.517647 0.607843 1" can_apply_immediately="true" color="0.6 0.6 1 1" - control_name="HTMLLinkColor" follows="left|top" height="47" layout="topleft" left="180" name="links" top_pad="-17" - width="44" /> + width="44" > + <color_swatch.init_callback + function="Pref.getUIColor" + parameter="HTMLLinkColor" /> + <color_swatch.commit_callback + function="Pref.applyUIColor" + parameter="HTMLLinkColor" /> + </color_swatch> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index b1308a1942..9b10edde33 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -109,19 +109,7 @@ name="ui_scale_slider" top_pad="2" width="180" /> - <spinner - control_name="UIScaleFactor" - height="16" - increment="0.025" - initial_value="1" - layout="topleft" - left_pad="10" - max_val="1.4" - min_val="0.75" - name="ui_scale_slider" - top_delta="0" - width="58" /> - <text + <text type="string" length="1" follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index a9874f4553..a419a02d75 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -94,7 +94,7 @@ <sidetray_tab name="sidebar_me" help_topic="sidebar_me" - tab_title="Me" + tab_title="My Profile" description="Edit your public profile and Picks." image="TabIcon_Me_Off" image_selected="TabIcon_Me_Selected" @@ -112,7 +112,7 @@ <sidetray_tab name="sidebar_appearance" help_topic="sidebar_appearance" - tab_title="Appearance" + tab_title="My Appearance" description="Change your appearance and current look." image="TabIcon_Appearance_Off" image_selected="TabIcon_Appearance_Selected" @@ -131,7 +131,7 @@ <sidetray_tab name="sidebar_inventory" help_topic="sidebar_inventory" - tab_title="Inventory" + tab_title="My Inventory" description="Browse your inventory." image="TabIcon_Things_Off" image_selected="TabIcon_Things_Selected" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index c850dce141..761c17cfd2 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2850,7 +2850,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="IM_to_label">To</string> <string name="IM_moderator_label">(Moderator)</string> - <string name="ringing-im"> Joining Voice Chat... </string> @@ -2863,6 +2862,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="answering-im"> Connecting... </string> + <string name="conference-title"> + Ad-hoc Conference + </string> <string name="inventory_item_offered-im"> Inventory item offered </string> diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml new file mode 100644 index 0000000000..a35e2c3663 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<avatar_icon default_icon_name="Generic_Person_Large"> +</avatar_icon> diff --git a/indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml b/indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml new file mode 100644 index 0000000000..2f72ad65a1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- Global settings for all widgets ("UI Controls") --> +<ui_ctrl + font="SansSerif" + /> diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index d31a81e128..7b28a3b72c 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -76,6 +76,7 @@ LLControlGroup::LLControlGroup(const std::string& name) : LLControlGroup::~LLControlGroup() {} void LLControlGroup::setBOOL(const std::string& name, BOOL val) {} BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } +F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; } U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; } void LLControlGroup::setString(const std::string& name, const std::string& val) {} std::string LLControlGroup::getString(const std::string& name) { return "test_string"; } diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index 7a30315b9a..b14c59ab9a 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -70,7 +70,7 @@ public: LLEventPump& getEventPump() { return mPump; } private: - void sendProgressEvent(const std::string& state, const std::string& change, + LLSD getProgressEventLLSD(const std::string& state, const std::string& change, const LLSD& data = LLSD()) { LLSD status_data; @@ -87,7 +87,13 @@ private: { status_data["data"] = data; } + return status_data; + } + void sendProgressEvent(const std::string& state, const std::string& change, + const LLSD& data = LLSD()) + { + LLSD status_data = getProgressEventLLSD(state, change, data); mPump.post(status_data); } @@ -140,15 +146,28 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential // Request SRV record. LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL; - // *NOTE:Mani - Completely arbitrary timeout value for SRV request. - filter.errorAfter(5, "SRV Request timed out!"); + // *NOTE:Mani - Completely arbitrary default timeout value for SRV request. + F32 seconds_to_timeout = 5.0f; + if(credentials.has("cfg_srv_timeout")) + { + seconds_to_timeout = credentials["cfg_srv_timeout"].asReal(); + } + + filter.eventAfter(seconds_to_timeout, + getProgressEventLLSD("offline", "fail.login")); + + std::string srv_pump_name = "LLAres"; + if(credentials.has("cfg_srv_pump")) + { + srv_pump_name = credentials["cfg_srv_pump"].asString(); + } - // Make request + // Make request LLSD request; request["op"] = "rewriteURI"; request["uri"] = uri; request["reply"] = replyPump.getName(); - rewrittenURIs = postAndWait(self, request, "LLAres", filter); + rewrittenURIs = postAndWait(self, request, srv_pump_name, filter); } // we no longer need the filter LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction")); diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp index a8ae2883d5..56c21016bd 100644 --- a/indra/viewer_components/login/tests/lllogin_test.cpp +++ b/indra/viewer_components/login/tests/lllogin_test.cpp @@ -47,6 +47,7 @@ public: bool call(const LLSD& event) { mDebug(STRINGIZE("LoginListener called!: " << event)); + mLastEvent = event; return false; } @@ -414,4 +415,40 @@ namespace tut ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline"); } + + template<> template<> + void llviewerlogin_object::test<5>() + { + DEBUG; + // Test SRV request timeout. + set_test_name("LLLogin SRV timeout testing"); + + // Testing normal login procedure. + LLEventStream llaresPump("LLAres"); // Dummy LLAres pump. + + // LLAresListener dummyLLAres("dummy_llares"); + // dummyLLAres.listenTo(llaresPump); + + LLLogin login; + LoginListener listener("test_ear"); + listener.listenTo(login.getEventPump()); + + LLSD credentials; + credentials["first"] = "these"; + credentials["last"] = "don't"; + credentials["passwd"] = "matter"; + credentials["cfg_srv_timeout"] = 0.0f; + + login.connect("login.bar.com", credentials); + + ensure_equals("SRV State", listener.lastEvent()["change"].asString(), "srvrequest"); + + // Get the mainloop eventpump, which needs a pinging in order to drive the + // SRV timeout. + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); + LLSD frame_event; + mainloop.post(frame_event); + + ensure_equals("SRV Failure", listener.lastEvent()["change"].asString(), "fail.login"); + } } |