diff options
| author | Mnikolenko Productengine <mnikolenko@productengine.com> | 2026-02-25 13:45:30 +0200 |
|---|---|---|
| committer | Mnikolenko Productengine <mnikolenko@productengine.com> | 2026-02-25 13:45:30 +0200 |
| commit | e9c4c1aacffa9eb45628f6356152a70e5a61a32b (patch) | |
| tree | 5bd58156971c04c6106679f0d5a4368005cdff69 /indra | |
| parent | aa4ad2e95da5207a1250ca5fd23f7f0e6528a44e (diff) | |
| parent | 3529bc5f9d29a71355f3a3666540abff57dc1a4c (diff) | |
Merge branch 'release/2026.02' into maxim/flat-ui-fonts-update
# Conflicts:
# indra/newview/skins/default/xui/en/panel_preferences_general.xml
Diffstat (limited to 'indra')
258 files changed, 3367 insertions, 5261 deletions
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 7cce190f6a..428f9e3326 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -1,57 +1,18 @@ -# -*- cmake -*- +# Allow explicit Python path via environment variable +if(DEFINED ENV{PYTHON}) + set(Python3_ROOT_DIR "$ENV{PYTHON}") +endif() -set(PYTHONINTERP_FOUND) +# On Windows, prefer registry entries to avoid Cygwin/MSYS Python +# The registry is searched first by default, which finds native Windows Python +# installations rather than Cygwin/MSYS Python +if(WINDOWS) + set(Python3_FIND_REGISTRY FIRST CACHE STRING "Python search order") +endif() -if (DEFINED ENV{PYTHON}) - # Allow python executable to be explicitly set - set(python "$ENV{PYTHON}") - set(PYTHONINTERP_FOUND ON) -elseif (WINDOWS) - # On Windows, explicitly avoid Cygwin Python. +# Find Python 3 interpreter +find_package(Python3 REQUIRED COMPONENTS Interpreter) - # if the user has their own version of Python installed, prefer that - foreach(hive HKEY_CURRENT_USER HKEY_LOCAL_MACHINE) - # prefer more recent Python versions to older ones, if multiple versions - # are installed - foreach(pyver 3.13 3.12 3.11 3.10 3.9 3.8 3.7) - list(APPEND regpaths "[${hive}\\SOFTWARE\\Python\\PythonCore\\${pyver}\\InstallPath]") - endforeach() - endforeach() - - # TODO: This logic has the disadvantage that if you have multiple versions - # of Python installed, the selected path won't necessarily be the newest - - # e.g. this GLOB will prefer Python310 to Python311. But since pymaybe is - # checked AFTER the registry entries, this will only surface as a problem if - # no installed Python appears in the registry. - file(GLOB pymaybe - "$ENV{PROGRAMFILES}/Python*" -## "$ENV{PROGRAMFILES(X86)}/Python*" - # The Windows environment variable is in fact as shown above, but CMake - # disallows querying an environment variable containing parentheses - - # thanks, Windows. Fudge by just appending " (x86)" to $PROGRAMFILES and - # hoping for the best. - "$ENV{PROGRAMFILES} (x86)/Python*" - "c:/Python*") - - find_program(python - NAMES python3.exe python.exe - NO_DEFAULT_PATH # added so that cmake does not find cygwin python - PATHS - ${regpaths} - ${pymaybe} - ) - find_package(Python3 COMPONENTS Interpreter) -else() - find_program(python python3) - - if (python) - set(PYTHONINTERP_FOUND ON) - endif (python) -endif (DEFINED ENV{PYTHON}) - -if (NOT python) - message(FATAL_ERROR "No Python interpreter found") -endif (NOT python) - -set(PYTHON_EXECUTABLE "${python}" CACHE FILEPATH "Python interpreter for builds") +# Set legacy variable name for compatibility with existing code +set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}" CACHE FILEPATH "Python interpreter for builds") mark_as_advanced(PYTHON_EXECUTABLE) diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 613c408157..6f2f7eae61 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -225,6 +225,7 @@ void LLAudioEngine::updateChannels() void LLAudioEngine::idle() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; // "Update" all of our audio sources, clean up dead ones. // Primarily does position updating, cleanup of unused audio sources. // Also does regeneration of the current priority of each audio source. diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index a0394da281..404e0c71ce 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -163,6 +163,28 @@ constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only constexpr U8 SIM_ACCESS_DOWN = 254; constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; +// map item types +constexpr U32 MAP_ITEM_TELEHUB = 0x01; +constexpr U32 MAP_ITEM_PG_EVENT = 0x02; +constexpr U32 MAP_ITEM_MATURE_EVENT = 0x03; +// constexpr U32 MAP_ITEM_POPULAR = 0x04; // No longer supported, 2009-03-02 KLW +// constexpr U32 MAP_ITEM_AGENT_COUNT = 0x05; +constexpr U32 MAP_ITEM_AGENT_LOCATIONS = 0x06; +constexpr U32 MAP_ITEM_LAND_FOR_SALE = 0x07; +constexpr U32 MAP_ITEM_CLASSIFIED = 0x08; +constexpr U32 MAP_ITEM_ADULT_EVENT = 0x09; +constexpr U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a; + +// Region map layer numbers +constexpr S32 MAP_SIM_OBJECTS = 0; +constexpr S32 MAP_SIM_TERRAIN = 1; +constexpr S32 MAP_SIM_LAND_FOR_SALE = 2; // Transparent alpha overlay of land for sale +constexpr S32 MAP_SIM_IMAGE_TYPES = 3; // Number of map layers +constexpr S32 MAP_SIM_INFO_MASK = 0x00FFFFFF; // Agent access may be stuffed into upper byte +constexpr S32 MAP_SIM_LAYER_MASK = 0x0000FFFF; // Layer info is in lower 16 bits +constexpr S32 MAP_SIM_RETURN_NULL_SIMS = 0x00010000; +constexpr S32 MAP_SIM_PRELUDE = 0x00020000; + // attachment constants constexpr U8 ATTACHMENT_ADD = 0x80; diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 5205699b92..5545bb71af 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -41,6 +41,9 @@ #include "llstring.h" #include "llfasttimer.h" +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> + static const F64 LL_APR_USEC_PER_SEC = 1000000.0; // should be APR_USEC_PER_SEC, but that relies on INT64_C which // isn't defined in glib under our build set up for some reason @@ -64,7 +67,7 @@ std::string LLDate::asString() const { std::ostringstream stream; toStream(stream); - return stream.str(); + return std::move(stream).str(); } //@ brief Converts time in seconds since EPOCH @@ -184,7 +187,7 @@ bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *se bool LLDate::fromString(const std::string& iso8601_date) { - std::istringstream stream(iso8601_date); + boost::iostreams::stream<boost::iostreams::array_source> stream(iso8601_date.data(), iso8601_date.size()); return fromStream(stream); } diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index b14464382b..6f5e57c3de 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -480,7 +480,7 @@ namespace } - typedef std::map<std::string, LLError::ELevel> LevelMap; + typedef std::unordered_map<std::string, LLError::ELevel> LevelMap; typedef std::vector<LLError::RecorderPtr> Recorders; typedef std::vector<LLError::CallSite*> CallSiteVector; @@ -501,7 +501,7 @@ namespace LevelMap mClassLevelMap; LevelMap mFileLevelMap; LevelMap mTagLevelMap; - std::map<std::string, unsigned int> mUniqueLogMessages; + std::unordered_map<std::string, unsigned int> mUniqueLogMessages; LLError::FatalFunction mCrashFunction; LLError::TimeFunction mTimeFunction; @@ -1404,7 +1404,7 @@ namespace LLError { std::ostringstream message_stream; - std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message); + auto messageIter = s->mUniqueLogMessages.find(message); if (messageIter != s->mUniqueLogMessages.end()) { messageIter->second++; diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index d254fa5407..3c58d1df22 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -70,7 +70,6 @@ namespace LLError Setting a level means log messages at that level or above. */ - LL_COMMON_API void setPrintLocation(bool); LL_COMMON_API void setDefaultLevel(LLError::ELevel); LL_COMMON_API ELevel getDefaultLevel(); LL_COMMON_API void setAlwaysFlush(bool flush); diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index e1fc4764f6..bb2cd4fb2e 100644 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -137,6 +137,18 @@ void llcoro::suspendUntilTimeout(float seconds) suspendUntilEventOnWithTimeout(bogus, seconds, timedout); } +void llcoro::suspendUntilNextFrame() +{ + LLCoros::checkStop(); + LLCoros::TempStatus st("waiting for next frame"); + + // Listen for the next event on the "mainloop" event pump. + // Once per frame we get mainloop.post(newFrame); + LLEventPumpOrPumpName mainloop_pump("mainloop"); + // Wait for the next event (the event data is ignored). + suspendUntilEventOn(mainloop_pump); +} + namespace { diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index 492563bb98..25a8a98e36 100644 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -85,6 +85,11 @@ void suspend(); void suspendUntilTimeout(float seconds); /** + * Yield control from a coroutine until the next mainloop's newFrame event. + */ +void suspendUntilNextFrame(); + +/** * Post specified LLSD event on the specified LLEventPump, then suspend for a * response on specified other LLEventPump. This is more than mere * convenience: the difference between this function and the sequence diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index a539e4fe28..f752e31563 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -187,13 +187,34 @@ static unsigned short get_fileattr(const std::wstring& utf16path, bool dontFollo CloseHandle(file_handle); return st_mode; } + // Retrieve last error before calling CloseHandle() + DWORD last_error = GetLastError(); + CloseHandle(file_handle); + set_errno_from_oserror(last_error); + } + else + { + set_errno_from_oserror(GetLastError()); } - // Retrieve last error and set errno before calling CloseHandle() - set_errno_from_oserror(GetLastError()); - if (file_handle != INVALID_HANDLE_VALUE) + // If CreateFileW approach failed (e.g., exFAT), try the simpler GetFileAttributesW() + // GetFileAttributesW() always follows symlinks, so we skip this fallback when dontFollowSymLink is true. + if (!dontFollowSymLink) { - CloseHandle(file_handle); + DWORD attributes = GetFileAttributesW(utf16path.c_str()); + if (attributes != INVALID_FILE_ATTRIBUTES) + { + bool is_directory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + unsigned short st_mode = is_directory ? S_IFDIR : S_IFREG; + st_mode |= (attributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD | S_IWRITE; + + // propagate user bits to group/other fields: + st_mode |= (st_mode & 0700) >> 3; + st_mode |= (st_mode & 0700) >> 6; + + return st_mode; + } + set_errno_from_oserror(GetLastError()); } return 0; } diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp index 823bea7a3c..03dd7856b6 100644 --- a/indra/llcommon/llheteromap.cpp +++ b/indra/llcommon/llheteromap.cpp @@ -27,6 +27,6 @@ LLHeteroMap::~LLHeteroMap() // pair.second is the std::pair; pair.second.first is the void*; // pair.second.second points to the deleter function (pair.second.second)(pair.second.first); - pair.second.first = NULL; + pair.second.first = nullptr; } } diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h index d8e6fefb17..211dfaae83 100644 --- a/indra/llcommon/llheteromap.h +++ b/indra/llcommon/llheteromap.h @@ -12,9 +12,10 @@ #if ! defined(LL_LLHETEROMAP_H) #define LL_LLHETEROMAP_H +#include <typeindex> #include <typeinfo> #include <utility> // std::pair -#include <map> +#include <unordered_map> /** * LLHeteroMap addresses an odd requirement. Usually when you want to put @@ -43,7 +44,7 @@ public: // Look up map entry by typeid(T). We don't simply use mMap[typeid(T)] // because that requires default-constructing T on every lookup. For // some kinds of T, that could be expensive. - TypeMap::iterator found = mMap.find(&typeid(T)); + TypeMap::iterator found = mMap.find(typeid(T)); if (found == mMap.end()) { // Didn't find typeid(T). Create an entry. Because we're storing @@ -52,8 +53,8 @@ public: void* ptr = new T(); void (*dlfn)(void*) = &deleter<T>; std::pair<TypeMap::iterator, bool> inserted = - mMap.insert(TypeMap::value_type(&typeid(T), - TypeMap::mapped_type(ptr, dlfn))); + mMap.emplace(typeid(T), + TypeMap::mapped_type(ptr, dlfn)); // Okay, now that we have an entry, claim we found it. found = inserted.first; } @@ -71,23 +72,9 @@ private: delete static_cast<T*>(p); } - // Comparing two std::type_info* values is tricky, because the standard - // does not guarantee that there will be only one type_info instance for a - // given type. In other words, &typeid(A) in one part of the program may - // not always equal &typeid(A) in some other part. Use special comparator. - struct type_info_ptr_comp - { - bool operator()(const std::type_info* lhs, const std::type_info* rhs) const - { - return lhs->before(*rhs); - } - }; - - // What we actually store is a map from std::type_info (permitting lookup + // What we actually store is a map from std::type_index (permitting lookup // by object type) to a void* pointer to the object PLUS its deleter. - typedef std::map< - const std::type_info*, std::pair<void*, void (*)(void*)>, - type_info_ptr_comp> + typedef std::unordered_map<std::type_index, std::pair<void*, void (*)(void*)>> TypeMap; TypeMap mMap; }; diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index b01ea0bfb1..b220afadfc 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -34,7 +34,6 @@ #include <list> #include <unordered_map> #include <boost/function.hpp> -#include <boost/unordered_map.hpp> #include "llerror.h" #include "llstl.h" @@ -267,7 +266,7 @@ namespace LLInitParam private: struct Inaccessable{}; public: - typedef std::map<std::string, T> value_name_map_t; + typedef std::unordered_map<std::string, T> value_name_map_t; typedef Inaccessable name_t; typedef TypeValues<T> type_value_t; typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; @@ -294,7 +293,7 @@ namespace LLInitParam static std::vector<std::string>* getPossibleValues() { - return NULL; + return nullptr; } void assignNamedValue(const Inaccessable& name) @@ -310,7 +309,7 @@ namespace LLInitParam return param_value_t::getValue(); } - static value_name_map_t* getValueNames() {return NULL;} + static value_name_map_t* getValueNames() { return nullptr; } }; // helper class to implement name value lookups @@ -321,7 +320,7 @@ namespace LLInitParam { typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t; public: - typedef typename std::map<std::string, T> value_name_map_t; + typedef typename std::unordered_map<std::string, T> value_name_map_t; typedef std::string name_t; typedef self_t type_value_t; typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; @@ -497,9 +496,9 @@ namespace LLInitParam typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&); typedef std::function<void (name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t; - typedef std::map<const std::type_info*, parser_read_func_t> parser_read_func_map_t; - typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t; - typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t; + typedef std::unordered_map<std::type_index, parser_read_func_t> parser_read_func_map_t; + typedef std::unordered_map<std::type_index, parser_write_func_t> parser_write_func_map_t; + typedef std::unordered_map<std::type_index, parser_inspect_func_t> parser_inspect_func_map_t; public: @@ -514,7 +513,7 @@ namespace LLInitParam template <typename T> bool readValue(T& param, typename std::enable_if_t<!std::is_enum_v<T>>* dummy = 0) { - parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(typeid(T)); if (found_it != mParserReadFuncs->end()) { return found_it->second(*this, (void*)¶m); @@ -525,14 +524,14 @@ namespace LLInitParam template <typename T> bool readValue(T& param, typename std::enable_if_t<std::is_enum_v<T> >* dummy = 0) { - parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(typeid(T)); if (found_it != mParserReadFuncs->end()) { return found_it->second(*this, (void*)¶m); } else { - found_it = mParserReadFuncs->find(&typeid(S32)); + found_it = mParserReadFuncs->find(typeid(S32)); if (found_it != mParserReadFuncs->end()) { S32 int_value; @@ -546,7 +545,7 @@ namespace LLInitParam template <typename T> bool writeValue(const T& param, name_stack_t& name_stack) { - parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); + parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(typeid(T)); if (found_it != mParserWriteFuncs->end()) { return found_it->second(*this, (const void*)¶m, name_stack); @@ -557,7 +556,7 @@ namespace LLInitParam // dispatch inspection to registered inspection functions, for each parameter in a param block template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values) { - parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T)); + parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(typeid(T)); if (found_it != mParserInspectFuncs->end()) { found_it->second(name_stack, min_count, max_count, possible_values); @@ -574,16 +573,16 @@ namespace LLInitParam protected: template <typename T> - void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL) + void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = nullptr) { - mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func)); - mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func)); + mParserReadFuncs->emplace(typeid(T), read_func); + mParserWriteFuncs->emplace(typeid(T), write_func); } template <typename T> void registerInspectFunc(parser_inspect_func_t inspect_func) { - mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func)); + mParserInspectFuncs->emplace(typeid(T), inspect_func); } bool mParseSilently; @@ -614,7 +613,7 @@ namespace LLInitParam { struct UserData { - virtual ~UserData() {} + virtual ~UserData() = default; }; typedef bool(*merge_func_t)(Param&, const Param&, bool); @@ -665,7 +664,7 @@ namespace LLInitParam void aggregateBlockData(BlockDescriptor& src_block_data); void addParam(ParamDescriptorPtr param, const char* name); - typedef boost::unordered_map<const std::string, ParamDescriptorPtr> param_map_t; + typedef std::unordered_map<std::string, ParamDescriptorPtr, ll::string_hash, std::equal_to<>> param_map_t; typedef std::vector<ParamDescriptorPtr> param_list_t; typedef std::list<ParamDescriptorPtr> all_params_list_t; typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t; @@ -679,38 +678,26 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; - //TODO: implement in terms of owned_ptr - template<typename T> + // TODO: implement in terms of owned_ptr + template<typename T> class LazyValue - { - public: - LazyValue() - : mPtr(NULL) - {} + { + public: + LazyValue() = default; - ~LazyValue() - { - delete mPtr; - } + ~LazyValue() { delete mPtr; } - LazyValue(const T& value) - { - mPtr = new T(value); - } + LazyValue(const T& value) { mPtr = new T(value); } - LazyValue(const LazyValue& other) - : mPtr(NULL) - { - *this = other; - } + LazyValue(const LazyValue& other) : mPtr(nullptr) { *this = other; } - LazyValue& operator = (const LazyValue& other) - { + LazyValue& operator=(const LazyValue& other) + { if (!other.mPtr) { delete mPtr; - mPtr = NULL; - } + mPtr = nullptr; + } else { if (!mPtr) @@ -721,23 +708,21 @@ namespace LLInitParam { *mPtr = *(other.mPtr); } - } - return *this; } + return *this; + } bool operator==(const LazyValue& other) const { - if (empty() || other.empty()) return false; + if (empty() || other.empty()) + return false; return *mPtr == *other.mPtr; } - bool empty() const - { - return mPtr == NULL; - } + bool empty() const { return mPtr == nullptr; } - void set(const T& other) - { + void set(const T& other) + { if (!mPtr) { mPtr = new T(other); @@ -748,36 +733,26 @@ namespace LLInitParam } } - const T& get() const - { - return *ensureInstance(); - } + const T& get() const { return *ensureInstance(); } - T& get() - { - return *ensureInstance(); - } + T& get() { return *ensureInstance(); } - operator const T&() const - { - return get(); - } + operator const T&() const { return get(); } - private: - // lazily allocate an instance of T - T* ensureInstance() const + private: + // lazily allocate an instance of T + T* ensureInstance() const + { + if (mPtr == nullptr) { - if (mPtr == NULL) - { - mPtr = new T(); - } - return mPtr; + mPtr = new T(); } + return mPtr; + } - private: - - mutable T* mPtr; - }; + private: + mutable T* mPtr = nullptr; + }; // root class of all parameter blocks @@ -864,7 +839,7 @@ namespace LLInitParam mParamProvided(false) {} - virtual ~BaseBlock() {} + virtual ~BaseBlock() = default; bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false); param_handle_t getHandleFromParam(const Param* param) const; diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h index e86098f20b..20561b0c65 100644 --- a/indra/llcommon/llpounceable.h +++ b/indra/llcommon/llpounceable.h @@ -38,9 +38,9 @@ #include "llsingleton.h" #include <boost/call_traits.hpp> #include <boost/utility/value_init.hpp> -#include <boost/unordered_map.hpp> #include <boost/signals2/signal.hpp> +#include <unordered_map> #include <type_traits> // Forward declare the user template, since we want to be able to point to it @@ -86,7 +86,7 @@ class LLPounceableQueueSingleton: // instance will call on the SAME LLPounceableQueueSingleton instance -- // given how class statics work. We must keep a separate queue for each // LLPounceable instance. Use a hash map for that. - typedef boost::unordered_map<owner_ptr, signal_t> map_t; + typedef std::unordered_map<owner_ptr, signal_t> map_t; public: // Disambiguate queues belonging to different LLPounceables. diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index 35335e1213..92f8ae3245 100644 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -32,21 +32,11 @@ #include "llsingleton.h" #include "llstl.h" -template <typename T> -struct LLRegistryDefaultComparator -{ - bool operator()(const T& lhs, const T& rhs) const - { - using std::less; - return less<T>()(lhs, rhs); - } -}; - -template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> > +template <typename KEY, typename VALUE> class LLRegistry { public: - typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t; + typedef LLRegistry<KEY, VALUE> registry_t; typedef const KEY& ref_const_key_t; typedef const VALUE& ref_const_value_t; typedef const VALUE* ptr_const_value_t; @@ -54,9 +44,9 @@ public: class Registrar { - friend class LLRegistry<KEY, VALUE, COMPARATOR>; + friend class LLRegistry<KEY, VALUE>; public: - typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t; + typedef std::map<KEY, VALUE> registry_map_t; bool add(ref_const_key_t key, ref_const_value_t value) { @@ -234,9 +224,9 @@ private: Registrar mDefaultRegistrar; }; -template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> > +template <typename KEY, typename VALUE, typename DERIVED_TYPE> class LLRegistrySingleton - : public LLRegistry<KEY, VALUE, COMPARATOR>, + : public LLRegistry<KEY, VALUE>, public LLSingleton<DERIVED_TYPE> { // This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton) @@ -244,7 +234,7 @@ class LLRegistrySingleton // LLRegistrySingleton. So each concrete subclass needs // LLSINGLETON(whatever) -- not this intermediate base class. public: - typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t; + typedef LLRegistry<KEY, VALUE> registry_t; typedef const KEY& ref_const_key_t; typedef const VALUE& ref_const_value_t; typedef VALUE* ptr_value_t; @@ -309,7 +299,7 @@ public: }; // convenience functions - typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t; + typedef typename LLRegistry<KEY, VALUE>::Registrar& ref_registrar_t; static ref_registrar_t currentRegistrar() { return singleton_t::instance().registry_t::currentRegistrar(); diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 77fe545c3f..ce39bc7af3 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -39,6 +39,9 @@ #include <limits> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> + // Defend against a caller forcibly passing a negative number into an unsigned // size_t index param inline @@ -103,6 +106,9 @@ protected: U32 mUseCount; public: + static void destruct(Impl*& var); + ///< safely decrement or destroy var + static void reset(Impl*& var, Impl* impl); ///< safely set var to refer to the new impl (possibly shared) @@ -166,7 +172,7 @@ public: virtual const LLSD& ref(size_t) const { return undef(); } virtual LLSD::map_const_iterator beginMap() const { return endMap(); } - virtual LLSD::map_const_iterator endMap() const { static const std::map<String, LLSD> empty; return empty.end(); } + virtual LLSD::map_const_iterator endMap() const { static const LLSD::llsd_map_t empty; return empty.end(); } virtual LLSD::array_const_iterator beginArray() const { return endArray(); } virtual LLSD::array_const_iterator endArray() const { static const std::vector<LLSD> empty; return empty.end(); } @@ -345,18 +351,7 @@ namespace LLSD::Real ImplString::asReal() const { - F64 v = 0.0; - std::istringstream i_stream(mValue); - i_stream >> v; - - // we would probably like to ignore all trailing whitespace as - // well, but for now, simply eat the next character, and make - // sure we reached the end of the string. - // *NOTE: gcc 2.95 does not generate an eof() event on the - // stream operation above, so we manually get here to force it - // across platforms. - int c = i_stream.get(); - return ((EOF ==c) ? v : 0.0); + return llsd::string_to_real(mValue); } @@ -431,7 +426,7 @@ namespace class ImplMap final : public LLSD::Impl { private: - typedef std::map<LLSD::String, LLSD, std::less<>> DataMap; + using DataMap = LLSD::llsd_map_t; DataMap mData; @@ -457,7 +452,7 @@ namespace << it.second.asXMLRPCValue() << "</member>"; } os << "</struct>"; - return os.str(); + return std::move(os).str(); } virtual bool has(std::string_view) const; @@ -467,8 +462,13 @@ namespace using LLSD::Impl::ref; // Unhiding ref(size_t) virtual LLSD get(std::string_view) const; virtual LLSD getKeys() const; + void insert(std::string&& k, const LLSD& v); + void insert(std::string&& k, LLSD&& v); void insert(std::string_view k, const LLSD& v); + void insert(std::string_view k, LLSD&& v); virtual void erase(const LLSD::String&); + LLSD& ref(std::string&&); + virtual const LLSD& ref(std::string&&) const; LLSD& ref(std::string_view); virtual const LLSD& ref(std::string_view) const; @@ -525,18 +525,58 @@ namespace return keys; } + void ImplMap::insert(std::string&& k, const LLSD& v) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; + mData.emplace(std::move(k), v); + } + + void ImplMap::insert(std::string&& k, LLSD&& v) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; + mData.emplace(std::move(k), std::move(v)); + } + void ImplMap::insert(std::string_view k, const LLSD& v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; mData.emplace(k, v); } + void ImplMap::insert(std::string_view k, LLSD&& v) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; + mData.emplace(k, std::move(v)); + } + void ImplMap::erase(const LLSD::String& k) { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; mData.erase(k); } + LLSD& ImplMap::ref(std::string&& k) + { + DataMap::iterator i = mData.lower_bound(k); + if (i == mData.end() || mData.key_comp()(k, i->first)) + { + return mData.emplace_hint(i, std::make_pair(std::move(k), LLSD()))->second; + } + + return i->second; + } + + const LLSD& ImplMap::ref(std::string&& k) const + { + DataMap::const_iterator i = mData.lower_bound(k); + if (i == mData.end() || mData.key_comp()(k, i->first)) + { + return undef(); + } + + return i->second; + } + LLSD& ImplMap::ref(std::string_view k) { DataMap::iterator i = mData.lower_bound(k); @@ -598,7 +638,7 @@ namespace ImplArray(const DataVector& data) : mData(data) { } public: - ImplArray() { } + ImplArray() = default; virtual ImplArray& makeArray(Impl*&); @@ -615,7 +655,7 @@ namespace os << it.asXMLRPCValue(); } os << "</data></array>"; - return os.str(); + return std::move(os).str(); } using LLSD::Impl::get; // Unhiding get(LLSD::String) @@ -625,10 +665,13 @@ namespace virtual LLSD get(size_t) const; void set(size_t, const LLSD&); void insert(size_t, const LLSD&); + void insert(size_t, LLSD&&); LLSD& append(const LLSD&); + LLSD& append(LLSD&&); virtual void erase(size_t); LLSD& ref(size_t); virtual const LLSD& ref(size_t) const; + void reserve(size_t size) { mData.reserve(size); } LLSD::array_iterator beginArray() { return mData.begin(); } LLSD::array_iterator endArray() { return mData.end(); } @@ -690,12 +733,31 @@ namespace mData.insert(mData.begin() + index, v); } + void ImplArray::insert(size_t i, LLSD&& v) + { + NEGATIVE_EXIT(i); + DataVector::size_type index = i; + + if (index >= mData.size()) // tbd - sanity check limit for index ? + { + mData.resize(index + 1); + } + + mData.insert(mData.begin() + index, std::move(v)); + } + LLSD& ImplArray::append(const LLSD& v) { mData.push_back(v); return mData.back(); } + LLSD& ImplArray::append(LLSD&& v) + { + mData.push_back(std::move(v)); + return mData.back(); + } + void ImplArray::erase(size_t i) { NEGATIVE_EXIT(i); @@ -763,6 +825,14 @@ LLSD::Impl::~Impl() --sOutstandingCount; } +void LLSD::Impl::destruct(Impl*& var) +{ + if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0) + { + delete var; + } +} + void LLSD::Impl::reset(Impl*& var, Impl* impl) { if (impl && impl->mUseCount != STATIC_USAGE_COUNT) @@ -961,7 +1031,7 @@ namespace LLSD::LLSD() : impl(0) { ALLOC_LLSD_OBJECT; } -LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0); } +LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::destruct(impl); } LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); } void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); } @@ -1037,13 +1107,31 @@ LLSD LLSD::emptyMap() bool LLSD::has(const std::string_view k) const { return safe(impl).has(k); } LLSD LLSD::get(const std::string_view k) const { return safe(impl).get(k); } LLSD LLSD::getKeys() const { return safe(impl).getKeys(); } +void LLSD::insert(std::string&& k, const LLSD& v) { makeMap(impl).insert(std::move(k), v); } +void LLSD::insert(std::string&& k, LLSD&& v) { makeMap(impl).insert(std::move(k), std::move(v)); } void LLSD::insert(std::string_view k, const LLSD& v) { makeMap(impl).insert(k, v); } +void LLSD::insert(std::string_view k, LLSD&& v) { makeMap(impl).insert(k, std::move(v)); } +LLSD& LLSD::with(std::string&& k, const LLSD& v) + { + makeMap(impl).insert(std::move(k), v); + return *this; + } +LLSD& LLSD::with(std::string&& k, LLSD&& v) + { + makeMap(impl).insert(std::move(k), std::move(v)); + return *this; + } LLSD& LLSD::with(std::string_view k, const LLSD& v) { makeMap(impl).insert(k, v); return *this; } +LLSD& LLSD::with(std::string_view k, LLSD&& v) + { + makeMap(impl).insert(k, std::move(v)); + return *this; + } void LLSD::erase(const String& k) { makeMap(impl).erase(k); } LLSD& LLSD::operator[](const std::string_view k) @@ -1051,6 +1139,13 @@ LLSD& LLSD::operator[](const std::string_view k) LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; return makeMap(impl).ref(k); } + +LLSD& LLSD::operator[](std::string&& k) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; + return makeMap(impl).ref(std::move(k)); +} + const LLSD& LLSD::operator[](const std::string_view k) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; @@ -1064,18 +1159,33 @@ LLSD LLSD::emptyArray() return v; } +LLSD LLSD::emptyReservedArray(size_t size) +{ + LLSD v; + makeArray(v.impl).reserve(size); + return v; +} + size_t LLSD::size() const { return safe(impl).size(); } LLSD LLSD::get(Integer i) const { return safe(impl).get(i); } void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); } +void LLSD::set(Integer i, LLSD&& v) { makeArray(impl).set(i, std::move(v)); } void LLSD::insert(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); } +void LLSD::insert(Integer i, LLSD&& v) { makeArray(impl).insert(i, std::move(v)); } LLSD& LLSD::with(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); return *this; } +LLSD& LLSD::with(Integer i, LLSD&& v) + { + makeArray(impl).insert(i, std::move(v)); + return *this; + } LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); } +LLSD& LLSD::append(LLSD&& v) { return makeArray(impl).append(std::move(v)); } void LLSD::erase(Integer i) { makeArray(impl).erase(i); } LLSD& LLSD::operator[](size_t i) @@ -1143,6 +1253,22 @@ LLSD::reverse_array_iterator LLSD::rendArray() { return makeArray(impl) namespace llsd { +LLSD::Real string_to_real(std::string_view in_string) +{ + LLSD::Real v = 0.0; + boost::iostreams::stream<boost::iostreams::array_source> i_stream(in_string.data(), in_string.size()); + i_stream >> v; + + // we would probably like to ignore all trailing whitespace as + // well, but for now, simply eat the next character, and make + // sure we reached the end of the string. + // *NOTE: gcc 2.95 does not generate an eof() event on the + // stream operation above, so we manually get here to force it + // across platforms. + int c = i_stream.get(); + return ((EOF == c) ? v : 0.0); +} + U32 allocationCount() { return LLSD::Impl::sAllocationCount; } U32 outstandingCount() { return LLSD::Impl::sOutstandingCount; } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index d2b3548831..afe35a65ba 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -34,6 +34,7 @@ #include "stdtypes.h" #include "lldate.h" +#include "llstl.h" #include "lluri.h" #include "lluuid.h" @@ -321,11 +322,34 @@ public: bool has(const std::string_view) const; LLSD get(const std::string_view) const; LLSD getKeys() const; // Return an LLSD array with keys as strings + void insert(const char* k, const LLSD& v) + { + return insert(std::string_view(k), v); + } + void insert(const char* k , LLSD&& v) + { + return insert(std::string_view(k), std::move(v)); + } + void insert(std::string&&, const LLSD&); + void insert(std::string&&, LLSD&&); void insert(std::string_view, const LLSD&); + void insert(std::string_view, LLSD&&); void erase(const String&); + LLSD& with(const char* k, const LLSD& v) + { + return with(std::string_view(k), v); + } + LLSD& with(const char* k, LLSD&& v) + { + return with(std::string_view(k), std::move(v)); + } + LLSD& with(std::string&&, const LLSD&); + LLSD& with(std::string&&, LLSD&&); LLSD& with(std::string_view, const LLSD&); + LLSD& with(std::string_view, LLSD&&); LLSD& operator[](const std::string_view); + LLSD& operator[](std::string&&); LLSD& operator[](const char* c) { return c ? (*this)[std::string_view(c)] : *this; @@ -339,14 +363,22 @@ public: /** @name Array Values */ //@{ + // Allocate an empty array static LLSD emptyArray(); + // Allocate an array with internal storage reserved but not initialized like a std::vector + static LLSD emptyReservedArray(size_t size); + LLSD get(Integer) const; void set(Integer, const LLSD&); + void set(Integer, LLSD&&); void insert(Integer, const LLSD&); + void insert(Integer, LLSD&&); LLSD& append(const LLSD&); + LLSD& append(LLSD&&); void erase(Integer); LLSD& with(Integer, const LLSD&); + LLSD& with(Integer, LLSD&&); // accept size_t so we can index relative to size() const LLSD& operator[](size_t) const; @@ -366,8 +398,9 @@ public: //@{ size_t size() const; - typedef std::map<String, LLSD>::iterator map_iterator; - typedef std::map<String, LLSD>::const_iterator map_const_iterator; + using llsd_map_t = std::map<String, LLSD, std::less<>>; + typedef llsd_map_t::iterator map_iterator; + typedef llsd_map_t::const_iterator map_const_iterator; map_iterator beginMap(); map_iterator endMap(); @@ -512,6 +545,8 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd); namespace llsd { + // Used by LLSD::ImplString to convert string type to real + LLSD::Real string_to_real(std::string_view in_string); #ifdef LLSD_DEBUG_INFO /** @name Unit Testing Interface */ diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp index 655869a704..bb806f32eb 100644 --- a/indra/llcommon/llsdjson.cpp +++ b/indra/llcommon/llsdjson.cpp @@ -66,7 +66,7 @@ LLSD LlsdFromJson(const boost::json::value& val) const boost::json::array& array = val.as_array(); size_t size = array.size(); // allocate elements 0 .. (size() - 1) to avoid incremental allocation - if (! array.empty()) + if (!array.empty()) { result[size - 1] = LLSD(); } @@ -80,7 +80,7 @@ LLSD LlsdFromJson(const boost::json::value& val) result = LLSD::emptyMap(); for (const auto& element : val.as_object()) { - result[element.key()] = LlsdFromJson(element.value()); + result[std::string_view(element.key())] = LlsdFromJson(element.value()); } break; } diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 37af366a20..ee7f0b01cc 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -775,7 +775,8 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) c // There must be a value for every key, thus // child_count must be greater than 0. parse_count += count; - map.insert(name, child); + map.insert(std::move(name), std::move(child)); // Move as name will be filled on next iteration + name.clear(); } else { @@ -822,7 +823,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_dept else { parse_count += count; - array.append(child); + array.append(std::move(child)); } c = get(istr); } @@ -841,7 +842,7 @@ bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const auto count = deserialize_string(istr, value, mMaxBytesLeft); if(PARSE_FAILURE == count) return false; account(count); - data = value; + data = std::move(value); return true; } @@ -872,10 +873,10 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const if(len) { value.resize(len); - account(fullread(istr, (char *)&value[0], len)); + account(fullread(istr, (char*)value.data(), len)); } c = get(istr); // strip off the trailing double-quote - data = value; + data = std::move(value); } else if(0 == strncmp("b64", buf, 3)) { @@ -885,7 +886,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const std::stringstream coded_stream; get(istr, *(coded_stream.rdbuf()), '\"'); c = get(istr); - std::string encoded(coded_stream.str()); + std::string encoded(std::move(coded_stream).str()); S32 len = apr_base64_decode_len(encoded.c_str()); std::vector<U8> value; if(len) @@ -894,7 +895,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const len = apr_base64_decode_binary(&value[0], encoded.c_str()); value.resize(len); } - data = value; + data = std::move(value); } else if(0 == strncmp("b16", buf, 3)) { @@ -925,7 +926,7 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const // copy the data out of the byte buffer value.insert(value.end(), byte_buffer, write); } - data = value; + data = std::move(value); } else { @@ -1077,7 +1078,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con } else { - data = value; + data = std::move(value); account(cnt); } if(istr.fail()) @@ -1094,7 +1095,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con std::string value; if(parseString(istr, value)) { - data = value; + data = std::move(value); } else { @@ -1159,7 +1160,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) con value.resize(size); account(fullread(istr, (char*)&value[0], size)); } - data = value; + data = std::move(value); } if(istr.fail()) { @@ -1218,7 +1219,7 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) con // There must be a value for every key, thus child_count // must be greater than 0. parse_count += child_count; - map.insert(name, child); + map.insert(std::move(name), std::move(child)); } else { @@ -1238,13 +1239,12 @@ S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) con S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const { - array = LLSD::emptyArray(); U32 value_nbo = 0; read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ S32 size = (S32)ntohl(value_nbo); - // *FIX: This would be a good place to reserve some space in the - // array... + // Preallocate array to avoid incremental allocation + array = LLSD::emptyReservedArray(size); S32 parse_count = 0; S32 count = 0; @@ -1260,7 +1260,7 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) if(child_count) { parse_count += child_count; - array.append(child); + array.append(std::move(child)); } ++count; c = istr.peek(); @@ -1279,18 +1279,15 @@ bool LLSDBinaryParser::parseString( std::istream& istr, std::string& value) const { - // *FIX: This is memory inefficient. U32 value_nbo = 0; read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ S32 size = (S32)ntohl(value_nbo); if(mCheckLimits && (size > mMaxBytesLeft)) return false; if(size < 0) return false; - std::vector<char> buf; if(size) { - buf.resize(size); - account(fullread(istr, &buf[0], size)); - value.assign(buf.begin(), buf.end()); + value.resize(size); + account(fullread(istr, value.data(), size)); } return true; } @@ -1785,7 +1782,7 @@ llssize deserialize_string_delim( } } - value = write_buffer.str(); + value = std::move(write_buffer).str(); return count; } @@ -1806,15 +1803,12 @@ llssize deserialize_string_raw( { // We probably have a valid raw string. determine // the size, and read it. - // *FIX: This is memory inefficient. - auto len = strtol(buf + 1, NULL, 0); + auto len = strtol(buf + 1, nullptr, 0); if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; - std::vector<char> buf; if(len) { - buf.resize(len); - count += fullread(istr, (char *)&buf[0], len); - value.assign(buf.begin(), buf.end()); + value.resize(len); + count += fullread(istr, value.data(), len); } c = istr.get(); ++count; @@ -2170,7 +2164,7 @@ std::string zip_llsd(LLSD& data) return std::string(); } - std::string source = llsd_strm.str(); + std::string source = std::move(llsd_strm).str(); U8 out[CHUNK]; diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 6396caf8d5..f399c51608 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -31,6 +31,8 @@ #include <deque> #include "apr_base64.h" +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> #include <boost/regex.hpp> extern "C" @@ -645,7 +647,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch if (mCurrentKey.empty()) { return startSkipping(); } LLSD& map = *mStack.back(); - LLSD& newElement = map[mCurrentKey]; + LLSD& newElement = map[std::move(mCurrentKey)]; mStack.push_back(&newElement); mCurrentKey.clear(); @@ -709,7 +711,8 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) return; case ELEMENT_KEY: - mCurrentKey = mCurrentContent; + mCurrentKey = std::move(mCurrentContent); // This is safe to move as we are in the end element handler + mCurrentContent.clear(); // Ensure mCurrentContent is empty for subsequent use return; default: @@ -742,14 +745,22 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) } else { - value = LLSD(mCurrentContent).asInteger(); + // This must treat "1.23" not as an error, but as a number, which is + // then truncated down to an integer. Hence, this code doesn't call + // std::istringstream::operator>>(int&), which would not consume the + // ".23" portion. + + // Utilizes implementation used internally by LLSD::ImplString::asInteger + value = (int)llsd::string_to_real(mCurrentContent); } } break; case ELEMENT_REAL: { - value = LLSD(mCurrentContent).asReal(); + // Utilizes implementation used internally by LLSD::ImplString::asReal + value = llsd::string_to_real(mCurrentContent); + // removed since this breaks when locale has decimal separator that isn't '.' // investigated changing local to something compatible each time but deemed higher // risk that just using LLSD.asReal() each time. @@ -766,19 +777,19 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) break; case ELEMENT_STRING: - value = mCurrentContent; + value = std::move(mCurrentContent); // This is safe to move as we are in the end element handler and this is cleared below break; case ELEMENT_UUID: - value = LLSD(mCurrentContent).asUUID(); + value = LLUUID(mCurrentContent); break; case ELEMENT_DATE: - value = LLSD(mCurrentContent).asDate(); + value = LLDate(mCurrentContent); break; case ELEMENT_URI: - value = LLSD(mCurrentContent).asURI(); + value = LLURI(mCurrentContent); break; case ELEMENT_BINARY: @@ -787,15 +798,14 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) // created by python and other non-linden systems - DEV-39358 // Fortunately we have very little binary passing now, // so performance impact shold be negligible. + poppy 2009-09-04 - boost::regex r; - r.assign("\\s"); + static const boost::regex r("\\s"); std::string stripped = boost::regex_replace(mCurrentContent, r, ""); S32 len = apr_base64_decode_len(stripped.c_str()); std::vector<U8> data; data.resize(len); len = apr_base64_decode_binary(&data[0], stripped.c_str()); data.resize(len); - value = data; + value = std::move(data); break; } diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 3fba8602ee..e6989211ae 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -25,10 +25,10 @@ #ifndef LLSINGLETON_H #define LLSINGLETON_H -#include <boost/unordered_set.hpp> #include <initializer_list> #include <list> #include <typeinfo> +#include <unordered_set> #include <vector> #include "mutex.h" #include "lockstatic.h" @@ -61,7 +61,7 @@ private: static vec_t dep_sort(); // we directly depend on these other LLSingletons - typedef boost::unordered_set<LLSingletonBase*> set_t; + typedef std::unordered_set<LLSingletonBase*> set_t; set_t mDepends; protected: diff --git a/indra/llcommon/llstaticstringtable.h b/indra/llcommon/llstaticstringtable.h index 66ba3487c4..edff955ee7 100644 --- a/indra/llcommon/llstaticstringtable.h +++ b/indra/llcommon/llstaticstringtable.h @@ -29,9 +29,10 @@ #define LL_STATIC_STRING_TABLE_H #include "lldefs.h" -#include <boost/unordered_map.hpp> #include "llstl.h" +#include <unordered_map> + class LLStaticHashedString { public: @@ -74,7 +75,7 @@ struct LLStaticStringHasher template< typename MappedObject > class LL_COMMON_API LLStaticStringTable - : public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher > + : public std::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher > { }; diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 7d41c42ba7..7a1c7caf82 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -34,6 +34,7 @@ #include <vector> #include <list> #include <set> +#include <typeindex> #include <typeinfo> #ifdef LL_LINUX @@ -229,12 +230,10 @@ void delete_and_clear_array(T*& ptr) template <typename T> inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_type const& key) { - // Typedef here avoids warnings because of new c++ naming rules. - typedef typename T::const_iterator map_iter; - map_iter iter = inmap.find(key); + auto iter = inmap.find(key); if(iter == inmap.end()) { - return NULL; + return nullptr; } else { @@ -243,8 +242,8 @@ inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_ty }; // helper function which returns true if key is in inmap. -template <typename K, typename T> -inline bool is_in_map(const std::map<K,T>& inmap, const K& key) +template <typename T> +inline bool is_in_map(const T& inmap, typename T::key_type const& key) { if(inmap.find(key) == inmap.end()) { @@ -260,12 +259,10 @@ inline bool is_in_map(const std::map<K,T>& inmap, const K& key) // To replace LLSkipMap getIfThere, use: // get_if_there(map, key, 0) // WARNING: Make sure default_value (generally 0) is not a valid map entry! -template <typename K, typename T> -inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value) +template <typename T> +inline typename T::mapped_type get_if_there(const T& inmap, typename T::key_type const& key, typename T::mapped_type default_value) { - // Typedef here avoids warnings because of new c++ naming rules. - typedef typename std::map<K,T>::const_iterator map_iter; - map_iter iter = inmap.find(key); + auto iter = inmap.find(key); if(iter == inmap.end()) { return default_value; @@ -709,5 +706,24 @@ struct ll_template_cast_impl<DEST, SOURCE> \ } \ } +// Transparent string hashing helper for use with std::unordered_* +// std::unordered_map<std::string, val, ll::string_hash, std::equal_to<>> +namespace ll +{ + struct string_hash + { + using is_transparent = void; + [[nodiscard]] size_t operator()(char const* rhs) const { return std::hash<std::string_view>{}(rhs); } + [[nodiscard]] size_t operator()(std::string_view rhs) const { return std::hash<std::string_view>{}(rhs); } + [[nodiscard]] size_t operator()(const std::string& rhs) const { return std::hash<std::string>{}(rhs); } + }; +} // namespace ll + +// Specialize ostream for std::type_index to allow log output +inline std::ostream& operator<<(std::ostream& s, std::type_index type) +{ + s << type.name(); + return s; +} #endif // LL_LLSTL_H diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index ca1cf03c4d..f91aadccc0 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -26,6 +26,7 @@ #ifndef LL_LLUUID_H #define LL_LLUUID_H +#include <functional> #include <iostream> #include <set> #include <vector> @@ -176,15 +177,27 @@ namespace std { inline size_t operator()(const LLUUID& id) const noexcept { - return (size_t)id.getDigest64(); + size_t h = 0; + // Golden ratio hash with avalanche mixing + // Process 8 bytes at a time by manually constructing 64-bit values + // Shift by 31: mixes upper half into lower half for better bit distribution + // Shift by 47: ensures highest bits influence final hash output + for (int i = 0; i < UUID_BYTES; i += 8) { + size_t chunk = (size_t)id.mData[i] | ((size_t)id.mData[i+1] << 8) | + ((size_t)id.mData[i+2] << 16) | ((size_t)id.mData[i+3] << 24) | + ((size_t)id.mData[i+4] << 32) | ((size_t)id.mData[i+5] << 40) | + ((size_t)id.mData[i+6] << 48) | ((size_t)id.mData[i+7] << 56); + h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47); + } + return h; } }; } -// For use with boost containers. +// For use with boost::container_hash inline size_t hash_value(const LLUUID& id) noexcept { - return (size_t)id.getDigest64(); + return std::hash<LLUUID>{}(id); } #endif // LL_LLUUID_H diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index 190539cea5..22bb50074a 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -44,6 +44,7 @@ #include "stringize.h" #include "llstring.h" #include <boost/filesystem.hpp> +#include "llprocess.h" #include <boost/bind.hpp> #include <algorithm> @@ -1100,6 +1101,61 @@ LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) c return SepOff(false, 0); } +void LLDir::openDir(const std::string& filepath) +{ + if (filepath.empty()) + { + LL_WARNS() << "Cannot open file browser: filepath is empty" << LL_ENDL; + return; + } + + // Extract directory path from full filepath + std::string dir_path = getDirName(filepath); + + LLProcess::Params params; + +#if LL_WINDOWS + // Windows: Use explorer.exe with /select flag to highlight the file + std::string system_root = LLStringUtil::getenv("SystemRoot"); + if (system_root.empty()) + { + system_root = LLStringUtil::getenv("WINDIR"); + } + if (system_root.empty()) + { + LL_WARNS() << "Neither SystemRoot nor WINDIR environment variable is set" << LL_ENDL; + system_root = "C:\\Windows"; // Last resort fallback + } + params.executable = system_root + "\\explorer.exe"; + params.args.add("/select,"); + params.args.add(filepath); +#elif LL_DARWIN + // macOS: Use 'open' command with -R flag to reveal in Finder + params.executable = "/usr/bin/open"; + params.args.add("-R"); + params.args.add(filepath); +#elif LL_LINUX + // Linux: Use xdg-open to open the directory + // Note: Most file managers don't support file selection, so we open the directory + params.executable = "/usr/bin/xdg-open"; + params.args.add(dir_path); +#else + LL_WARNS() << "Platform not supported for file browser opening" << LL_ENDL; + return; +#endif + + params.autokill = false; // Don't kill the file browser when viewer exits + + if (!LLProcess::create(params)) + { + LL_WARNS() << "Failed to open file browser for: " << filepath << LL_ENDL; + } + else + { + LL_INFOS() << "Opened file browser for: " << filepath << LL_ENDL; + } +} + void dir_exists_or_crash(const std::string &dir_name) { #if LL_WINDOWS diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h index b0d2b6aada..3c8e2e2da6 100644 --- a/indra/llfilesystem/lldir.h +++ b/indra/llfilesystem/lldir.h @@ -194,6 +194,9 @@ class LLDir virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG); + // Open the system file browser to reveal a file or directory + void openDir(const std::string& filepath); + // Utility routine std::string buildSLOSCacheDir() const; diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp index e971e1885a..dd7d1a043f 100644 --- a/indra/llfilesystem/lldiskcache.cpp +++ b/indra/llfilesystem/lldiskcache.cpp @@ -91,6 +91,8 @@ LLDiskCache::LLDiskCache(const std::string& cache_dir, // asset will have to be re-requested. void LLDiskCache::purge() { + LL_PROFILE_ZONE_SCOPED; + if (mEnableCacheDebugInfo) { LL_INFOS() << "Total dir size before purge is " << dirFileSize(sCacheDir) << LL_ENDL; @@ -112,6 +114,10 @@ void LLDiskCache::purge() boost::filesystem::directory_iterator iter(cache_path, ec); while (iter != boost::filesystem::directory_iterator() && !ec.failed()) { + if(!LLApp::isRunning()) + { + return; + } if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed()) { if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos) @@ -150,6 +156,10 @@ void LLDiskCache::purge() uintmax_t file_size_total = 0; for (file_info_t& entry : file_info) { + if (!LLApp::isRunning()) + { + return; + } file_size_total += entry.second.first; bool should_remove = file_size_total > mMaxSizeBytes; @@ -176,6 +186,10 @@ void LLDiskCache::purge() // Logging thousands of file results can take hundreds of milliseconds for (size_t i = 0; i < file_info.size(); ++i) { + if (!LLApp::isRunning()) + { + return; + } const file_info_t& entry = file_info[i]; const bool removed = file_removed[i]; const std::string action = removed ? "DELETE:" : "KEEP:"; diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp index 541266af4f..728ff396ef 100644 --- a/indra/llfilesystem/llfilesystem.cpp +++ b/indra/llfilesystem/llfilesystem.cpp @@ -77,11 +77,10 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil LL_PROFILE_ZONE_SCOPED; const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type); - llifstream file(filename, std::ios::binary); - if (file.is_open()) + boost::system::error_code ec; + if (boost::filesystem::exists(filename, ec) && boost::filesystem::is_regular_file(filename, ec)) { - file.seekg(0, std::ios::end); - return file.tellg() > 0; + return boost::filesystem::file_size(filename, ec) > 0; } return false; } @@ -120,15 +119,12 @@ S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType fi { const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type); - S32 file_size = 0; - llifstream file(filename, std::ios::binary); - if (file.is_open()) + boost::system::error_code ec; + if (boost::filesystem::exists(filename, ec) && boost::filesystem::is_regular_file(filename, ec)) { - file.seekg(0, std::ios::end); - file_size = (S32)file.tellg(); + return static_cast<S32>(boost::filesystem::file_size(filename, ec)); } - - return file_size; + return 0; } bool LLFileSystem::read(U8* buffer, S32 bytes) diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 3defad8f3b..f126accfb8 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -1017,10 +1017,9 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) if (i->first == INV_THUMBNAIL_LABEL) { const LLSD &thumbnail_map = i->second; - const std::string w = INV_ASSET_ID_LABEL; - if (thumbnail_map.has(w)) + if (thumbnail_map.has(INV_ASSET_ID_LABEL)) { - mThumbnailUUID = thumbnail_map[w]; + mThumbnailUUID = thumbnail_map[INV_ASSET_ID_LABEL]; } /* Example: <key> asset_id </key> @@ -1033,7 +1032,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) <integer> 1 </key> */ continue; - } + } if (i->first == INV_THUMBNAIL_ID_LABEL) { @@ -1044,10 +1043,9 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) if (i->first == INV_FAVORITE_LABEL) { const LLSD& favorite_map = i->second; - const std::string w = INV_TOGGLED_LABEL; - if (favorite_map.has(w)) + if (favorite_map.has(INV_TOGGLED_LABEL)) { - mFavorite = favorite_map[w].asBoolean(); + mFavorite = favorite_map[INV_TOGGLED_LABEL].asBoolean(); } continue; } @@ -1111,7 +1109,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) LLSD const &label = i->second; if (label.isString()) { - mType = LLAssetType::lookup(label.asString().c_str()); + mType = LLAssetType::lookup(label.asStringRef().c_str()); } else if (label.isInteger()) { @@ -1126,7 +1124,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) LLSD const &label = i->second; if (label.isString()) { - mInventoryType = LLInventoryType::lookup(label.asString().c_str()); + mInventoryType = LLInventoryType::lookup(label.asStringRef().c_str()); } else if (label.isInteger()) { @@ -1290,7 +1288,7 @@ void LLInventoryCategory::packMessage(LLMessageSystem* msg) const bool LLInventoryCategory::fromLLSD(const LLSD& sd) { - std::string w; + std::string_view w; w = INV_FOLDER_ID_LABEL_WS; if (sd.has(w)) diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index ecc5a7b0c5..c74ea3e42b 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -912,7 +912,7 @@ bool LLProfile::generate(const LLProfileParams& params, bool path_open,F32 detai case LL_PCODE_HOLE_CIRCLE: case LL_PCODE_HOLE_SAME: default: - addHole(params, true, circle_detail, 0, hollow, 1.f); + addHole(params, false, circle_detail, 0, hollow, 1.f); break; } } diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index ebafc53a4d..86b36315dc 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -276,7 +276,7 @@ void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &h // Provide some fallback for agents that return errors void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id) { - std::map<LLUUID,LLAvatarName>::iterator existing = mCache.find(agent_id); + cache_t::iterator existing = mCache.find(agent_id); if (existing == mCache.end()) { // there is no existing cache entry, so make a temporary name from legacy @@ -311,7 +311,7 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& bool updated_account = true; // assume obsolete value for new arrivals by default - std::map<LLUUID, LLAvatarName>::iterator it = mCache.find(agent_id); + cache_t::iterator it = mCache.find(agent_id); if (it != mCache.end() && (*it).second.getAccountName() == av_name.getAccountName()) { @@ -418,7 +418,7 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id, // Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy // protocol, we do not get an expiration date for each name and there's no reason to ask the // data again and again so we set the expiration time to the largest value admissible. - std::map<LLUUID,LLAvatarName>::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id); + cache_t::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id); LLAvatarName& av_name = av_record->second; av_name.setExpires(MAX_UNREFRESHED_TIME); } @@ -631,7 +631,7 @@ bool LLAvatarNameCache::getName(const LLUUID& agent_id, LLAvatarName *av_name) if (mRunning) { // ...only do immediate lookups when cache is running - std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id); + cache_t::iterator it = mCache.find(agent_id); if (it != mCache.end()) { *av_name = it->second; @@ -682,7 +682,7 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::getNameCallback(cons if (mRunning) { // ...only do immediate lookups when cache is running - std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id); + cache_t::iterator it = mCache.find(agent_id); if (it != mCache.end()) { const LLAvatarName& av_name = it->second; @@ -753,13 +753,11 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na LLUUID LLAvatarNameCache::findIdByName(const std::string& name) { - std::map<LLUUID, LLAvatarName>::iterator it; - std::map<LLUUID, LLAvatarName>::iterator end = mCache.end(); - for (it = mCache.begin(); it != end; ++it) + for (const auto& [id, avatar_name] : mCache) { - if (it->second.getUserName() == name) + if (avatar_name.getUserName() == name) { - return it->first; + return id; } } diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 0ddaee2aa1..6743943495 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -30,8 +30,10 @@ #include "llavatarname.h" // for convenience #include "llsingleton.h" +#include "lluuid.h" #include <boost/signals2.hpp> #include <set> +#include <unordered_map> class LLSD; class LLUUID; @@ -161,23 +163,23 @@ private: std::string mNameLookupURL; // Accumulated agent IDs for next query against service - typedef std::set<LLUUID> ask_queue_t; + using ask_queue_t = std::set<LLUUID>; ask_queue_t mAskQueue; // Agent IDs that have been requested, but with no reply. // Maps agent ID to frame time request was made. - typedef std::map<LLUUID, F64> pending_queue_t; + using pending_queue_t = std::unordered_map<LLUUID, F64>; pending_queue_t mPendingQueue; // Callbacks to fire when we received a name. // May have multiple callbacks for a single ID, which are // represented as multiple slots bound to the signal. // Avoid copying signals via pointers. - typedef std::map<LLUUID, callback_signal_t*> signal_map_t; + using signal_map_t = std::unordered_map<LLUUID, callback_signal_t*>; signal_map_t mSignalMap; // The cache at last, i.e. avatar names we know about. - typedef std::map<LLUUID, LLAvatarName> cache_t; + using cache_t = std::unordered_map<LLUUID, LLAvatarName>; cache_t mCache; // Time when unrefreshed cached names were checked last. diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 56dfaef873..95b7bb8c3d 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -179,12 +179,11 @@ void ReplySender::flush() } } - -typedef std::set<LLUUID> AskQueue; -typedef std::list<PendingReply*> ReplyQueue; -typedef std::map<LLUUID,U32> PendingQueue; -typedef std::map<LLUUID, LLCacheNameEntry*> Cache; -typedef std::map<std::string, LLUUID> ReverseCache; +using AskQueue = std::set<LLUUID>; +using ReplyQueue = std::list<PendingReply*>; +using PendingQueue = std::unordered_map<LLUUID, U32>; +using Cache = std::unordered_map<LLUUID, LLCacheNameEntry*>; +using ReverseCache = std::unordered_map<std::string, LLUUID>; class LLCacheName::Impl { @@ -214,7 +213,7 @@ public: Impl(LLMessageSystem* msg); ~Impl(); - bool getName(const LLUUID& id, std::string& first, std::string& last, std::map<std::string, std::string>& default_names); + bool getName(const LLUUID& id, std::string& first, std::string& last, cache_map_t& default_names); boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback); void addPending(const LLUUID& id, const LLHost& host); @@ -401,7 +400,7 @@ void LLCacheName::exportFile(std::ostream& ostr) } -bool LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last, std::map<std::string, std::string>& default_names) +bool LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last, cache_map_t &default_names) { if(id.isNull()) { diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 609387b6de..a333eac0f5 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -136,7 +136,8 @@ public: void localizeCacheName(std::string key, std::string value); private: - std::map<std::string, std::string> mCacheName; + using cache_map_t = std::unordered_map<std::string, std::string>; + cache_map_t mCacheName; class Impl; Impl& impl; diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index b24e5e4fcc..647064f607 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -37,6 +37,7 @@ #include "llsdserialize.h" #include "boost/json.hpp" // Boost.Json #include "llfilesystem.h" +#include "workqueue.h" #include "message.h" // for getting the port @@ -295,41 +296,73 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons } else { - try + constexpr size_t MAX_BODY_SIZE_THRESHOLD = 65536; + bool posted = false; + // Some messsages (ex: AISAPI) can return large bodies. + // If the body is larger than our threshold, post the + // parsing to the general queue to avoid stalling the + // main thread. + if (response->getBodySize() > MAX_BODY_SIZE_THRESHOLD) { - result = this->handleSuccess(response, status); - } - catch (std::bad_alloc&) - { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL; - } - } + response->addRef(); - buildStatusEntry(response, status, result); + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); + posted = main_queue->postTo( + general_queue, + [handler = shared_from_this(), response, status]() // Work done on general queue + { + std::pair<LLSD, LLCore::HttpStatus> result; + result.second = status; + try + { + result.first = handler->handleSuccess(response, result.second); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling (threaded)." << LL_ENDL; + } + // LLSD is not thread safe! Be carefull with moving the result around. + return result; + }, + [handler = shared_from_this(), response](std::pair<LLSD, LLCore::HttpStatus> result) mutable // Callback to main thread + { + handler->replyPost(response, result.second, result.first); + response->release(); + }); - if (!status) - { - LLSD &httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS]; + if (posted) + { + // Thread will do the cleanup and notify the pump. Done. + return; + } + else + { + // For whatever reason, failed to post, clean up and + // do the work on the main thread. + response->release(); + } + } - LLCore::BufferArray *body = response->getBody(); - LLCore::BufferArrayStream bas(body); - LLSD::String bodyData; - bodyData.reserve(response->getBodySize()); - bas >> std::noskipws; - bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>()); - httpStatus["error_body"] = LLSD(bodyData); - if (getBoolSetting(HTTP_LOGBODY_KEY)) + if (!posted) { - // commenting out, but keeping since this can be useful for debugging - LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL; + try + { + result = this->handleSuccess(response, status); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("CoreHTTP") << "Failed to allocate memory for response handling." << LL_ENDL; + } } } - mReplyPump.post(result); + replyPost(response, status, result); } -void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) +void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) const { LLSD httpresults = LLSD::emptyMap(); @@ -357,6 +390,31 @@ void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::H result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults; } +void HttpCoroHandler::replyPost(LLCore::HttpResponse* response, LLCore::HttpStatus &status, LLSD& result) +{ + buildStatusEntry(response, status, result); + + if (!status) + { + LLSD& httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS]; + + LLCore::BufferArray* body = response->getBody(); + LLCore::BufferArrayStream bas(body); + LLSD::String bodyData; + bodyData.reserve(response->getBodySize()); + bas >> std::noskipws; + bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>()); + httpStatus["error_body"] = LLSD(bodyData); + if (getBoolSetting(HTTP_LOGBODY_KEY)) + { + // commenting out, but keeping since this can be useful for debugging + LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL; + } + } + + mReplyPump.post(result); +} + void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result) { result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = static_cast<LLSD::Boolean>(status); @@ -389,8 +447,8 @@ public: HttpCoroLLSDHandler(LLEventStream &reply); protected: - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status); - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success); + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const; }; //------------------------------------------------------------------------- @@ -400,7 +458,7 @@ HttpCoroLLSDHandler::HttpCoroLLSDHandler(LLEventStream &reply): } -LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) +LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const { LLSD result; @@ -465,7 +523,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore: return result; } -LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse *response, bool &success) +LLSD HttpCoroLLSDHandler::parseBody(LLCore::HttpResponse *response, bool &success) const { success = true; if (response->getBodySize() == 0) @@ -496,8 +554,8 @@ class HttpCoroRawHandler : public HttpCoroHandler public: HttpCoroRawHandler(LLEventStream &reply); - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status); - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success); + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const; }; //------------------------------------------------------------------------- @@ -506,7 +564,7 @@ HttpCoroRawHandler::HttpCoroRawHandler(LLEventStream &reply): { } -LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) +LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const { LLSD result = LLSD::emptyMap(); @@ -552,7 +610,7 @@ LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:: return result; } -LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse *response, bool &success) +LLSD HttpCoroRawHandler::parseBody(LLCore::HttpResponse *response, bool &success) const { success = true; return LLSD(); @@ -571,8 +629,8 @@ class HttpCoroJSONHandler : public HttpCoroHandler public: HttpCoroJSONHandler(LLEventStream &reply); - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status); - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success); + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const; }; //------------------------------------------------------------------------- @@ -581,7 +639,7 @@ HttpCoroJSONHandler::HttpCoroJSONHandler(LLEventStream &reply) : { } -LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) +LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const { LLSD result = LLSD::emptyMap(); @@ -607,7 +665,7 @@ LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore: return result; } -LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &success) +LLSD HttpCoroJSONHandler::parseBody(LLCore::HttpResponse *response, bool &success) const { success = true; BufferArray * body(response->getBody()); diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 3dbfd6f00d..3072f78911 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -259,7 +259,7 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ /// +- ["url"] - The URL used to make the call. /// +- ["headers"] - A map of name name value pairs with the HTTP headers. /// -class HttpCoroHandler : public LLCore::HttpHandler +class HttpCoroHandler : public LLCore::HttpHandler, public std::enable_shared_from_this<HttpCoroHandler> { public: @@ -279,11 +279,12 @@ public: protected: /// this method may modify the status value - virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) = 0; - virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) = 0; + virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) const = 0; + virtual LLSD parseBody(LLCore::HttpResponse *response, bool &success) const = 0; private: - void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result); + void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result) const; + void replyPost(LLCore::HttpResponse* response, LLCore::HttpStatus& status, LLSD& result); LLEventStream &mReplyPump; }; diff --git a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp index 78876f9f36..b7c4b5e591 100644 --- a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp +++ b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp @@ -75,10 +75,7 @@ LLCDResult LLConvexDecompositionVHACD::quitSystem() LLConvexDecompositionVHACD::LLConvexDecompositionVHACD() { - //Create our vhacd instance and setup default parameters - mVHACD = VHACD::CreateVHACD(); - - mVHACDParameters.m_callback = &mVHACDCallback; + // Setup default parameters mVHACDParameters.m_logger = &mVHACDLogger; mDecompStages[0].mName = "Analyze"; @@ -206,27 +203,33 @@ LLConvexDecompositionVHACD::LLConvexDecompositionVHACD() LLConvexDecompositionVHACD::~LLConvexDecompositionVHACD() { - mBoundDecomp = nullptr; - mDecompData.clear(); - - mVHACD->Release(); + { + LLMutexLock lock(&mDecompDataMutex); + mBoundDecompID = INVALID_DECOMP_ID; + mDecompData.clear(); + } } void LLConvexDecompositionVHACD::genDecomposition(int& decomp) { - int new_decomp_id = static_cast<int>(mDecompData.size()) + 1; - mDecompData[new_decomp_id] = LLDecompData(); - decomp = new_decomp_id; + LLMutexLock lock(&mDecompDataMutex); + + mDecompData[mNextDecompID] = std::make_shared<LLDecompData>(); + decomp = mNextDecompID; + + ++mNextDecompID; // Increment decomposition ID. Never reuse to protect downstream consumers from misuse } void LLConvexDecompositionVHACD::deleteDecomposition(int decomp) { + LLMutexLock lock(&mDecompDataMutex); + auto iter = mDecompData.find(decomp); if (iter != mDecompData.end()) { - if (mBoundDecomp == &iter->second) + if (mBoundDecompID == decomp) { - mBoundDecomp = nullptr; + mBoundDecompID = INVALID_DECOMP_ID; } mDecompData.erase(iter); } @@ -234,29 +237,48 @@ void LLConvexDecompositionVHACD::deleteDecomposition(int decomp) void LLConvexDecompositionVHACD::bindDecomposition(int decomp) { - auto iter = mDecompData.find(decomp); - if (iter != mDecompData.end()) + LLMutexLock lock(&mDecompDataMutex); + + if (mDecompData.contains(decomp)) { - mBoundDecomp = &iter->second; + mBoundDecompID = decomp; } else { LL_WARNS() << "Failed to bind unknown decomposition: " << decomp << LL_ENDL; - mBoundDecomp = nullptr; + mBoundDecompID = INVALID_DECOMP_ID; } } +LLConvexDecompositionVHACD::data_ptr_t LLConvexDecompositionVHACD::getBoundDecomp() +{ + data_ptr_t bound_decomp; + { + LLMutexLock lock(&mDecompDataMutex); + auto it = mDecompData.find(mBoundDecompID); + if (it != mDecompData.end()) + { + bound_decomp = it->second; // Take a copy of the shared_ptr to avoid potential deletion + } + } + return bound_decomp; +} + LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, float val) { - if (name == std::string("Num Hulls")) + LLMutexLock lock(&mParamsMutex); + + using namespace std::literals; + + if (name == "Num Hulls"sv) { mVHACDParameters.m_maxConvexHulls = llclamp(ll_round(val), 1, MAX_HULLS); } - else if (name == std::string("Num Vertices")) + else if (name == "Num Vertices"sv) { mVHACDParameters.m_maxNumVerticesPerCH = llclamp(ll_round(val), 3, MAX_VERTICES_PER_HULL); } - else if (name == std::string("Error Tolerance")) + else if (name == "Error Tolerance"sv) { mVHACDParameters.m_minimumVolumePercentErrorAllowed = val; } @@ -270,11 +292,15 @@ LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, bool val) LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, int val) { - if (name == std::string("Fill Mode")) + LLMutexLock lock(&mParamsMutex); + + using namespace std::literals; + + if (name == "Fill Mode"sv) { mVHACDParameters.m_fillMode = (VHACD::FillMode)val; } - else if (name == std::string("Voxel Resolution")) + else if (name == "Voxel Resolution"sv) { mVHACDParameters.m_resolution = val; } @@ -283,19 +309,21 @@ LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, int val) LLCDResult LLConvexDecompositionVHACD::setMeshData( const LLCDMeshData* data, bool vertex_based ) { - if (!mBoundDecomp) + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp) { return LLCD_NULL_PTR; } - return mBoundDecomp->mSourceMesh.from(data, vertex_based); + return bound_decomp->mSourceMesh.from(data, vertex_based); } LLCDResult LLConvexDecompositionVHACD::registerCallback(int stage, llcdCallbackFunc callback ) { if (stage == 0) { - mVHACDCallback.setCallbackFunc(callback); + LLMutexLock lock(&mParamsMutex); + mCurrentCallbackFunc = callback; return LLCD_OK; } else @@ -306,44 +334,68 @@ LLCDResult LLConvexDecompositionVHACD::registerCallback(int stage, llcdCallbackF LLCDResult LLConvexDecompositionVHACD::executeStage(int stage) { - if (!mBoundDecomp) + if (stage != 0) + { + return LLCD_INVALID_STAGE; + } + + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp) { return LLCD_NULL_PTR; } - if (stage != 0) + bound_decomp->mDecomposedHulls.clear(); + + const auto& decomp_mesh = bound_decomp->mSourceMesh; + + VHACDCallback callbacks; + VHACD::IVHACD::Parameters current_params; { - return LLCD_INVALID_STAGE; + LLMutexLock lock(&mParamsMutex); + + current_params = mVHACDParameters; + callbacks.setCallbackFunc(mCurrentCallbackFunc); + } + current_params.m_callback = &callbacks; + + auto vhacd_impl = VHACD::CreateVHACD(); + if (!vhacd_impl) + { + LL_WARNS() << "Failed to create VHACD instance" << LL_ENDL; + return LLCD_NULL_PTR; } - mBoundDecomp->mDecomposedHulls.clear(); - const auto& decomp_mesh = mBoundDecomp->mSourceMesh; - if (!mVHACD->Compute((const double* const)decomp_mesh.mVertices.data(), static_cast<uint32_t>(decomp_mesh.mVertices.size()), (const uint32_t* const)decomp_mesh.mIndices.data(), static_cast<uint32_t>(decomp_mesh.mIndices.size()), mVHACDParameters)) + if (!vhacd_impl->Compute((const double*)decomp_mesh.mVertices.data(), static_cast<uint32_t>(decomp_mesh.mVertices.size()), + (const uint32_t*)decomp_mesh.mIndices.data(), static_cast<uint32_t>(decomp_mesh.mIndices.size()), + current_params)) { + vhacd_impl->Release(); return LLCD_INVALID_HULL_DATA; } - uint32_t num_nulls = mVHACD->GetNConvexHulls(); - if (num_nulls == 0) + uint32_t num_convex_hulls = vhacd_impl->GetNConvexHulls(); + if (num_convex_hulls == 0) { + vhacd_impl->Release(); return LLCD_INVALID_HULL_DATA; } - for (uint32_t i = 0; num_nulls > i; ++i) + for (uint32_t i = 0; num_convex_hulls > i; ++i) { VHACD::IVHACD::ConvexHull ch; - if (!mVHACD->GetConvexHull(i, ch)) + if (!vhacd_impl->GetConvexHull(i, ch)) continue; LLConvexMesh out_mesh; out_mesh.setVertices(ch.m_points); out_mesh.setIndices(ch.m_triangles); - mBoundDecomp->mDecomposedHulls.push_back(std::move(out_mesh)); + bound_decomp->mDecomposedHulls.push_back(std::move(out_mesh)); } - mVHACD->Clean(); + vhacd_impl->Release(); return LLCD_OK; } @@ -351,19 +403,21 @@ LLCDResult LLConvexDecompositionVHACD::executeStage(int stage) LLCDResult LLConvexDecompositionVHACD::buildSingleHull() { LL_INFOS() << "Building single hull mesh" << LL_ENDL; - if (!mBoundDecomp || mBoundDecomp->mSourceMesh.mVertices.empty()) + + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp || bound_decomp->mSourceMesh.mVertices.empty()) { return LLCD_NULL_PTR; } - mBoundDecomp->mSingleHullMesh.clear(); + bound_decomp->mSingleHullMesh.clear(); VHACD::QuickHull quickhull; - uint32_t num_tris = quickhull.ComputeConvexHull(mBoundDecomp->mSourceMesh.mVertices, MAX_VERTICES_PER_HULL); + uint32_t num_tris = quickhull.ComputeConvexHull(bound_decomp->mSourceMesh.mVertices, MAX_VERTICES_PER_HULL); if (num_tris > 0) { - mBoundDecomp->mSingleHullMesh.setVertices(quickhull.GetVertices()); - mBoundDecomp->mSingleHullMesh.setIndices(quickhull.GetIndices()); + bound_decomp->mSingleHullMesh.setVertices(quickhull.GetVertices()); + bound_decomp->mSingleHullMesh.setIndices(quickhull.GetIndices()); return LLCD_OK; } @@ -373,29 +427,31 @@ LLCDResult LLConvexDecompositionVHACD::buildSingleHull() int LLConvexDecompositionVHACD::getNumHullsFromStage(int stage) { - if (!mBoundDecomp || stage != 0) + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp || stage != 0) { return 0; } - return narrow(mBoundDecomp->mDecomposedHulls.size()); + return narrow(bound_decomp->mDecomposedHulls.size()); } LLCDResult LLConvexDecompositionVHACD::getSingleHull( LLCDHull* hullOut ) { memset( hullOut, 0, sizeof(LLCDHull) ); - if (!mBoundDecomp) + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp) { return LLCD_NULL_PTR; } - if (mBoundDecomp->mSingleHullMesh.vertices.empty()) + if (bound_decomp->mSingleHullMesh.vertices.empty()) { return LLCD_INVALID_HULL_DATA; } - mBoundDecomp->mSingleHullMesh.to(hullOut); + bound_decomp->mSingleHullMesh.to(hullOut); return LLCD_OK; } @@ -403,7 +459,8 @@ LLCDResult LLConvexDecompositionVHACD::getHullFromStage( int stage, int hull, LL { memset( hullOut, 0, sizeof(LLCDHull) ); - if (!mBoundDecomp) + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp) { return LLCD_NULL_PTR; } @@ -413,19 +470,21 @@ LLCDResult LLConvexDecompositionVHACD::getHullFromStage( int stage, int hull, LL return LLCD_INVALID_STAGE; } - if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull) + if (bound_decomp->mDecomposedHulls.empty() || S32(bound_decomp->mDecomposedHulls.size()) <= hull) { return LLCD_REQUEST_OUT_OF_RANGE; } - mBoundDecomp->mDecomposedHulls[hull].to(hullOut); + bound_decomp->mDecomposedHulls[hull].to(hullOut); return LLCD_OK; } LLCDResult LLConvexDecompositionVHACD::getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut ) { memset( meshDataOut, 0, sizeof(LLCDMeshData)); - if (!mBoundDecomp) + + data_ptr_t bound_decomp = getBoundDecomp(); + if (!bound_decomp) { return LLCD_NULL_PTR; } @@ -435,12 +494,12 @@ LLCDResult LLConvexDecompositionVHACD::getMeshFromStage( int stage, int hull, LL return LLCD_INVALID_STAGE; } - if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull) + if (bound_decomp->mDecomposedHulls.empty() || S32(bound_decomp->mDecomposedHulls.size()) <= hull) { return LLCD_REQUEST_OUT_OF_RANGE; } - mBoundDecomp->mDecomposedHulls[hull].to(meshDataOut); + bound_decomp->mDecomposedHulls[hull].to(meshDataOut); return LLCD_OK; } diff --git a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h index 675356629c..27c867704e 100644 --- a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h +++ b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h @@ -31,6 +31,7 @@ #include "llconvexdecomposition.h" #include "llsingleton.h" #include "llmath.h" +#include "llmutex.h" #include <vector> @@ -323,14 +324,25 @@ private: std::vector<LLConvexMesh> mDecomposedHulls; }; - std::unordered_map<int, LLDecompData> mDecompData; + using data_ptr_t = std::shared_ptr<LLDecompData>; - LLDecompData* mBoundDecomp = nullptr; + data_ptr_t getBoundDecomp(); + + // MUST lock before accessing mDecompData mBoundDecompID or mNextDecompID + LLMutex mDecompDataMutex; + + static constexpr int INVALID_DECOMP_ID = -1; + + int mBoundDecompID = INVALID_DECOMP_ID; + int mNextDecompID = 0; // Only for use inside genDecomposition. + + std::unordered_map<int, data_ptr_t> mDecompData; - VHACD::IVHACD* mVHACD = nullptr; - VHACDCallback mVHACDCallback; VHACDLogger mVHACDLogger; + + LLMutex mParamsMutex; VHACD::IVHACD::Parameters mVHACDParameters; + llcdCallbackFunc mCurrentCallbackFunc; LLConvexMesh mMeshFromHullData; LLConvexMesh mSingleHullMeshFromMeshData; diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index 930222e3db..1c47001272 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -214,7 +214,7 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const // to WriteGltfSceneToStream in the viewer. gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false); - return str.str(); + return std::move(str).str(); } void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index) @@ -924,6 +924,25 @@ void LLGLTFMaterial::updateTextureTracking() // for material overrides editor will set it } +// Test cases: +// Case 1. +// Input: scale 1.0,1.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation 0.349066; +// Expected output: scale 1.0,1.0; Offset horizontal 0.201, Offset vertical -0.141 Rotation -0.349066; +// Case 2. +// Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.1 Rotation 0; +// Expected output: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical -0.1 Rotation -0; +// Case 3. +// Input: scale 1.0,1.0; Offset horizontal 0.1, Offset vertical 0.2 Rotation 0.349066; +// Expected output: scale 1.0,1.0; Offset horizontal 0.295, Offset vertical -0.345 Rotation -0.349066; +// Case 4. +// Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.0 Rotation 0.349066; +// Expected output: scale 1.0,1.0; Offset horizontal 0.701, Offset vertical -0.141 Rotation -0.349066; +// +// Legacy offsets are right to left and top to bottom. +// PBR offsets are right to left and bottom to top. +// +// Legacy rotation is relative to face's center counter clockwise, +// PBR rotation is relative to top-left corner, clockwise void LLGLTFMaterial::convertTextureTransformToPBR( F32 tex_scale_s, F32 tex_scale_t, @@ -935,22 +954,65 @@ void LLGLTFMaterial::convertTextureTransformToPBR( F32& pbr_rotation) { pbr_scale.set(tex_scale_s, tex_scale_t); - pbr_rotation = -(tex_rotation) / 2.f; - const F32 adjusted_offset_s = tex_offset_s; - const F32 adjusted_offset_t = -tex_offset_t; + pbr_rotation = -tex_rotation; + + // Center of the tile + const F32 center_s = 0.5f; + const F32 center_t = 0.5f; + + // Center adjustment for scale F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s); F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t); - if (pbr_rotation != 0.0f) - { - const F32 c = cosf(pbr_rotation); - const F32 s = sinf(pbr_rotation); - const F32 tmp_s = center_adjust_s * c - center_adjust_t * s; - const F32 tmp_t = center_adjust_s * s + center_adjust_t * c; - center_adjust_s = tmp_s; - center_adjust_t = tmp_t; - } + // 2. Offset from center + F32 pos_s = center_adjust_s - center_s; + F32 pos_t = center_adjust_t - center_t; + + // 3. Rotate around center (clockwise, as per GLTF spec) + F32 c = cosf(pbr_rotation); + F32 s = sinf(pbr_rotation); + F32 rot_s = pos_s * c + pos_t * s; + F32 rot_t = -pos_s * s + pos_t * c; + + // 4. Move back to top-left and apply offset + pbr_offset.set(rot_s + center_s + tex_offset_s, rot_t + center_t - tex_offset_t); +} + +// Convert PBR transform values back to legacy TE transform values. +// This is the reverse of convertTextureTransformToPBR. +void LLGLTFMaterial::convertPBRTransformToTexture( + const LLVector2& pbr_scale, + const LLVector2& pbr_offset, + F32 pbr_rotation, + F32& tex_scale_s, + F32& tex_scale_t, + F32& tex_offset_s, + F32& tex_offset_t, + F32& tex_rotation) +{ + tex_scale_s = pbr_scale.mV[0]; + tex_scale_t = pbr_scale.mV[1]; + tex_rotation = -pbr_rotation; + + // Center of the tile + const F32 center_s = 0.5f; + const F32 center_t = 0.5f; + + // Center adjustment for scale + F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s); + F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t); + + // 2. Offset from center + F32 pos_s = center_adjust_s - center_s; + F32 pos_t = center_adjust_t - center_t; + + // 3. Rotate around center (clockwise, as per GLTF spec) + F32 c = cosf(pbr_rotation); + F32 s = sinf(pbr_rotation); + F32 rot_s = pos_s * c + pos_t * s; + F32 rot_t = -pos_s * s + pos_t * c; - pbr_offset.set(adjusted_offset_s + center_adjust_s, - adjusted_offset_t + center_adjust_t); + // 3. Recover legacy offset + tex_offset_s = pbr_offset.mV[0] - rot_s - center_s; + tex_offset_t = -(pbr_offset.mV[1] - rot_t - center_t); } diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 8d45cb6185..c37062e7d3 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -222,6 +222,14 @@ public: LLVector2& pbr_scale, LLVector2& pbr_offset, F32& pbr_rotation); + + // Convert PBR transform values to legacy TE transform values. + static void convertPBRTransformToTexture(const LLVector2& pbr_scale, + const LLVector2& pbr_offset, + F32 pbr_rotation, + F32& tex_scale_s, F32& tex_scale_t, + F32& tex_offset_s, F32& tex_offset_t, + F32& tex_rotation); protected: static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value); static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value); diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index bd6256d961..41dd5a8710 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -67,15 +67,11 @@ public: static const LLMaterialID null; - // Returns a 64 bits digest of the material Id, by XORing its two 64 bits - // long words. HB - inline U64 getDigest64() const - { - U64* tmp = (U64*)mID; - return tmp[0] ^ tmp[1]; - } - private: + // definitions follow class + friend std::hash<LLMaterialID>; + friend size_t hash_value(const LLMaterialID&) noexcept; + void parseFromBinary(const LLSD::Binary& pMaterialID); void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID); int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const; @@ -90,15 +86,27 @@ namespace std { inline size_t operator()(const LLMaterialID& id) const noexcept { - return (size_t)id.getDigest64(); + size_t h = 0; + // Golden ratio hash with avalanche mixing + // Process 8 bytes at a time by manually constructing 64-bit values + // Shift by 31: mixes upper half into lower half for better bit distribution + // Shift by 47: ensures highest bits influence final hash output + for (int i = 0; i < MATERIAL_ID_SIZE; i += 8) { + size_t chunk = (size_t)id.mID[i] | ((size_t)id.mID[i + 1] << 8) | + ((size_t)id.mID[i+2] << 16) | ((size_t)id.mID[i+3] << 24) | + ((size_t)id.mID[i+4] << 32) | ((size_t)id.mID[i+5] << 40) | + ((size_t)id.mID[i + 6] << 48) | ((size_t)id.mID[i + 7] << 56); + h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47); + } + return h; } }; } -// For use with boost containers. +// For use with boost::container_hash inline size_t hash_value(const LLMaterialID& id) noexcept { - return (size_t)id.getDigest64(); + return std::hash<LLMaterialID>{}(id); } #endif // LL_LLMATERIALID_H diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index f1e18776bf..96f99fd31c 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -27,13 +27,14 @@ #ifndef LL_LLFONTFREETYPE_H #define LL_LLFONTFREETYPE_H -#include <boost/unordered_map.hpp> #include "llpointer.h" #include "llstl.h" #include "llimagegl.h" #include "llfontbitmapcache.h" +#include <unordered_map> + // Hack. FT_Face is just a typedef for a pointer to a struct, // but there's no simple forward declarations file for FreeType, // and the main include file is 200K. @@ -191,7 +192,7 @@ private: fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) // *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique) - typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; + typedef std::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap mutable LLFontBitmapCache* mFontBitmapCachep; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index d13b98e274..4584ed1d86 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2376,7 +2376,7 @@ void clear_glerror() // // Static members -boost::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap; +std::unordered_map<LLGLenum, LLGLboolean> LLGLState::sStateMap; GLboolean LLGLDepthTest::sDepthEnabled = GL_FALSE; // OpenGL default GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default @@ -2419,7 +2419,7 @@ void LLGLState::resetTextureStates() void LLGLState::dumpStates() { LL_INFOS("RenderState") << "GL States:" << LL_ENDL; - for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); + for (std::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); iter != sStateMap.end(); ++iter) { LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"true":"false") << LL_ENDL; @@ -2451,7 +2451,7 @@ void LLGLState::checkStates(GLboolean writeAlpha) //llassert_always(colorMask[2]); // llassert_always(colorMask[3] == writeAlpha); - for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); + for (std::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); iter != sStateMap.end(); ++iter) { LLGLenum state = iter->first; diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index d19825d9ca..e1ab2a49e6 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -31,7 +31,7 @@ #include <functional> #include <string> -#include <boost/unordered_map.hpp> +#include <unordered_map> #include <list> #include "llerror.h" @@ -246,7 +246,7 @@ public: static void checkStates(GLboolean writeAlpha = GL_TRUE); protected: - static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap; + static std::unordered_map<LLGLenum, LLGLboolean> sStateMap; public: enum { CURRENT_STATE = -2, DISABLED_STATE = 0, ENABLED_STATE = 1 }; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 97ea6f67bd..4a3d32c7ff 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2189,7 +2189,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) { - if(sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask) + if(!data_in || sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask) { return ; } diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index 3115606d91..69b80db1e8 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -27,9 +27,11 @@ #ifndef LLCALLBACKMAP_H #define LLCALLBACKMAP_H -#include <map> +#include "llstl.h" + #include <string> #include <functional> +#include <unordered_map> class LLCallbackMap { @@ -37,7 +39,7 @@ public: // callback definition. typedef std::function<void* (void* data)> callback_t; - typedef std::map<std::string, LLCallbackMap> map_t; + typedef std::unordered_map<std::string, LLCallbackMap> map_t; typedef map_t::iterator map_iter_t; typedef map_t::const_iterator map_const_iter_t; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 62c5f60015..9361358ced 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -241,7 +241,7 @@ void LLFloater::initClass() } // defaults for floater param block pulled from widgets/floater.xml -static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(typeid(LLFloater::Params), "floater"); LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) : LLPanel(), // intentionally do not pass params here, see initFromParams diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index a818e72f59..c18495ce71 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -40,9 +40,9 @@ LLFloaterReg::instance_list_t LLFloaterReg::sNullInstanceList; LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap; LLFloaterReg::build_map_t LLFloaterReg::sBuildMap; -std::map<std::string, std::string, std::less<>> LLFloaterReg::sGroupMap; +LLFloaterReg::group_map_t LLFloaterReg::sGroupMap; bool LLFloaterReg::sBlockShowFloaters = false; -std::set<std::string, std::less<>> LLFloaterReg::sAlwaysShowableList; +LLFloaterReg::always_showable_t LLFloaterReg::sAlwaysShowableList; static LLFloaterRegListener sFloaterRegListener; @@ -96,11 +96,8 @@ LLFloater* LLFloaterReg::getLastFloaterCascading() candidate_rect.mTop = 100000; LLFloater* candidate_floater = NULL; - std::map<std::string,std::string>::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end(); - for( ; it != it_end; ++it) + for (const auto& [floater_name, group_name] : sGroupMap) { - const std::string& group_name = it->second; - instance_list_t& instances = sInstanceMap[group_name]; for (LLFloater* inst : instances) @@ -604,17 +601,11 @@ U32 LLFloaterReg::getVisibleFloaterInstanceCount() { U32 count = 0; - std::map<std::string,std::string>::const_iterator it = sGroupMap.begin(), it_end = sGroupMap.end(); - for( ; it != it_end; ++it) + for (const auto& [floater_name, group_name] : sGroupMap) { - const std::string& group_name = it->second; - instance_list_t& instances = sInstanceMap[group_name]; - - for (instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); ++iter) + for (LLFloater* inst : instances) { - LLFloater* inst = *iter; - if (inst->getVisible() && !inst->isMinimized()) { count++; diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 24d1476dda..71a11b6f42 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -29,9 +29,11 @@ /// llcommon #include "llrect.h" #include "llsd.h" +#include "llstl.h" #include <functional> #include <list> +#include <unordered_set> //******************************************************* // @@ -51,26 +53,29 @@ public: // 2) We can change the key of a floater without altering the list. typedef std::list<LLFloater*> instance_list_t; typedef const instance_list_t const_instance_list_t; - typedef std::map<std::string, instance_list_t, std::less<>> instance_map_t; + typedef std::unordered_map<std::string, instance_list_t, ll::string_hash, std::equal_to<>> instance_map_t; struct BuildData { LLFloaterBuildFunc mFunc; std::string mFile; }; - typedef std::map<std::string, BuildData, std::less<>> build_map_t; + typedef std::unordered_map<std::string, BuildData, ll::string_hash, std::equal_to<>> build_map_t; private: friend class LLFloaterRegListener; static instance_list_t sNullInstanceList; static instance_map_t sInstanceMap; static build_map_t sBuildMap; - static std::map<std::string, std::string, std::less<>> sGroupMap; + + using group_map_t = std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>>; + static group_map_t sGroupMap; static bool sBlockShowFloaters; /** * Defines list of floater names that can be shown despite state of sBlockShowFloaters. */ - static std::set<std::string, std::less<>> sAlwaysShowableList; + using always_showable_t = std::unordered_set<std::string, ll::string_hash, std::equal_to<>>; + static always_showable_t sAlwaysShowableList; public: // Registration diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 953963b683..40a3e439a6 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -29,8 +29,9 @@ #define LL_LLFUNCTORREGISTRY_H #include <string> -#include <map> +#include <unordered_map> +#include "llstring.h" #include "llsd.h" #include "llsingleton.h" @@ -56,7 +57,7 @@ class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> > public: typedef FUNCTOR_TYPE ResponseFunctor; - typedef typename std::map<std::string, FUNCTOR_TYPE> FunctorMap; + typedef typename std::unordered_map<std::string, FUNCTOR_TYPE, ll::string_hash, std::equal_to<>> FunctorMap; bool registerFunctor(const std::string& name, ResponseFunctor f) { diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 5892238593..53b5435324 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -194,7 +194,7 @@ protected: token_list_t mLineTokenList; token_list_t mDelimiterTokenList; - typedef std::map<std::string, std::string, std::less<>> element_attributes_t; + typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> element_attributes_t; typedef element_attributes_t::const_iterator attribute_iterator_t; element_attributes_t mAttributes; std::string getAttribute(std::string_view key); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 0ffe6cff5e..56475a2d8d 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1424,6 +1424,7 @@ LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelN // this function is called once at construction time, after the object is constructed. void LLNotifications::initSingleton() { + LL_PROFILE_ZONE_SCOPED; loadTemplates(); loadVisibilityRules(); createDefaultChannels(); @@ -1436,6 +1437,8 @@ void LLNotifications::cleanupSingleton() void LLNotifications::createDefaultChannels() { + LL_PROFILE_ZONE_SCOPED; + LL_INFOS("Notifications") << "Generating default notification channels" << LL_ENDL; // now construct the various channels AFTER loading the notifications, // because the history channel is going to rewrite the stored notifications file @@ -1578,6 +1581,8 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path bool LLNotifications::loadTemplates() { + LL_PROFILE_ZONE_SCOPED; + LL_INFOS("Notifications") << "Reading notifications template" << LL_ENDL; // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it // output all relevant pathnames instead of just the ones from the most @@ -1663,6 +1668,8 @@ bool LLNotifications::loadTemplates() bool LLNotifications::loadVisibilityRules() { + LL_PROFILE_ZONE_SCOPED; + const std::string xml_filename = "notification_visibility.xml"; // Note that here we're looking for the "en" version, the default // language, rather than the most localized version of this file. diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index c7c7435be2..ea1cb7f638 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -946,7 +946,7 @@ public: typedef std::vector<std::string> TemplateNames; TemplateNames getTemplateNames() const; // returns a list of notification names - typedef std::map<std::string, LLNotificationTemplatePtr, std::less<>> TemplateMap; + typedef std::unordered_map<std::string, LLNotificationTemplatePtr, ll::string_hash, std::equal_to<>> TemplateMap; TemplateMap::const_iterator templatesBegin() { return mTemplates.begin(); } TemplateMap::const_iterator templatesEnd() { return mTemplates.end(); } @@ -992,7 +992,7 @@ private: LLNotificationMap mUniqueNotifications; - typedef std::map<std::string, std::string, std::less<>> GlobalStringMap; + typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> GlobalStringMap; GlobalStringMap mGlobalStrings; bool mIgnoreAllNotifications; diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index fe861dc719..a928997c7d 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -250,7 +250,7 @@ private: LLButton* mDefaultBtn; LLUIString mLabel; - typedef std::map<std::string, std::string, std::less<>> ui_string_map_t; + typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> ui_string_map_t; ui_string_map_t mUIStrings; @@ -292,7 +292,7 @@ public: } private: - typedef std::map< std::string, LLPanelClassCreatorFunc, std::less<>> param_name_map_t; + typedef std::unordered_map<std::string, LLPanelClassCreatorFunc, ll::string_hash, std::equal_to<>> param_name_map_t; param_name_map_t mPanelClassesNames; }; diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp index 2aff434612..1dbd9f5b0c 100644 --- a/indra/llui/llradiogroup.cpp +++ b/indra/llui/llradiogroup.cpp @@ -67,7 +67,7 @@ protected: LLSD mPayload; // stores data that this item represents in the radio group }; -static LLWidgetNameRegistry::StaticRegistrar register_radio_item(&typeid(LLRadioGroup::ItemParams), "radio_item"); +static LLWidgetNameRegistry::StaticRegistrar register_radio_item(typeid(LLRadioGroup::ItemParams), "radio_item"); LLRadioGroup::Params::Params() : allow_deselect("allow_deselect"), diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp index 1b4008cff2..5b0d2315c1 100644 --- a/indra/llui/llrngwriter.cpp +++ b/indra/llui/llrngwriter.cpp @@ -94,7 +94,7 @@ void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam: block.inspectBlock(*this); // add includes for all possible children - const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); + const std::type_index& type = *LLWidgetTypeRegistry::instance().getValue(type_name); const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); // add include declarations for all valid children diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index a4510d1fc2..b5ba466750 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -39,7 +39,7 @@ const S32 MIN_COLUMN_WIDTH = 20; // defaults for LLScrollColumnHeader param block pulled from widgets/scroll_column_header.xml -static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid(LLScrollColumnHeader::Params), "scroll_column_header"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(typeid(LLScrollColumnHeader::Params), "scroll_column_header"); //--------------------------------------------------------------------------- // LLScrollColumnHeader diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 5e0985c79c..48e42d9fc0 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -2202,3 +2202,16 @@ void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) updateMaxScrollPos(); } + +bool LLTabContainer::getTabVisibility(const LLPanel* panel) const +{ + for (tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr) + { + LLTabTuple const* pTT = *itr; + if (pTT->mTabPanel == panel) + { + return pTT->mVisible; + } + } + return false; +} diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 4ac7e73d25..cbf56dc653 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -225,6 +225,7 @@ public: S32 getMaxTabWidth() const { return mMaxTabWidth; } void setTabVisibility( LLPanel const *aPanel, bool ); + bool getTabVisibility(const LLPanel* panel) const; void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 1b8572f532..5882c1edbb 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -132,7 +132,7 @@ struct LLTextBase::line_end_compare // // register LLTextBase::Params under name "textbase" -static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(&typeid(LLTextBase::Params), "textbase"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(typeid(LLTextBase::Params), "textbase"); LLTextBase::LineSpacingParams::LineSpacingParams() : multiple("multiple", 1.f), diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 74f03618cf..c5b1b5ba1d 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -129,7 +129,7 @@ void LLToolTipView::drawStickyRect() } // defaults for floater param block pulled from widgets/floater.xml -static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(&typeid(LLInspector::Params), "inspector"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(typeid(LLInspector::Params), "inspector"); // // LLToolTip diff --git a/indra/llui/lltrans.h b/indra/llui/lltrans.h index c5d01e6f8d..4dba4c5c3e 100644 --- a/indra/llui/lltrans.h +++ b/indra/llui/lltrans.h @@ -125,7 +125,7 @@ public: } private: - typedef std::map<std::string, LLTransTemplate, std::less<>> template_map_t; + typedef std::unordered_map<std::string, LLTransTemplate, ll::string_hash, std::equal_to<>> template_map_t; static template_map_t sStringTemplates; static template_map_t sDefaultStringTemplates; static LLStringUtil::format_map_t sDefaultArgs; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 38d5720556..0056e73cce 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -65,7 +65,6 @@ // for XUIParse #include "llquaternion.h" -#include <boost/tokenizer.hpp> #include <boost/algorithm/string/find_iterator.hpp> #include <boost/algorithm/string/finder.hpp> @@ -157,6 +156,7 @@ mWindow(NULL), // set later in startup mRootView(NULL), mHelpImpl(NULL) { + LL_PROFILE_ZONE_SCOPED; LLRender2D::createInstance(image_provider); LLSpellChecker::createInstance(); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 2ef64baaf6..091e0ab1cf 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -114,7 +114,7 @@ class LLUI : public LLSimpleton<LLUI> { LOG_CLASS(LLUI); public: - typedef std::map<std::string, LLControlGroup*, std::less<> > settings_map_t; + typedef std::unordered_map<std::string, LLControlGroup*, ll::string_hash, std::equal_to<>> settings_map_t; LLUI(const settings_map_t &settings, LLImageProviderInterface* image_provider, diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index a792cb8103..7a4f72fe4f 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -198,8 +198,8 @@ LLUIColor LLUIColorTable::getColor(std::string_view name, const LLColor4& defaul // update user color, loaded colors are parsed on initialization void LLUIColorTable::setColor(std::string_view name, const LLColor4& color) { - auto it = mUserSetColors.lower_bound(name); - if(it != mUserSetColors.end() && !(mUserSetColors.key_comp()(name, it->first))) + auto it = mUserSetColors.find(name); + if(it != mUserSetColors.end()) { it->second = color; } @@ -330,9 +330,8 @@ void LLUIColorTable::clearTable(string_color_map_t& table) // if the color already exists it changes the color void LLUIColorTable::setColor(std::string_view name, const LLColor4& color, string_color_map_t& table) { - string_color_map_t::iterator it = table.lower_bound(name); - if(it != table.end() - && !(table.key_comp()(name, it->first))) + string_color_map_t::iterator it = table.find(name); + if(it != table.end()) { it->second = color; } diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h index 0c6286e5eb..aff6f59db6 100644 --- a/indra/llui/lluicolortable.h +++ b/indra/llui/lluicolortable.h @@ -27,7 +27,7 @@ #ifndef LL_LLUICOLORTABLE_H_ #define LL_LLUICOLORTABLE_H_ -#include <map> +#include <unordered_map> #include "llinitparam.h" #include "llsingleton.h" @@ -42,7 +42,7 @@ class LLUIColorTable : public LLSingleton<LLUIColorTable> LOG_CLASS(LLUIColorTable); // consider using sorted vector, can be much faster - typedef std::map<std::string, LLUIColor, std::less<>> string_color_map_t; + typedef std::unordered_map<std::string, LLUIColor, ll::string_hash, std::equal_to<>> string_color_map_t; public: struct ColorParams : LLInitParam::ChoiceBlock<ColorParams> diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 9abccfd9a0..33ffc3dfc6 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -253,7 +253,7 @@ const LLInitParam::BaseBlock& get_empty_param_block() // adds a widget and its param block to various registries //static -void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name) +void LLUICtrlFactory::registerWidget(std::type_index widget_type, std::type_index param_block_type, const std::string& name) { // associate parameter block type with template .xml file std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type); diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index fc069c078f..f44b4ba4dc 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -65,7 +65,7 @@ class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry> // lookup widget name by type class LLWidgetNameRegistry -: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry> +: public LLRegistrySingleton<std::type_index, std::string, LLWidgetNameRegistry> { LLSINGLETON_EMPTY_CTOR(LLWidgetNameRegistry); }; @@ -74,7 +74,7 @@ class LLWidgetNameRegistry // this is used for schema generation //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)(); //class LLDefaultParamBlockRegistry -//: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry> +//: public LLRegistrySingleton<std::type_index, empty_param_block_func_t, LLDefaultParamBlockRegistry> //{ // LLSINGLETON(LLDefaultParamBlockRegistry); //}; @@ -202,7 +202,7 @@ private: static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest); // helper function for adding widget type info to various registries - static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag); + static void registerWidget(std::type_index widget_type, std::type_index param_block_type, const std::string& tag); static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); @@ -290,7 +290,7 @@ template <typename PARAM_BLOCK, int DUMMY> LLUICtrlFactory::ParamDefaults<PARAM_BLOCK, DUMMY>::ParamDefaults() { // look up template file for this param block... - const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); + const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(typeid(PARAM_BLOCK)); if (param_block_tag) { // ...and if it exists, back fill values using the most specific template first PARAM_BLOCK params; @@ -314,12 +314,12 @@ LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreator : LLChildRegistry<DERIVED>::StaticRegistrar(tag, func == nullptr ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func) { // add this widget to various registries - LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), tag); + LLUICtrlFactory::instance().registerWidget(typeid(T), typeid(typename T::Params), tag); // since registry_t depends on T, do this in line here // TODO: uncomment this for schema generation //typedef typename T::child_registry_t registry_t; - //LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance()); + //LLChildRegistryRegistry::instance().defaultRegistrar().add(typeid(T), registry_t::instance()); } #endif //LLUICTRLFACTORY_H diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index 8fd85a89a1..71ce2afdbd 100644 --- a/indra/llui/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp @@ -602,7 +602,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui"); // add includes for all possible children - const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); + const std::type_index& type = *LLWidgetTypeRegistry::instance().getValue(type_name); const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); // add choices for valid children @@ -1459,7 +1459,7 @@ void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int void LLSimpleXUIParser::characterData(const char *s, int len) { - mTextContents += std::string(s, len); + mTextContents.append(s, len); } void LLSimpleXUIParser::startElement(const char *name, const char **atts) @@ -1480,24 +1480,24 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts) mOutputStack.back().second++; S32 num_tokens_pushed = 0; - std::string child_name(name); + std::string_view child_name(name); if (mOutputStack.back().second == 1) { // root node for this block - mScope.push_back(child_name); + mScope.emplace_back(child_name); } else { // compound attribute if (child_name.find(".") == std::string::npos) { - mNameStack.push_back(std::make_pair(child_name, true)); + mNameStack.emplace_back(child_name, true); num_tokens_pushed++; - mScope.push_back(child_name); + mScope.emplace_back(child_name); } else { // parse out "dotted" name into individual tokens - tokenizer name_tokens(child_name, sep); + tokenizer name_tokens(std::string(child_name), sep); tokenizer::iterator name_token_it = name_tokens.begin(); if(name_token_it == name_tokens.end()) @@ -1603,8 +1603,8 @@ bool LLSimpleXUIParser::processText() LLStringUtil::trim(mTextContents); if (!mTextContents.empty()) { - mNameStack.push_back(std::make_pair(std::string("value"), true)); - mCurAttributeValueBegin = mTextContents.c_str(); + mNameStack.emplace_back("value", true); + mCurAttributeValueBegin = std::move(mTextContents); mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently); mNameStack.pop_back(); } @@ -1648,12 +1648,12 @@ bool LLSimpleXUIParser::readFlag(Parser& parser, void* val_ptr) bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - if (!strcmp(self.mCurAttributeValueBegin, "true")) + if (!strcmp(self.mCurAttributeValueBegin.c_str(), "true")) { *((bool*)val_ptr) = true; return true; } - else if (!strcmp(self.mCurAttributeValueBegin, "false")) + else if (!strcmp(self.mCurAttributeValueBegin.c_str(), "false")) { *((bool*)val_ptr) = false; return true; @@ -1665,56 +1665,56 @@ bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr) bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - *((std::string*)val_ptr) = self.mCurAttributeValueBegin; + *((std::string*)val_ptr) = std::move(self.mCurAttributeValueBegin); return true; } bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), uint_p[assign_a(*(U8*)val_ptr)]).full; } bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), int_p[assign_a(*(S8*)val_ptr)]).full; } bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), uint_p[assign_a(*(U16*)val_ptr)]).full; } bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), int_p[assign_a(*(S16*)val_ptr)]).full; } bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), uint_p[assign_a(*(U32*)val_ptr)]).full; } bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), int_p[assign_a(*(S32*)val_ptr)]).full; } bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(*(F32*)val_ptr)]).full; } bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr) { LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); - return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full; + return parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(*(F64*)val_ptr)]).full; } bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr) @@ -1722,7 +1722,7 @@ bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr) LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); LLColor4 value; - if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) + if (parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) { *(LLColor4*)(val_ptr) = value; return true; @@ -1736,7 +1736,7 @@ bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr) LLColor4 value; LLUIColor* colorp = (LLUIColor*)val_ptr; - if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) + if (parse(self.mCurAttributeValueBegin.c_str(), real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full) { colorp->set(value); return true; @@ -1749,7 +1749,7 @@ bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr) LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser); LLUUID temp_id; // LLUUID::set is destructive, so use temporary value - if (temp_id.set(std::string(self.mCurAttributeValueBegin))) + if (temp_id.set(self.mCurAttributeValueBegin)) { *(LLUUID*)(val_ptr) = temp_id; return true; diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index 2179ae54d3..3cc564772e 100644 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -40,7 +40,7 @@ class LLView; // lookup widget type by name class LLWidgetTypeRegistry -: public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry> +: public LLRegistrySingleton<std::string, std::type_index, LLWidgetTypeRegistry> { LLSINGLETON_EMPTY_CTOR(LLWidgetTypeRegistry); }; @@ -52,7 +52,7 @@ typedef std::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t; class LLChildRegistryRegistry -: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry> +: public LLRegistrySingleton<std::type_index, widget_registry_t, LLChildRegistryRegistry> { LLSINGLETON_EMPTY_CTOR(LLChildRegistryRegistry); }; @@ -247,7 +247,7 @@ private: S32 mCurReadDepth; std::string mCurFileName; std::string mTextContents; - const char* mCurAttributeValueBegin; + std::string mCurAttributeValueBegin; std::vector<S32> mTokenSizeStack; std::vector<std::string> mScope; std::vector<bool> mEmptyLeafNode; diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index 8e08239ee6..6bf38cc1f6 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -733,12 +733,17 @@ void LLWebRTCImpl::intSetMute(bool mute, int delay_ms) { mPeerCustomProcessor->setGain(mMute ? 0.0f : mGain); } + + // Sequence counter to prevent race conditions from rapid requests to mute/unmute + static std::atomic<uint32_t> mute_sequence(0); + uint32_t current_sequence = ++mute_sequence; + if (mMute) { mWorkerThread->PostDelayedTask( - [this] + [this, current_sequence] { - if (mDeviceModule) + if (mDeviceModule && (current_sequence == mute_sequence.load())) { mDeviceModule->ForceStopRecording(); } @@ -748,9 +753,9 @@ void LLWebRTCImpl::intSetMute(bool mute, int delay_ms) else { mWorkerThread->PostTask( - [this] + [this, current_sequence] { - if (mDeviceModule) + if (mDeviceModule && (current_sequence == mute_sequence.load())) { mDeviceModule->InitRecording(); mDeviceModule->ForceStartRecording(); @@ -1531,6 +1536,57 @@ void LLWebRTCPeerConnectionImpl::unsetDataObserver(LLWebRTCDataObserver* observe } } +class LLStatsCollectorCallback : public webrtc::RTCStatsCollectorCallback +{ +public: + typedef std::function<void(const LLWebRTCStatsMap&)> StatsCallback; + + LLStatsCollectorCallback(StatsCallback callback) : callback_(callback) {} + + void OnStatsDelivered(const webrtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override + { + if (callback_) + { + // Transform RTCStatsReport stats to simple map + LLWebRTCStatsMap stats_map; + for (const auto& stats : *report) + { + std::map<std::string, std::string> stat_attributes; + + // Convert each attribute to string format + for (const auto& attribute : stats.Attributes()) + { + stat_attributes[attribute.name()] = attribute.ToString(); + } + stats_map[stats.id()] = stat_attributes; + } + callback_(stats_map); + } + } + +private: + StatsCallback callback_; +}; + +void LLWebRTCPeerConnectionImpl::gatherConnectionStats() +{ + if (!mPeerConnection) + { + return; + } + + auto stats_callback = webrtc::make_ref_counted<LLStatsCollectorCallback>( + [this](const LLWebRTCStatsMap& generic_stats) + { + for (auto& observer : mSignalingObserverList) + { + observer->OnStatsDelivered(generic_stats); + } + }); + + mPeerConnection->GetStats(stats_callback.get()); +} + LLWebRTCImpl * gWebRTCImpl = nullptr; LLWebRTCDeviceInterface * getDeviceInterface() { diff --git a/indra/llwebrtc/llwebrtc.h b/indra/llwebrtc/llwebrtc.h index 7d06b7d2b4..e76e708f0c 100644 --- a/indra/llwebrtc/llwebrtc.h +++ b/indra/llwebrtc/llwebrtc.h @@ -38,6 +38,7 @@ #ifndef LLWEBRTC_H #define LLWEBRTC_H +#include <map> #include <string> #include <vector> @@ -55,6 +56,7 @@ namespace llwebrtc { +typedef std::map<std::string, std::map<std::string, std::string>> LLWebRTCStatsMap; class LLWebRTCLogCallback { @@ -240,6 +242,8 @@ class LLWebRTCSignalingObserver // Called when the data channel has been established and data // transfer can begin. virtual void OnDataChannelReady(LLWebRTCDataInterface *data_interface) = 0; + + virtual void OnStatsDelivered(const LLWebRTCStatsMap& stats_data) {} }; // LLWebRTCPeerConnectionInterface representsd a connection to a peer, @@ -273,6 +277,8 @@ class LLWebRTCPeerConnectionInterface virtual void unsetSignalingObserver(LLWebRTCSignalingObserver* observer) = 0; virtual void AnswerAvailable(const std::string &sdp) = 0; + + virtual void gatherConnectionStats() = 0; }; // The following define the dynamic linked library diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h index 01cfb17ced..c1e909df72 100644 --- a/indra/llwebrtc/llwebrtc_impl.h +++ b/indra/llwebrtc/llwebrtc_impl.h @@ -648,6 +648,8 @@ class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface, void enableSenderTracks(bool enable); void enableReceiverTracks(bool enable); + void gatherConnectionStats() override; + protected: LLWebRTCImpl * mWebRTCImpl; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 9d05d7e5a4..2bd9dd053c 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -436,7 +436,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool { if (!mWindowTimeout) { - mWindowTimeout = std::make_unique<LLWatchdogTimeout>("mainloop"); + mWindowTimeout = std::make_unique<LLWatchdogTimeout>("WindowThread"); // supposed to be executed within run(), // so no point checking if thread is alive resumeTimeout("TimeoutInit"); diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 5a83f8c541..34643d5f5c 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -761,6 +761,7 @@ void LLControlGroup::setUntypedValue(std::string_view name, const LLSD& val) // Returns number of controls loaded, so 0 if failure U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, bool require_declaration, eControlType declare_as) { + LL_PROFILE_ZONE_SCOPED; std::string name; LLXmlTree xml_controls; @@ -995,6 +996,7 @@ U32 LLControlGroup::saveToFile(const std::string& filename, bool nondefault_only U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values, bool error_when_no_comment) { + LL_PROFILE_ZONE_SCOPED; LLSD settings; llifstream infile; infile.open(filename.c_str()); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index c9bd0a8a32..5aa2b9715e 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -33,8 +33,10 @@ #include "llrect.h" #include "llrefcount.h" #include "llinstancetracker.h" +#include "llstl.h" #include <functional> +#include <unordered_map> #include <vector> #include <boost/signals2.hpp> @@ -165,7 +167,7 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string> LOG_CLASS(LLControlGroup); protected: - typedef std::map<std::string, LLControlVariablePtr, std::less<> > ctrl_name_table_t; + using ctrl_name_table_t = std::unordered_map<std::string, LLControlVariablePtr, ll::string_hash, std::equal_to<>>; ctrl_name_table_t mNameTable; static const std::string mTypeString[TYPE_COUNT]; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0949a3b59f..5818a900f5 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -197,7 +197,6 @@ set(viewer_SOURCE_FILES llfloateravatartextures.cpp llfloaterbanduration.cpp llfloaterbeacons.cpp - llfloaterbigpreview.cpp llfloaterbuildoptions.cpp llfloaterbulkpermission.cpp llfloaterbulkupload.cpp @@ -280,7 +279,6 @@ set(viewer_SOURCE_FILES llfloaterpay.cpp llfloaterperformance.cpp llfloaterperms.cpp - llfloaterpostprocess.cpp llfloaterprofile.cpp llfloaterpreference.cpp llfloaterpreferencesgraphicsadvanced.cpp @@ -305,7 +303,6 @@ set(viewer_SOURCE_FILES llfloatersidepanelcontainer.cpp llfloaterslapptest.cpp llfloatersnapshot.cpp - llfloatersounddevices.cpp llfloaterspellchecksettings.cpp llfloatertelehub.cpp llfloatertestinspectors.cpp @@ -317,7 +314,6 @@ set(viewer_SOURCE_FILES llfloatertranslationsettings.cpp llfloateruipreview.cpp llfloaterurlentry.cpp - llfloatervoiceeffect.cpp llfloatervoicevolume.cpp llfloaterwebcontent.cpp llfloaterwhitelistentry.cpp @@ -420,6 +416,7 @@ set(viewer_SOURCE_FILES llfloaterimnearbychat.cpp llfloaterimnearbychathandler.cpp llfloaterimnearbychatlistener.cpp + llnearbyvoicemoderation.cpp llnetmap.cpp llnotificationalerthandler.cpp llnotificationgrouphandler.cpp @@ -513,7 +510,6 @@ set(viewer_SOURCE_FILES llpanelsnapshotprofile.cpp llpanelteleporthistory.cpp llpaneltiptoast.cpp - llpanelvoiceeffect.cpp llpaneltopinfobar.cpp llpanelpulldown.cpp llpanelvoicedevicesettings.cpp @@ -881,7 +877,6 @@ set(viewer_HEADER_FILES llfloateravatartextures.h llfloaterbanduration.h llfloaterbeacons.h - llfloaterbigpreview.h llfloaterbuildoptions.h llfloaterbulkpermission.h llfloaterbulkupload.h @@ -968,7 +963,6 @@ set(viewer_HEADER_FILES llfloaterpay.h llfloaterperformance.h llfloaterperms.h - llfloaterpostprocess.h llfloaterprofile.h llfloaterpreference.h llfloaterpreferencesgraphicsadvanced.h @@ -993,7 +987,6 @@ set(viewer_HEADER_FILES llfloatersidepanelcontainer.h llfloaterslapptest.h llfloatersnapshot.h - llfloatersounddevices.h llfloaterspellchecksettings.h llfloatertelehub.h llfloatertestinspectors.h @@ -1005,7 +998,6 @@ set(viewer_HEADER_FILES llfloatertranslationsettings.h llfloateruipreview.h llfloaterurlentry.h - llfloatervoiceeffect.h llfloatervoicevolume.h llfloaterwebcontent.h llfloaterwhitelistentry.h @@ -1102,6 +1094,7 @@ set(viewer_HEADER_FILES llnameeditor.h llnamelistctrl.h llnavigationbar.h + llnearbyvoicemoderation.h llnetmap.h llnotificationhandler.h llnotificationlistitem.h @@ -1187,7 +1180,6 @@ set(viewer_HEADER_FILES llpaneltiptoast.h llpanelpulldown.h llpanelvoicedevicesettings.h - llpanelvoiceeffect.h llpaneltopinfobar.h llpanelvolume.h llpanelvolumepulldown.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 2aaedf9944..b7397ce158 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -26.1.0 +26.2.0 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8c8a6ebd4d..78d0e52e3d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -489,6 +489,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RecentJumpThresholdSecs</key> + <map> + <key>Comment</key> + <string>Seconds after a jump input during which finish-anim is suppressed to avoid interrupting rapid successive jumps.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> <key>AvatarAxisDeadZone0</key> <map> <key>Comment</key> @@ -641,7 +652,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/vawp/index.html</string> + <string>https://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/vawp/index.html</string> </map> <!--AvatarBakedTextureUploadTimeout is in use by QA--> <key>AvatarBakedTextureUploadTimeout</key> @@ -2467,7 +2478,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/guide.html</string> + <string>https://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/guide.html</string> </map> <key>DisableCameraConstraints</key> <map> @@ -2775,7 +2786,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://events.[GRID]/viewer/embed/event/[EVENT_ID]</string> + <string>https://events.[GRID]/viewer/embed/event/[EVENT_ID]</string> </map> <key>MainWorkTime</key> <map> @@ -3432,7 +3443,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC][DEBUG_MODE]</string> + <string>https://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC][DEBUG_MODE]</string> </map> <key>HowToHelpURL</key> <map> @@ -3443,7 +3454,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/howto/index.html</string> + <string>https://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/howto/index.html</string> </map> <key>HomeSidePanelURL</key> <map> @@ -4059,7 +4070,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://wiki.secondlife.com/wiki/[LSL_STRING]</string> + <string>https://wiki.secondlife.com/wiki/[LSL_STRING]</string> </map> <key>LSLFontSizeName</key> <map> @@ -4501,7 +4512,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>30.0</real> + <real>60.0</real> </map> <key>MapScale</key> <map> @@ -6104,6 +6115,39 @@ <key>Value</key> <integer>0</integer> </map> + <key>OpenDebugStatVoice</key> + <map> + <key>Comment</key> + <string>Expand Voice (WebRTC) stats display</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>OpenDebugStatVoiceOutgoing</key> + <map> + <key>Comment</key> + <string>Expand Outgoing audio (Voice) stats display</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>OpenDebugStatVoiceIncoming</key> + <map> + <key>Comment</key> + <string>Expand Incoming audio (Voice) stats display</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>OutBandwidth</key> <map> <key>Comment</key> @@ -10635,6 +10679,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>GroupTitlesTagMode</key> + <map> + <key>Comment</key> + <string>Select Group Titles tag mode: 0 - no group tags, 1 - only my group tag, 2 - all group tags</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>2</integer> + </map> <key>ShowAxes</key> <map> <key>Comment</key> @@ -14710,7 +14765,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/404.html</string> + <string>https://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/404.html</string> </map> <key>OpenIMOnVoice</key> <map> @@ -16398,6 +16453,39 @@ <key>Value</key> <integer>0</integer> </map> + <key>InventoryShowRecentTab</key> + <map> + <key>Comment</key> + <string>Show/hide Recent tab in the Inventory floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>InventoryShowWornTab</key> + <map> + <key>Comment</key> + <string>Show/hide Worn tab in the Inventory floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>InventoryShowFavoritesTab</key> + <map> + <key>Comment</key> + <string>Show/hide Favorites tab in the Inventory floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>StatsReportMaxDuration</key> <map> <key>Comment</key> @@ -16552,5 +16640,16 @@ <key>Value</key> <integer>2</integer> </map> + <key>PurgeDiskCacheOnStartup</key> + <map> + <key>Comment</key> + <string>Whether or not to LRU purge the disk cache during startup on main thread</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> </map> </llsd> diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index dd9e883fdf..abe61fe892 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -146,6 +146,9 @@ vec3 srgb_to_linear(vec3 c); void main() { vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; + + basecolor.a *= vertex_color.a; + if (basecolor.a < minimum_alpha) { discard; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index cc9d72fae6..53bd0c741f 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -51,9 +51,7 @@ in vec3 vary_norm; in vec4 vertex_color; //vertex color should be treated as sRGB #endif -#ifdef HAS_ALPHA_MASK uniform float minimum_alpha; -#endif uniform mat4 proj_mat; uniform mat4 inv_proj; @@ -225,6 +223,13 @@ void main() float final_alpha = diffuse_linear.a; +#ifdef IS_AVATAR_SKIN + if(final_alpha < minimum_alpha) + { + discard; + } +#endif + #ifdef USE_VERTEX_COLOR final_alpha *= vertex_color.a; diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 51fb019e93..bb8adf236a 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -1027,6 +1027,12 @@ bool Image::prepImpl(Asset& asset, const LLUUID& id) std::string dir = gDirUtilp->getDirName(asset.mFilename); std::string img_file = dir + gDirUtilp->getDirDelimiter() + mUri; + if (!gDirUtilp->fileExists(img_file)) + { + // URI might be escaped, unescape. + img_file = dir + gDirUtilp->getDirDelimiter() + LLURI::unescape(mUri); + } + LLUUID tracking_id = LLLocalBitmapMgr::getInstance()->addUnit(img_file); if (tracking_id.notNull() && mLoadIntoTexturePipe) { diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h index c231443a9e..53dee98cd1 100644 --- a/indra/newview/gltf/buffer_util.h +++ b/indra/newview/gltf/buffer_util.h @@ -141,6 +141,42 @@ namespace LL } template<> + inline void copyScalar<U32, LLVector4a>(U32* src, LLVector4a& dst) + { + dst.set((F32)*src, 0.f, 0.f, 0.f); + } + + template<> + inline void copyScalar<U16, LLVector4a>(U16* src, LLVector4a& dst) + { + dst.set((F32)*src, 0.f, 0.f, 0.f); + } + + template<> + inline void copyScalar<U8, LLVector4a>(U8* src, LLVector4a& dst) + { + dst.set((F32)*src, 0.f, 0.f, 0.f); + } + + template<> + inline void copyScalar<U32, LLVector2>(U32* src, LLVector2& dst) + { + dst.set((F32)*src, 0.f); + } + + template<> + inline void copyScalar<U16, LLVector2>(U16* src, LLVector2& dst) + { + dst.set((F32)*src, 0.f); + } + + template<> + inline void copyScalar<U8, LLVector2>(U8* src, LLVector2& dst) + { + dst.set((F32)*src, 0.f); + } + + template<> inline void copyVec2<F32, LLVector2>(F32* src, LLVector2& dst) { dst.set(src[0], src[1]); @@ -221,6 +257,12 @@ namespace LL } template<> + inline void copyVec4<U32, LLVector4a>(U32* src, LLVector4a& dst) + { + dst.set((F32)src[0], (F32)src[1], (F32)src[2], (F32)src[3]); + } + + template<> inline void copyVec4<U16, LLVector4a>(U16* src, LLVector4a& dst) { dst.set(src[0], src[1], src[2], src[3]); @@ -373,7 +415,7 @@ namespace LL } else { - LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL; + LL_ERRS("GLTF") << "Unsupported accessor type " << (S32)accessor.mType << LL_ENDL; } } diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp index 3a1d8079a9..5a94a2c6c6 100644 --- a/indra/newview/gltf/llgltfloader.cpp +++ b/indra/newview/gltf/llgltfloader.cpp @@ -440,7 +440,25 @@ void LLGLTFLoader::processNodeHierarchy(S32 node_idx, std::map<std::string, S32> (LLModel::NO_ERRORS == pModel->getStatus()) && validate_model(pModel)) { - mTransform.setIdentity(); + // Build the scene transform. + // Non-skinned meshes: scene transform carries coord rotation + hierarchy, + // preserving the object's rotation/position/scale for upload. + // Skinned meshes: transform is already baked into vertices, so scene is identity. + if (node.mSkin >= 0) + { + mTransform.setIdentity(); + } + else + { + glm::mat4 hierarchy_transform; + computeCombinedNodeTransform(mGLTFAsset, node_idx, hierarchy_transform); + glm::mat4 combined = coord_system_rotation * hierarchy_transform; + if (mApplyXYRotation) + { + combined = coord_system_rotationxy * combined; + } + mTransform = LLMatrix4(glm::value_ptr(combined)); + } transformation = mTransform; // adjust the transformation to compensate for mesh normalization @@ -684,7 +702,12 @@ std::string LLGLTFLoader::processTexture(std::string& full_path_out, S32 texture // Process embedded textures if (image.mBufferView >= 0) { - return extractTextureToTempFile(texture_index, texture_type); + std::string temp_path = extractTextureToTempFile(texture_index, texture_type); + if (!temp_path.empty()) + { + full_path_out = temp_path; + } + return temp_path; } return ""; @@ -734,23 +757,47 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& bas S32 skinIdx = nodeno.mSkin; - // Compute final combined transform matrix (hierarchy + coordinate rotation) + // Compute the vertex transform for this mesh. + // Non-skinned meshes: vertices are left untransformed; the node's hierarchy transform + // (rotation, translation, scale) is stored in the scene transform instead, matching + // the DAE loader. This ensures the uploaded object's bounding box and transform + // properties are correct. See: https://github.com/secondlife/viewer/issues/5431 + // Skinned meshes: coord rotation + hierarchy are baked into vertex positions because + // inverse bind matrices and skin weights are already computed in that space. + // TODO: consider aligning skinned meshes with the DAE loader (scene transform instead + // of vertex baking), which would require adjusting inverse bind matrices, bind shape + // matrix, and weight keying to match. S32 node_index = static_cast<S32>(&nodeno - &mGLTFAsset.mNodes[0]); glm::mat4 hierarchy_transform; computeCombinedNodeTransform(mGLTFAsset, node_index, hierarchy_transform); - // Combine transforms: coordinate rotation applied to hierarchy transform - glm::mat4 final_transform = coord_system_rotation * hierarchy_transform; - if (mApplyXYRotation) + glm::mat4 vertex_transform; + if (skinIdx >= 0) { - final_transform = coord_system_rotationxy * final_transform; + // Skinned mesh: bake coord rotation + hierarchy into vertices. + // Inverse bind matrices and skin weights depend on this transform being applied. + vertex_transform = coord_system_rotation * hierarchy_transform; + if (mApplyXYRotation) + { + vertex_transform = coord_system_rotationxy * vertex_transform; + } + } + else + { + // Non-skinned mesh: don't apply any transform to vertices. + // The hierarchy transform will be stored in the scene transform matrix. + vertex_transform = glm::mat4(1.0f); // identity } // Check if we have a negative scale (flipped coordinate system) - bool hasNegativeScale = glm::determinant(final_transform) < 0.0f; + // coord_system_rotation and coord_system_rotationxy are pure rotations (det=1), + // so negative scale depends only on the hierarchy transform. + bool hasNegativeScale = glm::determinant(hierarchy_transform) < 0.0f; + + bool hasVertexTransform = (vertex_transform != glm::mat4(1.0f)); // Pre-compute normal transform matrix (transpose of inverse of upper-left 3x3) - const glm::mat3 normal_transform = glm::transpose(glm::inverse(glm::mat3(final_transform))); + const glm::mat3 normal_transform = glm::transpose(glm::inverse(glm::mat3(vertex_transform))); // Mark unsuported joints with '-1' so that they won't get added into weights // GLTF maps all joints onto all meshes. Gather use count per mesh to cut unused ones. @@ -803,30 +850,49 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& bas return false; // Skip this primitive } - // Apply the global scale and center offset to all vertices + // Apply vertex transform (if any) to all vertices. + // Skinned meshes: this bakes coord rotation + hierarchy into vertices. + // Non-skinned meshes: vertex_transform is identity (no baking). for (U32 i = 0; i < prim.getVertexCount(); i++) { - // Use pre-computed final_transform - glm::vec4 pos(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2], 1.0f); - glm::vec4 transformed_pos = final_transform * pos; - GLTFVertex vert; - vert.position = glm::vec3(transformed_pos); - if (!prim.mNormals.empty()) + if (hasVertexTransform) { - // Use pre-computed normal_transform - glm::vec3 normal_vec(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]); - vert.normal = glm::normalize(normal_transform * normal_vec); + glm::vec4 pos(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2], 1.0f); + glm::vec4 transformed_pos = vertex_transform * pos; + vert.position = glm::vec3(transformed_pos); + + if (!prim.mNormals.empty()) + { + glm::vec3 normal_vec(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]); + vert.normal = glm::normalize(normal_transform * normal_vec); + } + else + { + vert.normal = glm::normalize(normal_transform * glm::vec3(0.0f, 0.0f, 1.0f)); + LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL; + } } else { - // Use default normal (pointing up in model space) - vert.normal = glm::normalize(normal_transform * glm::vec3(0.0f, 0.0f, 1.0f)); - LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL; + // No transform: store raw GLTF positions and normals. + // The scene transform will carry coord rotation + hierarchy. + vert.position = glm::vec3(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2]); + + if (!prim.mNormals.empty()) + { + vert.normal = glm::vec3(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[i][2]); + } + else + { + vert.normal = glm::vec3(0.0f, 0.0f, 1.0f); + LL_DEBUGS("GLTF_IMPORT") << "No normals found for primitive, using default normal." << LL_ENDL; + } } - vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], -prim.mTexCoords0[i][1]); + // Flip texture V coordinate + vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], 1.f - prim.mTexCoords0[i][1]); if (skinIdx >= 0) { diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 0e36698018..ae40e8830f 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -767,8 +767,21 @@ Function un.UserSettingsFiles StrCmp $DO_UNINSTALL_V2 "true" Keep # Don't remove user's settings files on auto upgrade
-# Ask if user wants to keep data files or not
-MessageBox MB_YESNO|MB_ICONQUESTION $(RemoveDataFilesMB) IDYES Remove IDNO Keep
+ClearErrors
+Push $0
+${GetParameters} $COMMANDLINE
+${GetOptionsS} $COMMANDLINE "/clrusrfiles" $0
+# GetOptionsS returns an error if option does not exist, jump past Goto.
+IfErrors +3 0
+ Pop $0
+ Goto Remove
+
+Pop $0
+ClearErrors
+
+ifSilent Keep 0
+ # Ask if user wants to keep data files or not
+ MessageBox MB_YESNO|MB_ICONQUESTION $(RemoveDataFilesMB) IDYES Remove IDNO Keep
Remove:
Push $0
@@ -864,11 +877,25 @@ RMDir "$INSTDIR" IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER
FOLDERFOUND:
+ifSilent NOFOLDER 0
MessageBox MB_OK $(DeleteProgramFilesMB) /SD IDOK IDOK NOFOLDER
NOFOLDER:
-MessageBox MB_YESNO $(DeleteRegistryKeysMB) IDYES DeleteKeys IDNO NoDelete
+ClearErrors
+Push $0
+${GetParameters} $COMMANDLINE
+${GetOptionsS} $COMMANDLINE "/clearreg" $0
+# GetOptionsS returns an error if option does not exist, jump past Goto.
+IfErrors +3 0
+ Pop $0
+ Goto DeleteKeys
+
+Pop $0
+ClearErrors
+
+ifSilent NoDelete 0
+ MessageBox MB_YESNO $(DeleteRegistryKeysMB) IDYES DeleteKeys IDNO NoDelete
DeleteKeys:
DeleteRegKey SHELL_CONTEXT "SOFTWARE\Classes\x-grid-location-info"
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 0d7ad0a124..3ab87cac13 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -426,6 +426,7 @@ LLAgent::LLAgent() : mIsDoNotDisturb(false), mControlFlags(0x00000000), + mLastJumpInputTime(0.0), mAutoPilot(false), mAutoPilotFlyOnStop(false), @@ -780,6 +781,10 @@ void LLAgent::moveUp(S32 direction) if (direction > 0) { + if (!getFlying()) + { + mLastJumpInputTime = LLTimer::getTotalSeconds(); + } setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP); } else if (direction < 0) @@ -2663,7 +2668,21 @@ void LLAgent::onAnimStop(const LLUUID& id) } else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND) { - setControlFlags(AGENT_CONTROL_FINISH_ANIM); + // FIRE-34049/FIRE-34273/https://github.com/secondlife/viewer/issues/4218 + // Avoid forcing AGENT_CONTROL_FINISH_ANIM, which can short-circuit the next pre-jump + // during rapid successive jumps. + // TODO: a more robust fix would require knowing which specific animation finished, + // information that is not currently provided by the simulator. + const bool up_pos = (mControlFlags & AGENT_CONTROL_UP_POS) != 0; + const F64 now = LLTimer::getTotalSeconds(); + const F64 elapsed = now - mLastJumpInputTime; + static LLCachedControl<F32> recent_jump_threshold_secs(gSavedSettings, "RecentJumpThresholdSecs"); + const bool recent_jump = (mLastJumpInputTime > 0.0) && (elapsed < recent_jump_threshold_secs); + + if (!up_pos && !recent_jump) + { + setControlFlags(AGENT_CONTROL_FINISH_ANIM); + } } } @@ -4850,6 +4869,8 @@ const std::string& LLAgent::getTeleportStateName() const void LLAgent::parseTeleportMessages(const std::string& xml_filename) { + LL_PROFILE_ZONE_SCOPED; + LLXMLNodePtr root; bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 3352890d99..e6d9623957 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -487,6 +487,7 @@ private: S32 mControlsTakenCount[TOTAL_CONTROLS]; S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS]; U32 mControlFlags; // Replacement for the mFooKey's + F64 mLastJumpInputTime; // Time of last jump input (key-down) in seconds from LLTimer::getTotalSeconds() //-------------------------------------------------------------------- // Animations diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 1da1647fe8..f67f2688a1 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1019,6 +1019,9 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } //------------------------------------------------------------------------- +U32 AISUpdate::sBatchFrameCount = 0; +LLTimer AISUpdate::sBatchTimer; + AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body) : mType(type) { @@ -1036,8 +1039,16 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& mFetchDepth = request_body["depth"].asInteger(); } - mTimer.setTimerExpirySec(AIS_EXPIRY_SECONDS); - mTimer.start(); + mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS); + mTaskTimer.start(); + + U32 current_frame = LLFrameTimer::getFrameCount(); + if (sBatchFrameCount != current_frame) + { + sBatchTimer.setTimerExpirySec(AIS_BATCH_EXPIRY_SECONDS); + sBatchTimer.start(); + sBatchFrameCount = current_frame; + } parseUpdate(update); } @@ -1058,11 +1069,25 @@ void AISUpdate::clearParseResults() void AISUpdate::checkTimeout() { - if (mTimer.hasExpired()) + if (mTaskTimer.hasExpired() || sBatchTimer.hasExpired()) { - llcoro::suspend(); + // If we are taking too long, don't starve other tasks, + // yield to mainloop. + // If we use normal suspend(), there will be a chance of + // waking up from other suspends, before main coro had + // a chance, so wait for a frame tick instead. + llcoro::suspendUntilNextFrame(); LLCoros::checkStop(); - mTimer.setTimerExpirySec(AIS_EXPIRY_SECONDS); + mTaskTimer.setTimerExpirySec(AIS_TASK_EXPIRY_SECONDS); + + U32 current_frame = LLFrameTimer::getFrameCount(); + if (sBatchFrameCount != current_frame) + { + // To give other tasks a chance batch timer + // has a longer delay. + sBatchTimer.setTimerExpirySec(AIS_BATCH_EXPIRY_SECONDS); + sBatchFrameCount = current_frame; + } } } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index cfc286da2e..1dab0dd1f9 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -130,9 +130,13 @@ private: void clearParseResults(); void checkTimeout(); - // Fetch can return large packets of data, throttle it to not cause lags - // Todo: make throttle work over all fetch requests isntead of per-request - const F32 AIS_EXPIRY_SECONDS = 0.008f; + // Fetches can return large packets of data, + // throttle them individually to not get stuck + // on a single large task. And throttle sum total + // to not cause lags when multiple large fetches + // returned results. + const F32 AIS_TASK_EXPIRY_SECONDS = 0.008f; + const F32 AIS_BATCH_EXPIRY_SECONDS = 0.010f; typedef std::map<LLUUID,size_t> uuid_int_map_t; uuid_int_map_t mCatDescendentDeltas; @@ -154,7 +158,9 @@ private: uuid_list_t mCategoryIds; bool mFetch; S32 mFetchDepth; - LLTimer mTimer; + LLTimer mTaskTimer; + static LLTimer sBatchTimer; + static U32 sBatchFrameCount; AISAPI::COMMAND_TYPE mType; }; diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index f3265afebd..ece18fb5cc 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -144,6 +144,8 @@ LLAppCoreHttp::~LLAppCoreHttp() void LLAppCoreHttp::init() { + LL_PROFILE_ZONE_SCOPED; + LLCoreHttpUtil::setPropertyMethods( std::bind(&LLControlGroup::getBOOL, std::ref(gSavedSettings), std::placeholders::_1), std::bind(&LLControlGroup::declareBOOL, std::ref(gSavedSettings), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, LLControlVariable::PERSIST_NONDFT)); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e956fc024e..bae9749772 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -732,6 +732,8 @@ public: bool LLAppViewer::init() { + LL_PROFILE_ZONE_SCOPED; + setupErrorHandling(mSecondInstance); // @@ -933,6 +935,7 @@ bool LLAppViewer::init() // Early out from user choice. LL_WARNS("InitInfo") << "initHardwareTest() failed." << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ; @@ -951,6 +954,7 @@ bool LLAppViewer::init() OSMessageBox(msg.c_str(), LLStringUtil::null, OSMB_OK); LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; @@ -986,6 +990,7 @@ bool LLAppViewer::init() // Already handled with a MBVideoDrvErr LL_WARNS("InitInfo") << "gGLManager.mHasRequirements is false." << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } @@ -999,6 +1004,7 @@ bool LLAppViewer::init() OSMessageBox(msg.c_str(), LLStringUtil::null, OSMB_OK); LL_WARNS("InitInfo") << "SSE2 is not supported" << LL_ENDL; // quit immediately + LL_PROFILER_FRAME_END; return false; } #endif @@ -1269,7 +1275,7 @@ bool LLAppViewer::init() gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath()); } #endif - + LL_PROFILER_FRAME_END; return true; } @@ -1343,6 +1349,7 @@ bool LLAppViewer::frame() bool LLAppViewer::doFrame() { + resumeMainloopTimeout("Main:doFrameStart"); #ifdef LL_DISCORD { LL_PROFILE_ZONE_NAMED("discord_callbacks"); @@ -1637,17 +1644,20 @@ bool LLAppViewer::doFrame() if (LLApp::isExiting()) { + pingMainloopTimeout("Main:qSnapshot"); // Save snapshot for next time, if we made it through initialization if (STATE_STARTED == LLStartUp::getStartupState()) { saveFinalSnapshot(); } + pingMainloopTimeout("Main:TerminateVoice"); if (LLVoiceClient::instanceExists()) { LLVoiceClient::getInstance()->terminate(); } + pingMainloopTimeout("Main:TerminatePump"); delete gServicePump; gServicePump = NULL; @@ -1656,6 +1666,11 @@ bool LLAppViewer::doFrame() LL_INFOS() << "Exiting main_loop" << LL_ENDL; } }LLPerfStats::StatsRecorder::endFrame(); + + // Not viewer's fault if something outside frame + // pauses viewer (ex: macOS doesn't call oneFrame), + // so stop tracking on exit. + pauseMainloopTimeout(); LL_PROFILER_FRAME_END; return ! LLApp::isRunning(); @@ -2191,6 +2206,8 @@ void LLAppViewer::initGeneralThread() bool LLAppViewer::initThreads() { + LL_PROFILE_ZONE_SCOPED; + static const bool enable_threads = true; LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); @@ -3038,6 +3055,8 @@ bool LLAppViewer::initConfiguration() // keeps growing, necessitating a method all its own. void LLAppViewer::initStrings() { + LL_PROFILE_ZONE_SCOPED; + std::string strings_file = "strings.xml"; std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file); if (strings_path_full.empty() || !LLFile::isfile(strings_path_full)) @@ -3127,6 +3146,7 @@ void LLAppViewer::sendOutOfDiskSpaceNotification() bool LLAppViewer::initWindow() { + LL_PROFILE_ZONE_SCOPED; LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL; // store setting in a global for easy access and modification @@ -3194,7 +3214,6 @@ bool LLAppViewer::initWindow() app->createErrorMarker(LAST_EXEC_FROZE); } }); - gViewerWindow->getWindow()->initWatchdog(); } LLNotificationsUI::LLNotificationManager::getInstance(); @@ -4174,6 +4193,7 @@ void LLAppViewer::requestQuit() return; } + pingMainloopTimeout("Main:qMetrics"); // Try to send metrics back to the grid metricsSend(!gDisconnected); @@ -4189,6 +4209,7 @@ void LLAppViewer::requestQuit() LLHUDManager::getInstance()->sendEffects(); effectp->markDead() ;//remove it. + pingMainloopTimeout("Main:qFloaters"); // Attempt to close all floaters that might be // editing things. if (gFloaterView) @@ -4197,6 +4218,7 @@ void LLAppViewer::requestQuit() gFloaterView->closeAllChildren(true); mClosingFloaters = true; } + pingMainloopTimeout("Main:qStats"); // Send preferences once, when exiting bool include_preferences = true; @@ -4204,6 +4226,7 @@ void LLAppViewer::requestQuit() gLogoutTimer.reset(); mQuitRequested = true; + pingMainloopTimeout("Main:LoggingOut"); } static bool finish_quit(const LLSD& notification, const LLSD& response) @@ -4365,6 +4388,7 @@ U32 LLAppViewer::getObjectCacheVersion() bool LLAppViewer::initCache() { + LL_PROFILE_ZONE_SCOPED; mPurgeCache = false; bool read_only = mSecondInstance; LLAppViewer::getTextureCache()->setReadOnly(read_only) ; @@ -4458,19 +4482,22 @@ bool LLAppViewer::initCache() if (mPurgeCache) { - LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); - purgeCache(); + LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); + purgeCache(); // clear the new C++ file system based cache LLDiskCache::getInstance()->clearCache(); - } - else + } + else if (gSavedSettings.getBOOL("PurgeDiskCacheOnStartup")) { // purge excessive files from the new file system based cache LLDiskCache::getInstance()->purge(); } + + // Start disk cache purge thread to + // purge excessive files from the file system based cache + LLAppViewer::getPurgeDiskCacheThread()->start(); } - LLAppViewer::getPurgeDiskCacheThread()->start(); LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); @@ -4513,6 +4540,7 @@ void LLAppViewer::loadKeyBindings() // As per GHI #4498, remove old, stale CEF cache folders from previous sessions void LLAppViewer::purgeCefStaleCaches() { + LL_PROFILE_ZONE_SCOPED; // TODO: we really shouldn't use a hard coded name for the cache folder here... const std::string browser_parent_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache"); if (LLFile::isdir(browser_parent_cache)) @@ -4720,6 +4748,8 @@ std::string get_name_cache_filename(const std::string &base_file, const std::str void LLAppViewer::loadNameCache() { + LL_PROFILE_ZONE_SCOPED; + // display names cache std::string filename = get_name_cache_filename("avatar_name_cache", "xml"); LL_INFOS("AvNameCache") << filename << LL_ENDL; @@ -5496,6 +5526,7 @@ void LLAppViewer::outOfMemorySoftQuit() LLLFSThread::sLocal->pause(); gLogoutTimer.reset(); mQuitRequested = true; + destroyMainloopTimeout(); LLError::LLUserWarningMsg::showOutOfMemory(); } @@ -5912,10 +5943,16 @@ void LLAppViewer::pingMainloopTimeout(std::string_view state) F32 LLAppViewer::getMainloopTimeoutSec() const { + if (isQuitting() || mQuitRequested) + { + constexpr F32 QUITTING_SECONDS = 240.f; + return QUITTING_SECONDS; + } if (LLStartUp::getStartupState() == STATE_STARTED && gAgent.getTeleportState() == LLAgent::TELEPORT_NONE) { - static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 30.f); + // consider making this value match 'disconnected' timout. + static LLCachedControl<F32> mainloop_started(gSavedSettings, "MainloopTimeoutStarted", 60.f); return mainloop_started(); } else @@ -5929,6 +5966,11 @@ void LLAppViewer::handleLoginComplete() { gLoggedInTime.start(); initMainloopTimeout("Mainloop Init"); + LLWindow* viewer_window = gViewerWindow->getWindow(); + if (viewer_window) // in case of a headless client + { + viewer_window->initWatchdog(); + } // Store some data to DebugInfo in case of a freeze. gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel(); diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 80c7f8beca..de3ce901c1 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -47,7 +47,7 @@ S32 LLAvatarListItem::sLeftPadding = 0; S32 LLAvatarListItem::sNameRightPadding = 0; S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT]; -static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(&typeid(LLAvatarListItem::Params), "avatar_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(typeid(LLAvatarListItem::Params), "avatar_list_item"); LLAvatarListItem::Params::Params() : default_style("default_style"), diff --git a/indra/newview/llcapabilityprovider.h b/indra/newview/llcapabilityprovider.h index 484bd2ef04..acc752588d 100644 --- a/indra/newview/llcapabilityprovider.h +++ b/indra/newview/llcapabilityprovider.h @@ -37,12 +37,12 @@ class LLCapabilityProvider { public: - virtual ~LLCapabilityProvider() {} + virtual ~LLCapabilityProvider() = default; /** * Get a capability URL, given a capability name. Returns empty string if * no such capability is defined on this provider. */ - virtual std::string getCapability(const std::string& name) const = 0; + virtual std::string getCapability(std::string_view name) const = 0; /** * Get host to which to send that capability request. */ diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 47803edc73..6bd15d4b61 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -647,7 +647,7 @@ void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++) { - if (clothing_by_type[type].empty()) + if (!clothing_by_type[type].empty()) continue; LLWearableType::EType w_type = static_cast<LLWearableType::EType>(type); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 99d770b6e2..2297fddf0c 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -59,11 +59,18 @@ public: virtual void onChange(EStatusType status, const LLSD& channelInfo, bool proximal) { + bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); conversation->showVoiceIndicator(conversation && status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking()); + && voice_enabled); + + static bool s_voice_enabled(false); + if (s_voice_enabled != voice_enabled) + { + s_voice_enabled = voice_enabled; + conversation->updateConversationIndicators(); + } } private: @@ -509,11 +516,25 @@ void LLConversationViewSession::refresh() // Update all speaking indicators LLSpeakingIndicatorManager::updateSpeakingIndicators(); + updateConversationIndicators(); + + requestArrange(); + if (vmi) + { + // Do the regular upstream refresh + LLFolderViewFolder::refresh(); + } +} + +void LLConversationViewSession::updateConversationIndicators() +{ + bool is_active_channel = isInActiveVoiceChannel(); + // we should show indicator for specified voice session only if this is current channel. EXT-5562. if (mSpeakingIndicator) { - mSpeakingIndicator->setIsActiveChannel(mIsInActiveVoiceChannel); - mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel); + mSpeakingIndicator->setIsActiveChannel(is_active_channel); + mSpeakingIndicator->setShowParticipantsSpeaking(is_active_channel); } LLConversationViewParticipant* participant = NULL; @@ -523,16 +544,9 @@ void LLConversationViewSession::refresh() participant = dynamic_cast<LLConversationViewParticipant*>(*iter); if (participant) { - participant->allowSpeakingIndicator(mIsInActiveVoiceChannel); + participant->allowSpeakingIndicator(is_active_channel); } } - - requestArrange(); - if (vmi) - { - // Do the regular upstream refresh - LLFolderViewFolder::refresh(); - } } void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) @@ -543,7 +557,7 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi { bool old_value = mIsInActiveVoiceChannel; mIsInActiveVoiceChannel = vmi->getUUID() == session_id; - mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel && !LLVoiceChannel::isSuspended()); + mCallIconLayoutPanel->setVisible(isInActiveVoiceChannel() && !LLVoiceChannel::isSuspended()); if (old_value != mIsInActiveVoiceChannel) { refresh(); @@ -567,6 +581,13 @@ bool LLConversationViewSession::highlightFriendTitle(LLConversationItem* vmi) return false; } +bool LLConversationViewSession::isInActiveVoiceChannel() +{ + return mIsInActiveVoiceChannel && + LLVoiceClient::getInstance()->voiceEnabled() && + LLVoiceClient::getInstance()->isVoiceWorking(); +} + // // Implementation of conversations list participant (avatar) widgets // diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index a6d240ed84..5844041127 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -94,7 +94,8 @@ public: void setHighlightState(bool hihglight_state); LLFloater* getSessionFloater(); - bool isInActiveVoiceChannel() { return mIsInActiveVoiceChannel; } + bool isInActiveVoiceChannel(); + void updateConversationIndicators(); bool highlightFriendTitle(LLConversationItem* vmi); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 7c631a7280..018d4c4bba 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1067,6 +1067,91 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs return true; } +F32 dot_product(const LLVector3& a, const LLVector3& b) +{ + return a.mV[VX] * b.mV[VX] + a.mV[VY] * b.mV[VY] + a.mV[VZ] * b.mV[VZ]; +} + +bool LLFace::calcAlignedPlanarGLTF( + const LLFace* align_to, + LLVector2* res_st_offset, + LLVector2* res_st_scale, + F32* res_st_rot, + S32 gltf_info_index) const +{ + if (!align_to) + { + return false; + } + + const LLTextureEntry* orig_tep = align_to->getTextureEntry(); + const LLTextureEntry* tep = getTextureEntry(); + if (!orig_tep || !tep) + { + return false; + } + + // Only support planar mapping for now + if (orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR || + tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) + { + return false; + } + + LLGLTFMaterial* orig_mat = orig_tep->getGLTFRenderMaterial(); + LLGLTFMaterial* this_mat = tep->getGLTFRenderMaterial(); + if (!orig_mat || !this_mat) + { + return false; + } + + // Get the original GLTF transform for the specified channel + const auto& orig_tt = orig_mat->mTextureTransform[gltf_info_index]; + + // Convert GLTF transform to legacy TE transform + F32 map_scaleS, map_scaleT, map_offsS, map_offsT, map_rot; + LLGLTFMaterial::convertPBRTransformToTexture( + orig_tt.mScale, + orig_tt.mOffset, + orig_tt.mRotation, + map_scaleS, map_scaleT, map_offsS, map_offsT, map_rot); + + // Calculate aligments + LLVector3 orig_pos, this_pos; + LLQuaternion orig_face_rot, this_face_rot; + F32 orig_proj_scale, this_proj_scale; + align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale); + getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale); + + // The rotation of "this face's" texture: + LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot; + LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot; + F32 x_ang, y_ang, z_ang; + this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang); + + // Offset and scale of "this face's" texture: + LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot; + LLVector3 st_scale(map_scaleS, map_scaleT, 1.f); + st_scale *= orig_proj_scale; + centers_dist.scaleVec(st_scale); + LLVector2 orig_st_offset(map_offsS, map_offsT); + + LLVector2 tex_res_st_offset = orig_st_offset + (LLVector2)centers_dist; + tex_res_st_offset.mV[VX] -= (S32)tex_res_st_offset.mV[VX]; + tex_res_st_offset.mV[VY] -= (S32)tex_res_st_offset.mV[VY]; + + st_scale /= this_proj_scale; + + // Convert aligned legacy TE transform back to GLTF transform + LLGLTFMaterial::convertTextureTransformToPBR( + st_scale.mV[0], st_scale.mV[1], + tex_res_st_offset.mV[0], tex_res_st_offset.mV[1], + z_ang, + *res_st_scale, *res_st_offset, *res_st_rot); + + return true; +} + void LLFace::updateRebuildFlags() { if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) @@ -1401,11 +1486,11 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, // They are used only to display a face selection marker // (white square with a rounded cross at the center) const auto& tt = gltf_mat->mTextureTransform[gltf_info_index]; - r = -tt.mRotation * 2; - ms = tt.mScale[VX]; - mt = tt.mScale[VY]; - os += tt.mOffset[VX] + (ms - 1) / 2; - ot -= tt.mOffset[VY] + (mt - 1) / 2; + LLGLTFMaterial::convertPBRTransformToTexture( + tt.mScale, + tt.mOffset, + tt.mRotation, + ms, mt, os, ot, r); } else { diff --git a/indra/newview/llface.h b/indra/newview/llface.h index df31e9ea90..6e9d23c3a2 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -103,6 +103,8 @@ public: LLVector3 getPositionAgent() const; LLVector2 surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal); void getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const; + bool calcAlignedPlanarGLTF(const LLFace* align_to, LLVector2* res_st_offset, + LLVector2* res_st_scale, F32* res_st_rot, S32 gltf_info_index = 0) const; bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset, LLVector2* st_scale, F32* st_rot, LLRender::eTexIndex map = LLRender::DIFFUSE_MAP) const; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index e9bee93a19..c8692224f1 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -495,7 +495,9 @@ bool LLFeatureManager::loadGPUClass() { mGPUClass = GPU_CLASS_2; } - else if (gbps <= class1_gbps*4.f) + else if ((gbps <= class1_gbps*4.f) + // Cap silicon's GPUs at med+ as they have high throughput, low capability + || gGLManager.mIsApple) { mGPUClass = GPU_CLASS_3; } diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index 95e7b9af41..ed07d49ac1 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -403,7 +403,7 @@ void LLFloater360Capture::suspendForAFrame() U32 curr_frame_count = LLFrameTimer::getFrameCount(); while (LLFrameTimer::getFrameCount() <= curr_frame_count + frame_count_delta) { - llcoro::suspend(); + llcoro::suspendUntilNextFrame(); } } diff --git a/indra/newview/llfloaterbigpreview.cpp b/indra/newview/llfloaterbigpreview.cpp deleted file mode 100644 index ba682494bb..0000000000 --- a/indra/newview/llfloaterbigpreview.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/** -* @file llfloaterbigpreview.cpp -* @brief Display of extended (big) preview for snapshots and SL Share -* @author merov@lindenlab.com -* -* $LicenseInfo:firstyear=2013&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2013, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterbigpreview.h" -#include "llsnapshotlivepreview.h" - -/////////////////////// -//LLFloaterBigPreview// -/////////////////////// - -LLFloaterBigPreview::LLFloaterBigPreview(const LLSD& key) : LLFloater(key), - mPreviewPlaceholder(NULL), - mFloaterOwner(NULL) -{ -} - -LLFloaterBigPreview::~LLFloaterBigPreview() -{ - if (mPreviewHandle.get()) - { - mPreviewHandle.get()->die(); - } -} - -void LLFloaterBigPreview::onCancel() -{ - closeFloater(); -} - -void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp) -{ - if (isFloaterOwner(floaterp)) - { - closeFloater(); - } -} - -bool LLFloaterBigPreview::postBuild() -{ - mPreviewPlaceholder = getChild<LLUICtrl>("big_preview_placeholder"); - return LLFloater::postBuild(); -} - -void LLFloaterBigPreview::draw() -{ - LLFloater::draw(); - - LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get()); - - // Display the preview if one is available - if (previewp && previewp->getBigThumbnailImage()) - { - // Get the preview rect - const LLRect& preview_rect = mPreviewPlaceholder->getRect(); - - // Get the preview texture size - S32 thumbnail_w = previewp->getBigThumbnailWidth(); - S32 thumbnail_h = previewp->getBigThumbnailHeight(); - - // Compute the scaling ratio and the size of the final texture in the rect: we want to prevent anisotropic scaling (distorted in x and y) - F32 ratio = llmax((F32)(thumbnail_w)/(F32)(preview_rect.getWidth()), (F32)(thumbnail_h)/(F32)(preview_rect.getHeight())); - thumbnail_w = (S32)((F32)(thumbnail_w)/ratio); - thumbnail_h = (S32)((F32)(thumbnail_h)/ratio); - - // Compute the preview offset within the preview rect: we want to center that preview in the available rect - const S32 local_offset_x = (preview_rect.getWidth() - thumbnail_w) / 2 ; - const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ; - - // Compute preview offset within the floater rect - S32 offset_x = preview_rect.mLeft + local_offset_x; - S32 offset_y = preview_rect.mBottom + local_offset_y; - - gGL.matrixMode(LLRender::MM_MODELVIEW); - // Apply floater transparency to the texture unless the floater is focused. - F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - LLColor4 color = LLColor4::white; - - // Draw the preview texture - gl_draw_scaled_image(offset_x, offset_y, - thumbnail_w, thumbnail_h, - previewp->getBigThumbnailImage(), color % alpha); - } -} - diff --git a/indra/newview/llfloaterbigpreview.h b/indra/newview/llfloaterbigpreview.h deleted file mode 100644 index 1d5804acf5..0000000000 --- a/indra/newview/llfloaterbigpreview.h +++ /dev/null @@ -1,54 +0,0 @@ -/** -* @file llfloaterbigpreview.h -* @brief Display of extended (big) preview for snapshots -* @author merov@lindenlab.com -* -* $LicenseInfo:firstyear=2013&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2013, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ -#ifndef LL_LLFLOATERBIGPREVIEW_H -#define LL_LLFLOATERBIGPREVIEW_H - -#include "llfloater.h" - -class LLFloaterBigPreview : public LLFloater -{ -public: - LLFloaterBigPreview(const LLSD& key); - ~LLFloaterBigPreview(); - - bool postBuild(); - void draw(); - void onCancel(); - - void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); } - void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; } - bool isFloaterOwner(LLFloater* floaterp) const { return (mFloaterOwner == floaterp); } - void closeOnFloaterOwnerClosing(LLFloater* floaterp); - -private: - LLHandle<LLView> mPreviewHandle; - LLUICtrl* mPreviewPlaceholder; - LLFloater* mFloaterOwner; -}; - -#endif // LL_LLFLOATERBIGPREVIEW_H - diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp index 999a473a49..79d74093a2 100644 --- a/indra/newview/llfloaterexperiences.cpp +++ b/indra/newview/llfloaterexperiences.cpp @@ -385,8 +385,11 @@ void LLFloaterExperiences::retrieveExperienceListCoro(std::string url, if (!status) { + LL_WARNS("Experience") << "Failed to retrieve list. Error: " << status.toTerseString() + << ". Type: " << errorNotify << " Message: " << status.getMessage() << LL_ENDL; + LLSD subs; - subs["ERROR_MESSAGE"] = status.getType(); + subs["ERROR_MESSAGE"] = llformat(" %d\n %s", (S32)status.getType(), status.getMessage().c_str()); LLNotificationsUtil::add(errorNotify, subs); return; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a0f2dbe197..5f9d3ac304 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -57,6 +57,8 @@ #include "llsdserialize.h" #include "llviewermenu.h" // is_agent_mappable #include "llviewerobjectlist.h" +#include "llvoavatar.h" +#include "llnearbyvoicemoderation.h" const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80; @@ -90,6 +92,7 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param mAutoResize = false; LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); + LLNearbyVoiceModeration::getInstance(); } LLFloaterIMContainer::~LLFloaterIMContainer() @@ -530,6 +533,33 @@ void LLFloaterIMContainer::idleUpdate() mGeneralTitleInUse = !needs_override; setTitle(needs_override ? conversation_floaterp->getTitle() : mGeneralTitle); } + const LLConversationItem* nearby_session = getSessionModel(LLUUID()); + if (nearby_session) + { + LLSpeakerMgr* speaker_mgr = (LLSpeakerMgr*)(LLLocalSpeakerMgr::getInstance()); + + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = nearby_session->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = nearby_session->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = + dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get()); + if (participant_model) + { + bool show_moderator_options = LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator(); + LLUUID participant_id = participant_model->getUUID(); + if (participant_id != gAgentID) + { + // Don't show moderator options if participant is not connected to the same spatial channel + LLSpeaker* speakerp = speaker_mgr->findSpeaker(participant_id).get(); + show_moderator_options &= speakerp && speakerp->isInVoiceChannel(); + } + participant_model->setModeratorOptionsVisible(show_moderator_options); + } + + current_participant_model++; + } + } } mParticipantRefreshTimer.setTimerExpirySec(1.0f); @@ -1685,6 +1715,10 @@ bool LLFloaterIMContainer::visibleContextMenuItem(const LLSD& userdata) { return isMuted(conversation_item->getUUID()); } + else if ("can_allow_text_chat" == item) + { + return !isNearbyChatSpeakerSelected(); + } return true; } @@ -2014,9 +2048,27 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self) { - // only group moderators can perform actions related to this "enable callback" - if (!isGroupModerator()) + if (LLNearbyVoiceModeration::getInstance()->isNearbyChatModerator() && isNearbyChatSpeakerSelected()) { + // Determine here which actions are allowed + if ("can_moderate_voice" == userdata) + { + return true; + } + else if (("can_mute" == userdata)) + { + return !is_self; + } + else if ("can_unmute" == userdata) + { + return true; + } + + return false; + } + else if (!isGroupModerator()) + { + // only group moderators can perform actions related to this "enable callback" return false; } @@ -2149,7 +2201,35 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid) void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID) { - if (!gAgent.getRegion()) return; + if (!gAgent.getRegion()) + { + return; + } + + if (isNearbyChatSpeakerSelected()) + { + if ("selected" == command) + { + // Request a mute/unmute using a capability request via the simulator + LLNearbyVoiceModeration::getInstance()->requestMuteIndividual(userID, !isMuted(userID)); + } + else + if ("mute_all" == command) + { + // Send the mute_all request to the server + const bool mute_state = true; + LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state); + } + else + if ("unmute_all" == command) + { + // Send the unmute_all request to the server + const bool mute_state = false; + LLNearbyVoiceModeration::getInstance()->requestMuteAll(mute_state); + } + + return; + } if (command.compare("selected")) { @@ -2267,6 +2347,31 @@ LLSpeaker * LLFloaterIMContainer::getSpeakerOfSelectedParticipant(LLSpeakerMgr * return speaker_managerp->findSpeaker(participant_itemp->getUUID()); } +bool LLFloaterIMContainer::isNearbyChatSpeakerSelected() +{ + LLFolderViewItem *selectedItem = mConversationsRoot->getCurSelectedItem(); + if (!selectedItem) + { + LL_WARNS() << "Current selected item is null" << LL_ENDL; + return NULL; + } + + conversations_widgets_map::const_iterator iter = mConversationsWidgets.begin(); + conversations_widgets_map::const_iterator end = mConversationsWidgets.end(); + const LLUUID * conversation_uuidp = NULL; + while(iter != end) + { + if (iter->second == selectedItem || iter->second == selectedItem->getParentFolder()) + { + conversation_uuidp = &iter->first; + break; + } + ++iter; + } + // Nearby chat ID is LLUUID::null + return conversation_uuidp->isNull(); +} + void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid) { LLIMSpeakerMgr * speaker_managerp = dynamic_cast<LLIMSpeakerMgr*>(getSpeakerMgrForSelectedParticipant()); diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 30eed8be36..9f1690a9b9 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -178,6 +178,7 @@ private: void banSelectedMember(const LLUUID& participant_uuid); void openNearbyChat(); bool isParticipantListExpanded(); + bool isNearbyChatSpeakerSelected(); void idleUpdate(); // for convenience (self) from static idle void idleProcessEvents(); diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 84a9fad708..6d642638b3 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -142,7 +142,7 @@ void LLFloaterIMSession::onClickCloseBtn(bool app_qutting) { if (app_qutting) { - LLFloaterIMSessionTab::onClickCloseBtn(); + LLFloaterIMSessionTab::onClickCloseBtn(app_qutting); return; } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 65c13797ac..453161b792 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -48,6 +48,7 @@ #include "llfloaterimnearbychat.h" #include "llgroupiconctrl.h" #include "lllayoutstack.h" +#include "llnotificationsutil.h" #include "llpanelemojicomplete.h" #include "lltoolbarview.h" @@ -1417,3 +1418,20 @@ bool LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) } return handled; } + +void LLFloaterIMSessionTab::onClickCloseBtn(bool app_quitting) +{ + bool is_ad_hoc = (mSession ? mSession->isAdHocSessionType() : false); + if (is_ad_hoc && !app_quitting) + { + LLNotificationsUtil::add("ConfirmLeaveAdhoc", LLSD(), LLSD(), [this](const LLSD& notification, const LLSD& response) + { + if (0 == LLNotificationsUtil::getSelectedOption(notification, response)) + closeFloater(); + }); + } + else + { + closeFloater(); + } +} diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 6d04d622e1..b27ac1b8f9 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -85,6 +85,8 @@ public: void closeFloater(bool app_quitting = false) override; void deleteAllChildren() override; + virtual void onClickCloseBtn(bool app_quitting = false) override; + // Handle the left hand participant list widgets void addConversationViewParticipant(LLConversationItem* item, bool update_view = true); void removeConversationViewParticipant(const LLUUID& participant_id); diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp index c961070787..33e054aab9 100644 --- a/indra/newview/llfloaterlinkreplace.cpp +++ b/indra/newview/llfloaterlinkreplace.cpp @@ -225,6 +225,21 @@ void LLFloaterLinkReplace::linkCreatedCallback(LLHandle<LLFloaterLinkReplace> fl << " - description update = " << (needs_description_update ? "true" : "false") << LL_NEWLINE << " - outfit_folder_id = " << outfit_folder_id.asString() << LL_ENDL; + std::string old_description; + if (needs_wearable_ordering_update) + { + LLViewerInventoryItem* old_item = gInventory.getItem(old_item_id); + LLViewerInventoryItem* target_item = gInventory.getItem(target_item_id); + if (old_item && target_item && + old_item->getType() == LLAssetType::AT_CLOTHING && + target_item->getType() == LLAssetType::AT_CLOTHING && + old_item->getWearableType() == target_item->getWearableType()) + { + // Preserve the original description, which contains ordering info + old_description = old_item->getActualDescription(); + } + } + // If we are replacing an object, bodypart or gesture link within an outfit folder, // we need to change the actual description of the link itself. LLAppearanceMgr *should* // have created COF links that will be used to save the outfit with an empty description. @@ -246,7 +261,14 @@ void LLFloaterLinkReplace::linkCreatedCallback(LLHandle<LLFloaterLinkReplace> fl { LLPointer<LLViewerInventoryItem> item = *it; - if ((item->getType() == LLAssetType::AT_BODYPART || + if (item->getType() == LLAssetType::AT_CLOTHING && !old_description.empty()) + { + // Use the old description to set ordering info + LLSD updates; + updates["desc"] = old_description; + update_inventory_item(item->getUUID(), updates, LLPointer<LLInventoryCallback>(NULL)); + } + else if ((item->getType() == LLAssetType::AT_BODYPART || item->getType() == LLAssetType::AT_OBJECT || item->getType() == LLAssetType::AT_GESTURE) && !item->getActualDescription().empty()) @@ -347,12 +369,9 @@ void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items) bool is_outfit_folder = gInventory.isObjectDescendentOf(source_item->getParentUUID(), outfit_folder_id); // If either the new or old item in the COF is a wearable, we need to update wearable ordering after the link has been replaced bool needs_wearable_ordering_update = (is_outfit_folder && source_item->getType() == LLAssetType::AT_CLOTHING) || target_item->getType() == LLAssetType::AT_CLOTHING; - // Other items in the COF need a description update (description of the actual link item must be empty) - bool needs_description_update = is_outfit_folder && target_item->getType() != LLAssetType::AT_CLOTHING; LL_DEBUGS() << "is_outfit_folder = " << (is_outfit_folder ? "true" : "false") << LL_NEWLINE - << "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE - << "needs_description_update = " << (needs_description_update ? "true" : "false") << LL_ENDL; + << "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_ENDL; LLInventoryObject::const_object_list_t obj_array; obj_array.push_back(LLConstPointer<LLInventoryObject>(target_item)); @@ -361,7 +380,7 @@ void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items) source_item->getUUID(), target_item->getUUID(), needs_wearable_ordering_update, - needs_description_update, + is_outfit_folder, (is_outfit_folder ? source_item->getParentUUID() : LLUUID::null) )); link_inventory_array(source_item->getParentUUID(), obj_array, cb); } diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp deleted file mode 100644 index 616c13cdc7..0000000000 --- a/indra/newview/llfloaterpostprocess.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @file llfloaterpostprocess.cpp - * @brief LLFloaterPostProcess class definition - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterpostprocess.h" - -#include "llsliderctrl.h" -#include "llcheckboxctrl.h" -#include "llnotificationsutil.h" -#include "lluictrlfactory.h" -#include "llviewerdisplay.h" -#include "llpostprocess.h" -#include "llcombobox.h" -#include "lllineeditor.h" -#include "llviewerwindow.h" - - -LLFloaterPostProcess::LLFloaterPostProcess(const LLSD& key) - : LLFloater(key) -{ -} - -LLFloaterPostProcess::~LLFloaterPostProcess() -{ - - -} -bool LLFloaterPostProcess::postBuild() -{ - /// Color Filter Callbacks - childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); - //childSetCommitCallback("ColorFilterGamma", &LLFloaterPostProcess::onFloatControlMoved, &(gPostProcess->tweaks.gamma())); - childSetCommitCallback("ColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness"); - childSetCommitCallback("ColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation"); - childSetCommitCallback("ColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast"); - - childSetCommitCallback("ColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base"); - childSetCommitCallback("ColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base"); - childSetCommitCallback("ColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base"); - childSetCommitCallback("ColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base"); - - /// Night Vision Callbacks - childSetCommitCallback("NightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision"); - childSetCommitCallback("NightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier"); - childSetCommitCallback("NightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size"); - childSetCommitCallback("NightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength"); - - /// Bloom Callbacks - childSetCommitCallback("BloomToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_bloom"); - childSetCommitCallback("BloomExtract", &LLFloaterPostProcess::onFloatControlMoved, (char*)"extract_low"); - childSetCommitCallback("BloomSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_width"); - childSetCommitCallback("BloomStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_strength"); - - // Effect loading and saving. - LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo"); - getChild<LLComboBox>("PPLoadEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onLoadEffect, this, comboBox)); - comboBox->setCommitCallback(boost::bind(&LLFloaterPostProcess::onChangeEffectName, this, _1)); - - LLLineEditor* editBox = getChild<LLLineEditor>("PPEffectNameEditor"); - getChild<LLComboBox>("PPSaveEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onSaveEffect, this, editBox)); - - syncMenu(); - return true; -} - -// Bool Toggle -void LLFloaterPostProcess::onBoolToggle(LLUICtrl* ctrl, void* userData) -{ - char const * boolVariableName = (char const *)userData; - - // check the bool - LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl); - gPostProcess->tweaks[boolVariableName] = cbCtrl->getValue(); -} - -// Float Moved -void LLFloaterPostProcess::onFloatControlMoved(LLUICtrl* ctrl, void* userData) -{ - char const * floatVariableName = (char const *)userData; - LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - gPostProcess->tweaks[floatVariableName] = sldrCtrl->getValue(); -} - -// Color Moved -void LLFloaterPostProcess::onColorControlRMoved(LLUICtrl* ctrl, void* userData) -{ - char const * floatVariableName = (char const *)userData; - LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - gPostProcess->tweaks[floatVariableName][0] = sldrCtrl->getValue(); -} - -// Color Moved -void LLFloaterPostProcess::onColorControlGMoved(LLUICtrl* ctrl, void* userData) -{ - char const * floatVariableName = (char const *)userData; - LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - gPostProcess->tweaks[floatVariableName][1] = sldrCtrl->getValue(); -} - -// Color Moved -void LLFloaterPostProcess::onColorControlBMoved(LLUICtrl* ctrl, void* userData) -{ - char const * floatVariableName = (char const *)userData; - LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - gPostProcess->tweaks[floatVariableName][2] = sldrCtrl->getValue(); -} - -// Color Moved -void LLFloaterPostProcess::onColorControlIMoved(LLUICtrl* ctrl, void* userData) -{ - char const * floatVariableName = (char const *)userData; - LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - gPostProcess->tweaks[floatVariableName][3] = sldrCtrl->getValue(); -} - -void LLFloaterPostProcess::onLoadEffect(LLComboBox* comboBox) -{ - LLSD::String effectName(comboBox->getSelectedValue().asString()); - - gPostProcess->setSelectedEffect(effectName); - - syncMenu(); -} - -void LLFloaterPostProcess::onSaveEffect(LLLineEditor* editBox) -{ - std::string effectName(editBox->getValue().asString()); - - if (gPostProcess->mAllEffects.has(effectName)) - { - LLSD payload; - payload["effect_name"] = effectName; - LLNotificationsUtil::add("PPSaveEffectAlert", LLSD(), payload, boost::bind(&LLFloaterPostProcess::saveAlertCallback, this, _1, _2)); - } - else - { - gPostProcess->saveEffect(effectName); - syncMenu(); - } -} - -void LLFloaterPostProcess::onChangeEffectName(LLUICtrl* ctrl) -{ - // get the combo box and name - LLLineEditor* editBox = getChild<LLLineEditor>("PPEffectNameEditor"); - - // set the parameter's new name - editBox->setValue(ctrl->getValue()); -} - -bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - // if they choose save, do it. Otherwise, don't do anything - if (option == 0) - { - gPostProcess->saveEffect(notification["payload"]["effect_name"].asString()); - - syncMenu(); - } - return false; -} - -void LLFloaterPostProcess::syncMenu() -{ - // add the combo boxe contents - LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo"); - - comboBox->removeall(); - - LLSD::map_const_iterator currEffect; - for(currEffect = gPostProcess->mAllEffects.beginMap(); - currEffect != gPostProcess->mAllEffects.endMap(); - ++currEffect) - { - comboBox->add(currEffect->first); - } - - // set the current effect as selected. - comboBox->selectByValue(gPostProcess->getSelectedEffect()); - - /// Sync Color Filter Menu - getChild<LLUICtrl>("ColorFilterToggle")->setValue(gPostProcess->tweaks.useColorFilter()); - //getChild<LLUICtrl>("ColorFilterGamma")->setValue(gPostProcess->tweaks.gamma()); - getChild<LLUICtrl>("ColorFilterBrightness")->setValue(gPostProcess->tweaks.brightness()); - getChild<LLUICtrl>("ColorFilterSaturation")->setValue(gPostProcess->tweaks.saturation()); - getChild<LLUICtrl>("ColorFilterContrast")->setValue(gPostProcess->tweaks.contrast()); - getChild<LLUICtrl>("ColorFilterBaseR")->setValue(gPostProcess->tweaks.contrastBaseR()); - getChild<LLUICtrl>("ColorFilterBaseG")->setValue(gPostProcess->tweaks.contrastBaseG()); - getChild<LLUICtrl>("ColorFilterBaseB")->setValue(gPostProcess->tweaks.contrastBaseB()); - getChild<LLUICtrl>("ColorFilterBaseI")->setValue(gPostProcess->tweaks.contrastBaseIntensity()); - - /// Sync Night Vision Menu - getChild<LLUICtrl>("NightVisionToggle")->setValue(gPostProcess->tweaks.useNightVisionShader()); - getChild<LLUICtrl>("NightVisionBrightMult")->setValue(gPostProcess->tweaks.brightMult()); - getChild<LLUICtrl>("NightVisionNoiseSize")->setValue(gPostProcess->tweaks.noiseSize()); - getChild<LLUICtrl>("NightVisionNoiseStrength")->setValue(gPostProcess->tweaks.noiseStrength()); - - /// Sync Bloom Menu - getChild<LLUICtrl>("BloomToggle")->setValue(LLSD(gPostProcess->tweaks.useBloomShader())); - getChild<LLUICtrl>("BloomExtract")->setValue(gPostProcess->tweaks.extractLow()); - getChild<LLUICtrl>("BloomSize")->setValue(gPostProcess->tweaks.bloomWidth()); - getChild<LLUICtrl>("BloomStrength")->setValue(gPostProcess->tweaks.bloomStrength()); -} diff --git a/indra/newview/llfloaterpostprocess.h b/indra/newview/llfloaterpostprocess.h deleted file mode 100644 index 50b48d8410..0000000000 --- a/indra/newview/llfloaterpostprocess.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file llfloaterpostprocess.h - * @brief LLFloaterPostProcess class definition - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERPOSTPROCESS_H -#define LL_LLFLOATERPOSTPROCESS_H - -#include "llfloater.h" - -class LLButton; -class LLComboBox; -class LLLineEditor; -class LLSliderCtrl; -class LLTabContainer; -class LLPanelPermissions; -class LLPanelObject; -class LLPanelVolume; -class LLPanelContents; -class LLPanelFace; - -/** - * Menu for adjusting the post process settings of the world - */ -class LLFloaterPostProcess : public LLFloater -{ -public: - - LLFloaterPostProcess(const LLSD& key); - virtual ~LLFloaterPostProcess(); - bool postBuild(); - - /// post process callbacks - static void onBoolToggle(LLUICtrl* ctrl, void* userData); - static void onFloatControlMoved(LLUICtrl* ctrl, void* userData); - static void onColorControlRMoved(LLUICtrl* ctrl, void* userData); - static void onColorControlGMoved(LLUICtrl* ctrl, void* userData); - static void onColorControlBMoved(LLUICtrl* ctrl, void* userData); - static void onColorControlIMoved(LLUICtrl* ctrl, void* userData); - void onLoadEffect(LLComboBox* comboBox); - void onSaveEffect(LLLineEditor* editBox); - void onChangeEffectName(LLUICtrl* ctrl); - - /// prompts a user when overwriting an effect - bool saveAlertCallback(const LLSD& notification, const LLSD& response); - - /// sync up sliders - void syncMenu(); -}; - -#endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index f23bd5f2e3..537dca99da 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -620,8 +620,6 @@ void LLFloaterPreference::apply() std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); setCacheLocation(cache_location); - LLViewerMedia::getInstance()->setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue()); - if (hasChild("web_proxy_enabled", true) &&hasChild("web_proxy_editor", true) && hasChild("web_proxy_port", true)) { bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue(); @@ -1742,6 +1740,22 @@ void LLFloaterPreference::onChangeMaturity() || sim_access == SIM_ACCESS_ADULT); getChild<LLIconCtrl>("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT); + + // Update Legacy Search maturity settings + bool can_access_mature = gAgent.canAccessMature(); + bool can_access_adult = gAgent.canAccessAdult(); + if (!can_access_mature) + { + gSavedSettings.setBOOL("ShowMatureSims", false); + gSavedSettings.setBOOL("ShowMatureLand", false); + gSavedSettings.setBOOL("ShowMatureClassifieds", false); + } + if (!can_access_adult) + { + gSavedSettings.setBOOL("ShowAdultSims", false); + gSavedSettings.setBOOL("ShowAdultLand", false); + gSavedSettings.setBOOL("ShowAdultClassifieds", false); + } } void LLFloaterPreference::onChangeComplexityMode(const LLSD& newvalue) diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 9b7a4e5134..3c84f5b459 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -123,19 +123,32 @@ void LLFloaterSearch::initiateSearch(const LLSD& tokens) subs["COLLECTION"] = ""; if (subs["TYPE"] == "standard") { + std::string collection_args; if (mCollectionType.find(collection) != mCollectionType.end()) { - subs["COLLECTION"] = "&collection_chosen=" + std::string(collection); + collection_args = "&collection_chosen=" + std::string(collection); } - else + else if (tokens.has("collections") && tokens["collections"].isArray()) + { + const LLSD &sd = tokens["collections"]; + for (LLSD::array_const_iterator it = sd.beginArray(); + it != sd.endArray(); + ++it) + { + if (mCollectionType.find(it->asString()) != mCollectionType.end()) + { + collection_args += "&collection_chosen=" + std::string(*it); + } + } + } + if (collection_args.empty()) { - std::string collection_args(""); for (std::set<std::string>::iterator it = mCollectionType.begin(); it != mCollectionType.end(); ++it) { collection_args += "&collection_chosen=" + std::string(*it); } - subs["COLLECTION"] = collection_args; } + subs["COLLECTION"] = collection_args; } // Default to PG diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index faf7ed0d8c..83d7a92846 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1043,7 +1043,7 @@ bool LLFloaterSnapshot::postBuild() getChild<LLComboBox>("profile_size_combo")->selectNthItem(0); getChild<LLComboBox>("postcard_size_combo")->selectNthItem(0); getChild<LLComboBox>("texture_size_combo")->selectNthItem(0); - getChild<LLComboBox>("local_size_combo")->selectNthItem(8); + getChild<LLComboBox>("local_size_combo")->selectNthItem(0); getChild<LLComboBox>("local_format_combo")->selectNthItem(0); impl->mPreviewHandle = previewp->getHandle(); diff --git a/indra/newview/llfloatersounddevices.cpp b/indra/newview/llfloatersounddevices.cpp deleted file mode 100644 index f11c5c0ad8..0000000000 --- a/indra/newview/llfloatersounddevices.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file llfloatersounddevices.cpp - * @author Leyla Farazha - * @brief Sound Preferences used for minimal skin - * -* $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#include "llviewerprecompiledheaders.h" - -#include "llfloatersounddevices.h" - -#include "lldraghandle.h" - -#include "llpanelvoicedevicesettings.h" - -// Library includes -#include "indra_constants.h" - -// protected -LLFloaterSoundDevices::LLFloaterSoundDevices(const LLSD& key) -: LLTransientDockableFloater(NULL, false, key) -{ - LLTransientFloaterMgr::getInstance()->addControlView(this); - - // force docked state since this floater doesn't save it between recreations - setDocked(true); -} - -LLFloaterSoundDevices::~LLFloaterSoundDevices() -{ - LLTransientFloaterMgr::getInstance()->removeControlView(this); -} - -// virtual -bool LLFloaterSoundDevices::postBuild() -{ - LLTransientDockableFloater::postBuild(); - - updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730) - - LLPanelVoiceDeviceSettings* panel = findChild<LLPanelVoiceDeviceSettings>("device_settings_panel"); - if (panel) - { - panel->setUseTuningMode(false); - getChild<LLUICtrl>("voice_input_device")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel)); - getChild<LLUICtrl>("voice_output_device")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel)); - getChild<LLUICtrl>("mic_volume_slider")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel)); - } - return true; -} - -//virtual -void LLFloaterSoundDevices::setDocked(bool docked, bool pop_on_undock/* = true*/) -{ - LLTransientDockableFloater::setDocked(docked, pop_on_undock); -} - -// virtual -void LLFloaterSoundDevices::setFocus(bool b) -{ - LLTransientDockableFloater::setFocus(b); - - // Force using active floater transparency - // We have to override setFocus() for because selecting an item of the - // combobox causes the floater to lose focus and thus become transparent. - updateTransparency(TT_ACTIVE); -} diff --git a/indra/newview/llfloatervoiceeffect.cpp b/indra/newview/llfloatervoiceeffect.cpp deleted file mode 100644 index 9f7c9aba87..0000000000 --- a/indra/newview/llfloatervoiceeffect.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/** - * @file llfloatervoiceeffect.cpp - * @author Aimee - * @brief Selection and preview of voice effect. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloatervoiceeffect.h" - -#include "llscrolllistctrl.h" -#include "lltrans.h" -#include "llweb.h" - -LLFloaterVoiceEffect::LLFloaterVoiceEffect(const LLSD& key) - : LLFloater(key) -{ - mCommitCallbackRegistrar.add("VoiceEffect.Record", boost::bind(&LLFloaterVoiceEffect::onClickRecord, this)); - mCommitCallbackRegistrar.add("VoiceEffect.Play", boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); - mCommitCallbackRegistrar.add("VoiceEffect.Stop", boost::bind(&LLFloaterVoiceEffect::onClickStop, this)); -// mCommitCallbackRegistrar.add("VoiceEffect.Activate", boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); -} - -// virtual -LLFloaterVoiceEffect::~LLFloaterVoiceEffect() -{ - if(LLVoiceClient::instanceExists()) - { - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->removeObserver(this); - } - } -} - -// virtual -bool LLFloaterVoiceEffect::postBuild() -{ - setDefaultBtn("record_btn"); - getChild<LLButton>("record_btn")->setFocus(true); - getChild<LLUICtrl>("voice_morphing_link")->setTextArg("[URL]", LLTrans::getString("voice_morphing_url")); - - mVoiceEffectList = getChild<LLScrollListCtrl>("voice_effect_list"); - if (mVoiceEffectList) - { - mVoiceEffectList->setCommitCallback(boost::bind(&LLFloaterVoiceEffect::onClickPlay, this)); -// mVoiceEffectList->setDoubleClickCallback(boost::bind(&LLFloaterVoiceEffect::onClickActivate, this)); - } - - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->addObserver(this); - - // Disconnect from the current voice channel ready to record a voice sample for previewing - effect_interface->enablePreviewBuffer(true); - } - - refreshEffectList(); - updateControls(); - - return true; -} - -// virtual -void LLFloaterVoiceEffect::onClose(bool app_quitting) -{ - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->enablePreviewBuffer(false); - } -} - -void LLFloaterVoiceEffect::refreshEffectList() -{ - if (!mVoiceEffectList) - { - return; - } - - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (!effect_interface) - { - mVoiceEffectList->setEnabled(false); - return; - } - - LL_DEBUGS("Voice")<< "Rebuilding Voice Morph list."<< LL_ENDL; - - // Preserve selected items and scroll position - S32 scroll_pos = mVoiceEffectList->getScrollPos(); - uuid_vec_t selected_items; - std::vector<LLScrollListItem*> items = mVoiceEffectList->getAllSelected(); - for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++) - { - selected_items.push_back((*it)->getUUID()); - } - - mVoiceEffectList->deleteAllItems(); - - { - // Add the "No Voice Morph" entry - LLSD element; - - element["id"] = LLUUID::null; - element["columns"][NAME_COLUMN]["column"] = "name"; - element["columns"][NAME_COLUMN]["value"] = getString("no_voice_effect"); - element["columns"][NAME_COLUMN]["font"]["style"] = "BOLD"; - - LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); - // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( - if(sl_item) - { - ((LLScrollListText*)sl_item->getColumn(0))->setFontStyle(LLFontGL::BOLD); - } - } - - // Add each Voice Morph template, if there are any (template list includes all usable effects) - const voice_effect_list_t& template_list = effect_interface->getVoiceEffectTemplateList(); - if (!template_list.empty()) - { - for (voice_effect_list_t::const_iterator it = template_list.begin(); it != template_list.end(); ++it) - { - const LLUUID& effect_id = it->second; - - std::string localized_effect = "effect_" + it->first; - std::string effect_name = hasString(localized_effect) ? getString(localized_effect) : it->first; // XML contains localized effects names - - LLSD effect_properties = effect_interface->getVoiceEffectProperties(effect_id); - - // Tag the active effect. - if (effect_id == LLVoiceClient::instance().getVoiceEffectDefault()) - { - effect_name += " " + getString("active_voice_effect"); - } - - // Tag available effects that are new this session - if (effect_properties["is_new"].asBoolean()) - { - effect_name += " " + getString("new_voice_effect"); - } - - LLDate expiry_date = effect_properties["expiry_date"].asDate(); - bool is_template_only = effect_properties["template_only"].asBoolean(); - - std::string font_style = "NORMAL"; - if (!is_template_only) - { - font_style = "BOLD"; - } - - LLSD element; - element["id"] = effect_id; - - element["columns"][NAME_COLUMN]["column"] = "name"; - element["columns"][NAME_COLUMN]["value"] = effect_name; - element["columns"][NAME_COLUMN]["font"]["style"] = font_style; - - element["columns"][1]["column"] = "expires"; - if (!is_template_only) - { - element["columns"][DATE_COLUMN]["value"] = expiry_date; - element["columns"][DATE_COLUMN]["type"] = "date"; - } - else { - element["columns"][DATE_COLUMN]["value"] = getString("unsubscribed_voice_effect"); - } -// element["columns"][DATE_COLUMN]["font"]["style"] = "NORMAL"; - - LLScrollListItem* sl_item = mVoiceEffectList->addElement(element, ADD_BOTTOM); - // *HACK: Copied from llfloatergesture.cpp : ["font"]["style"] does not affect font style :( - if(sl_item) - { - LLFontGL::StyleFlags style = is_template_only ? LLFontGL::NORMAL : LLFontGL::BOLD; - LLScrollListText* slt = dynamic_cast<LLScrollListText*>(sl_item->getColumn(0)); - llassert(slt); - if (slt) - { - slt->setFontStyle(style); - } - } - } - } - - // Re-select items that were selected before, and restore the scroll position - for(uuid_vec_t::iterator it = selected_items.begin(); it != selected_items.end(); it++) - { - mVoiceEffectList->selectByID(*it); - } - mVoiceEffectList->setScrollPos(scroll_pos); - mVoiceEffectList->setEnabled(true); -} - -void LLFloaterVoiceEffect::updateControls() -{ - bool recording = false; - - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - recording = effect_interface->isPreviewRecording(); - } - - getChild<LLButton>("record_btn")->setVisible(!recording); - getChild<LLButton>("record_stop_btn")->setVisible(recording); -} - -// virtual -void LLFloaterVoiceEffect::onVoiceEffectChanged(bool effect_list_updated) -{ - if (effect_list_updated) - { - refreshEffectList(); - } - updateControls(); -} - -void LLFloaterVoiceEffect::onClickRecord() -{ - LL_DEBUGS("Voice") << "Record clicked" << LL_ENDL; - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->recordPreviewBuffer(); - } - updateControls(); -} - -void LLFloaterVoiceEffect::onClickPlay() -{ - LL_DEBUGS("Voice") << "Play clicked" << LL_ENDL; - if (!mVoiceEffectList) - { - return; - } - - const LLUUID& effect_id = mVoiceEffectList->getCurrentID(); - - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->playPreviewBuffer(effect_id); - } - updateControls(); -} - -void LLFloaterVoiceEffect::onClickStop() -{ - LL_DEBUGS("Voice") << "Stop clicked" << LL_ENDL; - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->stopPreviewBuffer(); - } - updateControls(); -} - -//void LLFloaterVoiceEffect::onClickActivate() -//{ -// LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); -// if (effect_interface && mVoiceEffectList) -// { -// effect_interface->setVoiceEffect(mVoiceEffectList->getCurrentID()); -// } -//} - diff --git a/indra/newview/llfloatervoiceeffect.h b/indra/newview/llfloatervoiceeffect.h deleted file mode 100644 index 323beb64ae..0000000000 --- a/indra/newview/llfloatervoiceeffect.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file llfloatervoiceeffect.h - * @author Aimee - * @brief Selection and preview of voice effects. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERVOICEEFFECT_H -#define LL_LLFLOATERVOICEEFFECT_H - -#include "llfloater.h" -#include "llvoiceclient.h" - -class LLButton; -class LLScrollListCtrl; - -class LLFloaterVoiceEffect - : public LLFloater - , public LLVoiceEffectObserver -{ -public: - LOG_CLASS(LLFloaterVoiceEffect); - - LLFloaterVoiceEffect(const LLSD& key); - virtual ~LLFloaterVoiceEffect(); - - bool postBuild() override; - void onClose(bool app_quitting) override; - -private: - enum ColumnIndex - { - NAME_COLUMN = 0, - DATE_COLUMN = 1, - }; - - void refreshEffectList(); - void updateControls(); - - /// Called by voice effect provider when voice effect list is changed. - virtual void onVoiceEffectChanged(bool effect_list_updated) override; - - void onClickRecord(); - void onClickPlay(); - void onClickStop(); -// void onClickActivate(); - - LLUUID mSelectedID; - LLScrollListCtrl* mVoiceEffectList; -}; - -#endif diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index ac8477a615..b784419780 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -170,7 +170,7 @@ namespace void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::string& data_in) { - std::istringstream str(data_in); + boost::iostreams::stream<boost::iostreams::array_source> str(data_in.data(), data_in.size()); LLSD data; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 542c0fdfdd..b4cce02bda 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1860,7 +1860,14 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) { LLVector3d global_pos; landmark->getGlobalPos(global_pos); - LLLandmarkActions::getSLURLfromPosGlobal(global_pos, ©_slurl_to_clipboard_callback_inv, true); + if (!global_pos.isExactlyZero()) + { + LLLandmarkActions::getSLURLfromPosGlobal(global_pos, ©_slurl_to_clipboard_callback_inv, true); + } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } } } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 458ea24d33..7522ea4907 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2555,7 +2555,7 @@ bool get_is_favorite(const LLUUID& obj_id) return obj && obj->getIsFavorite(); } - return object->getIsFavorite(); + return object && object->getIsFavorite(); } void set_favorite(const LLUUID& obj_id, bool favorite) diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 1c1bb35723..1fe2965784 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -338,14 +338,21 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) { LLVector3d global_pos; landmark->getGlobalPos(global_pos); - boost::function<void(std::string& slurl)> copy_slurl_to_clipboard_cb = [](const std::string& slurl) + if (!global_pos.isExactlyZero()) { - gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); - LLSD args; - args["SLURL"] = slurl; - LLNotificationsUtil::add("CopySLURL", args); - }; - LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true); + boost::function<void(std::string& slurl)> copy_slurl_to_clipboard_cb = [](const std::string& slurl) + { + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl)); + LLSD args; + args["SLURL"] = slurl; + LLNotificationsUtil::add("CopySLURL", args); + }; + LLLandmarkActions::getSLURLfromPosGlobal(global_pos, copy_slurl_to_clipboard_cb, true); + } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } }; LLLandmark* landmark = LLLandmarkActions::getLandmark(mUUIDs.front(), copy_slurl_cb); if (landmark) diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp index a435a4f7c7..aa6ba6d023 100644 --- a/indra/newview/llinventorylistitem.cpp +++ b/indra/newview/llinventorylistitem.cpp @@ -41,7 +41,7 @@ #include "llinventorymodel.h" #include "llviewerinventory.h" -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(&typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item"); constexpr S32 WIDGET_SPACING = 3; constexpr S32 FAVORITE_IMAGE_SIZE = 14; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 7056ed1ce4..c2f9c483c0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3425,6 +3425,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, LLSD inventory; if (!is_cache_obsolete) { + LL_PROFILE_ZONE_NAMED("inventory load from file - llsd parse"); LLPointer<LLSDParser> parser = new LLSDBinaryParser(); if (parser->parse(file, inventory, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) @@ -3436,56 +3437,61 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, if (!is_cache_obsolete) { - const LLSD& llsd_cats = inventory["categories"]; - if (llsd_cats.isArray()) { - LLSD::array_const_iterator iter = llsd_cats.beginArray(); - LLSD::array_const_iterator end = llsd_cats.endArray(); - for (; iter != end; ++iter) + LL_PROFILE_ZONE_NAMED("inventory load from file - categories"); + const LLSD& llsd_cats = inventory["categories"]; + if (llsd_cats.isArray()) { - LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null); - if (inv_cat->importLLSDMap(*iter)) + LLSD::array_const_iterator iter = llsd_cats.beginArray(); + LLSD::array_const_iterator end = llsd_cats.endArray(); + for (; iter != end; ++iter) { - categories.push_back(inv_cat); + LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null); + if (inv_cat->importLLSDMap(*iter)) + { + categories.push_back(inv_cat); + } } } } - const LLSD& llsd_items = inventory["items"]; - if (llsd_items.isArray()) { - LLSD::array_const_iterator iter = llsd_items.beginArray(); - LLSD::array_const_iterator end = llsd_items.endArray(); - for (; iter != end; ++iter) + LL_PROFILE_ZONE_NAMED("inventory load from file - items"); + const LLSD& llsd_items = inventory["items"]; + if (llsd_items.isArray()) { - LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem; - if (inv_item->fromLLSD(*iter)) + LLSD::array_const_iterator iter = llsd_items.beginArray(); + LLSD::array_const_iterator end = llsd_items.endArray(); + for (; iter != end; ++iter) { - if (inv_item->getUUID().isNull()) + LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem; + if (inv_item->fromLLSD(*iter)) { - LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: " - << inv_item->getName() << LL_ENDL; - } - else - { - if (inv_item->getType() == LLAssetType::AT_UNKNOWN) + if (inv_item->getUUID().isNull()) { - cats_to_update.insert(inv_item->getParentUUID()); + LL_DEBUGS(LOG_INV) << "Ignoring inventory with null item id: " << inv_item->getName() << LL_ENDL; } else { - items.push_back(inv_item); + if (inv_item->getType() == LLAssetType::AT_UNKNOWN) + { + cats_to_update.insert(inv_item->getParentUUID()); + } + else + { + items.push_back(inv_item); + } } } - } - // TODO(brad) - figure out how to reenable this without breaking everything else - // static constexpr U64 BATCH_SIZE = 512U; - // if ((++lines_count % BATCH_SIZE) == 0) - // { - // // SL-19968 - make sure message system code gets a chance to run every so often - // pump_idle_startup_network(); - // } + // TODO(brad) - figure out how to reenable this without breaking everything else + // static constexpr U64 BATCH_SIZE = 512U; + // if ((++lines_count % BATCH_SIZE) == 0) + // { + // // SL-19968 - make sure message system code gets a chance to run every so often + // pump_idle_startup_network(); + // } + } } } } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 9fbabec8f3..05ada9121a 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -201,13 +201,13 @@ private: // 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; + typedef std::unordered_map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t; + typedef std::unordered_map<LLUUID, LLPointer<LLViewerInventoryItem>> item_map_t; cat_map_t mCategoryMap; item_map_t mItemMap; // This last set of indices is used to map parents to children. - typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t; - typedef std::map<LLUUID, item_array_t*> parent_item_map_t; + typedef std::unordered_map<LLUUID, cat_array_t*> parent_cat_map_t; + typedef std::unordered_map<LLUUID, item_array_t*> parent_item_map_t; parent_cat_map_t mParentChildCategoryTree; parent_item_map_t mParentChildItemTree; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 8d57a4e7bb..06dd830416 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2125,8 +2125,7 @@ LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) { LL_PROFILE_ZONE_SCOPED; - std::map<LLUUID, LLFolderViewItem*>::iterator map_it; - map_it = mItemMap.find(id); + auto map_it = mItemMap.find(id); if (map_it != mItemMap.end()) { return map_it->second; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index dc2e304ab3..ca2d5814bc 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -300,7 +300,7 @@ protected: LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge; Params mParams; // stored copy of parameter block - std::map<LLUUID, LLFolderViewItem*> mItemMap; + std::unordered_map<LLUUID, LLFolderViewItem*> mItemMap; /** * Pointer to LLInventoryFolderViewModelBuilder. * diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index 73425e9f4c..b9d1c7ba18 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -80,6 +80,40 @@ public: } }; +class LLFetchFirstLandmarkByPos : public LLInventoryCollectFunctor +{ +private: + LLVector3d mPos; + bool mFound = false; +public: + LLFetchFirstLandmarkByPos(const LLVector3d& pos) : + mPos(pos), mFound(false) + { + } + + /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if (mFound || !item || item->getType() != LLAssetType::AT_LANDMARK) + return false; + + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); + if (!landmark) // the landmark not been loaded yet + return false; + + LLVector3d landmark_global_pos; + if (!landmark->getGlobalPos(landmark_global_pos)) + return false; + //we have to round off each coordinates to compare positions properly + mFound = ll_round(mPos.mdV[VX]) == ll_round(landmark_global_pos.mdV[VX]) + && ll_round(mPos.mdV[VY]) == ll_round(landmark_global_pos.mdV[VY]) + && ll_round(mPos.mdV[VZ]) == ll_round(landmark_global_pos.mdV[VZ]); + return mFound; + } + + // only care about first found landmark, so stop when found + /*virtual*/ bool exceedsLimit() { return mFound; } +}; + class LLFetchLandmarksByName : public LLInventoryCollectFunctor { private: @@ -155,6 +189,9 @@ public: mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos); return mFounded; } + + // only care about first found landmark, so stop when found + /*virtual*/ bool exceedsLimit() { return mFounded; } }; static void fetch_landmarks(LLInventoryModel::cat_array_t& cats, @@ -197,23 +234,61 @@ bool LLLandmarkActions::landmarkAlreadyExists() //static bool LLLandmarkActions::hasParcelLandmark() { + static LLUUID sLastItemID; + static S32 sLastFrame = -1; + if (sLastItemID.notNull()) + { + LLInventoryItem* item = gInventory.getItem(sLastItemID); + if (item) + { + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); + if (landmark) + { + LLVector3d landmark_global_pos; + if (landmark->getGlobalPos(landmark_global_pos) + && LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos)) + { + return true; + } + } + } + // Cached landmark does not match current parcel anymore, + // repeat inventory search to find a replacement landmark + // or to make sure there are none. + sLastItemID.setNull(); + sLastFrame = -1; + } + + if (sLastFrame == LLFrameTimer::getFrameCount()) + { + // Ideally this should also check parcel change and landmark additions, + // not just frame change. + // But should be sufficient to check only frame as this is used + // after inventory and parcel operations. + return false; + } + sLastFrame = LLFrameTimer::getFrameCount(); + LLFirstAgentParcelLandmark get_first_agent_landmark; LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; fetch_landmarks(cats, items, get_first_agent_landmark); - return !items.empty(); - + if (!items.empty()) + { + sLastItemID = items[0]->getUUID(); + return true; + } + return false; } -// *TODO: This could be made more efficient by only fetching the FIRST -// landmark that meets the criteria LLViewerInventoryItem* LLLandmarkActions::findLandmarkForGlobalPos(const LLVector3d &pos) { // Determine whether there are landmarks pointing to the current parcel. + // Will stop after first found landmark. LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - LLFetchlLandmarkByPos is_current_pos_landmark(pos); - fetch_landmarks(cats, items, is_current_pos_landmark); + LLFetchFirstLandmarkByPos get_landmark_from_pos(pos); + fetch_landmarks(cats, items, get_landmark_from_pos); if(items.empty()) { @@ -385,7 +460,14 @@ void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItem { LLVector3d global_pos; landmark->getGlobalPos(global_pos); - LLLandmarkActions::getSLURLfromPosGlobal(global_pos,©_slurl_to_clipboard_callback,true); + if (!global_pos.isExactlyZero()) + { + LLLandmarkActions::getSLURLfromPosGlobal(global_pos, ©_slurl_to_clipboard_callback, true); + } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } } diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp index 51c38aba3a..0a90cf0699 100644 --- a/indra/newview/llmachineid.cpp +++ b/indra/newview/llmachineid.cpp @@ -398,6 +398,8 @@ bool getSerialNumber(unsigned char *unique_id, size_t len) S32 LLMachineID::init() { + LL_PROFILE_ZONE_SCOPED; + size_t len = sizeof(static_unique_id); memset(static_unique_id, 0, len); S32 ret_code = 0; diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 1279b77ad4..c04f874923 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -33,9 +33,42 @@ #include "httprequest.h" #include "httpheaders.h" #include "httpoptions.h" +#include <boost/container_hash/hash.hpp> class LLViewerRegion; +// struct for TE-specific material ID query +class TEMaterialPair +{ +public: + U32 te; + LLMaterialID materialID; + + bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); } +}; + +inline bool operator<(const TEMaterialPair& lhs, const TEMaterialPair& rhs) +{ + return (lhs.te < rhs.te) ? true : (lhs.materialID < rhs.materialID); +} + +// std::hash implementation for TEMaterialPair +namespace std +{ + template<> + struct hash<TEMaterialPair> + { + inline size_t operator()(const TEMaterialPair& p) const noexcept + { + // Utilize boost::hash_combine to generate a good hash + size_t seed = 0; + boost::hash_combine(seed, p.te + 1); + boost::hash_combine(seed, p.materialID); + return seed; + } + }; +} // namespace std + class LLMaterialMgr : public LLSingleton<LLMaterialMgr> { LLSINGLETON(LLMaterialMgr); @@ -83,29 +116,6 @@ private: void onRegionRemoved(LLViewerRegion* regionp); private: - // struct for TE-specific material ID query - class TEMaterialPair - { - public: - - U32 te; - LLMaterialID materialID; - - bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); } - }; - - // definitions follow class - friend std::hash<TEMaterialPair>; - friend size_t hash_value(const TEMaterialPair&) noexcept; - - friend inline bool operator<( - const LLMaterialMgr::TEMaterialPair& lhs, - const LLMaterialMgr::TEMaterialPair& rhs) - { - return (lhs.te < rhs.te) ? true : - (lhs.materialID < rhs.materialID); - } - typedef std::set<LLMaterialID> material_queue_t; typedef std::map<LLUUID, material_queue_t> get_queue_t; typedef std::pair<const LLUUID, LLMaterialID> pending_material_t; @@ -113,7 +123,7 @@ private: typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t; - typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t; + typedef std::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t; typedef std::set<LLUUID> getall_queue_t; typedef std::map<LLUUID, F64> getall_pending_map_t; typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t; @@ -142,23 +152,5 @@ private: U32 getMaxEntries(const LLViewerRegion* regionp); }; -// std::hash implementation for TEMaterialPair -namespace std -{ - template<> struct hash<LLMaterialMgr::TEMaterialPair> - { - inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept - { - return size_t((p.te + 1) * p.materialID.getDigest64()); - } - }; -} - -// For use with boost containers. -inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept -{ - return size_t((p.te + 1) * p.materialID.getDigest64()); -} - #endif // LL_LLMATERIALMGR_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index ed342935ad..20bda5039d 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3331,6 +3331,8 @@ void LLMeshRepoThread::notifyLoadedMeshes() loaded_queue.swap(mLoadedQ); mLoadedMutex->unlock(); + LL_PROFILE_ZONE_NAMED("notify loaded meshes"); + update_metrics = true; // Process the elements free of the lock @@ -3362,6 +3364,8 @@ void LLMeshRepoThread::notifyLoadedMeshes() unavil_queue.swap(mUnavailableQ); mLoadedMutex->unlock(); + LL_PROFILE_ZONE_NAMED("notify unavail meshes"); + update_metrics = true; // Process the elements free of the lock @@ -3380,6 +3384,7 @@ void LLMeshRepoThread::notifyLoadedMeshes() { if (mLoadedMutex->trylock()) { + LL_PROFILE_ZONE_NAMED("notify misc meshes"); std::deque<LLPointer<LLMeshSkinInfo>> skin_info_q; std::deque<UUIDBasedRequest> skin_info_unavail_q; std::list<LLModel::Decomposition*> decomp_q; diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 56ad8297c7..061b4b5428 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -442,7 +442,7 @@ public: LLCondition* mSignal; //map of known mesh headers - typedef boost::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data + typedef std::unordered_map<LLUUID, LLMeshHeader> mesh_header_map; // pair is header_size and data mesh_header_map mMeshHeader; class HeaderRequest : public RequestStats diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 9157e34833..b7bba02b9d 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -582,6 +582,8 @@ std::vector<LLMute> LLMuteList::getMutes() const //----------------------------------------------------------------------------- bool LLMuteList::loadFromFile(const std::string& filename) { + LL_PROFILE_ZONE_SCOPED; + if(!filename.size()) { LL_WARNS() << "Mute List Filename is Empty!" << LL_ENDL; @@ -803,6 +805,10 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**) std::string unclean_filename; msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, unclean_filename); std::string filename = LLDir::getScrubbedFileName(unclean_filename); + if (filename.empty()) + { + LL_WARNS() << "Received empty mute list filename." << LL_ENDL; + } LLMuteList* mute_list = getInstance(); mute_list->mLoadState = ML_REQUESTED; @@ -835,16 +841,16 @@ void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**) void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_status) { - LL_INFOS() << "LLMuteList::processMuteListFile()" << LL_ENDL; - std::string* local_filename_and_path = (std::string*)user_data; if(local_filename_and_path && !local_filename_and_path->empty() && (error_code == 0)) { + LL_INFOS() << "Received mute list from server" << LL_ENDL; LLMuteList::getInstance()->loadFromFile(*local_filename_and_path); LLFile::remove(*local_filename_and_path); } else { + LL_INFOS() << "LLMuteList xfer failed with code " << error_code << LL_ENDL; LLMuteList::getInstance()->mLoadState = ML_FAILED; } delete local_filename_and_path; @@ -962,6 +968,8 @@ bool LLRenderMuteList::saveToFile() bool LLRenderMuteList::loadFromFile() { + LL_PROFILE_ZONE_SCOPED; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt"); LLFILE* fp = LLFile::fopen(filename, "rb"); if (!fp) diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index dfead5ee8a..9a0612e9f9 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -712,7 +712,14 @@ void LLNavigationBar::resizeLayoutPanel() } void LLNavigationBar::invokeSearch(std::string search_text) { - LLFloaterReg::showInstance("search", LLSD().with("category", "standard").with("query", LLSD(search_text))); + LLSD key; + key["category"] = "standard"; + key["query"] = search_text; + LLSD collections = LLSD::emptyArray(); + collections.append("destinations"); + collections.append("places"); + key["collections"] = collections; + LLFloaterReg::showInstance("search", key); } void LLNavigationBar::clearHistoryCache() diff --git a/indra/newview/llnearbyvoicemoderation.cpp b/indra/newview/llnearbyvoicemoderation.cpp new file mode 100644 index 0000000000..a5ee0e9423 --- /dev/null +++ b/indra/newview/llnearbyvoicemoderation.cpp @@ -0,0 +1,220 @@ +/** + * @file llnearbyvoicemoderation.cpp + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llnotificationsutil.h" +#include "llviewerregion.h" +#include "llvoavatar.h" +#include "llvoicechannel.h" +#include "llvoiceclient.h" +#include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" +#include "roles_constants.h" + +#include "llnearbyvoicemoderation.h" + +LLNearbyVoiceModeration::LLNearbyVoiceModeration() +{ +} + +LLNearbyVoiceModeration::~LLNearbyVoiceModeration() +{ +} + +LLVOAvatar* LLNearbyVoiceModeration::getVOAvatarFromId(const LLUUID& agent_id) +{ + LLViewerObject *obj = gObjectList.findObject(agent_id); + while (obj && obj->isAttachment()) + { + obj = (LLViewerObject*)obj->getParent(); + } + + if (obj && obj->isAvatar()) + { + return (LLVOAvatar*)obj; + } + else + { + return NULL; + } +} + +const std::string LLNearbyVoiceModeration::getCapUrlFromRegion(LLViewerRegion* region) +{ + if (! region || ! region->capabilitiesReceived()) + { + return std::string(); + } + + std::string url = region->getCapability("SpatialVoiceModerationRequest"); + if (url.empty()) + { + LL_INFOS() << "Capability URL for region " << region->getName() << " is empty" << LL_ENDL; + return std::string(); + } + LL_INFOS() << "Capability URL for region " << region->getName() << " is " << url << LL_ENDL; + + return url; +} + +void LLNearbyVoiceModeration::requestMuteIndividual(const LLUUID& agent_id, bool mute) +{ + LLVOAvatar* avatar = getVOAvatarFromId(agent_id); + if (avatar) + { + const std::string cap_url = getCapUrlFromRegion(avatar->getRegion()); + if (cap_url.length()) + { + const std::string operand = mute ? "mute" : "unmute"; + + LLSD body; + body["operand"] = operand; + body["agent_id"] = agent_id; + + const std::string agent_name = avatar->getFullname(); + LL_INFOS() << "Resident " << agent_name + << " (" << agent_id << ")" << " applying " << operand << LL_ENDL; + + std::string success_msg = + STRINGIZE("Resident " << agent_name + << " (" << agent_id << ")" << " nearby voice was set to " << operand); + + std::string failure_msg = + STRINGIZE("Unable to change voice muting for resident " + << agent_name << " (" << agent_id << ")"); + + LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost( + cap_url, + body, + success_msg, + failure_msg); + } + } +} + +void LLNearbyVoiceModeration::requestMuteAll(bool mute) +{ + // Use our own avatar to get the region name + LLViewerRegion* region = gAgent.getRegion(); + + const std::string cap_url = getCapUrlFromRegion(region); + if (cap_url.length()) + { + const std::string operand = mute ? "mute_all" : "unmute_all"; + + LLSD body; + body["operand"] = operand; + + LL_INFOS() << "For all residents in this region, applying: " << operand << LL_ENDL; + + std::string success_msg = + STRINGIZE("Nearby voice for all residents was set to: " << operand); + + std::string failure_msg = + STRINGIZE("Unable to set nearby voice for all residents to: " << operand); + + LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost( + cap_url, + body, + success_msg, + failure_msg); + } +} + +void LLNearbyVoiceModeration::setMutedInfo(const std::string& channelID, bool mute) +{ + auto it = mChannelMuteMap.find(channelID); + if (it == mChannelMuteMap.end()) + { + if (mute) + { + // Channel is new and being muted + showMutedNotification(true); + } + mChannelMuteMap[channelID] = mute; + } + else + { + if (it->second != mute) + { + // Flag changed + showMutedNotification(mute); + it->second = mute; + } + } + if (mute && LLVoiceClient::getInstance()->getUserPTTState()) + { + LLVoiceClient::getInstance()->setUserPTTState(false); + } +} + +bool LLNearbyVoiceModeration::showNotificationIfNeeded() +{ + if (LLVoiceClient::getInstance()->inProximalChannel() && + LLVoiceClient::getInstance()->getIsModeratorMuted(gAgentID)) + { + return showMutedNotification(true); + } + return false; +} + +bool LLNearbyVoiceModeration::showMutedNotification(bool is_muted) +{ + // Check if the current voice channel is nearby chat + if (LLVoiceClient::getInstance()->inProximalChannel()) + { + LLNotificationsUtil::add(is_muted ? "NearbyVoiceMutedByModerator" : "NearbyVoiceUnmutedByModerator"); + return true; + } + return false; +} + +bool LLNearbyVoiceModeration::isNearbyChatModerator() +{ + // Region doesn't support WebRTC voice + if (!gAgent.getRegion() || !gAgent.getRegion()->isRegionWebRTCEnabled()) + { + return false; + } + + // Only show moderator options when connected to spatial voice chat + LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel(); + if (!channel || channel->getSessionID().notNull() || !LLAgent::isActionAllowed("speak")) + { + return false; + } + + if (LLViewerParcelMgr::getInstance()->isVoiceRestricted()) + { + // Only the parcel owner should have access to moderate parcel voice space + return LLViewerParcelMgr::getInstance()->allowVoiceModeration(); + } + else + { + return gAgent.canManageEstate(); + } +} diff --git a/indra/newview/llfloatersounddevices.h b/indra/newview/llnearbyvoicemoderation.h index 9b21b62747..619f169883 100644 --- a/indra/newview/llfloatersounddevices.h +++ b/indra/newview/llnearbyvoicemoderation.h @@ -1,9 +1,7 @@ /** - * @file llfloatersounddevices.h - * @author Leyla Farazha - * @brief Sound Preferences used for minimal skin + * @file llnearbyvoicemoderation.h * -* $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -25,25 +23,28 @@ * $/LicenseInfo$ */ -#ifndef LL_LLFLOATERSOUNDDEVICES_H -#define LL_LLFLOATERSOUNDDEVICES_H +#pragma once -#include "lltransientdockablefloater.h" +class LLVOAvatar; -class LLFloaterSoundDevices : public LLTransientDockableFloater -{ -public: +class LLNearbyVoiceModeration : public LLSingleton <LLNearbyVoiceModeration> { + LLSINGLETON(LLNearbyVoiceModeration); + ~LLNearbyVoiceModeration(); - LOG_CLASS(LLFloaterSoundDevices); + public: + void requestMuteIndividual(const LLUUID& userID, bool mute); + void requestMuteAll(bool mute); - LLFloaterSoundDevices(const LLSD& key); - ~LLFloaterSoundDevices(); - - bool postBuild() override; - void setDocked(bool docked, bool pop_on_undock = true) override; - void setFocus(bool b) override; -}; + void setMutedInfo(const std::string& channelID, bool mute); + bool showMutedNotification(bool is_muted); + bool showNotificationIfNeeded(); + bool isNearbyChatModerator(); -#endif //LL_LLFLOATERSOUNDDEVICES_H + private: + LLVOAvatar* getVOAvatarFromId(const LLUUID& id); + const std::string getCapUrlFromRegion(LLViewerRegion* region); + boost::signals2::connection mParcelCallbackConnection; + std::map<std::string, bool> mChannelMuteMap; +}; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index af472c4259..63ec43458b 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -47,6 +47,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llappviewer.h" // for gDisconnected +#include "llavataractions.h" #include "llcallingcard.h" // LLAvatarTracker #include "llfloaterland.h" #include "llfloaterworldmap.h" @@ -397,20 +398,41 @@ void LLNetMap::draw() LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal()); - // Draw avatars + std::vector<std::pair<U32, bool>> indexed_avatars; + indexed_avatars.reserve(avatar_ids.size()); for (U32 i = 0; i < avatar_ids.size(); i++) { - LLUUID uuid = avatar_ids[i]; + indexed_avatars.emplace_back(i, LLAvatarActions::isFriend(avatar_ids[i])); + } + + // Sort avatars so non-friends are drawn first and friend dots will appear on top + std::sort(indexed_avatars.begin(), indexed_avatars.end(), + [](const auto& a, const auto& b) { return a.second < b.second; }); + + uuid_vec_t sorted_avatar_ids; + std::vector<LLVector3d> sorted_positions; + sorted_avatar_ids.reserve(avatar_ids.size()); + sorted_positions.reserve(positions.size()); + + // Reorder avatar_ids and positions based on sorted indices + for (const auto& indexed_avatar : indexed_avatars) + { + sorted_avatar_ids.push_back(avatar_ids[indexed_avatar.first]); + sorted_positions.push_back(positions[indexed_avatar.first]); + } + + // Draw avatars + for (U32 i = 0; i < sorted_avatar_ids.size(); i++) + { + LLUUID uuid = sorted_avatar_ids[i]; // Skip self, we'll draw it later if (uuid == gAgent.getID()) continue; - pos_map = globalPosToView(positions[i]); - - bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); + pos_map = globalPosToView(sorted_positions[i]); - LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; + LLColor4 color = LLAvatarActions::isFriend(uuid) ? map_avatar_friend_color : map_avatar_color; - unknown_relative_z = positions[i].mdV[VZ] >= COARSEUPDATE_MAX_Z && + unknown_relative_z = sorted_positions[i].mdV[VZ] >= COARSEUPDATE_MAX_Z && camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z; LLWorldMapView::drawAvatar( diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 8589afae06..852f2dab21 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -850,7 +850,12 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id) // Start observing changes in "My Outfits" category. mCategoriesObserver->addCategory(cat_id, - boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id), true); + [this, cat_id]() + { + mPendingOutfitRefreshes.insert(cat_id); + startIdleLoop(cat_id); + }, + true); outfit_category->fetch(); refreshOutfit(cat_id); @@ -901,6 +906,18 @@ void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat, } } +bool LLOutfitGallery::updateOneOutfit() +{ + if (mPendingOutfitRefreshes.empty()) + return false; + + auto it = mPendingOutfitRefreshes.begin(); + LLUUID outfit_id = *it; + mPendingOutfitRefreshes.erase(it); + refreshOutfit(outfit_id); + return true; +} + void LLOutfitGallery::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id) { if (mOutfitMenu && cat_id.notNull()) diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 5801a32a39..183b6ea9d5 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -98,6 +98,7 @@ public: /*virtual*/ void updateAddedCategory(LLUUID cat_id); /*virtual*/ void updateRemovedCategory(LLUUID cat_id); /*virtual*/ void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name); + /*virtual*/ bool updateOneOutfit(); // bulk processing, scheduled by observer when updates are needed /*virtual*/ bool hasItemSelected(); /*virtual*/ bool canWearSelected(); @@ -190,6 +191,7 @@ private: typedef item_num_map_t::value_type item_numb_map_value_t; item_num_map_t mItemIndexMap; std::map<S32, LLOutfitGalleryItem*> mIndexToItemMap; + std::set<LLUUID> mPendingOutfitRefreshes; LLInventoryCategoriesObserver* mOutfitsObserver; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 32831fcd9b..7db79c7010 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -1055,6 +1055,15 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) } } +void LLOutfitListBase::startIdleLoop(const LLUUID cat_id) +{ + if (mRefreshListState.CategoryUUID.isNull()) + { + mRefreshListState.CategoryUUID = cat_id; + gIdleCallbacks.addFunction(onIdle, this); + } +} + // static void LLOutfitListBase::onIdle(void* userdata) { @@ -1129,6 +1138,14 @@ void LLOutfitListBase::onIdleRefreshList() return; } + // Let derived classes process their own updates. + while (updateOneOutfit()) + { + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; + } + sortOutfits(); highlightBaseOutfit(); diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index bcf7e45696..408ff07116 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -95,6 +95,17 @@ public: virtual void updateAddedCategory(LLUUID cat_id) = 0; virtual void updateRemovedCategory(LLUUID cat_id) = 0; virtual void updateChangedCategoryName(LLViewerInventoryCategory *cat, std::string name) = 0; + + /* + * Optional hook for derived classes to perform additional processing. + * This is called by the outfit list update logic after the core + * bookkeeping for an outfit has been handled. + * + * @return true if update processing should continue, + * false if no additional work is required. + * The base implementation returns false. + */ + virtual bool updateOneOutfit() { return false; }; virtual void sortOutfits(); void removeSelected(); @@ -138,6 +149,7 @@ protected: bool isOutfitFolder(LLViewerInventoryCategory* cat) const; + void startIdleLoop(const LLUUID cat_id); static void onIdle(void* userdata); void onIdleRefreshList(); @@ -150,6 +162,7 @@ protected: uuid_vec_t::const_iterator RemovedIterator; } mRefreshListState; std::set<LLUUID> mChangedItems; + std::set<LLUUID> mPendingOutfitRefreshes; bool mIsInitialized; LLInventoryCategoriesObserver* mCategoriesObserver; diff --git a/indra/newview/llpaneldirbrowser.cpp b/indra/newview/llpaneldirbrowser.cpp index 8c981cad55..69329c4ea4 100644 --- a/indra/newview/llpaneldirbrowser.cpp +++ b/indra/newview/llpaneldirbrowser.cpp @@ -559,9 +559,6 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**) LLUUID owner_id; std::string name; std::string date; - bool show_pg = gSavedSettings.getBOOL("ShowPGEvents"); - bool show_mature = gSavedSettings.getBOOL("ShowMatureEvents"); - bool show_adult = gSavedSettings.getBOOL("ShowAdultEvents"); msg->getUUID("AgentData", "AgentID", agent_id); msg->getUUID("QueryData", "QueryID", query_id ); @@ -618,27 +615,6 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**) LL_WARNS() << "skipped event due to owner_id null, event_id " << event_id << LL_ENDL; continue; } - - // skip events that don't match the flags - // there's no PG flag, so we make sure neither adult nor mature is set - if (((event_flags & (EVENT_FLAG_ADULT | EVENT_FLAG_MATURE)) == EVENT_FLAG_NONE) && !show_pg) - { - //llwarns << "Skipped pg event because we're not showing pg, event_id " << event_id << llendl; - continue; - } - - if ((event_flags & EVENT_FLAG_MATURE) && !show_mature) - { - //llwarns << "Skipped mature event because we're not showing mature, event_id " << event_id << llendl; - continue; - } - - if ((event_flags & EVENT_FLAG_ADULT) && !show_adult) - { - //llwarns << "Skipped adult event because we're not showing adult, event_id " << event_id << llendl; - continue; - } - LLSD content; content["type"] = EVENT_CODE; diff --git a/indra/newview/llpaneldirevents.cpp b/indra/newview/llpaneldirevents.cpp index 227ed877cd..7ac1229637 100644 --- a/indra/newview/llpaneldirevents.cpp +++ b/indra/newview/llpaneldirevents.cpp @@ -143,18 +143,17 @@ void LLPanelDirEvents::performQueryOrDelete(U32 event_id) static LLUICachedControl<bool> incpg("ShowPGEvents", true); static LLUICachedControl<bool> incmature("ShowMatureEvents", false); static LLUICachedControl<bool> incadult("ShowAdultEvents", false); + if (!(incpg || incmature || incadult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } U32 scope = DFQ_DATE_EVENTS; if (incpg) scope |= DFQ_INC_PG; if (incmature && gAgent.canAccessMature()) scope |= DFQ_INC_MATURE; if (incadult && gAgent.canAccessAdult()) scope |= DFQ_INC_ADULT; - if ( !( scope & (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT ))) - { - LLNotificationsUtil::add("NoContentToSearch"); - return; - } - setupNewSearch(); std::ostringstream params; diff --git a/indra/newview/llpaneldirland.cpp b/indra/newview/llpaneldirland.cpp index 53c58d8fa9..f85a8b948e 100644 --- a/indra/newview/llpaneldirland.cpp +++ b/indra/newview/llpaneldirland.cpp @@ -62,20 +62,6 @@ bool LLPanelDirLand::postBuild() childSetValue("type", gSavedSettings.getString("FindLandType")); - bool adult_enabled = gAgent.canAccessAdult(); - bool mature_enabled = gAgent.canAccessMature(); - childSetVisible("incpg", true); - if (!mature_enabled) - { - childSetValue("incmature", false); - childDisable("incmature"); - } - if (!adult_enabled) - { - childSetValue("incadult", false); - childDisable("incadult"); - } - childSetCommitCallback("pricecheck", onCommitPrice, this); childSetCommitCallback("areacheck", onCommitArea, this); diff --git a/indra/newview/llpaneldirplaces.cpp b/indra/newview/llpaneldirplaces.cpp index 2d54566038..3501baf697 100644 --- a/indra/newview/llpaneldirplaces.cpp +++ b/indra/newview/llpaneldirplaces.cpp @@ -121,6 +121,11 @@ void LLPanelDirPlaces::performQuery() static LLUICachedControl<bool> inc_pg("ShowPGSims", true); static LLUICachedControl<bool> inc_mature("ShowMatureSims", false); static LLUICachedControl<bool> inc_adult("ShowAdultSims", false); + if (!(inc_pg || inc_mature || inc_adult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } if (inc_pg) { @@ -137,12 +142,6 @@ void LLPanelDirPlaces::performQuery() flags |= DFQ_INC_ADULT; } - if (0x0 == flags) - { - LLNotificationsUtil::add("NoContentToSearch"); - return; - } - queryCore(query_string, category, flags); } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 353e4b0ae4..345426824e 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -852,6 +852,27 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); } + + // Also align GLTF material if any + S32 gltf_info_index = 0; // base texture + LLVector2 gltf_offset, gltf_scale; + F32 gltf_rot; + if (facep->calcAlignedPlanarGLTF(mCenterFace, &gltf_offset, &gltf_scale, &gltf_rot, gltf_info_index)) + { + LLGLTFMaterial new_override; + const LLTextureEntry* tep = object->getTE(te); + if (tep && tep->getGLTFMaterialOverride()) + { + new_override = *tep->getGLTFMaterialOverride(); + } + + LLGLTFMaterial::TextureTransform& transform = new_override.mTextureTransform[gltf_info_index]; + transform.mOffset.set(gltf_offset.mV[0], gltf_offset.mV[1]); + transform.mScale.set(gltf_scale.mV[0], gltf_scale.mV[1]); + transform.mRotation = gltf_rot; + + LLGLTFMaterialList::queueModify(object, te, &new_override); + } } if (!set_aligned) { diff --git a/indra/newview/llpanelgenerictip.cpp b/indra/newview/llpanelgenerictip.cpp index bc2b28269f..1b5228713e 100644 --- a/indra/newview/llpanelgenerictip.cpp +++ b/indra/newview/llpanelgenerictip.cpp @@ -43,5 +43,13 @@ LLPanelGenericTip::LLPanelGenericTip( S32 max_line_count = gSavedSettings.getS32("TipToastMessageLineCount"); snapToMessageHeight(getChild<LLTextBox> ("message"), max_line_count); + + // Check if notification should respond to mouse clicks + if (notification->getPayload().has("respond_on_mousedown") + && notification->getPayload()["respond_on_mousedown"]) + { + setMouseDownCallback(boost::bind(&LLNotification::respond, + notification, notification->getResponseTemplate())); + } } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index ad7aa57842..04eebcefc1 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -216,14 +216,14 @@ bool LLPanelMainInventory::postBuild() mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2)); } - LLInventoryPanel* favorites_panel = getChild<LLInventoryPanel>(FAVORITES); - if (favorites_panel) + mFavoritesPanel = getChild<LLInventoryPanel>(FAVORITES); + if (mFavoritesPanel) { - favorites_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); - LLInventoryFilter& favorites_filter = favorites_panel->getFilter(); + mFavoritesPanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); + LLInventoryFilter& favorites_filter = mFavoritesPanel->getFilter(); favorites_filter.setEmptyLookupMessage("InventoryNoMatchingFavorites"); favorites_filter.markDefault(); - favorites_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, favorites_panel, _1, _2)); + mFavoritesPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mFavoritesPanel, _1, _2)); } mSearchTypeCombo = getChild<LLComboBox>("search_type"); @@ -319,6 +319,10 @@ bool LLPanelMainInventory::postBuild() menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); } + mFilterTabs->setTabVisibility(mRecentPanel, gSavedSettings.getBOOL("InventoryShowRecentTab")); + mFilterTabs->setTabVisibility(mWornItemsPanel, gSavedSettings.getBOOL("InventoryShowWornTab")); + mFilterTabs->setTabVisibility(mFavoritesPanel, gSavedSettings.getBOOL("InventoryShowFavoritesTab")); + // Trigger callback for focus received so we can deselect items in inbox/outbox LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this)); @@ -1613,8 +1617,10 @@ void LLPanelMainInventory::initSingleFolderRoot(const LLUUID& start_folder_id) void LLPanelMainInventory::initInventoryViews() { mAllItemsPanel->initializeViewBuilding(); - mRecentPanel->initializeViewBuilding(); - mWornItemsPanel->initializeViewBuilding(); + if (gSavedSettings.getBOOL("InventoryShowRecentTab")) + mRecentPanel->initializeViewBuilding(); + if (gSavedSettings.getBOOL("InventoryShowWornTab")) + mWornItemsPanel->initializeViewBuilding(); } void LLPanelMainInventory::toggleViewMode() @@ -2056,6 +2062,27 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { setViewMode(MODE_COMBINATION); } + + if (command_name == "toggle_recent_tab") + { + bool visibility = !gSavedSettings.getBOOL("InventoryShowRecentTab"); + gSavedSettings.setBOOL("InventoryShowRecentTab", visibility); + mFilterTabs->setTabVisibility(mRecentPanel, visibility); + mRecentPanel->initializeViewBuilding(); + } + if (command_name == "toggle_worn_tab") + { + bool visibility = !gSavedSettings.getBOOL("InventoryShowWornTab"); + gSavedSettings.setBOOL("InventoryShowWornTab", visibility); + mFilterTabs->setTabVisibility(mWornItemsPanel, visibility); + mWornItemsPanel->initializeViewBuilding(); + } + if (command_name == "toggle_favorites_tab") + { + bool visibility = !gSavedSettings.getBOOL("InventoryShowFavoritesTab"); + gSavedSettings.setBOOL("InventoryShowFavoritesTab", visibility); + mFilterTabs->setTabVisibility(mFavoritesPanel, visibility); + } } void LLPanelMainInventory::onVisibilityChange( bool new_visibility ) @@ -2283,6 +2310,19 @@ bool LLPanelMainInventory::isActionChecked(const LLSD& userdata) return isCombinationViewMode(); } + if (command_name == "recent_tab") + { + return mFilterTabs->getTabVisibility(mRecentPanel); + } + if (command_name == "worn_tab") + { + return mFilterTabs->getTabVisibility(mWornItemsPanel); + } + if (command_name == "favorites_tab") + { + return mFilterTabs->getTabVisibility(mFavoritesPanel); + } + return false; } diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index a78c0c0fad..03650e7fc1 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -199,6 +199,7 @@ private: LLInventoryPanel* mAllItemsPanel = nullptr; LLInventoryPanel* mRecentPanel = nullptr; LLInventoryPanel* mWornItemsPanel = nullptr; + LLInventoryPanel* mFavoritesPanel = nullptr; bool mResortActivePanel; LLSaveFolderState* mSavedFolderState; std::string mFilterText; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index a31a54bb67..d27ce81e4f 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1830,7 +1830,7 @@ void LLPanelObjectInventory::onFocusReceived() LLFolderViewItem* LLPanelObjectInventory::getItemByID( const LLUUID& id ) { - std::map<LLUUID, LLFolderViewItem*>::iterator map_it = mItemMap.find(id); + auto map_it = mItemMap.find(id); if (map_it != mItemMap.end()) { return map_it->second; diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 154639e4bb..13e27b489c 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -109,7 +109,7 @@ protected: bool isSelectionRemovable(); private: - std::map<LLUUID, LLFolderViewItem*> mItemMap; + std::unordered_map<LLUUID, LLFolderViewItem*> mItemMap; LLScrollContainer* mScroller; LLFolderView* mFolders; diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index cbf5819fda..cff09b0778 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -786,7 +786,9 @@ void LLPanelPermissions::refresh() getChildView("Edit Cost")->setEnabled(change_sale_allowed && !is_for_sale_mixed); // Set the checkbox to tentative if the prices of each object selected // are not the same. - getChild<LLUICtrl>("checkbox for sale")->setTentative( is_for_sale_mixed); + // If object is marked for sale yet is not transferable, mark as tentative, + // as it is in a state where it can't be sold + getChild<LLUICtrl>("checkbox for sale")->setTentative((!can_transfer && num_for_sale) || is_for_sale_mixed); getChildView("sale type")->setEnabled(num_for_sale && can_transfer && !is_sale_price_mixed); getChildView("Next owner can:")->setEnabled(true); diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp deleted file mode 100644 index a0129b2cb1..0000000000 --- a/indra/newview/llpanelvoiceeffect.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @file llpanelvoiceeffect.cpp - * @author Aimee - * @brief Panel to select Voice Morphs. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelvoiceeffect.h" - -#include "llcombobox.h" -#include "llfloaterreg.h" -#include "llpanel.h" -#include "lltrans.h" -#include "lltransientfloatermgr.h" -#include "llvoiceclient.h" -#include "llweb.h" - -static LLPanelInjector<LLPanelVoiceEffect> t_panel_voice_effect("panel_voice_effect"); - -LLPanelVoiceEffect::LLPanelVoiceEffect() - : mVoiceEffectCombo(NULL) -{ - mCommitCallbackRegistrar.add("Voice.CommitVoiceEffect", boost::bind(&LLPanelVoiceEffect::onCommitVoiceEffect, this)); -} - -LLPanelVoiceEffect::~LLPanelVoiceEffect() -{ - LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox"); - LLTransientFloaterMgr::getInstance()->removeControlView(combo_list_view); - - if(LLVoiceClient::instanceExists()) - { - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->removeObserver(this); - } - } -} - -// virtual -bool LLPanelVoiceEffect::postBuild() -{ - mVoiceEffectCombo = getChild<LLComboBox>("voice_effect"); - - // Need to tell LLTransientFloaterMgr about the combo list, otherwise it can't - // be clicked while in a docked floater as it extends outside the floater area. - LLView* combo_list_view = mVoiceEffectCombo->getChildView("ComboBox"); - LLTransientFloaterMgr::getInstance()->addControlView(combo_list_view); - - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (effect_interface) - { - effect_interface->addObserver(this); - } - - update(true); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -/// PRIVATE SECTION -////////////////////////////////////////////////////////////////////////// - -void LLPanelVoiceEffect::onCommitVoiceEffect() -{ - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (!effect_interface) - { - mVoiceEffectCombo->setEnabled(false); - return; - } - - LLSD value = mVoiceEffectCombo->getValue(); - if (value.asInteger() == PREVIEW_VOICE_EFFECTS) - { - // Open the Voice Morph preview floater - LLFloaterReg::showInstance("voice_effect"); - } - else if (value.asInteger() == GET_VOICE_EFFECTS) - { - // Open the voice morphing info web page - LLWeb::loadURL(LLTrans::getString("voice_morphing_url")); - } - else - { - effect_interface->setVoiceEffect(value.asUUID()); - } - - mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect()); -} - -// virtual -void LLPanelVoiceEffect::onVoiceEffectChanged(bool effect_list_updated) -{ - update(effect_list_updated); -} - -void LLPanelVoiceEffect::update(bool list_updated) -{ - if (mVoiceEffectCombo) - { - LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); - if (!effect_interface) return; - if (list_updated) - { - // Add the default "No Voice Morph" entry. - mVoiceEffectCombo->removeall(); - mVoiceEffectCombo->add(getString("no_voice_effect"), LLUUID::null); - mVoiceEffectCombo->addSeparator(); - - // Add entries for each Voice Morph. - const voice_effect_list_t& effect_list = effect_interface->getVoiceEffectList(); - if (!effect_list.empty()) - { - for (voice_effect_list_t::const_iterator it = effect_list.begin(); it != effect_list.end(); ++it) - { - mVoiceEffectCombo->add(it->first, it->second, ADD_BOTTOM); - } - - mVoiceEffectCombo->addSeparator(); - } - - // Add the fixed entries to go to the preview floater or marketing page. - mVoiceEffectCombo->add(getString("preview_voice_effects"), PREVIEW_VOICE_EFFECTS); - mVoiceEffectCombo->add(getString("get_voice_effects"), GET_VOICE_EFFECTS); - } - - if (effect_interface && LLVoiceClient::instance().isVoiceWorking()) - { - // Select the current Voice Morph. - mVoiceEffectCombo->setValue(effect_interface->getVoiceEffect()); - mVoiceEffectCombo->setEnabled(true); - } - else - { - // If voice isn't working or Voice Effects are not supported disable the control. - mVoiceEffectCombo->setValue(LLUUID::null); - mVoiceEffectCombo->setEnabled(false); - } - } -} diff --git a/indra/newview/llpanelvoiceeffect.h b/indra/newview/llpanelvoiceeffect.h deleted file mode 100644 index f920e41081..0000000000 --- a/indra/newview/llpanelvoiceeffect.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file llpanelvoiceeffect.h - * @author Aimee - * @brief Panel to select Voice Effects. - * - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_PANELVOICEEFFECT_H -#define LL_PANELVOICEEFFECT_H - -#include "llpanel.h" -#include "llvoiceclient.h" - -class LLComboBox; - -class LLPanelVoiceEffect - : public LLPanel - , public LLVoiceEffectObserver -{ -public: - LOG_CLASS(LLPanelVoiceEffect); - - LLPanelVoiceEffect(); - virtual ~LLPanelVoiceEffect(); - - bool postBuild() override; - -private: - void onCommitVoiceEffect(); - void update(bool list_updated); - - /// Called by voice effect provider when voice effect list is changed. - void onVoiceEffectChanged(bool effect_list_updated) override; - - // Fixed entries in the Voice Morph list - typedef enum e_voice_effect_combo_items - { - NO_VOICE_EFFECT = 0, - PREVIEW_VOICE_EFFECTS = 1, - GET_VOICE_EFFECTS = 2 - } EVoiceEffectComboItems; - - LLComboBox* mVoiceEffectCombo; -}; - - -#endif //LL_PANELVOICEEFFECT_H diff --git a/indra/newview/llperfstats.h b/indra/newview/llperfstats.h index 1a2098ec7e..38deb87237 100644 --- a/indra/newview/llperfstats.h +++ b/indra/newview/llperfstats.h @@ -223,7 +223,7 @@ namespace LLPerfStats static void updateMeanFrameTime(U64 tot_frame_time_raw); // StatsArray is a uint64_t for each possible statistic type. using StatsArray = std::array<uint64_t, static_cast<size_t>(LLPerfStats::StatType_t::STATS_COUNT)>; - using StatsMap = std::unordered_map<LLUUID, StatsArray, boost::hash<LLUUID>>; + using StatsMap = std::unordered_map<LLUUID, StatsArray>; using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>; using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(LLPerfStats::ObjType_t::OT_COUNT)>; diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 9a991727b2..eefd19e153 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -79,6 +79,7 @@ LLPreviewNotecard::LLPreviewNotecard(const LLSD& key) //const LLUUID& item_id, LLPreviewNotecard::~LLPreviewNotecard() { delete mLiveFile; + mEditor = nullptr; } bool LLPreviewNotecard::postBuild() @@ -166,7 +167,7 @@ bool LLPreviewNotecard::handleKeyHere(KEY key, MASK mask) // virtual bool LLPreviewNotecard::canClose() { - if(mForceClose || mEditor->isPristine()) + if(mForceClose || !mEditor || mEditor->isPristine()) { return true; } diff --git a/indra/newview/llscriptruntimeperms.h b/indra/newview/llscriptruntimeperms.h index 300304c21b..6350b61d08 100644 --- a/indra/newview/llscriptruntimeperms.h +++ b/indra/newview/llscriptruntimeperms.h @@ -24,10 +24,7 @@ * $/LicenseInfo$ */ -#ifndef LL_LLSCRIPTRUNTIME_PERMS_H -#define LL_LLSCRIPTRUNTIME_PERMS_H - -#include <boost/array.hpp> +#pragma once typedef struct _script_perm { std::string question; @@ -37,12 +34,12 @@ typedef struct _script_perm { question(q), permbit(b), caution(c) {} } script_perm_t; -const U32 NUM_SCRIPT_PERMISSIONS = 18; +const U32 NUM_SCRIPT_PERMISSIONS = 19; const S32 SCRIPT_PERMISSION_DEBIT = 0; const S32 SCRIPT_PERMISSION_TRIGGER_ANIMATION = 3; const S32 SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS = 14; -static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSIONS = {{ +static const std::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSIONS = {{ _script_perm("ScriptTakeMoney", (0x1 << 1), true), _script_perm("ActOnControlInputs", (0x1 << 2), false), _script_perm("RemapControlInputs", (0x1 << 3), false), @@ -60,7 +57,7 @@ static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSI _script_perm("OverrideYourAnimations", (0x1 << 15), false), _script_perm("ScriptReturnObjects", (0x1 << 16), false), _script_perm("ForceSitAvatar", (0x1 << 17), false), - _script_perm("ChangeEnvSettings", (0x1 << 18), false) + _script_perm("ChangeEnvSettings", (0x1 << 18), false), + _script_perm("PrivilegedLandAccess",(0x1 << 19), true) } }; -#endif // LL_LLSCRIPTRUNTIME_PERMS_H diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 4326bd549c..6e18bb979a 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -137,6 +137,9 @@ void LLSpatialGroup::clearDrawMap() bool LLSpatialGroup::isHUDGroup() const { + if (hasState(DEAD)) + return false; + LLSpatialPartition* part = (LLSpatialPartition*)mSpatialPartition; return part && part->isHUDPartition(); } diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 1a7ce74ccc..8c8734b52f 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -875,7 +875,7 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id) //debug bool LLTextureCache::isInCache(const LLUUID& id) { - LLMutexLock lock(&mHeaderMutex); + LLMutexLock lock(&mHeaderIDMapMutex); id_map_t::const_iterator iter = mHeaderIDMap.find(id); return (iter != mHeaderIDMap.end()) ; @@ -991,6 +991,8 @@ void LLTextureCache::setReadOnly(bool read_only) // Returns the unused amount of max_size if any S64 LLTextureCache::initCache(ELLPath location, S64 max_size, bool texture_cache_mismatch) { + LL_PROFILE_ZONE_SCOPED; + llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized. S64 entries_size = (max_size * 36) / 100; //0.36 * max_size @@ -1115,10 +1117,13 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create { S32 idx = -1; - id_map_t::iterator iter1 = mHeaderIDMap.find(id); - if (iter1 != mHeaderIDMap.end()) { - idx = iter1->second; + LLMutexLock lock(&mHeaderIDMapMutex); + id_map_t::iterator iter1 = mHeaderIDMap.find(id); + if (iter1 != mHeaderIDMap.end()) + { + idx = iter1->second; + } } if (idx < 0) @@ -1146,10 +1151,19 @@ S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create // Erase entry from LRU regardless mLRU.erase(curiter2); // Look up entry and use it if it is valid - id_map_t::iterator iter3 = mHeaderIDMap.find(oldid); - if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) + + S32 found_idx = -1; { - idx = iter3->second; + LLMutexLock lock(&mHeaderIDMapMutex); + id_map_t::iterator iter3 = mHeaderIDMap.find(oldid); + if (iter3 != mHeaderIDMap.end() && iter3->second >= 0) + { + found_idx = iter3->second; + } + } + if (found_idx >= 0) + { + idx = found_idx; removeCachedTexture(oldid) ;//remove the existing cached texture to release the entry index. break; } @@ -1285,7 +1299,10 @@ bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 bool update_header = false ; if(entry.mImageSize < 0) //is a brand-new entry { - mHeaderIDMap[entry.mID] = idx; + { + LLMutexLock lock(&mHeaderIDMapMutex); + mHeaderIDMap[entry.mID] = idx; + } mTexturesSizeMap[entry.mID] = new_body_size ; mTexturesSizeTotal += new_body_size ; @@ -1323,8 +1340,8 @@ bool LLTextureCache::updateEntry(S32& idx, Entry& entry, S32 new_image_size, S32 U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries) { + LLMutexLock lock(&mHeaderIDMapMutex); U32 num_entries = mHeaderEntriesInfo.mEntries; - mHeaderIDMap.clear(); mTexturesSizeMap.clear(); mFreeList.clear(); @@ -1618,7 +1635,10 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) LLFile::rmdir(mTexturesDirName); } } - mHeaderIDMap.clear(); + { + LLMutexLock lock(&mHeaderIDMapMutex); + mHeaderIDMap.clear(); + } mTexturesSizeMap.clear(); mTexturesSizeTotal = 0; mFreeList.clear(); @@ -1665,6 +1685,7 @@ void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec) { if (iter1->second > 0) { + LLMutexLock lock(&mHeaderIDMapMutex); id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first); if (iter2 != mHeaderIDMap.end()) { @@ -1706,8 +1727,13 @@ void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec) Entry entry = mPurgeEntryList.back().second; mPurgeEntryList.pop_back(); // make sure record is still valid - id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID); - if (iter_header != mHeaderIDMap.end() && iter_header->second == idx) + bool remove_entry = false; + { + LLMutexLock lock(&mHeaderIDMapMutex); + id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID); + remove_entry = (iter_header != mHeaderIDMap.end() && iter_header->second == idx); + } + if (remove_entry) { std::string tex_filename = getTextureFileName(entry.mID); removeEntry(idx, entry, tex_filename); @@ -1750,6 +1776,7 @@ void LLTextureCache::purgeTextures(bool validate) { if (iter1->second > 0) { + LLMutexLock lock(&mHeaderIDMapMutex); id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first); if (iter2 != mHeaderIDMap.end()) { @@ -2004,7 +2031,7 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d { U32 offset; { - LLMutexLock lock(&mHeaderMutex); + LLMutexLock lock(&mHeaderIDMapMutex); id_map_t::const_iterator iter = mHeaderIDMap.find(id); if(iter == mHeaderIDMap.end()) { @@ -2018,9 +2045,10 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d U8* data; S32 head[4]; { + LL_PROFILE_ZONE_NAMED("Read fast cache"); LLMutexLock lock(&mFastCacheMutex); - openFastCache(); + openFastCache(); // only reopens if needed, lasts 10 seconds mFastCachep->seek(APR_SET, offset); @@ -2051,7 +2079,9 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d closeFastCache(); } - LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true); + + // directly construct image from new buffer. + LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true /*take ownership*/); return raw; } @@ -2229,7 +2259,10 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id) mTexturesSizeTotal -= mTexturesSizeMap[id] ; mTexturesSizeMap.erase(id); } - mHeaderIDMap.erase(id); + { + LLMutexLock lock(&mHeaderIDMapMutex); + mHeaderIDMap.erase(id); + } // We are inside header's mutex so mHeaderAPRFilePoolp is safe to use, // but getLocalAPRFilePool() is not safe, it might be in use by worker LLAPRFile::remove(getTextureFileName(id), mHeaderAPRFilePoolp); @@ -2260,7 +2293,10 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename) entry.mImageSize = -1; entry.mBodySize = 0; - mHeaderIDMap.erase(entry.mID); + { + LLMutexLock lock(&mHeaderIDMapMutex); + mHeaderIDMap.erase(entry.mID); + } mTexturesSizeMap.erase(entry.mID); mFreeList.insert(idx); } diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index faf722dc8f..a09bcc1572 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -148,7 +148,7 @@ public: U32 getMaxEntries() { return sCacheMaxEntries; }; bool isInCache(const LLUUID& id) ; bool isInLocal(const LLUUID& id) ; //not thread safe at the moment - + LLMutex* getFastCacheMutex() { return &mFastCacheMutex; } protected: // Accessed by LLTextureCacheWorker std::string getLocalFileName(const LLUUID& id); @@ -194,6 +194,7 @@ private: // Internal LLMutex mWorkersMutex; LLMutex mHeaderMutex; + LLMutex mHeaderIDMapMutex; // To avoid deadlocks, never lock mFastCacheMutex after mHeaderIDMapMutex. LLMutex mListMutex; LLMutex mFastCacheMutex; LLAPRFile* mHeaderAPRFile; diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp index 25dc0982b8..55e178e084 100644 --- a/indra/newview/lltoastscriptquestion.cpp +++ b/indra/newview/lltoastscriptquestion.cpp @@ -48,7 +48,12 @@ bool LLToastScriptQuestion::postBuild() LLTextBox* mFooter = getChild<LLTextBox>("bottom_info_message"); mMessage->setValue(mNotification->getMessage()); - mFooter->setValue(mNotification->getFooter()); + std::string footer = mNotification->getFooter(); + mFooter->setValue(footer); + if (footer.empty()) + { + mFooter->setVisible(false); + } snapToMessageHeight(); @@ -78,21 +83,69 @@ void LLToastScriptQuestion::snapToMessageHeight() if (mMessage->getVisible() && mFooter->getVisible()) { - S32 heightDelta = 0; - S32 maxTextHeight = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) + S32 height_delta = 0; + S32 max_text_height = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT) + (mFooter->getFont()->getLineHeight() * MAX_LINES_COUNT); - LLRect messageRect = mMessage->getRect(); - LLRect footerRect = mFooter->getRect(); + LLRect message_rect = mMessage->getRect(); + + S32 old_message_height = message_rect.getHeight(); + S32 new_message_height = mMessage->getTextBoundingRect().getHeight(); + S32 new_footer_height = mFooter->getTextBoundingRect().getHeight(); + + constexpr S32 FOOTER_PADDING = 8; // new height should include padding for newly added footer + S32 required_text_height = new_message_height + new_footer_height + FOOTER_PADDING; + S32 new_text_height = llmin(required_text_height, max_text_height); + + // Footer was invisible, so use old_message_height for old height + height_delta = new_text_height - old_message_height; + + reshape( getRect().getWidth(), llmax(getRect().getHeight() + height_delta, MIN_PANEL_HEIGHT)); + + // Floater was resized, now resize and shift children + // Message follows top, so it's top is in a correct position, but needs to be resized down + S32 message_delta = new_message_height - old_message_height; + message_rect = mMessage->getRect(); // refresh since it might have changed after reshape + message_rect.mBottom = message_rect.mBottom - message_delta; + mMessage->setRect(message_rect); + mMessage->needsReflow(); + // Button panel should stay the same size, just translate it + LLPanel* panel = getChild<LLPanel>("buttons_panel"); + panel->translate(0, -message_delta); + // Footer should be both moved and resized + LLRect footer_rect = mFooter->getRect(); + footer_rect.mTop = footer_rect.mTop - message_delta; + footer_rect.mBottom = footer_rect.mTop - new_footer_height; + mFooter->setRect(footer_rect); + mFooter->needsReflow(); + } + else if (mMessage->getVisible()) + { + S32 height_delta = 0; + S32 max_text_height = (mMessage->getFont()->getLineHeight() * MAX_LINES_COUNT); + + LLRect message_rect = mMessage->getRect(); + + S32 old_message_height = message_rect.getHeight(); + S32 new_message_height = mMessage->getTextBoundingRect().getHeight(); - S32 oldTextHeight = messageRect.getHeight() + footerRect.getHeight(); + S32 new_text_height = llmin(new_message_height, max_text_height); - S32 requiredTextHeight = mMessage->getTextBoundingRect().getHeight() + mFooter->getTextBoundingRect().getHeight(); - S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); + // Footer was invisible, so use old_message_height for old height + height_delta = new_text_height - old_message_height; - heightDelta = newTextHeight - oldTextHeight - heightDelta; + reshape(getRect().getWidth(), llmax(getRect().getHeight() + height_delta, MIN_PANEL_HEIGHT)); - reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); + // Floater was resized, now resize and shift children + // Message follows top, so it's top is in a correct position, but needs to be resized down + S32 message_delta = new_message_height - old_message_height; + message_rect = mMessage->getRect(); // refresh since it might have changed after reshape + message_rect.mBottom = message_rect.mBottom - message_delta; + mMessage->setRect(message_rect); + mMessage->needsReflow(); + // Button panel should stay the same size, just translate it + LLPanel* panel = getChild<LLPanel>("buttons_panel"); + panel->translate(0, -message_delta); } } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8b4b508d7c..0c93b24751 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -813,6 +813,7 @@ void setting_setup_signal_listener(LLControlGroup& group, const std::string& set void settings_setup_listeners() { + LL_PROFILE_ZONE_SCOPED; setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 35ac7919ac..9dfa9a0efd 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -576,9 +576,9 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot) LLImageGL::updateStats(gFrameTimeSeconds); static LLCachedControl<S32> avatar_name_tag_mode(gSavedSettings, "AvatarNameTagMode", 1); - static LLCachedControl<bool> name_tag_show_group_titles(gSavedSettings, "NameTagShowGroupTitles", true); + static LLCachedControl<S32> name_tag_show_group_titles(gSavedSettings, "GroupTitlesTagMode", 2 /*all group tags*/); LLVOAvatar::sRenderName = avatar_name_tag_mode; - LLVOAvatar::sRenderGroupTitles = name_tag_show_group_titles && avatar_name_tag_mode > 0; + LLVOAvatar::sRenderGroupTitles = avatar_name_tag_mode > 0 ? name_tag_show_group_titles : 0; gPipeline.mBackfaceCull = true; gFrameCount++; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index ab5235c3ad..82fc4c6d87 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -44,7 +44,6 @@ #include "llfloateravatarrendersettings.h" #include "llfloateravatartextures.h" #include "llfloaterbanduration.h" -#include "llfloaterbigpreview.h" #include "llfloaterbeacons.h" #include "llfloaterbuildoptions.h" #include "llfloaterbulkpermission.h" @@ -120,7 +119,6 @@ #include "llfloaterpay.h" #include "llfloaterperformance.h" #include "llfloaterperms.h" -#include "llfloaterpostprocess.h" #include "llfloaterpreference.h" #include "llfloaterpreferencesgraphicsadvanced.h" #include "llfloaterpreferenceviewadvanced.h" @@ -143,7 +141,6 @@ #include "llfloatersidepanelcontainer.h" #include "llfloaterslapptest.h" #include "llfloatersnapshot.h" -#include "llfloatersounddevices.h" #include "llfloaterspellchecksettings.h" #include "llfloatertelehub.h" #include "llfloatertestinspectors.h" @@ -154,7 +151,6 @@ #include "llfloatertoybox.h" #include "llfloatertranslationsettings.h" #include "llfloateruipreview.h" -#include "llfloatervoiceeffect.h" #include "llfloaterwebcontent.h" #include "llfloatervoicevolume.h" #include "llfloaterwhitelistentry.h" @@ -370,7 +366,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("emoji_picker", "floater_emoji_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiPicker>); LLFloaterReg::add("emoji_complete", "floater_emoji_complete.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEmojiComplete>); - LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>); LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>); LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>); @@ -499,7 +494,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater); LLFloaterReg::add("settings_color", "floater_settings_color.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsColor>); LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>); - LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>); LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>); LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>); @@ -512,8 +506,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>); LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSLappTest>); - LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>); - LLFloaterUIPreviewUtil::registerFloater(); LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload"); LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload"); @@ -522,8 +514,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("upload_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptPreview>, "upload"); LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload"); - LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>); - LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>); LLFloaterReg::add("window_size", "floater_window_size.xml", &LLFloaterReg::build<LLFloaterWindowSize>); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f29760c824..dbcf4fbbf4 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -140,7 +140,7 @@ #include "llwindow.h" #include "llpathfindingmanager.h" #include "llstartup.h" -#include "boost/unordered_map.hpp" +#include <unordered_map> #include <boost/regex.hpp> #include <boost/algorithm/string.hpp> #include <boost/json.hpp> @@ -153,7 +153,7 @@ using namespace LLAvatarAppearanceDefines; typedef LLPointer<LLViewerObject> LLViewerObjectPtr; -static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels; +static std::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels; LLVOAvatar* find_avatar_from_object(LLViewerObject* object); LLVOAvatar* find_avatar_from_object(const LLUUID& object_id); @@ -413,7 +413,23 @@ static LLSLMMenuUpdater* gSLMMenuUpdater = NULL; LLSLMMenuUpdater::LLSLMMenuUpdater() { - mMarketplaceListingsItem = gMenuHolder->getChild<LLView>("MarketplaceListings")->getHandle(); + LLView* me_menu = gMenuHolder->findChild<LLView>("Me"); + if (!me_menu) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Me' menu in 'menu_viewer'" << LL_ENDL; + return; + } + + LLView* marketplace_listings = me_menu->findChild<LLView>("MarketplaceListings"); + if (!marketplace_listings) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'MarketplaceListings' in 'Me' menu" << LL_ENDL; + return; + } + + mMarketplaceListingsItem = marketplace_listings->getHandle(); } void LLSLMMenuUpdater::setMerchantMenu() { @@ -473,6 +489,8 @@ void check_merchant_status(bool force) void init_menus() { + LL_PROFILE_ZONE_SCOPED; + // Initialize actions initialize_menus(); @@ -549,7 +567,29 @@ void init_menus() color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); } - LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder"); + LLView* menu_stack = gViewerWindow->getMainView()->findChildView("menu_stack"); + if (!menu_stack) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find menu_stack in main_view" << LL_ENDL; + return; + } + + LLView* status_bar_container = menu_stack->findChildView("status_bar_container"); + if (!status_bar_container) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find status_bar_container in main_view" << LL_ENDL; + return; + } + + LLView* menu_bar_holder = status_bar_container->findChildView("menu_bar_holder"); + if (!menu_bar_holder) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find status_bar_container in main_view" << LL_ENDL; + return; + } gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT)); @@ -563,8 +603,33 @@ void init_menus() // *TODO:Also fix cost in llfolderview.cpp for Inventory menus const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str); - gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str); + + LLView* main_upload_menu = gMenuHolder->findChild<LLView>("Upload"); + if (!main_upload_menu) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Upload' menu in 'menu_viewer'" << LL_ENDL; + return; + } + + LLView* upload_sound = main_upload_menu->findChild<LLView>("Upload Sound"); + if (!upload_sound) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Upload Sound' menu item in 'Upload' menu" << LL_ENDL; + return; + } + upload_sound->setLabelArg("[COST]", sound_upload_cost_str); + + LLView* upload_anim = main_upload_menu->findChild<LLView>("Upload Animation"); + if (!upload_anim) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Can't find 'Upload Animation' menu item in 'Upload' menu" << LL_ENDL; + return; + } + upload_anim->setLabelArg("[COST]", animation_upload_cost_str); + gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", true); gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", true); @@ -572,13 +637,6 @@ void init_menus() gDetachAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach", true); gDetachHUDAvatarMenu = gMenuHolder->getChild<LLMenuGL>("Avatar Detach HUD", true); - // Don't display the Memory console menu if the feature is turned off - LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", true); - if (memoryMenu) - { - memoryMenu->setVisible(false); - } - gMenuBarView->createJumpKeys(); // Let land based option enable when parcel changes @@ -2959,11 +3017,45 @@ void handle_object_show_original() show_item_original(object->getAttachmentItemID()); } +void handle_object_set_favorite(const LLSD& userdata) +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) + { + return; + } + LLViewerObject *parent = (LLViewerObject*)object->getParent(); + while (parent) + { + if(parent->isAvatar()) + { + break; + } + object = parent; + parent = (LLViewerObject*)parent->getParent(); + } + if (!object || object->isAvatar()) + { + return; + } + + LLUUID item_id = gInventory.getLinkedItemID(object->getAttachmentItemID()); + + std::string action = userdata.asString(); + if (action == "Add") + { + set_favorite(item_id, true); + } + if (action == "Remove") + { + set_favorite(item_id, false); + } +} static void init_default_item_label(LLUICtrl* ctrl) { const std::string& item_name = ctrl->getName(); - boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); + std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); if (it == sDefaultItemLabels.end()) { // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value @@ -2979,7 +3071,7 @@ static void init_default_item_label(LLUICtrl* ctrl) static LLStringExplicit get_default_item_label(const std::string& item_name) { LLStringExplicit res(""); - boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); + std::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); if (it != sDefaultItemLabels.end()) { res = it->second; @@ -3015,6 +3107,41 @@ bool enable_object_touch(LLUICtrl* ctrl) return new_value; }; +bool enable_object_favorite(const LLSD& userdata) +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) + { + return false; + } + LLViewerObject* parent = (LLViewerObject*)object->getParent(); + while (parent) + { + if (parent->isAvatar()) + { + break; + } + object = parent; + parent = (LLViewerObject*)parent->getParent(); + } + if (!object || object->isAvatar()) + { + return false; + } + + std::string action = userdata.asString(); + LLUUID item_id = gInventory.getLinkedItemID(object->getAttachmentItemID()); + if (action == "Add") + { + return !get_is_favorite(item_id); + } + if (action == "Remove") + { + return get_is_favorite(item_id); + } + return false; +} + //void label_touch(std::string& label, void*) //{ // LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); @@ -6666,11 +6793,8 @@ class LLAvatarEnableResetSkeleton : public view_listener_t { bool handleEvent(const LLSD& userdata) { - if (LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())) - { - return true; - } - return false; + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + return obj && obj->getAvatar(); } }; @@ -8715,6 +8839,12 @@ LLVOAvatar* find_avatar_from_object(LLViewerObject* object) } else if( !object->isAvatar() ) { + // Check for animesh objects (animated objects with a control avatar) + LLVOAvatar* avatar = object->getAvatar(); + if (avatar) + { + return avatar; + } object = NULL; } } @@ -9496,17 +9626,6 @@ class LLWorldEnableEnvPreset : public view_listener_t } }; - -/// Post-Process callbacks -class LLWorldPostProcess : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloaterReg::showInstance("env_post_process"); - return true; - } -}; - class LLWorldCheckBanLines : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -9689,6 +9808,8 @@ void initialize_spellcheck_menu() void initialize_menus() { + LL_PROFILE_ZONE_SCOPED; + // A parameterized event handler used as ctrl-8/9/0 zoom controls below. class LLZoomer : public view_listener_t { @@ -9798,7 +9919,6 @@ void initialize_menus() view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings"); view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset"); view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset"); - view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess"); view_listener_t::addMenu(new LLWorldCheckBanLines() , "World.CheckBanLines"); view_listener_t::addMenu(new LLWorldShowBanLines() , "World.ShowBanLines"); @@ -10110,6 +10230,7 @@ void initialize_menus() view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); commit.add("Object.Touch", boost::bind(&handle_object_touch)); commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); + commit.add("Object.SetFavorite", boost::bind(&handle_object_set_favorite, _2)); commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); commit.add("Object.Delete", boost::bind(&handle_object_delete)); view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); @@ -10138,6 +10259,7 @@ void initialize_menus() enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material)); enable.add("Object.EnableOpen", boost::bind(&enable_object_open)); enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1)); + enable.add("Object.EnableFavorites", boost::bind(&enable_object_favorite, _2)); enable.add("Object.EnableDelete", boost::bind(&enable_object_delete)); enable.add("Object.EnableWear", boost::bind(&object_is_wearable)); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 36e8e27800..5d8bd45218 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5749,28 +5749,40 @@ void process_script_question(LLMessageSystem *msg, void **user_data) args["NAME"] = clean_owner_name; S32 known_questions = 0; bool has_not_only_debit = questions ^ SCRIPT_PERMISSIONS[SCRIPT_PERMISSION_DEBIT].permbit; + bool caution_enabled = gSavedSettings.getBOOL("PermissionsCautionEnabled"); // check the received permission flags against each permission + std::string warning_msg; for (const script_perm_t& script_perm : SCRIPT_PERMISSIONS) { if (questions & script_perm.permbit) { - count++; known_questions |= script_perm.permbit; // check whether permission question should cause special caution dialog caution |= (script_perm.caution); - if (("ScriptTakeMoney" == script_perm.question) && has_not_only_debit) + // Cautions go into top part of the dialog, questions go into the footer + if (caution_enabled && script_perm.caution) + { + warning_msg += "\n" + LLTrans::getString(script_perm.question + "Caution") + "\n"; continue; + } if (LLTrans::getString(script_perm.question).empty()) { continue; } - script_question += " " + LLTrans::getString(script_perm.question) + "\n"; + count++; + script_question += "\n " + LLTrans::getString(script_perm.question); } } + if (!warning_msg.empty()) + { + LLStringUtil::format(warning_msg, args); + args["WARNINGS"] = warning_msg; + } + args["QUESTIONS"] = script_question; if (known_questions != questions) @@ -5795,12 +5807,12 @@ void process_script_question(LLMessageSystem *msg, void **user_data) // check whether cautions are even enabled or not const char* notification = "ScriptQuestion"; - if(caution && gSavedSettings.getBOOL("PermissionsCautionEnabled")) + if(caution && caution_enabled) { - args["FOOTERTEXT"] = (count > 1) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n\n" + script_question : ""; + args["FOOTERTEXT"] = (count > 0) ? LLTrans::getString("AdditionalPermissionsRequestHeader") + "\n" + script_question : ""; notification = "ScriptQuestionCaution"; } - else if(experienceid.notNull()) + else if (experienceid.notNull()) { payload["experience"]=experienceid; LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index dfb0521167..db1ef54ffa 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4650,9 +4650,10 @@ const LLQuaternion LLViewerObject::getRenderRotation() const } else { - if (!mDrawable->isRoot()) + LLDrawable* parent = mDrawable->getParent(); + if (!mDrawable->isRoot() && parent) { - ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix()); + ret = getRotation() * LLQuaternion(parent->getWorldMatrix()); } else { diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 50edb408c7..34e5cc9de8 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -174,7 +174,7 @@ bool LLViewerObjectList::removeFromLocalIDTable(LLViewerObject* objectp) U32 local_id = objectp->mLocalID; U64 indexid = (((U64)objectp->mRegionIndex) << 32) | (U64)local_id; - std::map<U64, LLUUID>::iterator iter = mIndexAndLocalIDToUUID.find(indexid); + auto iter = mIndexAndLocalIDToUUID.find(indexid); if (iter == mIndexAndLocalIDToUUID.end()) { return false; diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 547ef9fb2d..adc90a0483 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -204,7 +204,7 @@ protected: uuid_set_t mDeadObjects; - std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap; + std::unordered_map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap; //set of objects that need to update their cost uuid_set_t mStaleObjectCost; @@ -221,7 +221,7 @@ protected: static U32 sSimulatorMachineIndex; std::map<U64, U32> mIPAndPortToIndex; - std::map<U64, LLUUID> mIndexAndLocalIDToUUID; + std::unordered_map<U64, LLUUID> mIndexAndLocalIDToUUID; friend class LLViewerObject; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 6a029645fb..b794047135 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -702,6 +702,16 @@ bool LLViewerParcelMgr::allowAgentVoice() const return allowAgentVoice(gAgent.getRegion(), mAgentParcel); } +bool LLViewerParcelMgr::isVoiceRestricted() const +{ + return mAgentParcel && !mAgentParcel->getParcelFlagUseEstateVoiceChannel(); +} + +bool LLViewerParcelMgr::allowVoiceModeration() const +{ + return isVoiceRestricted() && isParcelOwnedByAgent(mAgentParcel, GP_SESSION_MODERATOR); +} + bool LLViewerParcelMgr::allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const { return region && region->isVoiceEnabled() diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 8439283eb0..0d79496ccc 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -174,6 +174,12 @@ public: bool allowAgentVoice() const; bool allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const; + // Returns true if this parcel is using private voice channel + bool isVoiceRestricted() const; + + // Can this agent moderate Nearby voice chat on this parcel? + bool allowVoiceModeration() const; + // Can this agent start flying on this parcel? // Used for parcel property icons in nav bar. bool allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const; diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index f6ee00cb25..d33d426769 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -126,8 +126,6 @@ #include "llfloater.h" #include <boost/signals2.hpp> -#include <boost/unordered_set.hpp> -#include <boost/unordered_map.hpp> #include <boost/json.hpp> #include "glm/glm.hpp" diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index cd70f8f9b9..f31befd1ab 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -104,7 +104,7 @@ S32 LLViewerRegion::sLastCameraUpdated = 0; S32 LLViewerRegion::sNewObjectCreationThrottle = -1; LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup; -typedef std::map<std::string, std::string> CapabilityMap; +typedef std::unordered_map<std::string, std::string, ll::string_hash, std::equal_to<>> CapabilityMap; static void log_capabilities(const CapabilityMap &capmap); @@ -3300,6 +3300,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("SetDisplayName"); capabilityNames.append("SimConsoleAsync"); capabilityNames.append("SimulatorFeatures"); + capabilityNames.append("SpatialVoiceModerationRequest"); capabilityNames.append("StartGroupProposal"); capabilityNames.append("TerrainNavMeshProperties"); capabilityNames.append("TextureStats"); @@ -3437,7 +3438,7 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri } } -std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const +std::string LLViewerRegion::getCapabilityDebug(std::string_view name) const { CapabilityMap::const_iterator iter = mImpl->mSecondCapabilitiesTracker.find(name); if (iter == mImpl->mSecondCapabilitiesTracker.end()) @@ -3448,15 +3449,14 @@ std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const return iter->second; } - -bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) +bool LLViewerRegion::isSpecialCapabilityName(std::string_view name) { return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; } -std::string LLViewerRegion::getCapability(const std::string& name) const +std::string LLViewerRegion::getCapability(std::string_view name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + if (!capabilitiesReceived() && (name != "Seed") && (name != "ObjectMedia")) { LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL; } @@ -3464,21 +3464,20 @@ std::string LLViewerRegion::getCapability(const std::string& name) const CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); if(iter == mImpl->mCapabilities.end()) { - return ""; + return {}; } return iter->second; } -bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const +bool LLViewerRegion::isCapabilityAvailable(std::string_view name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + if (!capabilitiesReceived() && (name != "Seed") && (name != "ObjectMedia")) { LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL; } - CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); - if(iter == mImpl->mCapabilities.end()) + if (!mImpl->mCapabilities.contains(name)) { return false; } @@ -3734,9 +3733,14 @@ bool LLViewerRegion::avatarHoverHeightEnabled() const void log_capabilities(const CapabilityMap &capmap) { + // Copy into sorted map for ordered output + using SortedCapabilityMap = std::map<std::string, std::string>; + SortedCapabilityMap sorted_capmap; + sorted_capmap.insert(capmap.begin(), capmap.end()); + S32 count = 0; - CapabilityMap::const_iterator iter; - for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count) + SortedCapabilityMap::const_iterator iter; + for (iter = sorted_capmap.begin(); iter != sorted_capmap.end(); ++iter, ++count) { if (!iter->second.empty()) { @@ -3797,6 +3801,16 @@ std::string LLViewerRegion::getSimHostName() return std::string("..."); } + +bool LLViewerRegion::isRegionWebRTCEnabled() +{ + if (mSimulatorFeaturesReceived && mSimulatorFeatures.has("VoiceServerType")) + { + return mSimulatorFeatures["VoiceServerType"].asString() == "webrtc"; + } + return false; +} + void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index b3ec857907..f1eb335582 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -274,10 +274,10 @@ public: S32 getNumSeedCapRetries(); void setCapability(const std::string& name, const std::string& url); void setCapabilityDebug(const std::string& name, const std::string& url); - bool isCapabilityAvailable(const std::string& name) const; + bool isCapabilityAvailable(std::string_view name) const; // implements LLCapabilityProvider - virtual std::string getCapability(const std::string& name) const; - std::string getCapabilityDebug(const std::string& name) const; + virtual std::string getCapability(std::string_view name) const; + std::string getCapabilityDebug(std::string_view name) const; // has region received its final (not seed) capability list? @@ -287,7 +287,7 @@ public: void setCapabilitiesError(); boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); - static bool isSpecialCapabilityName(const std::string &name); + static bool isSpecialCapabilityName(std::string_view name); void logActiveCapabilities() const; // Utilities to post and get via @@ -424,6 +424,8 @@ public: std::string getSimHostName(); + bool isRegionWebRTCEnabled(); + static bool isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;} // rebuild reflection probe list diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index d39d466205..db6d83db5f 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -263,6 +263,20 @@ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > HUDS_FRAME_PCT("huds_ LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > UI_FRAME_PCT("ui_frame_pct"); LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > SWAP_FRAME_PCT("swap_frame_pct"); LLTrace::SampleStatHandle<LLUnit<F32, LLUnits::Percent> > IDLE_FRAME_PCT("idle_frame_pct"); + + + +LLTrace::SampleStatHandle<U32> WEBRTC_PACKETS_IN_LOST("webrtc_packets_in_lost", "Lost incoming packets"), + WEBRTC_PACKETS_IN_RECEIVED("webrtc_packets_in_recv", "Incoming packets received"), + WEBRTC_PACKETS_OUT_SENT("webrtc_packets_out_sent", "Outgoing packets sent"), + WEBRTC_PACKETS_OUT_LOST("webrtc_packets_out_lost", "Lost outgoing packets"); + +LLTrace::SampleStatHandle<F32> WEBRTC_JITTER_OUT("webrtc_jitter_out", "Timing variation of outgoing audio"), + WEBRTC_JITTER_IN("webrtc_jitter_in", "Timing variation of incoming audio"), + WEBRTC_LATENCY("webrtc_latency", "Round-trip audio delay"), + WEBRTC_UPLOAD_BANDWIDTH("webrtc_upload_bandwidth", "Estimated upload bandwidth"), + WEBRTC_JITTER_BUFFER("webrtc_jitter_buffer", "Average delay added to smooth incoming audio"); + } LLViewerStats::LLViewerStats() diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 1ac8b2f66b..8ec0dd0024 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -232,6 +232,9 @@ extern LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT extern LLTrace::SampleStatHandle<F64> NOTRMALIZED_FRAMETIME_JITTER_SESSION; extern LLTrace::SampleStatHandle<F64> NORMALIZED_FRAMTIME_JITTER_PERIOD; +extern LLTrace::SampleStatHandle<U32> WEBRTC_PACKETS_IN_LOST, WEBRTC_PACKETS_IN_RECEIVED, WEBRTC_PACKETS_OUT_SENT, WEBRTC_PACKETS_OUT_LOST; +extern LLTrace::SampleStatHandle<F32> WEBRTC_JITTER_OUT, WEBRTC_JITTER_IN, WEBRTC_LATENCY, WEBRTC_UPLOAD_BANDWIDTH, WEBRTC_JITTER_BUFFER; + } class LLViewerStats : public LLSingleton<LLViewerStats> diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 1e83482752..0f23596c9a 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1488,7 +1488,9 @@ bool LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/) // from local images, but this might become unsafe in case of changes to fetcher if (mBoostLevel == BOOST_PREVIEW) { - mRawImage->biasedScaleToPowerOfTwo(1024); + // A local file with a preview flag likely means mesh's texture upload + // which should follow normal upload scaling rules + mRawImage->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); } else { // leave black border, do not scale image content @@ -1896,12 +1898,10 @@ bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 curre mRawDiscardLevel = INVALID_DISCARD_LEVEL; mIsFetching = false; mLastPacketTimer.reset(); + return false; } - else - { - mIsRawImageValid = true; - addToCreateTexture(); - } + + mIsRawImageValid = true; if (mBoostLevel == LLGLTexture::BOOST_ICON) { @@ -1914,7 +1914,11 @@ bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 curre // // BOOST_ICON gets scaling because profile icons can have a bunch of different formats, not just j2c // Might need another pass to use discard for j2c and scaling for everything else. - mRawImage = mRawImage->scaled(expected_width, expected_height); + LLPointer<LLImageRaw> scaled = mRawImage->scaled(expected_width, expected_height); + if (scaled.notNull()) + { + mRawImage = scaled; + } } } @@ -1929,10 +1933,16 @@ bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 curre // // Todo: probably needs to be remade to use discard, all thumbnails are supposed to be j2c, // so no need to scale, should be posible to use discard to scale image down. - mRawImage = mRawImage->scaled(expected_width, expected_height); + LLPointer<LLImageRaw> scaled = mRawImage->scaled(expected_width, expected_height); + if (scaled.notNull()) + { + mRawImage = scaled; + } } } + addToCreateTexture(); + return true; } else @@ -2574,14 +2584,31 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() S32 best_raw_discard = gl_discard; // Current GL quality level S32 current_aux_discard = MAX_DISCARD_LEVEL + 1; S32 best_aux_discard = MAX_DISCARD_LEVEL + 1; + LLImageRaw *current_raw_image = nullptr; if (mIsRawImageValid) { - // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels. + // If we have an existing raw image, we have a baseline for the raw + // and auxiliary quality levels. + // Note: we call updateImagesCreateTextures before callbacks, which + // leads to destroyRawImage and deletes raw image. So this case + // might be rare or even never trigger as there is never a raw image, + // only a saved one. current_raw_discard = mRawDiscardLevel; best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel); best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw current_aux_discard = llmin(current_aux_discard, best_aux_discard); + current_raw_image = mRawImage; + } + else if (mSavedRawImage.notNull()) + { + // We have a saved raw image, we can use that as our baseline for + // raw and auxiliary quality levels. + current_raw_discard = mSavedRawDiscardLevel; + best_raw_discard = llmin(best_raw_discard, mSavedRawDiscardLevel); + best_aux_discard = llmin(best_aux_discard, mSavedRawDiscardLevel); // We always decode the aux when we decode the base raw + current_aux_discard = llmin(current_aux_discard, best_aux_discard); + current_raw_image = mSavedRawImage; } else { @@ -2646,12 +2673,17 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() if (need_readback) { readbackRawImage(); + if (mIsRawImageValid) + { + current_raw_discard = mRawDiscardLevel; + current_raw_image = mRawImage; + } } // // Run raw/auxiliary data callbacks // - if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel())) + if (run_raw_callbacks && current_raw_image != nullptr && (current_raw_discard <= getMaxDiscardLevel())) { // Do callbacks which require raw image data. //LL_INFOS() << "doLoadedCallbacks raw for " << getID() << LL_ENDL; @@ -2662,7 +2694,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() { callback_list_t::iterator curiter = iter++; LLLoadedCallbackEntry *entryp = *curiter; - if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel)) + if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > current_raw_discard)) { // If we've loaded all the data there is to load or we've loaded enough // to satisfy the interested party, then this is the last time that @@ -2673,11 +2705,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() { LL_WARNS() << "Raw Image with no Aux Data for callback" << LL_ENDL; } - bool final = mRawDiscardLevel <= entryp->mDesiredDiscard; + bool final = current_raw_discard <= entryp->mDesiredDiscard; //LL_INFOS() << "Running callback for " << getID() << LL_ENDL; - //LL_INFOS() << mRawImage->getWidth() << "x" << mRawImage->getHeight() << LL_ENDL; - entryp->mLastUsedDiscard = mRawDiscardLevel; - entryp->mCallback(true, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData); + //LL_INFOS() << current_raw_image->getWidth() << "x" << current_raw_image->getHeight() << LL_ENDL; + entryp->mLastUsedDiscard = current_raw_discard; + entryp->mCallback(true, this, current_raw_image, mAuxRawImage, current_raw_discard, final, entryp->mUserData); if (final) { iter = mLoadedCallbackList.erase(curiter); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 11ca3098fd..96962bbeae 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1191,15 +1191,19 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time) LLTimer timer; image_list_t::iterator enditer = mFastCacheList.begin(); - for (image_list_t::iterator iter = mFastCacheList.begin(); - iter != mFastCacheList.end();) { - image_list_t::iterator curiter = iter++; - enditer = iter; - LLViewerFetchedTexture *imagep = *curiter; - imagep->loadFromFastCache(); - if (timer.getElapsedTimeF32() > max_time) - break; + // prelock fast cache mutex to avoid waiting multiple times. + LLMutexLock cache_lock(LLAppViewer::getTextureCache()->getFastCacheMutex()); + for (image_list_t::iterator iter = mFastCacheList.begin(); + iter != mFastCacheList.end();) + { + image_list_t::iterator curiter = iter++; + enditer = iter; + LLViewerFetchedTexture* imagep = *curiter; + imagep->loadFromFastCache(); + if (timer.getElapsedTimeF32() > max_time) + break; + } } mFastCacheList.erase(mFastCacheList.begin(), enditer); return timer.getElapsedTimeF32(); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 583fb25330..50af9756a3 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -96,6 +96,7 @@ LLViewerWearable::~LLViewerWearable() // virtual LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; // suppress texlayerset updates while wearables are being imported. Layersets will be updated // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. LLOverrideBakedTextureUpdate stop_bakes(false); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ee7b1fb693..8695b96952 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2075,10 +2075,6 @@ void LLViewerWindow::initGLDefaults() gBox.prerender(); } -struct MainPanel : public LLPanel -{ -}; - void LLViewerWindow::initBase() { S32 height = getWindowHeightScaled(); @@ -2117,6 +2113,8 @@ void LLViewerWindow::initBase() main_view->setShape(full_window); getRootView()->addChild(main_view); + mMainView = main_view; + // placeholder widget that controls where "world" is rendered mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); mPopupView = main_view->getChild<LLPopupView>("popup_holder"); @@ -4920,6 +4918,19 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save if (image->save(filepath)) { playSnapshotAnimAndSound(); + + // Show clickable notification with filepath + LLSD args; + args["FILEPATH"] = filepath; + + LLSD payload; + payload["filepath"] = filepath; + + LLNotificationsUtil::add("SnapshotSavedToComputer", + args, + payload.with("respond_on_mousedown", true), + boost::bind(&LLViewerWindow::onSnapshotNotificationClick, _1, _2)); + success_cb(); } else @@ -4934,6 +4945,16 @@ void LLViewerWindow::resetSnapshotLoc() } // static +void LLViewerWindow::onSnapshotNotificationClick(const LLSD& notification, const LLSD& response) +{ + std::string filepath = notification["payload"]["filepath"].asString(); + if (!filepath.empty()) + { + gDirUtilp->openDir(filepath); + } +} + +// static void LLViewerWindow::movieSize(S32 new_width, S32 new_height) { LLCoordWindow size; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index f3c7ef3289..ec28a3fc4a 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -144,6 +144,10 @@ private: }; +struct MainPanel : public LLPanel +{ +}; + static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 7680; // max snapshot image size 7680 * 7680 UHDTV2 class LLViewerWindow : public LLWindowCallbacks @@ -248,6 +252,7 @@ public: // ACCESSORS // LLRootView* getRootView() const; + MainPanel* getMainView() const { return mMainView; } // 3D world area in scaled pixels (via UI scale), use for most UI computations LLRect getWorldViewRectScaled() const; @@ -405,6 +410,7 @@ public: void resetSnapshotLoc(); void playSnapshotAnimAndSound(); + static void onSnapshotNotificationClick(const LLSD& notification, const LLSD& response); // draws selection boxes around selected objects, must call displayObjects first void renderSelections( bool for_gl_pick, bool pick_parcel_walls, bool for_hud ); @@ -501,6 +507,7 @@ private: LLRect mWorldViewRectRaw; // area of screen for 3D world LLRect mWorldViewRectScaled; // area of screen for 3D world scaled by UI size LLRootView* mRootView; // a view of size mWindowRectRaw, containing all child views + MainPanel* mMainView; // a view of size mWindowRectRaw, directly containing the base elements of the ui tree LLView* mFloaterSnapRegion = nullptr; LLView* mNavBarContainer = nullptr; LLPanel* mStatusBarContainer = nullptr; diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp index c2bcd32921..f4c2c27cee 100644 --- a/indra/newview/llvlmanager.cpp +++ b/indra/newview/llvlmanager.cpp @@ -68,7 +68,11 @@ void LLVLManager::addLayerData(LLVLData *vl_datap, const S32Bytes mesg_size) } else { - LL_ERRS() << "Unknown layer type!" << (S32)vl_datap->mType << LL_ENDL; + // Corrupted message? New feature? + LL_WARNS() << "Unknown layer type!" << (S32)vl_datap->mType + << " for region " << vl_datap->mRegionp->getName() << LL_ENDL; + delete vl_datap; // addLayerData took ownership + return; } mPacketData.push_back(vl_datap); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 438f84d625..efb09479e2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -217,6 +217,13 @@ enum ERenderName RENDER_NAME_FADE }; +enum ERenderGroupTitle +{ + RENDER_GROUP_TITLE_NEVER, + RENDER_GROUP_TITLE_SELF, + RENDER_GROUP_TITLE_ALWAYS +}; + #define JELLYDOLLS_SHOULD_IMPOSTOR //----------------------------------------------------------------------------- @@ -607,7 +614,7 @@ const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = }; S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; -bool LLVOAvatar::sRenderGroupTitles = true; +S32 LLVOAvatar::sRenderGroupTitles = RENDER_GROUP_TITLE_ALWAYS; S32 LLVOAvatar::sNumVisibleChatBubbles = 0; bool LLVOAvatar::sDebugInvisible = false; bool LLVOAvatar::sShowAttachmentPoints = false; @@ -3552,9 +3559,10 @@ void LLVOAvatar::idleUpdateNameTagText(bool new_name) addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, LLFontGL::getFontSansSerifSmall()); } + bool render_title = (sRenderGroupTitles == RENDER_GROUP_TITLE_ALWAYS) || + (isSelf() && (sRenderGroupTitles == RENDER_GROUP_TITLE_SELF)); - if (sRenderGroupTitles - && title && title->getString() && title->getString()[0] != '\0') + if (render_title && title && title->getString() && title->getString()[0] != '\0') { std::string title_str = title->getString(); LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); @@ -11417,12 +11425,17 @@ void LLVOAvatar::calculateUpdateRenderComplexity() LLPerfStats::tunables.userFPSTuningStrategy != LLPerfStats::TUNE_SCENE_ONLY && !isVisuallyMuted()) { - LLUUID id = getID(); // <== use id to make sure this avatar didn't get deleted between frames - LL::WorkQueue::getInstance("mainloop")->post([this, id]() + const LLUUID id = getID(); // <== use id to make sure this avatar didn't get deleted between frames + LL::WorkQueue::getInstance("mainloop")->post([id]() { - if (gObjectList.findObject(id) != nullptr) + LLViewerObject* obj = gObjectList.findObject(id); + if (obj + && !obj->isDead() + && obj->isAvatar() + && obj->mDrawable) { - gPipeline.profileAvatar(this); + LLVOAvatar* avatar = (LLVOAvatar*)obj; + gPipeline.profileAvatar(avatar); } }); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 1e563c4869..fc3a97a25d 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -354,7 +354,7 @@ public: //-------------------------------------------------------------------- public: static S32 sRenderName; - static bool sRenderGroupTitles; + static S32 sRenderGroupTitles; static const U32 NON_IMPOSTORS_MAX_SLIDER; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors * slider in panel_preferences_graphics1.xml */ static U32 sMaxNonImpostors; // affected by control "RenderAvatarMaxNonImpostors" @@ -1120,7 +1120,7 @@ private: bool mNameFriend; bool mNameCloud; F32 mNameAlpha; - bool mRenderGroupTitles; + S32 mRenderGroupTitles; //-------------------------------------------------------------------- // Display the name (then optionally fade it out) diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 71a9e71a9f..2d732d0a71 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -39,6 +39,7 @@ #include "llagent.h" #include "lltrans.h" #include "lluiusage.h" +#include "llnearbyvoicemoderation.h" const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f; @@ -712,6 +713,13 @@ bool LLVoiceClient::getPTTIsToggle() void LLVoiceClient::inputUserControlState(bool down) { + if (down && !getUserPTTState()) + { + // Nearby chat is muted by moderator, don't toggle PTT + if (LLNearbyVoiceModeration::getInstance()->showNotificationIfNeeded()) + return; + } + if(mPTTIsToggle) { if(down) // toggle open-mic state on 'down' diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index d132cbfa36..107a08fdf8 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -1107,7 +1107,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() while (!sPump && !sShuttingDown) { // Can't use the pump until we have it available. - llcoro::suspend(); + llcoro::suspendUntilNextFrame(); } if (sShuttingDown) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 3a700423b3..2a0fdbfac1 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -61,10 +61,12 @@ #include "llrand.h" #include "llviewerwindow.h" #include "llviewercamera.h" +#include "llviewerstats.h" #include "llversioninfo.h" #include "llviewernetwork.h" #include "llnotificationsutil.h" +#include "llnearbyvoicemoderation.h" #include "llcorehttputil.h" #include "lleventfilter.h" @@ -80,6 +82,8 @@ const std::string WEBRTC_VOICE_SERVER_TYPE = "webrtc"; +const F32 STATS_TIMER_DELAY = 2.0; + namespace { const F32 MAX_AUDIO_DIST = 50.0f; @@ -2904,6 +2908,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() } mWebRTCAudioInterface->setReceiveVolume(mSpeakerVolume); LLWebRTCVoiceClient::getInstance()->OnConnectionEstablished(mChannelID, mRegionID); + resetConnectionStats(); setVoiceConnectionState(VOICE_STATE_WAIT_FOR_DATA_CHANNEL); break; } @@ -2957,6 +2962,13 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() sendJoin(); } } + + static LLTimer stats_timer; + if (stats_timer.getElapsedTimeF32() > STATS_TIMER_DELAY) + { + mWebRTCPeerConnectionInterface->gatherConnectionStats(); + stats_timer.reset(); + } } break; } @@ -3173,12 +3185,54 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b if (participant_obj.contains("m") && participant_obj["m"].is_bool()) { - participant->mIsModeratorMuted = participant_obj["m"].as_bool(); + bool is_moderator_muted = participant_obj["m"].as_bool(); + if (isSpatial()) + { + // ignore muted flags from non-primary server + if (mPrimary || primary) + { + participant->mIsModeratorMuted = is_moderator_muted; + if (gAgentID == agent_id) + { + LLNearbyVoiceModeration::getInstance()->setMutedInfo(mChannelID, is_moderator_muted); + } + } + } + else + { + participant->mIsModeratorMuted = is_moderator_muted; + } + } + } + } + else + { + if (isSpatial() && (mPrimary || primary)) + { + // mute info message can be received before join message, so try to mute again later + if (participant_obj.contains("m") && participant_obj["m"].is_bool()) + { + bool is_moderator_muted = participant_obj["m"].as_bool(); + std::string channel_id = mChannelID; + F32 delay { 1.5f }; + doAfterInterval( + [channel_id, agent_id, is_moderator_muted]() + { + LLWebRTCVoiceClient::participantStatePtr_t participant = + LLWebRTCVoiceClient::getInstance()->findParticipantByID(channel_id, agent_id); + if (participant) + { + participant->mIsModeratorMuted = is_moderator_muted; + if (gAgentID == agent_id) + { + LLNearbyVoiceModeration::getInstance()->setMutedInfo(channel_id, is_moderator_muted); + } + } + }, delay); } } } } - // tell the simulator to set the mute and volume data for this // participant, if there are any updates. boost::json::object root; @@ -3250,6 +3304,112 @@ void LLVoiceWebRTCConnection::sendJoin() mWebRTCDataInterface->sendData(json_data, false); } +void LLVoiceWebRTCConnection::OnStatsDelivered(const llwebrtc::LLWebRTCStatsMap& stats_data) +{ + LL::WorkQueue::postMaybe(mMainQueue, [=, this] + { + if (mShutDown) + { + return; + } + for (const auto& [stats_id, attributes] : stats_data) + { + if (attributes.contains("currentRoundTripTime")) + { + F32 rtt_seconds = 0.0f; + LLStringUtil::convertToF32(attributes.at("currentRoundTripTime"), rtt_seconds); + sample(LLStatViewer::WEBRTC_LATENCY, rtt_seconds * 1000.0f); + } + if (attributes.contains("availableOutgoingBitrate")) + { + F32 bitrate_bps = 0.0f; + LLStringUtil::convertToF32(attributes.at("availableOutgoingBitrate"), bitrate_bps); + sample(LLStatViewer::WEBRTC_UPLOAD_BANDWIDTH, bitrate_bps / 1000.0f); + } + + // Stat type detection below is heuristic-based. + // It's relied on specific fields to distinguish outbound-rtp, remote-inbound-rtp, and inbound-rtp. + // This approach works with current WebRTC stats but may need updating later. + + // Outbound RTP + if (attributes.contains("mediaSourceId")) + { + U32 out_packets_sent = 0; + LLStringUtil::convertToU32(attributes.at("packetsSent"), out_packets_sent); + sample(LLStatViewer::WEBRTC_PACKETS_OUT_SENT, out_packets_sent); + } + // Remote-Inbound RTP + else if (attributes.contains("localId")) + { + if (attributes.contains("packetsLost")) + { + U32 out_packets_lost = 0; + LLStringUtil::convertToU32(attributes.at("packetsLost"), out_packets_lost); + sample(LLStatViewer::WEBRTC_PACKETS_OUT_LOST, out_packets_lost); + } + if (attributes.contains("jitter")) + { + F32 jitter_seconds = 0.0f; + LLStringUtil::convertToF32(attributes.at("jitter"), jitter_seconds); + sample(LLStatViewer::WEBRTC_JITTER_OUT, jitter_seconds * 1000.0f); + } + } + // Inbound RTP + else if (attributes.contains("jitterBufferDelay")) + { + if (attributes.contains("packetsLost")) + { + U32 in_packets_lost = 0; + LLStringUtil::convertToU32(attributes.at("packetsLost"), in_packets_lost); + sample(LLStatViewer::WEBRTC_PACKETS_IN_LOST, in_packets_lost); + } + if (attributes.contains("packetsReceived")) + { + U32 in_packets_recv = 0; + LLStringUtil::convertToU32(attributes.at("packetsReceived"), in_packets_recv); + sample(LLStatViewer::WEBRTC_PACKETS_IN_RECEIVED, in_packets_recv); + } + if (attributes.contains("jitter")) + { + F32 jitter_seconds = 0.0f; + LLStringUtil::convertToF32(attributes.at("jitter"), jitter_seconds); + sample(LLStatViewer::WEBRTC_JITTER_IN, jitter_seconds * 1000.0f); + } + if (attributes.contains("jitterBufferDelay") && attributes.contains("jitterBufferEmittedCount")) + { + F32 total_delay_seconds = 0.0f; + F32 emitted_count_f = 0.0f; + + // total delay in seconds + LLStringUtil::convertToF32(attributes.at("jitterBufferDelay"), total_delay_seconds); + + // number of packets played out + LLStringUtil::convertToF32(attributes.at("jitterBufferEmittedCount"), emitted_count_f); + if (emitted_count_f > 0.0f) + { + F32 avg_delay_seconds = total_delay_seconds / emitted_count_f; + F32 avg_delay_ms = avg_delay_seconds * 1000.0f; + sample(LLStatViewer::WEBRTC_JITTER_BUFFER, avg_delay_seconds * 1000.0f); + } + } + } + } + }); +} + +void LLVoiceWebRTCConnection::resetConnectionStats() +{ + sample(LLStatViewer::WEBRTC_JITTER_BUFFER, 0); + sample(LLStatViewer::WEBRTC_JITTER_IN, 0); + sample(LLStatViewer::WEBRTC_JITTER_OUT, 0); + sample(LLStatViewer::WEBRTC_LATENCY, 0); + sample(LLStatViewer::WEBRTC_PACKETS_IN_LOST, 0); + sample(LLStatViewer::WEBRTC_PACKETS_IN_RECEIVED, 0); + sample(LLStatViewer::WEBRTC_PACKETS_OUT_SENT, 0); + sample(LLStatViewer::WEBRTC_PACKETS_OUT_LOST, 0); + sample(LLStatViewer::WEBRTC_UPLOAD_BANDWIDTH, 0); +} + ///////////////////////////// // WebRTC Spatial Connection diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index 2ce575852a..6786b049c2 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -540,6 +540,8 @@ private: static bool sShuttingDown; LLEventMailDrop mWebRTCPump; + + LLSD mLastWebRTCStats; }; @@ -603,6 +605,8 @@ class LLVoiceWebRTCConnection : //@{ void OnDataReceived(const std::string &data, bool binary) override; void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) override; + + void OnStatsDelivered(const llwebrtc::LLWebRTCStatsMap& stats_data) override; //@} void OnDataReceivedImpl(const std::string &data, bool binary); @@ -638,6 +642,8 @@ class LLVoiceWebRTCConnection : void OnVoiceConnectionRequestSuccess(const LLSD &body); + void resetConnectionStats(); + protected: typedef enum e_voice_connection_state { diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index cc593fe7b4..f639024228 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -82,7 +82,7 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); LLPanelWearableOutfitItem::Params::Params() : add_btn("add_btn"), @@ -222,7 +222,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(&typeid(LLPanelClothingListItem::Params), "clothing_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(typeid(LLPanelClothingListItem::Params), "clothing_list_item"); LLPanelClothingListItem::Params::Params() @@ -309,7 +309,7 @@ bool LLPanelClothingListItem::postBuild() ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(&typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item"); LLPanelBodyPartsListItem::Params::Params() @@ -380,7 +380,7 @@ bool LLPanelBodyPartsListItem::postBuild() return true; } -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(&typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item"); LLPanelDeletableWearableListItem::Params::Params() : delete_btn("delete_btn") @@ -467,7 +467,7 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name, ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(&typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item"); +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item"); LLPanelDummyClothingListItem::Params::Params() : add_panel("add_panel"), diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index 68e7f3ee29..91bc699708 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -37,18 +37,6 @@ #include "llviewertexture.h" #include "llgltexture.h" -// map item types -const U32 MAP_ITEM_TELEHUB = 0x01; -const U32 MAP_ITEM_PG_EVENT = 0x02; -const U32 MAP_ITEM_MATURE_EVENT = 0x03; -//const U32 MAP_ITEM_POPULAR = 0x04; // No longer supported, 2009-03-02 KLW -//const U32 MAP_ITEM_AGENT_COUNT = 0x05; -const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06; -const U32 MAP_ITEM_LAND_FOR_SALE = 0x07; -const U32 MAP_ITEM_CLASSIFIED = 0x08; -const U32 MAP_ITEM_ADULT_EVENT = 0x09; -const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a; - // Description of objects like hubs, events, land for sale, people and more (TBD). // Note: we don't store a "type" in there so we need to store instances of this class in // well known objects (i.e. list of objects which type is "well known"). diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d1ea8c2ee5..c9d53bbcbc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2734,6 +2734,10 @@ void LLPipeline::clearRebuildGroups() { LLSpatialGroup* group = *iter; + if (!group || group->isDead()) + { + continue; + } // If the group contains HUD objects, save the group if (group->isHUDGroup()) { diff --git a/indra/newview/skins/default/xui/da/floater_sound_devices.xml b/indra/newview/skins/default/xui/da/floater_sound_devices.xml deleted file mode 100644 index cb4cbba570..0000000000 --- a/indra/newview/skins/default/xui/da/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="Lyd enheder"> - <text name="voice_label"> - Stemme chat - </text> - <check_box label="Aktiveret" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/da/floater_voice_effect.xml b/indra/newview/skins/default/xui/da/floater_voice_effect.xml deleted file mode 100644 index 86ad251103..0000000000 --- a/indra/newview/skins/default/xui/da/floater_voice_effect.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Steder" name="voice_effects" title="STEMME MORPH"> - <string name="no_voice_effect"> - (Ingen stemme "morph") - </string> - <string name="active_voice_effect"> - (Aktiv) - </string> - <string name="unsubscribed_voice_effect"> - (Ikke aktiveret) - </string> - <string name="new_voice_effect"> - (Ny!) - </string> - <text name="preview_text"> - For at se - </text> - <text name="status_text"> - Optag en prøve, klik derefter på en stemme for at høre hvordan det vil lyde. - </text> - <button label="Optag" name="record_btn" tool_tip="Optag en stemmeprøve."/> - <button label="Stop" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Abonnér nu] - </text> - <scroll_list name="voice_effect_list" tool_tip="Optag en prøve med din stemme og klik på en effekt for at teste."> - <scroll_list.columns label="Stemme navn" name="name"/> - <scroll_list.columns label="Udløber" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/da/panel_voice_effect.xml b/indra/newview/skins/default/xui/da/panel_voice_effect.xml deleted file mode 100644 index 50f561ec7f..0000000000 --- a/indra/newview/skins/default/xui/da/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Voice Morphing Off - </string> - <string name="preview_voice_effects"> - Se stemme "morph" ▶ - </string> - <string name="get_voice_effects"> - Hente stemme "morph" ▶ - </string> - <combo_box name="voice_effect" tool_tip="Vælg en stemme "morph" for at ændre din stemme"> - <combo_box.item label="Stemme morph slukket" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/de/floater_big_preview.xml b/indra/newview/skins/default/xui/de/floater_big_preview.xml deleted file mode 100644 index c5ce56d1d9..0000000000 --- a/indra/newview/skins/default/xui/de/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="VORSCHAU"/> diff --git a/indra/newview/skins/default/xui/de/floater_post_process.xml b/indra/newview/skins/default/xui/de/floater_post_process.xml deleted file mode 100644 index a6ed8cc3df..0000000000 --- a/indra/newview/skins/default/xui/de/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Post-Process Floater" title="POST-PROCESSING-EINSTELLUNGEN"> - <tab_container name="Post-Process Tabs"> - <panel label="Farbfilter" name="wmiColorFilterPanel"> - <check_box label="Ein" name="wmiColorFilterToggle" /> - <text name="wmiColorFilterBrightnessText"> - Helligkeit - </text> - <text name="wmiColorFilterSaturationText"> - Sättigung - </text> - <text name="wmiColorFilterContrastText"> - Kontrast - </text> - <text name="wmiColorFilterBaseText"> - Kontrast-Grundfarbe - </text> - <slider label="R" name="wmiColorFilterBaseR" /> - <slider label="G" name="wmiColorFilterBaseG" /> - <slider label="B" name="wmiColorFilterBaseB" /> - <slider label="I" name="wmiColorFilterBaseI" /> - </panel> - <panel label="Nachtsicht" name="wmiNightVisionPanel"> - <check_box label="Ein" name="wmiNightVisionToggle" /> - <text name="wmiNightVisionBrightMultText"> - Lichtverstärkungsmultiplikator - </text> - <text name="wmiNightVisionNoiseSizeText"> - Rauschen-Größe - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Rauschen-Stärke - </text> - </panel> - <panel label="Bloom" name="wmiBloomPanel"> - <check_box label="Ein" name="wmiBloomToggle" /> - <text name="wmiBloomExtractText"> - Luminanz-Extraktion - </text> - <text name="wmiBloomSizeText"> - Bloom-Größe - </text> - <text name="wmiBloomStrengthText"> - Bloom-Stärke - </text> - </panel> - <panel label="Extras" name="Extras"> - <button label="Effekt laden" label_selected="Effekt laden" name="PPLoadEffect" /> - <button label="Effekt speichern" label_selected="Effekt speichern" name="PPSaveEffect" /> - <line_editor label="Effektname" name="PPEffectNameEditor" /> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/de/floater_sound_devices.xml b/indra/newview/skins/default/xui/de/floater_sound_devices.xml deleted file mode 100644 index 22ccb2c1a2..0000000000 --- a/indra/newview/skins/default/xui/de/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="SOUNDGERÄTE"> - <text name="voice_label"> - Voice-Chat - </text> - <check_box label="Aktiviert" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/de/floater_voice_effect.xml b/indra/newview/skins/default/xui/de/floater_voice_effect.xml deleted file mode 100644 index 8d37950480..0000000000 --- a/indra/newview/skins/default/xui/de/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Orte" name="voice_effects" title="VOICE-MORPHING-VORSCHAU"> - <string name="no_voice_effect"> - (Kein Voice-Morphing) - </string> - <string name="active_voice_effect"> - (Aktiv) - </string> - <string name="unsubscribed_voice_effect"> - (nicht abonniert) - </string> - <string name="new_voice_effect"> - (Neu!) - </string> - <string name="effect_Arena"> - Arena - </string> - <string name="effect_Beast"> - Bestie - </string> - <string name="effect_Buff"> - Muskulös - </string> - <string name="effect_Buzz"> - Buzz - </string> - <string name="effect_Camille"> - Camille - </string> - <string name="effect_Creepy"> - Unheimlich - </string> - <string name="effect_CreepyBot"> - UnheimlicherBot - </string> - <string name="effect_Cyber"> - Cyber - </string> - <string name="effect_DeepBot"> - TieferBot - </string> - <string name="effect_Demon"> - Dämon - </string> - <string name="effect_Female Elf"> - Weibliche Elfe - </string> - <string name="effect_Flirty"> - Kokett - </string> - <string name="effect_Foxy"> - Attraktiv - </string> - <string name="effect_Halloween 2010 Bonus"> - Bonus_Halloween_2010 - </string> - <string name="effect_Helium"> - Helium - </string> - <string name="effect_Husky"> - Rauchig - </string> - <string name="effect_Husky Whisper"> - Rauchiges Flüstern - </string> - <string name="effect_Intercom"> - Intercom - </string> - <string name="effect_Julia"> - Julia - </string> - <string name="effect_Lo Lilt"> - Leises Trällern - </string> - <string name="effect_Macho"> - Macho - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Model"> - Modell - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Alptraum - </string> - <string name="effect_PopBot"> - PopBot - </string> - <string name="effect_Rachel"> - Rachel - </string> - <string name="effect_Radio"> - Radio - </string> - <string name="effect_Robot"> - Roboter - </string> - <string name="effect_Roxanne"> - Roxanne - </string> - <string name="effect_Rumble"> - Rumpeln - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samantha - </string> - <string name="effect_Sexy"> - Sexy - </string> - <string name="effect_Shorty"> - Shorty - </string> - <string name="effect_Smaller"> - Kleiner - </string> - <string name="effect_Sneaky"> - Hinterhältig - </string> - <string name="effect_Stallion"> - Hengst - </string> - <string name="effect_Sultry"> - Feurig - </string> - <string name="effect_Thunder"> - Donner - </string> - <string name="effect_Vixen"> - Erotisch - </string> - <string name="effect_WhinyBot"> - JammernderBot - </string> - <text name="preview_text"> - Zur Vorschau - </text> - <text name="status_text"> - Stimme aufnehmen und auf einen Effekt klicken, um diesen auf Ihre Stimme anzuwenden. - </text> - <button label="Aufnehmen" name="record_btn" tool_tip="Nehmen Sie Ihre Stimme auf."/> - <button label="Stopp" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Jetzt abonnieren] - </text> - <scroll_list name="voice_effect_list" tool_tip="Nehmen Sie Ihre Stimme auf und klicken Sie dann auf einen Effekt, um diesen auszuprobieren."> - <scroll_list.columns label="Bezeichnung" name="name"/> - <scroll_list.columns label="Gültig bis" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/de/panel_voice_effect.xml b/indra/newview/skins/default/xui/de/panel_voice_effect.xml deleted file mode 100644 index 533deb8597..0000000000 --- a/indra/newview/skins/default/xui/de/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Voice-Morphing Aus - </string> - <string name="preview_voice_effects"> - Voice-Morphing ausprobieren ▶ - </string> - <string name="get_voice_effects"> - Voice-Morphing abonnieren ▶ - </string> - <combo_box name="voice_effect" tool_tip="Wählen Sie einen Voice-Morph-Effekt aus, um Ihre Stimme zu verändern."> - <combo_box.item label="Voice-Morphing Aus" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/en/floater_big_preview.xml b/indra/newview/skins/default/xui/en/floater_big_preview.xml deleted file mode 100644 index 362853d06f..0000000000 --- a/indra/newview/skins/default/xui/en/floater_big_preview.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater - positioning="cascading" - can_close="true" - can_resize="true" - can_minimize="false" - help_topic="floater_big_preview" - layout="topleft" - name="floater_big_preview" - save_rect="true" - single_instance="true" - reuse_instance="true" - title="PREVIEW" - height="465" - width="770"> - <panel - height="450" - width="750" - visible="true" - name="big_preview_placeholder" - top="5" - follows="all" - left="10"> - </panel> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml deleted file mode 100644 index 37339f79c8..0000000000 --- a/indra/newview/skins/default/xui/en/floater_post_process.xml +++ /dev/null @@ -1,426 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater - legacy_header_height="18" - height="400" - layout="topleft" - name="Post-Process Floater" - help_topic="post_process_floater" - title="POST-PROCESS SETTINGS" - width="400"> - <tab_container - follows="left|top" - height="400" - layout="topleft" - left="0" - name="Post-Process Tabs" - tab_position="top" - top="0" - width="400"> - <panel - border="true" - follows="left|top|right|bottom" - height="400" - label="Color Filter" - layout="topleft" - left="1" - mouse_opaque="false" - help_topic="post_process_color_filter_tab" - name="wmiColorFilterPanel" - top="0" - width="398"> - <check_box - control_name="wmiColorFilterToggle" - height="16" - label="Enable" - layout="topleft" - left="14" - name="wmiColorFilterToggle" - top="4" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiColorFilterBrightnessText" - top_pad="4" - width="355"> - Brightness - </text> - <slider - control_name="wmiColorFilterBrightness" - decimal_digits="2" - follows="left" - height="10" - increment="0.01" - initial_value="1.0" - layout="topleft" - left_delta="4" - max_val="4" - name="wmiColorFilterBrightness" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiColorFilterSaturationText" - top_pad="4" - width="355"> - Saturation - </text> - <slider - control_name="wmiColorFilterSaturation" - decimal_digits="2" - follows="left" - height="10" - increment="0.01" - initial_value="1.0" - layout="topleft" - left_delta="4" - max_val="2" - min_val="-1" - name="wmiColorFilterSaturation" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiColorFilterContrastText" - top_pad="4" - width="355"> - Contrast - </text> - <slider - control_name="wmiColorFilterContrast" - decimal_digits="2" - follows="left" - height="10" - increment="0.01" - initial_value="1.0" - layout="topleft" - left_delta="4" - max_val="4" - name="wmiColorFilterContrast" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiColorFilterBaseText" - top_pad="4" - width="355"> - Contrast Base Color - </text> - <slider - control_name="wmiColorFilterBaseR" - follows="left" - height="10" - increment="0.01" - initial_value="1.0" - label="R" - layout="topleft" - left_delta="4" - name="wmiColorFilterBaseR" - top_pad="20" - width="200" /> - <slider - control_name="wmiColorFilterBaseG" - follows="left" - height="10" - increment="0.01" - initial_value="1.0" - label="G" - layout="topleft" - left_delta="0" - name="wmiColorFilterBaseG" - top_pad="10" - width="200" /> - <slider - control_name="wmiColorFilterBaseB" - follows="left" - height="10" - increment="0.01" - initial_value="1.0" - label="B" - layout="topleft" - left_delta="0" - name="wmiColorFilterBaseB" - top_pad="10" - width="200" /> - <slider - control_name="wmiColorFilterBaseI" - follows="left" - height="10" - increment="0.01" - initial_value="0.5" - label="I" - layout="topleft" - left_delta="0" - name="wmiColorFilterBaseI" - top_pad="10" - width="200" /> - </panel> - <panel - border="true" - follows="left|top|right|bottom" - height="400" - label="Night Vision" - layout="topleft" - left_delta="0" - mouse_opaque="false" - help_topic="post_process_night_vision_tab" - name="wmiNightVisionPanel" - top_delta="-236" - width="398"> - <check_box - control_name="wmiNightVisionToggle" - height="16" - label="Enable" - layout="topleft" - left="14" - name="wmiNightVisionToggle" - top="4" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiNightVisionBrightMultText" - top_pad="5" - width="355"> - Light Amplification Multiple - </text> - <slider - control_name="wmiNightVisionBrightMult" - follows="left" - height="10" - increment="0.01" - initial_value="3.0" - layout="topleft" - left_delta="4" - max_val="10" - min_val="1" - name="wmiNightVisionBrightMult" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiNightVisionNoiseSizeText" - top_pad="4" - width="355"> - Noise Size - </text> - <slider - control_name="wmiNightVisionNoiseSize" - follows="left" - height="10" - initial_value="1" - layout="topleft" - left_delta="4" - max_val="100" - min_val="1" - name="wmiNightVisionNoiseSize" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiNightVisionNoiseStrengthText" - top_pad="4" - width="355"> - Noise Strength - </text> - <slider - control_name="wmiNightVisionNoiseStrength" - follows="left" - height="10" - increment="0.01" - initial_value="0.3" - layout="topleft" - left_delta="4" - name="wmiNightVisionNoiseStrength" - top_pad="20" - width="200" /> - </panel> - <panel - border="true" - follows="left|top|right|bottom" - height="400" - label="Bloom" - layout="topleft" - left_delta="0" - help_topic="post_process_bloom_tab" - name="wmiBloomPanel" - top_delta="-236" - width="398"> - <check_box - control_name="wmiBloomToggle" - height="16" - label="Enable" - layout="topleft" - left="14" - name="wmiBloomToggle" - top="4" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiBloomExtractText" - top_pad="5" - width="355"> - Luminosity Extraction - </text> - <slider - control_name="wmiBloomExtract" - follows="left" - height="10" - increment="0.01" - initial_value="0.9" - layout="topleft" - left_delta="4" - name="wmiBloomExtract" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiBloomSizeText" - top_pad="4" - width="355"> - Bloom Size - </text> - <slider - control_name="wmiBloomSize" - follows="left" - height="10" - increment="0.01" - initial_value="3.0" - layout="topleft" - left_delta="4" - max_val="20" - name="wmiBloomSize" - top_pad="20" - width="200" /> - <text - type="string" - length="1" - follows="left|top|right" - font="SansSerif" - height="16" - layout="topleft" - left_delta="-4" - name="wmiBloomStrengthText" - top_pad="4" - width="355"> - Bloom Strength - </text> - <slider - control_name="wmiBloomStrength" - follows="left" - height="10" - increment="0.01" - initial_value="1.2" - layout="topleft" - left_delta="4" - max_val="10" - name="wmiBloomStrength" - top_pad="20" - width="200" /> - </panel> - <panel - border="true" - follows="left|top|right|bottom" - height="400" - label="Extras" - layout="topleft" - left_delta="0" - mouse_opaque="false" - help_topic="post_process_extras_tab" - name="Extras" - top_delta="-236" - width="398"> - <button - height="20" - label="LoadEffect" - label_selected="LoadEffect" - layout="topleft" - left="15" - name="PPLoadEffect" - top="13" - width="100" /> - <button - height="20" - label="SaveEffect" - label_selected="SaveEffect" - layout="topleft" - left_delta="0" - name="PPSaveEffect" - top_pad="7" - width="100" /> - <combo_box - height="18" - layout="topleft" - left_delta="120" - name="PPEffectsCombo" - top="15" - width="150" /> - <line_editor - border_style="line" - border_thickness="1" - follows="left|right|bottom" - font="SansSerif" - height="20" - label="Effect Name" - layout="topleft" - left_delta="0" - max_length_bytes="40" - name="PPEffectNameEditor" - tab_group="1" - top_pad="22" - width="150" /> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_sound_devices.xml b/indra/newview/skins/default/xui/en/floater_sound_devices.xml deleted file mode 100644 index dec0e9b6c6..0000000000 --- a/indra/newview/skins/default/xui/en/floater_sound_devices.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater - border_visible="false" - border="false" - legacy_header_height="18" - can_minimize="true" - can_resize="false" - can_close="false" - chrome="true" - save_dock_state="true" - save_visibility="true" - save_rect="true" - single_instance="true" - bevel_style="in" - height="164" - layout="topleft" - name="floater_sound_devices" - title="SOUND DEVICES" - width="490"> - <panel - layout="topleft" - follows="all" - filename="panel_sound_devices.xml" - name="device_settings_panel" - width="400" - left="10" - top="26" - class="panel_voice_device_settings"/> - <text - name="voice_label" - top="136" - left="12" - height="14" - width="80" - layout="topleft" - >Voice Chat</text> - <check_box - layout="topleft" - control_name="EnableVoiceChat" - follows="bottom|left" - top="138" - left="80" - name="enable_voice" - width="100" - height="14" - label="Enabled" - /> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index 1600c422c3..191db4f854 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -418,6 +418,64 @@ </stat_view> </stat_view> </stat_view> + <stat_view name="voice" + label="Voice" + setting="OpenDebugStatVoice"> + <stat_bar + name="webrtc_latency" + label="Latency" + stat="webrtc_latency" + unit_label="ms" + decimal_digits="1"/> + <stat_bar + name="webrtc_upload_bandwidth" + label="Upload bandwidth" + stat="webrtc_upload_bandwidth" + unit_label="kbps" + decimal_digits="0"/> + <stat_view name="incoming_audio" + label="Incoming audio" + setting="OpenDebugStatVoiceIncoming"> + <stat_bar + name="incoming_packet_recv" + label="Packets received" + stat="webrtc_packets_in_recv"/> + <stat_bar + name="packets_in_lost" + label="Packets lost" + stat="webrtc_packets_in_lost"/> + <stat_bar + name="jitter_in" + label="Jitter" + stat="webrtc_jitter_in" + unit_label="ms" + decimal_digits="1"/> + <stat_bar + name="jitter_buffer" + label="Jitter buffer" + stat="webrtc_jitter_buffer" + unit_label="ms" + decimal_digits="1"/> + </stat_view> + <stat_view name="outgoing_audio" + label="Outgoing audio" + setting="OpenDebugStatVoiceOutgoing"> + <stat_bar + name="packets_out_sent" + label="Packets sent" + stat="webrtc_packets_out_sent"/> + <stat_bar + name="packets_out_lost" + label="Packets lost" + stat="webrtc_packets_out_lost"/> + <stat_bar + name="jitter_out" + label="Jitter" + stat="webrtc_jitter_out" + unit_label="ms" + decimal_digits="1"/> + </stat_view> + </stat_view> </container_view> </scroll_container> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_voice_effect.xml b/indra/newview/skins/default/xui/en/floater_voice_effect.xml deleted file mode 100644 index d037bdb813..0000000000 --- a/indra/newview/skins/default/xui/en/floater_voice_effect.xml +++ /dev/null @@ -1,162 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater - legacy_header_height="27" - can_resize="true" - height="500" - name="voice_effects" - help_topic="voice_effects" - title="VOICE MORPHING PREVIEW" - background_visible="true" - label="Places" - layout="topleft" - min_height="360" - min_width="200" - save_rect="true" - width="300"> - <string name="no_voice_effect"> - (No Voice Morph) - </string> - <string name="active_voice_effect"> - (Active) - </string> - <string name="unsubscribed_voice_effect"> - (Unsubscribed) - </string> - <string name="new_voice_effect"> - (New!) - </string> - - <!-- effect names begin --> - <string name="effect_Arena">Arena</string> - <string name="effect_Beast">Beast</string> - <string name="effect_Buff">Buff</string> - <string name="effect_Buzz">Buzz</string> - <string name="effect_Camille">Camille</string> - <string name="effect_Creepy">Creepy</string> - <string name="effect_CreepyBot">CreepyBot</string> - <string name="effect_Cyber">Cyber</string> - <string name="effect_DeepBot">DeepBot</string> - <string name="effect_Demon">Demon</string> - <string name="effect_Female Elf">Female Elf</string> - <string name="effect_Flirty">Flirty</string> - <string name="effect_Foxy">Foxy</string> - <string name="effect_Halloween 2010 Bonus">Halloween_2010_Bonus</string> - <string name="effect_Helium">Helium</string> - <string name="effect_Husky">Husky</string> - <string name="effect_Husky Whisper">Husky Whisper</string> - <string name="effect_Intercom">Intercom</string> - <string name="effect_Julia">Julia</string> - <string name="effect_Lo Lilt">Lo Lilt</string> - <string name="effect_Macho">Macho</string> - <string name="effect_Micro">Micro</string> - <string name="effect_Mini">Mini</string> - <string name="effect_Model">Model</string> - <string name="effect_Nano">Nano</string> - <string name="effect_Nightmare">Nightmare</string> - <string name="effect_PopBot">PopBot</string> - <string name="effect_Rachel">Rachel</string> - <string name="effect_Radio">Radio</string> - <string name="effect_Robot">Robot</string> - <string name="effect_Roxanne">Roxanne</string> - <string name="effect_Rumble">Rumble</string> - <string name="effect_Sabrina">Sabrina</string> - <string name="effect_Samantha">Samantha</string> - <string name="effect_Sexy">Sexy</string> - <string name="effect_Shorty">Shorty</string> - <string name="effect_Smaller">Smaller</string> - <string name="effect_Sneaky">Sneaky</string> - <string name="effect_Stallion">Stallion</string> - <string name="effect_Sultry">Sultry</string> - <string name="effect_Thunder">Thunder</string> - <string name="effect_Vixen">Vixen</string> - <string name="effect_WhinyBot">WhinyBot</string> - <!-- effect names end --> - - <text - height="16" - word_wrap="true" - use_ellipses="true" - type="string" - follows="left|top|right" - layout="topleft" - font="SansSerifBold" - color="White" - left="10" - name="preview_text" - right="-10" - top="27">To Preview - </text> - <text - height="23" - word_wrap="true" - use_ellipses="true" - type="string" - follows="left|top|right" - layout="topleft" - left="10" - name="status_text" - right="-5" - top_pad="0"> -Record a sample, then click on a voice to hear how it will sound. - </text> - <button - follows="left|top" - height="23" - label="Record" - layout="topleft" - left="10" - name="record_btn" - tool_tip="Record a sample of your voice." - top_pad="5" - width="100"> - <button.commit_callback - function="VoiceEffect.Record" /> - </button> - <button - follows="left|top" - height="23" - label="Stop" - layout="topleft" - left_delta="0" - name="record_stop_btn" - top_delta="0" - width="100"> - <button.commit_callback - function="VoiceEffect.Stop" /> - </button> - <text - height="23" - halign="right" - use_ellipses="true" - type="string" - follows="left|top|right" - layout="topleft" - left_pad="10" - top_delta="10" - name="voice_morphing_link" - right="-10"> - [[URL] Subscribe Now] - </text> - <scroll_list - bottom="-10" - draw_heading="true" - follows="all" - layout="topleft" - left="10" - multi_select="false" - name="voice_effect_list" - right="-10" - tool_tip="Record a sample of your voice, then click an effect to preview." - top="95"> - <scroll_list.columns - label="Voice Name" - name="name" - relative_width="0.60" /> - <scroll_list.columns - dynamic_width="true" - label="Expires" - name="expires" - relative_width="0.30" /> - </scroll_list> - -</floater> diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml index d978619355..c9adf46ad7 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml @@ -48,6 +48,28 @@ <menu_item_call.on_click function="Object.ShowOriginal" /> </menu_item_call> + <menu_item_call + label="Add to favorites" + layout="topleft" + name="Add to favorites"> + <menu_item_call.on_click + function="Object.SetFavorite" + parameter="Add" /> + <menu_item_call.on_visible + function="Object.EnableFavorites" + parameter="Add"/> + </menu_item_call> + <menu_item_call + label="Remove from favorites" + layout="topleft" + name="Remove from favorites"> + <menu_item_call.on_click + function="Object.SetFavorite" + parameter="Remove" /> + <menu_item_call.on_visible + function="Object.EnableFavorites" + parameter="Remove" /> + </menu_item_call> <menu_item_separator layout="topleft" /> diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 62cdaa5886..5a28f0dde5 100644 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -176,57 +176,60 @@ <on_click function="Group.DoToSelected" parameter="leave_group"/> <on_enable function="Avatar.EnableItem" parameter="can_leave_group" /> </menu_item_call> - <menu_item_separator layout="topleft" name="Moderator Options Separator"/> - <context_menu - label="Moderator Options" - layout="topleft" - name="Moderator Options"> - <menu_item_check - label="Allow text chat" - layout="topleft" - name="AllowTextChat"> - <on_check function="Avatar.CheckItem" parameter="is_allowed_text_chat" /> - <on_click function="Avatar.DoToSelected" parameter="toggle_allow_text_chat" /> - <on_enable function="Avatar.EnableItem" parameter="can_allow_text_chat" /> - </menu_item_check> - <menu_item_separator layout="topleft" name="moderate_voice_separator" /> - <menu_item_call - label="Mute this participant" - layout="topleft" - name="ModerateVoiceMuteSelected"> - <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_mute" /> - <on_visible function="Avatar.VisibleItem" parameter="show_mute" /> - </menu_item_call> + <menu_item_separator layout="topleft" name="Moderator Options Separator"/> + <context_menu + label="Moderator Options" + layout="topleft" + name="Moderator Options"> + <menu_item_check + label="Allow text chat" + layout="topleft" + name="AllowTextChat"> + <on_check function="Avatar.CheckItem" parameter="is_allowed_text_chat" /> + <on_click function="Avatar.DoToSelected" parameter="toggle_allow_text_chat" /> + <on_enable function="Avatar.EnableItem" parameter="can_allow_text_chat" /> + <on_visible function="Avatar.VisibleItem" parameter="can_allow_text_chat" /> + </menu_item_check> + <menu_item_separator layout="topleft" name="moderate_voice_separator"> + <on_visible function="Avatar.VisibleItem" parameter="can_allow_text_chat" /> + </menu_item_separator> + <menu_item_call + label="Mute this participant" + layout="topleft" + name="ModerateVoiceMuteSelected"> + <on_click function="Avatar.DoToSelected" parameter="selected" /> + <on_enable function="Avatar.EnableItem" parameter="can_mute" /> + <on_visible function="Avatar.VisibleItem" parameter="show_mute" /> + </menu_item_call> + <menu_item_call + label="Unmute this participant" + layout="topleft" + name="ModerateVoiceUnMuteSelected"> + <on_click function="Avatar.DoToSelected" parameter="selected" /> + <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> + <on_visible function="Avatar.VisibleItem" parameter="show_unmute" /> + </menu_item_call> + <menu_item_call + label="Mute everyone" + layout="topleft" + name="ModerateVoiceMute"> + <on_click function="Avatar.DoToSelected" parameter="mute_all" /> + <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" /> + </menu_item_call> + <menu_item_call + label="Unmute everyone" + layout="topleft" + name="ModerateVoiceUnmute"> + <on_click function="Avatar.DoToSelected" parameter="unmute_all" /> + <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" /> + </menu_item_call> + </context_menu> + <menu_item_separator layout="topleft" name="Group Ban Separator"/> <menu_item_call - label="Unmute this participant" - layout="topleft" - name="ModerateVoiceUnMuteSelected"> - <on_click function="Avatar.DoToSelected" parameter="selected" /> - <on_enable function="Avatar.EnableItem" parameter="can_unmute" /> - <on_visible function="Avatar.VisibleItem" parameter="show_unmute" /> - </menu_item_call> - <menu_item_call - label="Mute everyone" - layout="topleft" - name="ModerateVoiceMute"> - <on_click function="Avatar.DoToSelected" parameter="mute_all" /> - <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" /> - </menu_item_call> - <menu_item_call - label="Unmute everyone" - layout="topleft" - name="ModerateVoiceUnmute"> - <on_click function="Avatar.DoToSelected" parameter="unmute_all" /> - <on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" /> - </menu_item_call> - </context_menu> - <menu_item_separator layout="topleft" name="Group Ban Separator"/> - <menu_item_call - label="Ban member" - layout="topleft" - name="BanMember"> - <on_click function="Avatar.DoToSelected" parameter="ban_member" /> - <on_enable function="Avatar.EnableItem" parameter="can_ban_member" /> - </menu_item_call> + label="Ban member" + layout="topleft" + name="BanMember"> + <on_click function="Avatar.DoToSelected" parameter="ban_member" /> + <on_enable function="Avatar.EnableItem" parameter="can_ban_member" /> + </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml index 97f53d3a17..f85f897700 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_view_default.xml @@ -53,11 +53,7 @@ function="Inventory.GearDefault.Visible" parameter="multi_folder_view" /> </menu_item_check> - <menu_item_separator> - <menu_item_separator.on_visible - function="Inventory.GearDefault.Visible" - parameter="single_folder_view" /> - </menu_item_separator> + <menu_item_separator/> <menu_item_check label="List view" layout="topleft" @@ -100,4 +96,46 @@ function="Inventory.GearDefault.Visible" parameter="single_folder_view" /> </menu_item_check> + <menu_item_check + label="Recent tab" + layout="topleft" + name="recent_tab"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="toggle_recent_tab" /> + <on_check + function="Inventory.GearDefault.Check" + parameter="recent_tab" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> + </menu_item_check> + <menu_item_check + label="Worn tab" + layout="topleft" + name="worn_tab"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="toggle_worn_tab" /> + <on_check + function="Inventory.GearDefault.Check" + parameter="worn_tab" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> + </menu_item_check> + <menu_item_check + label="Favorites tab" + layout="topleft" + name="favorites_tab"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="toggle_favorites_tab" /> + <on_check + function="Inventory.GearDefault.Check" + parameter="favorites_tab" /> + <on_visible + function="Inventory.GearDefault.Visible" + parameter="multi_folder_view" /> + </menu_item_check> </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 c93cb7822e..ffe4bcebd5 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -960,7 +960,8 @@ </menu_item_check> <menu_item_check label="Midday (Legacy)" - name="legacy noon"> + name="legacy noon" + shortcut="control|shift|T"> <menu_item_check.on_click function="World.EnvSettings" parameter="legacy noon" /> @@ -992,7 +993,8 @@ </menu_item_check> <menu_item_check label="Use Shared Environment" - name="Use Shared Environment"> + name="Use Shared Environment" + shortcut="control|shift|X"> <menu_item_check.on_click function="World.EnvSettings" parameter="region" /> @@ -2601,18 +2603,6 @@ function="World.EnvPreset" parameter="fast timers" /> </menu_item_check> <menu_item_check - label="Memory" - name="Memory" - shortcut="control|shift|0" - use_mac_ctrl="true"> - <menu_item_check.on_check - function="Advanced.CheckConsole" - parameter="memory view" /> - <menu_item_check.on_click - function="Advanced.ToggleConsole" - parameter="memory view" /> - </menu_item_check> - <menu_item_check label="Scene Statistics" name="Scene Statistics"> <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e8da8a6322..bc69242651 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8596,10 +8596,10 @@ Scripts associated with this experience will be able to do the following on regi priority="critical" persist="true" type="notify"> -Warning: The object '<nolink>[OBJECTNAME]</nolink>' wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings. - -Do not allow access if you do not fully understand why it wants access to your account. +Warning: +[WARNINGS] +Do not allow access if you do not fully understand why it wants access to your account. <tag>confirm</tag> <form name="form"> <button @@ -8612,9 +8612,7 @@ Do not allow access if you do not fully understand why it wants access to your a name="Deny" text="Deny"/> </form> - <footer> -[FOOTERTEXT] - </footer> + <footer>[FOOTERTEXT]</footer> </notification> <notification @@ -9129,6 +9127,14 @@ Failed to save snapshot to [PATH]: Disk is full. [NEED_MEMORY]KB is required but Failed to save snapshot to [PATH]: Directory does not exist. </notification> + <notification icon="notifytip.tga" + name="SnapshotSavedToComputer" type="notifytip"> +Screenshot saved to: + [FILEPATH] + +Click to open folder. + </notification> + <notification icon="notifytip.tga" name="PresetNotSaved" @@ -9204,6 +9210,23 @@ Your voice has been muted by moderator. </notification> <notification + icon="notifytip.tga" + name="NearbyVoiceMutedByModerator" + type="notifytip"> + The moderator has muted your voice chat. +People in this location will not hear you if you speak. + <tag>voice</tag> + </notification> + + <notification + icon="notifytip.tga" + name="NearbyVoiceUnmutedByModerator" + type="notifytip"> + Your voice chat can now be heard by people in this location. + <tag>voice</tag> + </notification> + + <notification icon="alertmodal.tga" name="FailedToGetBenefits" type="alertmodal"> @@ -9688,6 +9711,22 @@ Are you sure you want to leave this call? <notification icon="alertmodal.tga" + name="ConfirmLeaveAdhoc" + type="alertmodal"> +Are you sure you want to leave this conference chat? + <tag>confirm</tag> + <tag>voice</tag> + <usetemplate + ignoretext="Confirm before I leave conference chat" + name="okcancelignore" + notext="No" + yestext="Yes"> + <unique/> + </usetemplate> + </notification> + + <notification + icon="alertmodal.tga" name="ConfirmMuteAll" type="alert"> You have selected to mute all participants in a group call. diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index bfe738f472..eaf638d35f 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -49,7 +49,7 @@ embedded_items="false" enabled="false" follows="left|right|top|bottom" - height="85" + height="85" layout="topleft" left="10" mouse_opaque="false" @@ -67,16 +67,16 @@ <panel background_visible="false" follows="left|right|bottom" - height="30" + height="30" width="290" label="control_panel" layout="topleft" left="10" name="control_panel" top_pad="5"> - <!-- + <!-- Notes: - This panel holds buttons of notification. Change of its size can affect the layout of buttons. + This panel holds buttons of notification. Change of its size can affect the layout of buttons. --> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 809a5faab9..6d1b952639 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -296,16 +296,16 @@ tool_tip="Show username, like bobsmith123" top_delta="0" /> <check_box - control_name="NameTagShowGroupTitles" - enabled_control="AvatarNameTagMode" + control_name="UseDisplayNames" + follows="top|left" height="16" - label="Group titles" + label="Display names" layout="topleft" left="35" - width="100" - name="show_all_title_checkbox1" - tool_tip="Show group titles, like Officer or Member" - top_pad="5" /> + name="display_names_check" + width="100" + tool_tip="Check to use display names in chat, IM, name tags, etc." + top_pad="5"/> <check_box control_name="NameTagShowFriends" enabled_control="AvatarNameTagMode" @@ -314,19 +314,29 @@ layout="topleft" left_pad="50" name="show_friends" - tool_tip="Highlight the name tags of your friends"/> - <check_box - control_name="UseDisplayNames" - follows="top|left" - height="16" - label="View Display Names" - layout="topleft" - left="35" - name="display_names_check" - width="237" - tool_tip="Check to use display names in chat, IM, name tags, etc." - top_pad="5"/> - + tool_tip="Highlight the name tags of your friends"/> + <combo_box + height="23" + layout="topleft" + control_name="GroupTitlesTagMode" + enabled_control="AvatarNameTagMode" + left="38" + top_pad="3" + name="group_title" + width="130"> + <combo_box.item + label="No group tags" + name="no_tags" + value="0" /> + <combo_box.item + label="Only my group tag" + name="my_tag" + value="1" /> + <combo_box.item + label="All group tags" + name="all_tags" + value="2" /> + </combo_box> <text type="string" length="1" @@ -335,7 +345,7 @@ layout="topleft" left="30" name="inworld_typing_rg_label" - top_pad="1" + top_pad="5" width="400"> Pressing letter keys: </text> diff --git a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml index 1b1e31165a..9045e6a8ae 100644 --- a/indra/newview/skins/default/xui/en/panel_script_question_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_script_question_toast.xml @@ -6,7 +6,7 @@ bg_alpha_color="PanelNotificationBackground" bg_opaque_color="PanelNotificationBackground" chrome="true" - height="270" + height="220" label="script_question_panel" layout="topleft" left="0" @@ -39,9 +39,9 @@ width="285"> </panel> <text - follows="all" + follows="left|right|top" font="SansSerifBold" - height="55" + height="15" layout="topleft" mouse_opaque="false" name="bottom_info_message" diff --git a/indra/newview/skins/default/xui/en/panel_voice_effect.xml b/indra/newview/skins/default/xui/en/panel_voice_effect.xml deleted file mode 100644 index 42cd510efd..0000000000 --- a/indra/newview/skins/default/xui/en/panel_voice_effect.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel - follows="all" - height="26" - layout="topleft" - name="panel_voice_effect" - width="200"> - <string name="no_voice_effect"> - Voice Morphing Off - </string> - <string name="preview_voice_effects"> - Preview Voice Morphing ▶ - </string> - <string name="get_voice_effects"> - Get Voice Morphing ▶ - </string> - <combo_box - enabled="false" - follows="left|top|right" - height="23" - name="voice_effect" - tool_tip="Select a Voice Morph to change your voice" - top_pad="0" - width="200"> - <combo_box.item - label="Voice Morphing Off" - name="no_voice_effect" - top_pad="0" - value="0" /> - <combo_box.commit_callback - function="Voice.CommitVoiceEffect" /> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 8e0eea97d1..1860d38b0e 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -518,6 +518,8 @@ http://secondlife.com/support for help fixing this problem. <string name="reconnect_nearby">You will now be reconnected to Nearby Voice Chat</string> <string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string> <string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string> + <string name="ScriptTakeMoneyCaution">The object '<nolink>[OBJECTNAME]</nolink>' wants total access to your Linden Dollars account. If you allow access, it can remove funds from your account at any time, or empty your account completely, on an ongoing basis with no additional warnings.</string> + <string name="PrivilegedLandAccessCaution">The object '<nolink>[OBJECTNAME]</nolink>' wants privileged access to your land. If you allow access it may sell your land with no additional warnings.</string> <string name="AdditionalPermissionsRequestHeader">If you allow access to your account, you will also be allowing the object to:</string> <string name="ScriptTakeMoney">Take Linden dollars (L$) from you</string> <string name="ActOnControlInputs">Act on your control inputs</string> @@ -535,6 +537,7 @@ http://secondlife.com/support for help fixing this problem. <string name="ChangeYourDefaultAnimations">Change your default animations</string> <string name="ForceSitAvatar">Force your avatar to sit</string> <string name="ChangeEnvSettings">Change your environment settings</string> + <string name="PrivilegedLandAccess">Sell land on your behalf.</string> <string name="NotConnected">Not Connected</string> <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> diff --git a/indra/newview/skins/default/xui/es/floater_big_preview.xml b/indra/newview/skins/default/xui/es/floater_big_preview.xml deleted file mode 100644 index b112243d7a..0000000000 --- a/indra/newview/skins/default/xui/es/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="VISTA PREVIA"/> diff --git a/indra/newview/skins/default/xui/es/floater_post_process.xml b/indra/newview/skins/default/xui/es/floater_post_process.xml deleted file mode 100644 index 5c62ccde36..0000000000 --- a/indra/newview/skins/default/xui/es/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="CONFIGURACIÓN DEL PROCESAMIENTO"> - <tab_container name="Post-Process Tabs"> - <panel label="Color del filtro" name="wmiColorFilterPanel"> - <check_box label="Activar" name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - Brillo - </text> - <text name="wmiColorFilterSaturationText"> - Saturación - </text> - <text name="wmiColorFilterContrastText"> - Contraste - </text> - <text name="wmiColorFilterBaseText"> - Color base del contraste - </text> - <slider label="R" name="wmiColorFilterBaseR"/> - <slider label="V" name="wmiColorFilterBaseG"/> - <slider label="A" name="wmiColorFilterBaseB"/> - <slider label="I" name="wmiColorFilterBaseI"/> - </panel> - <panel label="Visión nocturna" name="wmiNightVisionPanel"> - <check_box label="Activar" name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - Amplificación de luz - </text> - <text name="wmiNightVisionNoiseSizeText"> - Cantidad de ruido - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Intensidad del ruido - </text> - </panel> - <panel label="Bloom" name="wmiBloomPanel"> - <check_box label="Activar" name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - Extracción de la luminosidad - </text> - <text name="wmiBloomSizeText"> - Bloom: cantidad - </text> - <text name="wmiBloomStrengthText"> - Bloom: intensidad - </text> - </panel> - <panel label="Extras" name="Extras"> - <button label="Cargar efecto" label_selected="Cargar efecto" name="PPLoadEffect"/> - <button label="Guardar efecto" label_selected="Guardar efecto" name="PPSaveEffect"/> - <line_editor label="Nombre del efecto" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/es/floater_sound_devices.xml b/indra/newview/skins/default/xui/es/floater_sound_devices.xml deleted file mode 100644 index 0291f9e796..0000000000 --- a/indra/newview/skins/default/xui/es/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="DISPOSITIVOS DE SONIDO"> - <text name="voice_label"> - Chat de voz - </text> - <check_box label="Activados" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/es/floater_voice_effect.xml b/indra/newview/skins/default/xui/es/floater_voice_effect.xml deleted file mode 100644 index 02ebe80ff7..0000000000 --- a/indra/newview/skins/default/xui/es/floater_voice_effect.xml +++ /dev/null @@ -1,138 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Lugares" name="voice_effects" title="PROBAR TRANSFORMACIÓN DE VOZ"> - <string name="no_voice_effect"> - (Sin transformación de voz) - </string> - <string name="active_voice_effect"> - (Activo) - </string> - <string name="unsubscribed_voice_effect"> - (Suscripción cancelada) - </string> - <string name="new_voice_effect"> - (¡Nuevo!) - </string> - <string name="effect_Arena"> - Campo - </string> - <string name="effect_Beast"> - Bestia - </string> - <string name="effect_Buff"> - Musculoso - </string> - <string name="effect_Buzz"> - Murmullo - </string> - <string name="effect_Camille"> - Camila - </string> - <string name="effect_Creepy"> - Aterrador - </string> - <string name="effect_CreepyBot"> - Robot aterrador - </string> - <string name="effect_Cyber"> - Cyber - </string> - <string name="effect_DeepBot"> - Robot profundo - </string> - <string name="effect_Demon"> - Diablo - </string> - <string name="effect_Flirty"> - Coqueta - </string> - <string name="effect_Foxy"> - Astuto - </string> - <string name="effect_Halloween_2010_Bonus"> - Halloween_2010_Bonus - </string> - <string name="effect_Helium"> - Helio - </string> - <string name="effect_Husky"> - Corpulento - </string> - <string name="effect_Intercom"> - Intercom - </string> - <string name="effect_Macho"> - Macho - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Pesadilla - </string> - <string name="effect_PopBot"> - Robot pop - </string> - <string name="effect_Rachel"> - Raquel - </string> - <string name="effect_Radio"> - Radio - </string> - <string name="effect_Robot"> - Robot - </string> - <string name="effect_Roxanne"> - Roxana - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samanta - </string> - <string name="effect_Sexy"> - Sexy - </string> - <string name="effect_Shorty"> - Bajito - </string> - <string name="effect_Sneaky"> - Furtivo - </string> - <string name="effect_Stallion"> - Mujeriego - </string> - <string name="effect_Sultry"> - Sensual - </string> - <string name="effect_Thunder"> - Trueno - </string> - <string name="effect_Vixen"> - Tigresa - </string> - <string name="effect_WhinyBot"> - Robot llorica - </string> - <text name="preview_text"> - Para probarla - </text> - <text name="status_text"> - Graba una muestra y pulsa en una voz para escuchar cómo suena. - </text> - <button label="Grabar" name="record_btn" tool_tip="Graba una muestra de tu voz."/> - <button label="Parar" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Suscríbete ahora] - </text> - <scroll_list name="voice_effect_list" tool_tip="Graba una muestra de tu voz y pulsa en un efecto para ver cómo suena."> - <scroll_list.columns label="Nombre de la voz" name="name"/> - <scroll_list.columns label="Caduca" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/es/panel_voice_effect.xml b/indra/newview/skins/default/xui/es/panel_voice_effect.xml deleted file mode 100644 index 94a0428941..0000000000 --- a/indra/newview/skins/default/xui/es/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Transformación de voz desactivada - </string> - <string name="preview_voice_effects"> - Probar transformación de voz ▶ - </string> - <string name="get_voice_effects"> - Obtener transformación de voz ▶ - </string> - <combo_box name="voice_effect" tool_tip="Selecciona una transformación de voz para cambiar tu voz"> - <combo_box.item label="Transformación de voz desactivada" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/fr/floater_big_preview.xml b/indra/newview/skins/default/xui/fr/floater_big_preview.xml deleted file mode 100644 index 0c09a4c188..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="APERÇU"/> diff --git a/indra/newview/skins/default/xui/fr/floater_post_process.xml b/indra/newview/skins/default/xui/fr/floater_post_process.xml deleted file mode 100644 index a22c7512e5..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_post_process.xml +++ /dev/null @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Post-Process Floater" title="PARAMÈTRES POST-TRAITEMENT"> - <tab_container name="Post-Process Tabs"> - <panel label="Filtre couleur" name="wmiColorFilterPanel"> - <check_box label="Activer" name="wmiColorFilterToggle" /> - <text name="wmiColorFilterBrightnessText"> - Luminosité - </text> - <text name="wmiColorFilterSaturationText"> - Saturation - </text> - <text name="wmiColorFilterContrastText"> - Contraste - </text> - <text name="wmiColorFilterBaseText"> - Couleur de base du contraste - </text> - <slider label="R" name="wmiColorFilterBaseR" /> - <slider label="V" name="wmiColorFilterBaseG" /> - <slider label="B" name="wmiColorFilterBaseB" /> - <slider label="I" name="wmiColorFilterBaseI" /> - </panel> - <panel label="Vision de nuit" name="wmiNightVisionPanel"> - <check_box label="Activer" name="wmiNightVisionToggle" /> - <text name="wmiNightVisionBrightMultText"> - Multiple d'amplificateur de lumière - </text> - <text name="wmiNightVisionNoiseSizeText"> - Taille du bruit - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Force du bruit - </text> - </panel> - <panel label="Éclat" name="wmiBloomPanel"> - <check_box label="Activer" name="wmiBloomToggle" /> - <text name="wmiBloomExtractText"> - Extraction de la luminosité - </text> - <text name="wmiBloomSizeText"> - Taille de l'éclat - </text> - <text name="wmiBloomStrengthText"> - Force de l'éclat - </text> - </panel> - <panel label="Extras" name="Extras"> - <button label="Charger effet" label_selected="Charger effet" name="PPLoadEffect" /> - <button label="Enregistrer effet" label_selected="Enregistrer effet" - name="PPSaveEffect" /> - <line_editor label="Nom de l'effet" name="PPEffectNameEditor" /> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_sound_devices.xml b/indra/newview/skins/default/xui/fr/floater_sound_devices.xml deleted file mode 100644 index 080ade9dd4..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="PERIPHERIQUES AUDIO"> - <text name="voice_label"> - Chat vocal - </text> - <check_box label="Activé" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_voice_effect.xml b/indra/newview/skins/default/xui/fr/floater_voice_effect.xml deleted file mode 100644 index f9a76d127e..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Endroits" name="voice_effects" title="APERÇU DES EFFETS DE VOIX"> - <string name="no_voice_effect"> - (Aucun effet de voix) - </string> - <string name="active_voice_effect"> - (Actif) - </string> - <string name="unsubscribed_voice_effect"> - (Pas d'abonnement) - </string> - <string name="new_voice_effect"> - (Nouveau !) - </string> - <string name="effect_Arena"> - Stade - </string> - <string name="effect_Beast"> - Brute - </string> - <string name="effect_Buff"> - Nasal - </string> - <string name="effect_Buzz"> - Friture - </string> - <string name="effect_Camille"> - Camille - </string> - <string name="effect_Creepy"> - Effrayant - </string> - <string name="effect_CreepyBot"> - BotEffrayant - </string> - <string name="effect_Cyber"> - Cyber - </string> - <string name="effect_DeepBot"> - BotGrave - </string> - <string name="effect_Demon"> - Démon - </string> - <string name="effect_Female Elf"> - Femme elfe - </string> - <string name="effect_Flirty"> - Flirt - </string> - <string name="effect_Foxy"> - Séduction - </string> - <string name="effect_Halloween 2010 Bonus"> - Halloween_2010_Bonus - </string> - <string name="effect_Helium"> - Hélium - </string> - <string name="effect_Husky"> - Rauque - </string> - <string name="effect_Husky Whisper"> - Murmure rauque - </string> - <string name="effect_Intercom"> - Interphone - </string> - <string name="effect_Julia"> - Julia - </string> - <string name="effect_Lo Lilt"> - Mélodieux - </string> - <string name="effect_Macho"> - Macho - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Model"> - Modèle - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Cauchemar - </string> - <string name="effect_PopBot"> - BotPop - </string> - <string name="effect_Rachel"> - Rachel - </string> - <string name="effect_Radio"> - Radio - </string> - <string name="effect_Robot"> - Robot - </string> - <string name="effect_Roxanne"> - Roxanne - </string> - <string name="effect_Rumble"> - Grondement - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samantha - </string> - <string name="effect_Sexy"> - Sexy - </string> - <string name="effect_Shorty"> - Petite voix - </string> - <string name="effect_Smaller"> - Plus faible - </string> - <string name="effect_Sneaky"> - Sournois - </string> - <string name="effect_Stallion"> - Étalon - </string> - <string name="effect_Sultry"> - Sensuel - </string> - <string name="effect_Thunder"> - Tonnerre - </string> - <string name="effect_Vixen"> - Mégère - </string> - <string name="effect_WhinyBot"> - BotPleurnichard - </string> - <text name="preview_text"> - Aperçu - </text> - <text name="status_text"> - Enregistrez un extrait et cliquez sur un effet pour obtenir un aperçu. - </text> - <button label="Enregistrer" name="record_btn" tool_tip="Enregistrez un extrait de votre voix."/> - <button label="Arrêter" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] S'abonner] - </text> - <scroll_list name="voice_effect_list" tool_tip="Enregistrez un extrait de votre voix, puis cliquez sur un effet pour obtenir un aperçu."> - <scroll_list.columns label="Nom de l'effet" name="name"/> - <scroll_list.columns label="Date d'expiration" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/fr/panel_voice_effect.xml b/indra/newview/skins/default/xui/fr/panel_voice_effect.xml deleted file mode 100644 index a134854706..0000000000 --- a/indra/newview/skins/default/xui/fr/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Effet de voix désactivé - </string> - <string name="preview_voice_effects"> - Aperçu des effets de voix ▶ - </string> - <string name="get_voice_effects"> - Obtenir un effet de voix ▶ - </string> - <combo_box name="voice_effect" tool_tip="Sélectionner un effet pour modifier le son de votre voix"> - <combo_box.item label="Effet de voix désactivé" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/it/floater_big_preview.xml b/indra/newview/skins/default/xui/it/floater_big_preview.xml deleted file mode 100644 index 7bc50a6d39..0000000000 --- a/indra/newview/skins/default/xui/it/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="ANTEPRIMA"/> diff --git a/indra/newview/skins/default/xui/it/floater_post_process.xml b/indra/newview/skins/default/xui/it/floater_post_process.xml deleted file mode 100644 index 3aa8b29101..0000000000 --- a/indra/newview/skins/default/xui/it/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="IMPOSTAZIONI DI POST-PRODUZIONE"> - <tab_container name="Post-Process Tabs"> - <panel label="Filtro Colore" name="wmiColorFilterPanel"> - <check_box label="Abilita" name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - Luminosità - </text> - <text name="wmiColorFilterSaturationText"> - Saturazione - </text> - <text name="wmiColorFilterContrastText"> - Contrasto - </text> - <text name="wmiColorFilterBaseText"> - Colore Base Contrasto - </text> - <slider label="R" name="wmiColorFilterBaseR"/> - <slider label="G" name="wmiColorFilterBaseG"/> - <slider label="B" name="wmiColorFilterBaseB"/> - <slider label="I" name="wmiColorFilterBaseI"/> - </panel> - <panel label="Visione Notturna" name="wmiNightVisionPanel"> - <check_box label="Abilita" name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - Amplificazione Multipla Luce - </text> - <text name="wmiNightVisionNoiseSizeText"> - Ampiezza disturbo - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Forza disturbo - </text> - </panel> - <panel label="Raggiatura" name="wmiBloomPanel"> - <check_box label="Abilita" name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - Estrazione luminosità - </text> - <text name="wmiBloomSizeText"> - Dimensione raggiatura - </text> - <text name="wmiBloomStrengthText"> - Forza raggiatura - </text> - </panel> - <panel label="Extra" name="Extras"> - <button label="Carica effetto" label_selected="Carica effetto" name="PPLoadEffect"/> - <button label="Salva effetto" label_selected="Salva effetto" name="PPSaveEffect"/> - <line_editor label="Nome Effetto" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/it/floater_sound_devices.xml b/indra/newview/skins/default/xui/it/floater_sound_devices.xml deleted file mode 100644 index 9799b48d89..0000000000 --- a/indra/newview/skins/default/xui/it/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="DISPOSITIVI AUDIO"> - <text name="voice_label"> - Chat vocale - </text> - <check_box label="Abilitato" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/it/floater_voice_effect.xml b/indra/newview/skins/default/xui/it/floater_voice_effect.xml deleted file mode 100644 index f102622f5d..0000000000 --- a/indra/newview/skins/default/xui/it/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Luoghi" name="voice_effects" title="ANTEPRIMA MANIPOLAZIONE VOCE"> - <string name="no_voice_effect"> - (Nessuna manipolazione voce) - </string> - <string name="active_voice_effect"> - (Attivato) - </string> - <string name="unsubscribed_voice_effect"> - (Iscrizione annullata) - </string> - <string name="new_voice_effect"> - (Nuovo!) - </string> - <string name="effect_Arena"> - Arena - </string> - <string name="effect_Beast"> - Bestia - </string> - <string name="effect_Buff"> - Appassionato - </string> - <string name="effect_Buzz"> - Euforia - </string> - <string name="effect_Camille"> - Camilla - </string> - <string name="effect_Creepy"> - Terrificante - </string> - <string name="effect_CreepyBot"> - TerrificanteBot - </string> - <string name="effect_Cyber"> - Cyber - </string> - <string name="effect_DeepBot"> - ProfondoBot - </string> - <string name="effect_Demon"> - Demonio - </string> - <string name="effect_Female Elf"> - Elfo donna - </string> - <string name="effect_Flirty"> - Civettuolo - </string> - <string name="effect_Foxy"> - Scaltro - </string> - <string name="effect_Halloween 2010 Bonus"> - Halloween_2010_Bonus - </string> - <string name="effect_Helium"> - Elio - </string> - <string name="effect_Husky"> - Fusto - </string> - <string name="effect_Husky Whisper"> - Sospiro rauco - </string> - <string name="effect_Intercom"> - Interfono - </string> - <string name="effect_Julia"> - Julia - </string> - <string name="effect_Lo Lilt"> - Inflessione bassa - </string> - <string name="effect_Macho"> - Macho - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Model"> - Modella - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Incubo - </string> - <string name="effect_PopBot"> - PopBot - </string> - <string name="effect_Rachel"> - Rachele - </string> - <string name="effect_Radio"> - Radio - </string> - <string name="effect_Robot"> - Robot - </string> - <string name="effect_Roxanne"> - Rosanna - </string> - <string name="effect_Rumble"> - Rombo - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samanta - </string> - <string name="effect_Sexy"> - Sexy - </string> - <string name="effect_Shorty"> - Bassotto - </string> - <string name="effect_Smaller"> - Più piccolo - </string> - <string name="effect_Sneaky"> - Vile - </string> - <string name="effect_Stallion"> - Stallone - </string> - <string name="effect_Sultry"> - Focoso - </string> - <string name="effect_Thunder"> - Tuono - </string> - <string name="effect_Vixen"> - Maliziosa - </string> - <string name="effect_WhinyBot"> - PiangiBot - </string> - <text name="preview_text"> - Per l'anteprima - </text> - <text name="status_text"> - Registra un campione di voce, quindi fai clic su un effetto per ascoltare il risultato. - </text> - <button label="Registra" name="record_btn" tool_tip="Registra un campione della tua voce."/> - <button label="Ferma" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Subscribe Now] - </text> - <scroll_list name="voice_effect_list" tool_tip="Registra un campione della tua voce, quindi fai clic su uno degli effetti per un'anteprima del risultato."> - <scroll_list.columns label="Nome effetto" name="name"/> - <scroll_list.columns label="Scade il" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/it/panel_voice_effect.xml b/indra/newview/skins/default/xui/it/panel_voice_effect.xml deleted file mode 100644 index b43f766e5e..0000000000 --- a/indra/newview/skins/default/xui/it/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Disattiva manipolazione voce - </string> - <string name="preview_voice_effects"> - Anteprima manipolazione voce ▶ - </string> - <string name="get_voice_effects"> - Ottieni manipolazione voce ▶ - </string> - <combo_box name="voice_effect" tool_tip="Scegli un effetto di manipolazione per modificare il suono della tua voce"> - <combo_box.item label="Disattiva manipolazione voce" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/ja/floater_big_preview.xml b/indra/newview/skins/default/xui/ja/floater_big_preview.xml deleted file mode 100644 index e88d6fc488..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="プレビュー"/>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/ja/floater_post_process.xml b/indra/newview/skins/default/xui/ja/floater_post_process.xml deleted file mode 100644 index 91ecbb73a2..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="ポストプロセス設定"> - <tab_container name="Post-Process Tabs"> - <panel label="カラー・フィルタ" name="wmiColorFilterPanel"> - <check_box label="有効" name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - 明度 - </text> - <text name="wmiColorFilterSaturationText"> - 彩度 - </text> - <text name="wmiColorFilterContrastText"> - 輝度 - </text> - <text name="wmiColorFilterBaseText"> - 輝度の基準色 - </text> - <slider label="赤" name="wmiColorFilterBaseR"/> - <slider label="緑" name="wmiColorFilterBaseG"/> - <slider label="青" name="wmiColorFilterBaseB"/> - <slider label="I" name="wmiColorFilterBaseI"/> - </panel> - <panel label="暗視" name="wmiNightVisionPanel"> - <check_box label="有効" name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - 光の増幅(マルチ) - </text> - <text name="wmiNightVisionNoiseSizeText"> - ノイズ・サイズ - </text> - <text name="wmiNightVisionNoiseStrengthText"> - ノイズ強度 - </text> - </panel> - <panel label="ブルーム" name="wmiBloomPanel"> - <check_box label="有効" name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - 明度の抽出 - </text> - <text name="wmiBloomSizeText"> - ブルーム・サイズ - </text> - <text name="wmiBloomStrengthText"> - ブルーム強度 - </text> - </panel> - <panel label="その他" name="Extras"> - <button label="効果読み込み" label_selected="効果読み込み" name="PPLoadEffect"/> - <button label="効果保存" label_selected="効果保存" name="PPSaveEffect"/> - <line_editor label="効果名" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_sound_devices.xml b/indra/newview/skins/default/xui/ja/floater_sound_devices.xml deleted file mode 100644 index 28d2388bed..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="サウンドデバイス"> - <text name="voice_label"> - ボイスチャット - </text> - <check_box label="有効" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_voice_effect.xml b/indra/newview/skins/default/xui/ja/floater_voice_effect.xml deleted file mode 100644 index b38ea9331a..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="場所" name="voice_effects" title="ボイスモーフィングのプレビュー"> - <string name="no_voice_effect"> - (ボイスモーフィングなし) - </string> - <string name="active_voice_effect"> - (アクティブ) - </string> - <string name="unsubscribed_voice_effect"> - (取消し済み) - </string> - <string name="new_voice_effect"> - (新登場!) - </string> - <string name="effect_Arena"> - アリーナ - </string> - <string name="effect_Beast"> - 野獣 - </string> - <string name="effect_Buff"> - がっしり - </string> - <string name="effect_Buzz"> - ブザー - </string> - <string name="effect_Camille"> - カミール - </string> - <string name="effect_Creepy"> - 気味の悪い - </string> - <string name="effect_CreepyBot"> - 気味わるボット - </string> - <string name="effect_Cyber"> - サイバー - </string> - <string name="effect_DeepBot"> - ディープボット - </string> - <string name="effect_Demon"> - デーモン - </string> - <string name="effect_Female Elf"> - 女性のエルフ - </string> - <string name="effect_Flirty"> - 気のありそうな - </string> - <string name="effect_Foxy"> - 魅惑的 - </string> - <string name="effect_Halloween 2010 Bonus"> - ハロウィン_2010_ボーナス - </string> - <string name="effect_Helium"> - ヘリウム - </string> - <string name="effect_Husky"> - ハスキー - </string> - <string name="effect_Husky Whisper"> - スモーキーウィスパー - </string> - <string name="effect_Intercom"> - インターホン - </string> - <string name="effect_Julia"> - ジュリア - </string> - <string name="effect_Lo Lilt"> - 軽快 - </string> - <string name="effect_Macho"> - マッチョ - </string> - <string name="effect_Micro"> - ミクロ - </string> - <string name="effect_Mini"> - ミニ - </string> - <string name="effect_Model"> - モデル - </string> - <string name="effect_Nano"> - ナノ - </string> - <string name="effect_Nightmare"> - 悪夢 - </string> - <string name="effect_PopBot"> - ポップボット - </string> - <string name="effect_Rachel"> - レイチェル - </string> - <string name="effect_Radio"> - ラジオ - </string> - <string name="effect_Robot"> - ロボット - </string> - <string name="effect_Roxanne"> - ロクサン - </string> - <string name="effect_Rumble"> - ランブル - </string> - <string name="effect_Sabrina"> - サブリナ - </string> - <string name="effect_Samantha"> - サマンサ - </string> - <string name="effect_Sexy"> - セクシー - </string> - <string name="effect_Shorty"> - チビ - </string> - <string name="effect_Smaller"> - 小さめ - </string> - <string name="effect_Sneaky"> - コソコソ - </string> - <string name="effect_Stallion"> - 雄馬 - </string> - <string name="effect_Sultry"> - 艶かしい - </string> - <string name="effect_Thunder"> - サンダー - </string> - <string name="effect_Vixen"> - 性悪な - </string> - <string name="effect_WhinyBot"> - 不機嫌ボット - </string> - <text name="preview_text"> - プレビュー - </text> - <text name="status_text"> - 声をテスト録音してからボイスエフェクトを1つクリックして聞いてみます。 - </text> - <button label="録音" name="record_btn" tool_tip="あなたの声を録音します。"/> - <button label="停止" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] 今すぐ申し込む] - </text> - <scroll_list name="voice_effect_list" tool_tip="声を録音してボイスモーフィングを1つクリックすると、そのエフェクトをプレビューできます。"> - <scroll_list.columns label="ボイス名" name="name"/> - <scroll_list.columns label="有効期限" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/ja/panel_voice_effect.xml b/indra/newview/skins/default/xui/ja/panel_voice_effect.xml deleted file mode 100644 index 57a1bb7838..0000000000 --- a/indra/newview/skins/default/xui/ja/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - ボイスモーフィングなし - </string> - <string name="preview_voice_effects"> - ボイスモーフィングをプレビュー - </string> - <string name="get_voice_effects"> - ボイスモーフィングを取得 - </string> - <combo_box name="voice_effect" tool_tip="ボイスモーフィングを選択してボイスを変更"> - <combo_box.item label="ボイスモーフィングなし" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/pl/floater_big_preview.xml b/indra/newview/skins/default/xui/pl/floater_big_preview.xml deleted file mode 100644 index e730cff618..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> -<floater name="floater_big_preview" title="PODGLĄD" /> diff --git a/indra/newview/skins/default/xui/pl/floater_post_process.xml b/indra/newview/skins/default/xui/pl/floater_post_process.xml deleted file mode 100644 index 47c40d2315..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_post_process.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="Post-Process Floater" title="USTAWIENIA PRZETWARZANIA KOŃCOWEGO"> - <tab_container name="Post-Process Tabs"> - <panel label="Filtr koloru" name="wmiColorFilterPanel"> - <check_box label="Włącz" name="wmiColorFilterToggle" /> - <text name="wmiColorFilterBrightnessText"> - Jasność - </text> - <text name="wmiColorFilterSaturationText"> - Nasycenie - </text> - <text name="wmiColorFilterContrastText"> - Kontrast - </text> - <text name="wmiColorFilterBaseText"> - Kontrast koloru podstawowego - </text> - </panel> - <panel label="Noktowizja" name="wmiNightVisionPanel"> - <check_box label="Włącz" name="wmiNightVisionToggle" /> - <text name="wmiNightVisionBrightMultText"> - Wielokrotne wzmocnienie światła - </text> - <text name="wmiNightVisionNoiseSizeText"> - Rozmiar szumu - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Moc szumu - </text> - </panel> - <panel label="Poświata" name="wmiBloomPanel"> - <check_box label="Włącz" name="wmiBloomToggle" /> - <text name="wmiBloomExtractText"> - Ekstracja luminacji - </text> - <text name="wmiBloomSizeText"> - Rozmiar poświaty - </text> - <text name="wmiBloomStrengthText"> - Moc poświaty - </text> - </panel> - <panel label="Dodatki" name="Extras"> - <button label="Wczytaj efekt" label_selected="Wczytaj efekt" name="PPLoadEffect" /> - <button label="Zapisz efekt" label_selected="Zapisz efekt" name="PPSaveEffect" /> - <line_editor label="Nazwa efektu" name="PPEffectNameEditor" /> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_sound_devices.xml b/indra/newview/skins/default/xui/pl/floater_sound_devices.xml deleted file mode 100644 index 93a27f68a7..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="floater_sound_devices" title="URZĄDZENIA DŹWIĘKOWE"> - <text name="voice_label"> - Czat głos. - </text> - <check_box name="enable_voice" label="Włączone" /> -</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_voice_effect.xml b/indra/newview/skins/default/xui/pl/floater_voice_effect.xml deleted file mode 100644 index b02266caa9..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_voice_effect.xml +++ /dev/null @@ -1,98 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater name="voice_effects" title="PODGLĄD PRZEKSZTAŁCANIA GŁOSU" label="Miejsca"> - <string name="no_voice_effect"> - (Bez Przekształcania) - </string> - <string name="active_voice_effect"> - (Aktywny) - </string> - <string name="unsubscribed_voice_effect"> - (Bez subskrybcji) - </string> - <string name="new_voice_effect"> - (Nowy!) - </string> - <string name="effect_Beast"> - Bestia - </string> - <string name="effect_Buzz"> - Brzęczenie - </string> - <string name="effect_Creepy"> - Przerażający - </string> - <string name="effect_Cyber"> - Cybernetyczny - </string> - <string name="effect_Female Elf"> - Kobiecy Elf - </string> - <string name="effect_Flirty"> - Flirt - </string> - <string name="effect_Foxy"> - Ponętny - </string> - <string name="effect_Helium"> - Hel - </string> - <string name="effect_Husky Whisper"> - Szept Husky - </string> - <string name="effect_Macho"> - Maczo - </string> - <string name="effect_Micro"> - Mikrus - </string> - <string name="effect_Mini"> - Miniaturowy - </string> - <string name="effect_Nano"> - Malutki - </string> - <string name="effect_Nightmare"> - Koszmar - </string> - <string name="effect_Rumble"> - Burczenie - </string> - <string name="effect_Sexy"> - Seksowny - </string> - <string name="effect_Shorty"> - Krótki - </string> - <string name="effect_Smaller"> - Mniejszy - </string> - <string name="effect_Sneaky"> - Podstępny - </string> - <string name="effect_Stallion"> - Ogier - </string> - <string name="effect_Sultry"> - Gorąco - </string> - <string name="effect_Thunder"> - Grzmot - </string> - <string name="effect_Vixen"> - Lisica - </string> - <text name="preview_text"> - Podgląd - </text> - <text name="status_text"> - Nagraj próbkę, a następnie kliknij na głos aby usłyszeć jego brzmienie. - </text> - <button label="Nagraj" name="record_btn" tool_tip="Nagraj próbkę swojego głosu." /> - <text name="voice_morphing_link"> - [[URL] Subskrybuj teraz] - </text> - <scroll_list name="voice_effect_list" tool_tip="Nagraj próbkę swojego głosu, a następnie kliknij na efekt aby odsłuchać podgląd."> - <scroll_list.columns label="Nazwa głosu" name="name" /> - <scroll_list.columns label="Wygasa" name="expires" /> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/pl/panel_voice_effect.xml b/indra/newview/skins/default/xui/pl/panel_voice_effect.xml deleted file mode 100644 index 94878943a1..0000000000 --- a/indra/newview/skins/default/xui/pl/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Wyłącz Przekształcanie - </string> - <string name="preview_voice_effects"> - Przeglądaj Przekształcania ▶ - </string> - <string name="get_voice_effects"> - Uzyskaj Przekształcanie ▶ - </string> - <combo_box name="voice_effect" tool_tip="Wybierz odpowienie Przekształcanie Głosu, aby zmienić brzmienie swojego głosu"> - <combo_box.item label="Wyłącz Przekształcanie" name="no_voice_effect" /> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/pt/floater_big_preview.xml b/indra/newview/skins/default/xui/pt/floater_big_preview.xml deleted file mode 100644 index 76ca176689..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="VISUALIZAR"/> diff --git a/indra/newview/skins/default/xui/pt/floater_post_process.xml b/indra/newview/skins/default/xui/pt/floater_post_process.xml deleted file mode 100644 index d4f2e96539..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="AJUSTES DE PÓS-PROCESSAMENTO"> - <tab_container name="Post-Process Tabs"> - <panel label="Filtro de Cor" name="wmiColorFilterPanel"> - <check_box label="Habilitar" name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - Brilho - </text> - <text name="wmiColorFilterSaturationText"> - Saturação - </text> - <text name="wmiColorFilterContrastText"> - Contraste - </text> - <text name="wmiColorFilterBaseText"> - Cor Base do Contraste - </text> - <slider label="R" name="wmiColorFilterBaseR"/> - <slider label="G" name="wmiColorFilterBaseG"/> - <slider label="B" name="wmiColorFilterBaseB"/> - <slider label="I" name="wmiColorFilterBaseI"/> - </panel> - <panel label="visão Noturna" name="wmiNightVisionPanel"> - <check_box label="Habilitar" name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - Múltiplo de Amplificação de Luz - </text> - <text name="wmiNightVisionNoiseSizeText"> - Tamanho de Ruído - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Intensidade de Ruído - </text> - </panel> - <panel label="Florescência" name="wmiBloomPanel"> - <check_box label="Habilitar" name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - Extração de Luminosidade - </text> - <text name="wmiBloomSizeText"> - Tamanho da florescência - </text> - <text name="wmiBloomStrengthText"> - Inensidade da florescência - </text> - </panel> - <panel label="Extras" name="Extras"> - <button label="CarregaEfeito" label_selected="CarregaEfeito" name="PPLoadEffect"/> - <button label="SalvaEfeito" label_selected="SalvaEfeito" name="PPSaveEffect"/> - <line_editor label="Nome do Efeito" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_sound_devices.xml b/indra/newview/skins/default/xui/pt/floater_sound_devices.xml deleted file mode 100644 index 948d727540..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="DISPOSITIVOS DE SOM"> - <text name="voice_label"> - Bate-papo de voz - </text> - <check_box label="Ativado" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml deleted file mode 100644 index 71d3c33ae5..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Lugares" name="voice_effects" title="AMOSTRA DE DISTORÇÃO DE VOZ"> - <string name="no_voice_effect"> - (Não distorcer voz) - </string> - <string name="active_voice_effect"> - (Ativo) - </string> - <string name="unsubscribed_voice_effect"> - (Cancelou) - </string> - <string name="new_voice_effect"> - (Novo!) - </string> - <string name="effect_Arena"> - Arena - </string> - <string name="effect_Beast"> - Fera - </string> - <string name="effect_Buff"> - Entusiasmado - </string> - <string name="effect_Buzz"> - Zumbido - </string> - <string name="effect_Camille"> - Camille - </string> - <string name="effect_Creepy"> - Assustador - </string> - <string name="effect_CreepyBot"> - RobôAssustador - </string> - <string name="effect_Cyber"> - Cyber - </string> - <string name="effect_DeepBot"> - RobôVozGrossa - </string> - <string name="effect_Demon"> - Demônio - </string> - <string name="effect_Female Elf"> - Elfa - </string> - <string name="effect_Flirty"> - Paquerador - </string> - <string name="effect_Foxy"> - Sensual - </string> - <string name="effect_Halloween 2010 Bonus"> - Bônus_Halloween_2010 - </string> - <string name="effect_Helium"> - Hélio - </string> - <string name="effect_Husky"> - Rouco - </string> - <string name="effect_Husky Whisper"> - Sussurro rouco - </string> - <string name="effect_Intercom"> - Interfone - </string> - <string name="effect_Julia"> - Julia - </string> - <string name="effect_Lo Lilt"> - Cantarolado baixo - </string> - <string name="effect_Macho"> - Macho - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Model"> - Modelo - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Pesadelo - </string> - <string name="effect_PopBot"> - RobôPop - </string> - <string name="effect_Rachel"> - Rachel - </string> - <string name="effect_Radio"> - Rádio - </string> - <string name="effect_Robot"> - Robô - </string> - <string name="effect_Roxanne"> - Roxanne - </string> - <string name="effect_Rumble"> - Ronco - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samantha - </string> - <string name="effect_Sexy"> - Sexy - </string> - <string name="effect_Shorty"> - Baixinho - </string> - <string name="effect_Smaller"> - Menor - </string> - <string name="effect_Sneaky"> - Sorrateiro - </string> - <string name="effect_Stallion"> - Garanhão - </string> - <string name="effect_Sultry"> - Ardente - </string> - <string name="effect_Thunder"> - Trovão - </string> - <string name="effect_Vixen"> - Maliciosa - </string> - <string name="effect_WhinyBot"> - RobôReclamão - </string> - <text name="preview_text"> - Visualizar - </text> - <text name="status_text"> - Grave uma amostra da sua voz, depois clique em um efeito para ouvir o resultado. - </text> - <button label="Gravar" name="record_btn" tool_tip="Grave uma amostra da sua voz."/> - <button label="Parar" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Assine agora] - </text> - <scroll_list name="voice_effect_list" tool_tip="Grave sua voz por alguns instantes, depois clique num efeito para ouvir a distorção."> - <scroll_list.columns label="Nome da voz" name="name"/> - <scroll_list.columns label="Vence em" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/pt/panel_voice_effect.xml b/indra/newview/skins/default/xui/pt/panel_voice_effect.xml deleted file mode 100644 index 1d7878408a..0000000000 --- a/indra/newview/skins/default/xui/pt/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Distorção de voz desligada - </string> - <string name="preview_voice_effects"> - Checar distorção de voz ▶ - </string> - <string name="get_voice_effects"> - Distorcer voz ▶ - </string> - <combo_box name="voice_effect" tool_tip="Selecione um efeito de distorção para mudar sua voz."> - <combo_box.item label="Distorção de voz desligada" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/ru/floater_big_preview.xml b/indra/newview/skins/default/xui/ru/floater_big_preview.xml deleted file mode 100644 index cdacebadef..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="ПРОСМОТР"/> diff --git a/indra/newview/skins/default/xui/ru/floater_post_process.xml b/indra/newview/skins/default/xui/ru/floater_post_process.xml deleted file mode 100644 index ae97670548..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="НАСТРОЙКИ ПОСЛЕДУЮЩЕЙ ОБРАБОТКИ"> - <tab_container name="Post-Process Tabs"> - <panel label="Цветовой фильтр" name="wmiColorFilterPanel"> - <check_box label="Вкл." name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - Яркость - </text> - <text name="wmiColorFilterSaturationText"> - Насыщенность - </text> - <text name="wmiColorFilterContrastText"> - Контрастность - </text> - <text name="wmiColorFilterBaseText"> - Основной цвет контрастности - </text> - <slider label="К" name="wmiColorFilterBaseR"/> - <slider label="З" name="wmiColorFilterBaseG"/> - <slider label="С" name="wmiColorFilterBaseB"/> - <slider label="И" name="wmiColorFilterBaseI"/> - </panel> - <panel label="Ночное видение" name="wmiNightVisionPanel"> - <check_box label="Вкл." name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - Коэффициент усиления света - </text> - <text name="wmiNightVisionNoiseSizeText"> - Размер искажений - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Мощность искажений - </text> - </panel> - <panel label="Ореол" name="wmiBloomPanel"> - <check_box label="Вкл." name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - Яркость света - </text> - <text name="wmiBloomSizeText"> - Размер ореола - </text> - <text name="wmiBloomStrengthText"> - Мощность ореола - </text> - </panel> - <panel label="Дополнительно" name="Extras"> - <button label="Загрузить эффект" label_selected="Загрузить эффект" name="PPLoadEffect"/> - <button label="Сохранить эффект" label_selected="Сохранить эффект" name="PPSaveEffect"/> - <line_editor label="Название эффекта" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_sound_devices.xml b/indra/newview/skins/default/xui/ru/floater_sound_devices.xml deleted file mode 100644 index fc8de858cd..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="ЗВУКОВЫЕ УСТРОЙСТВА"> - <text name="voice_label"> - Голосовой чат - </text> - <check_box label="Включен" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_voice_effect.xml b/indra/newview/skins/default/xui/ru/floater_voice_effect.xml deleted file mode 100644 index d3cef042a3..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Места" name="voice_effects" title="ПРОСМОТР ИЗМЕНЕНИЯ ГОЛОСА"> - <string name="no_voice_effect"> - (Нет изменения голоса) - </string> - <string name="active_voice_effect"> - (Активно) - </string> - <string name="unsubscribed_voice_effect"> - (Нет подписки) - </string> - <string name="new_voice_effect"> - (Новый!) - </string> - <string name="effect_Arena"> - Arena - </string> - <string name="effect_Beast"> - Beast - </string> - <string name="effect_Buff"> - Buff - </string> - <string name="effect_Buzz"> - Buzz - </string> - <string name="effect_Camille"> - Camille - </string> - <string name="effect_Creepy"> - Creepy - </string> - <string name="effect_CreepyBot"> - CreepyBot - </string> - <string name="effect_Cyber"> - Cyber - </string> - <string name="effect_DeepBot"> - DeepBot - </string> - <string name="effect_Demon"> - Demon - </string> - <string name="effect_Female Elf"> - Фея - </string> - <string name="effect_Flirty"> - Flirty - </string> - <string name="effect_Foxy"> - Foxy - </string> - <string name="effect_Halloween 2010 Bonus"> - Бонус_за_Хэллоуин_2010 - </string> - <string name="effect_Helium"> - Helium - </string> - <string name="effect_Husky"> - Husky - </string> - <string name="effect_Husky Whisper"> - Хриплый шепот - </string> - <string name="effect_Intercom"> - Внутренняя связь - </string> - <string name="effect_Julia"> - Julia - </string> - <string name="effect_Lo Lilt"> - Напев - </string> - <string name="effect_Macho"> - Macho - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Model"> - Модель - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Nightmare - </string> - <string name="effect_PopBot"> - PopBot - </string> - <string name="effect_Rachel"> - Rachel - </string> - <string name="effect_Radio"> - Radio - </string> - <string name="effect_Robot"> - Robot - </string> - <string name="effect_Roxanne"> - Roxanne - </string> - <string name="effect_Rumble"> - Урчание - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samantha - </string> - <string name="effect_Sexy"> - Sexy - </string> - <string name="effect_Shorty"> - Shorty - </string> - <string name="effect_Smaller"> - Меньше - </string> - <string name="effect_Sneaky"> - Sneaky - </string> - <string name="effect_Stallion"> - Stallion - </string> - <string name="effect_Sultry"> - Sultry - </string> - <string name="effect_Thunder"> - Thunder - </string> - <string name="effect_Vixen"> - Vixen - </string> - <string name="effect_WhinyBot"> - WhinyBot - </string> - <text name="preview_text"> - Прослушивание - </text> - <text name="status_text"> - Запишите образец, затем щелкните, чтобы услышать, как будет звучать голос. - </text> - <button label="Запись" name="record_btn" tool_tip="Записать образец вашего голоса."/> - <button label="Стоп" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Подписаться] - </text> - <scroll_list name="voice_effect_list" tool_tip="Запишите образец вашего голоса, затем щелкните, чтобы прослушать эффект."> - <scroll_list.columns label="Название голоса" name="name"/> - <scroll_list.columns label="Истекает" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/ru/panel_voice_effect.xml b/indra/newview/skins/default/xui/ru/panel_voice_effect.xml deleted file mode 100644 index de0b38198f..0000000000 --- a/indra/newview/skins/default/xui/ru/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Изменение голоса отключено - </string> - <string name="preview_voice_effects"> - Прослушать изменение голоса ▶ - </string> - <string name="get_voice_effects"> - Приобрести изменение голоса ▶ - </string> - <combo_box name="voice_effect" tool_tip="Выбор типа изменения для своего голоса"> - <combo_box.item label="Изменение голоса отключено" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/tr/floater_big_preview.xml b/indra/newview/skins/default/xui/tr/floater_big_preview.xml deleted file mode 100644 index c99a71d3c2..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="ÖNİZLEME"/> diff --git a/indra/newview/skins/default/xui/tr/floater_post_process.xml b/indra/newview/skins/default/xui/tr/floater_post_process.xml deleted file mode 100644 index 5e419f8ffa..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="İŞLEM SONRASI AYARLARI"> - <tab_container name="Post-Process Tabs"> - <panel label="Renk Filtresi" name="wmiColorFilterPanel"> - <check_box label="Etkinleştir" name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - Parlaklık - </text> - <text name="wmiColorFilterSaturationText"> - Doygunluk - </text> - <text name="wmiColorFilterContrastText"> - Kontrast - </text> - <text name="wmiColorFilterBaseText"> - Kontrast Baz Rengi - </text> - <slider label="R" name="wmiColorFilterBaseR"/> - <slider label="G" name="wmiColorFilterBaseG"/> - <slider label="B" name="wmiColorFilterBaseB"/> - <slider label="I" name="wmiColorFilterBaseI"/> - </panel> - <panel label="Gece Görüşü" name="wmiNightVisionPanel"> - <check_box label="Etkinleştir" name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - Işık Yükseltme Çarpanı - </text> - <text name="wmiNightVisionNoiseSizeText"> - Gürültü Büyüklüğü - </text> - <text name="wmiNightVisionNoiseStrengthText"> - Gürültü Gücü - </text> - </panel> - <panel label="Işıma" name="wmiBloomPanel"> - <check_box label="Etkinleştir" name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - Parlaklık Çıkarma - </text> - <text name="wmiBloomSizeText"> - Işıma Büyüklüğü - </text> - <text name="wmiBloomStrengthText"> - Işıma Gücü - </text> - </panel> - <panel label="Ekstralar" name="Extras"> - <button label="EfektYükle" label_selected="EfektYükle" name="PPLoadEffect"/> - <button label="EfektKaydet" label_selected="EfektKaydet" name="PPSaveEffect"/> - <line_editor label="Efekt Adı" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_sound_devices.xml b/indra/newview/skins/default/xui/tr/floater_sound_devices.xml deleted file mode 100644 index 470a222d7e..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="SES CİHAZLARI"> - <text name="voice_label"> - Sesli Sohbet - </text> - <check_box label="Etkin" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_voice_effect.xml b/indra/newview/skins/default/xui/tr/floater_voice_effect.xml deleted file mode 100644 index 7a157244cd..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="Yerler" name="voice_effects" title="SES ŞEKİLLENDİRME ÖNİZLEMESİ"> - <string name="no_voice_effect"> - (Ses Şekillendirme Yok) - </string> - <string name="active_voice_effect"> - (Etkin) - </string> - <string name="unsubscribed_voice_effect"> - (Abonelik İptal) - </string> - <string name="new_voice_effect"> - (Yeni!) - </string> - <string name="effect_Arena"> - Arena - </string> - <string name="effect_Beast"> - Yaratık - </string> - <string name="effect_Buff"> - Yapılı - </string> - <string name="effect_Buzz"> - Vızıltı - </string> - <string name="effect_Camille"> - Camille - </string> - <string name="effect_Creepy"> - Korkutucu - </string> - <string name="effect_CreepyBot"> - KorkutucuBot - </string> - <string name="effect_Cyber"> - Siber - </string> - <string name="effect_DeepBot"> - DerinBot - </string> - <string name="effect_Demon"> - İblis - </string> - <string name="effect_Female Elf"> - Dişi Cin - </string> - <string name="effect_Flirty"> - Cilveli - </string> - <string name="effect_Foxy"> - Alımlı - </string> - <string name="effect_Halloween 2010 Bonus"> - Halloween_2010_Bonus - </string> - <string name="effect_Helium"> - Helyum - </string> - <string name="effect_Husky"> - Güçlü - </string> - <string name="effect_Husky Whisper"> - Boğuk Fısıltı - </string> - <string name="effect_Intercom"> - İnterkom - </string> - <string name="effect_Julia"> - Julia - </string> - <string name="effect_Lo Lilt"> - Yavaş Mırıltı - </string> - <string name="effect_Macho"> - Maço - </string> - <string name="effect_Micro"> - Mikro - </string> - <string name="effect_Mini"> - Mini - </string> - <string name="effect_Model"> - Model - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - Kabus - </string> - <string name="effect_PopBot"> - PopBot - </string> - <string name="effect_Rachel"> - Rachel - </string> - <string name="effect_Radio"> - Radyo - </string> - <string name="effect_Robot"> - Robot - </string> - <string name="effect_Roxanne"> - Roxanne - </string> - <string name="effect_Rumble"> - Gurultu - </string> - <string name="effect_Sabrina"> - Sabrina - </string> - <string name="effect_Samantha"> - Samantha - </string> - <string name="effect_Sexy"> - Seksi - </string> - <string name="effect_Shorty"> - Bücür - </string> - <string name="effect_Smaller"> - Daha Küçük - </string> - <string name="effect_Sneaky"> - Sinsi - </string> - <string name="effect_Stallion"> - Maskülen - </string> - <string name="effect_Sultry"> - İhtiraslı - </string> - <string name="effect_Thunder"> - Gök gürültüsü - </string> - <string name="effect_Vixen"> - Çekici - </string> - <string name="effect_WhinyBot"> - AğlakBot - </string> - <text name="preview_text"> - Önizleme için - </text> - <text name="status_text"> - Bir örnek kaydettikten sonra sese tıklayarak nasıl olduğunu duyun. - </text> - <button label="Kaydet" name="record_btn" tool_tip="Sesinizin örneğini kaydedin."/> - <button label="Durdur" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] Hemen Abone Ol] - </text> - <scroll_list name="voice_effect_list" tool_tip="Sesinizin örneğini kaydettikten sonra önizleme için bir efekte tıklayın."> - <scroll_list.columns label="Ses Adı" name="name"/> - <scroll_list.columns label="Bitiş Tarihi" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/tr/panel_voice_effect.xml b/indra/newview/skins/default/xui/tr/panel_voice_effect.xml deleted file mode 100644 index b46833d7e6..0000000000 --- a/indra/newview/skins/default/xui/tr/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - Ses Şekillendirme Kapalı - </string> - <string name="preview_voice_effects"> - Ses Şekillendirme Önizleme ▶ - </string> - <string name="get_voice_effects"> - Ses Şekillendirmeyi Etkinleştir ▶ - </string> - <combo_box name="voice_effect" tool_tip="Sesinizi değiştirmek için bir Ses Şekli seçin"> - <combo_box.item label="Ses Şekillendirme Kapalı" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/skins/default/xui/zh/floater_big_preview.xml b/indra/newview/skins/default/xui/zh/floater_big_preview.xml deleted file mode 100644 index ae68cd7ddf..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_big_preview.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_big_preview" title="預覽"/> diff --git a/indra/newview/skins/default/xui/zh/floater_post_process.xml b/indra/newview/skins/default/xui/zh/floater_post_process.xml deleted file mode 100644 index 2908f7c1d0..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_post_process.xml +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Post-Process Floater" title="後處理設定:"> - <tab_container name="Post-Process Tabs"> - <panel label="顏色過濾" name="wmiColorFilterPanel"> - <check_box label="啟用" name="wmiColorFilterToggle"/> - <text name="wmiColorFilterBrightnessText"> - 亮度 - </text> - <text name="wmiColorFilterSaturationText"> - 飽和度 - </text> - <text name="wmiColorFilterContrastText"> - 對比 - </text> - <text name="wmiColorFilterBaseText"> - 對比基本色 - </text> - <slider label="R" name="wmiColorFilterBaseR"/> - <slider label="G" name="wmiColorFilterBaseG"/> - <slider label="B" name="wmiColorFilterBaseB"/> - <slider label="I" name="wmiColorFilterBaseI"/> - </panel> - <panel label="夜視" name="wmiNightVisionPanel"> - <check_box label="啟用" name="wmiNightVisionToggle"/> - <text name="wmiNightVisionBrightMultText"> - 光放大倍數 - </text> - <text name="wmiNightVisionNoiseSizeText"> - 噪音規模 - </text> - <text name="wmiNightVisionNoiseStrengthText"> - 噪音強度 - </text> - </panel> - <panel label="開花" name="wmiBloomPanel"> - <check_box label="啟用" name="wmiBloomToggle"/> - <text name="wmiBloomExtractText"> - 光度萃取 - </text> - <text name="wmiBloomSizeText"> - 開花大小 - </text> - <text name="wmiBloomStrengthText"> - 開花強度 - </text> - </panel> - <panel label="其他" name="Extras"> - <button label="LoadEffect" label_selected="LoadEffect" name="PPLoadEffect"/> - <button label="SaveEffect" label_selected="SaveEffect" name="PPSaveEffect"/> - <line_editor label="效果名稱" name="PPEffectNameEditor"/> - </panel> - </tab_container> -</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_sound_devices.xml b/indra/newview/skins/default/xui/zh/floater_sound_devices.xml deleted file mode 100644 index 0374c74f8f..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_sound_devices.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_sound_devices" title="聲音裝置"> - <text name="voice_label"> - 語音聊天 - </text> - <check_box label="已啟用" name="enable_voice"/> -</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_voice_effect.xml b/indra/newview/skins/default/xui/zh/floater_voice_effect.xml deleted file mode 100644 index aab5fa6028..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_voice_effect.xml +++ /dev/null @@ -1,159 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater label="地點" name="voice_effects" title="語音變聲試聽"> - <string name="no_voice_effect"> - (無變聲效果) - </string> - <string name="active_voice_effect"> - (使用中) - </string> - <string name="unsubscribed_voice_effect"> - (已停止訂用) - </string> - <string name="new_voice_effect"> - (新的!) - </string> - <string name="effect_Arena"> - 競技場 - </string> - <string name="effect_Beast"> - 野獸 - </string> - <string name="effect_Buff"> - Buff - </string> - <string name="effect_Buzz"> - Buzz - </string> - <string name="effect_Camille"> - 卡蜜兒 - </string> - <string name="effect_Creepy"> - 怪異 - </string> - <string name="effect_CreepyBot"> - 怪異機器人 - </string> - <string name="effect_Cyber"> - 科幻 - </string> - <string name="effect_DeepBot"> - 深沉機器人 - </string> - <string name="effect_Demon"> - 魔鬼 - </string> - <string name="effect_Female Elf"> - 女性 - 小精靈 - </string> - <string name="effect_Flirty"> - 調情 - </string> - <string name="effect_Foxy"> - 香豔 - </string> - <string name="effect_Halloween 2010 Bonus"> - 2010萬聖節加贈 - </string> - <string name="effect_Helium"> - 氦氣 - </string> - <string name="effect_Husky"> - 沙啞 - </string> - <string name="effect_Husky Whisper"> - 沙啞耳語 - </string> - <string name="effect_Intercom"> - 對講機 - </string> - <string name="effect_Julia"> - 茱莉亞 - </string> - <string name="effect_Lo Lilt"> - 輕微抑揚頓挫 - </string> - <string name="effect_Macho"> - 陽剛 - </string> - <string name="effect_Micro"> - Micro - </string> - <string name="effect_Mini"> - 迷你 - </string> - <string name="effect_Model"> - 模型 - </string> - <string name="effect_Nano"> - Nano - </string> - <string name="effect_Nightmare"> - 惡夢 - </string> - <string name="effect_PopBot"> - PopBot - </string> - <string name="effect_Rachel"> - 瑞秋 - </string> - <string name="effect_Radio"> - 收音機 - </string> - <string name="effect_Robot"> - 機器人 - </string> - <string name="effect_Roxanne"> - 蘿姍 - </string> - <string name="effect_Rumble"> - 低沉隆隆聲 - </string> - <string name="effect_Sabrina"> - 薩賓娜 - </string> - <string name="effect_Samantha"> - 姍曼莎 - </string> - <string name="effect_Sexy"> - 性感 - </string> - <string name="effect_Shorty"> - 矮個兒 - </string> - <string name="effect_Smaller"> - 較小 - </string> - <string name="effect_Sneaky"> - 鬼祟 - </string> - <string name="effect_Stallion"> - 種馬 - </string> - <string name="effect_Sultry"> - 勾魂 - </string> - <string name="effect_Thunder"> - 雷聲 - </string> - <string name="effect_Vixen"> - 潑婦 - </string> - <string name="effect_WhinyBot"> - 哭鬧機器人 - </string> - <text name="preview_text"> - 預覽 - </text> - <text name="status_text"> - 錄下一段樣本,再點按聲音檢查結果。 - </text> - <button label="錄音" name="record_btn" tool_tip="錄下一段你的聲音。"/> - <button label="停止" name="record_stop_btn"/> - <text name="voice_morphing_link"> - [[URL] 現在訂用] - </text> - <scroll_list name="voice_effect_list" tool_tip="錄下一段你的聲音,再點選一個效果試聽。"> - <scroll_list.columns label="語音名稱" name="name"/> - <scroll_list.columns label="過期" name="expires"/> - </scroll_list> -</floater> diff --git a/indra/newview/skins/default/xui/zh/panel_voice_effect.xml b/indra/newview/skins/default/xui/zh/panel_voice_effect.xml deleted file mode 100644 index 6c8a452014..0000000000 --- a/indra/newview/skins/default/xui/zh/panel_voice_effect.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel name="panel_voice_effect"> - <string name="no_voice_effect"> - 關閉變聲效果 - </string> - <string name="preview_voice_effects"> - 預覽變聲效果 ▶ - </string> - <string name="get_voice_effects"> - 取得變聲效果 ▶ - </string> - <combo_box name="voice_effect" tool_tip="選取一個變聲效果來改變你的聲音"> - <combo_box.item label="關閉變聲效果" name="no_voice_effect"/> - </combo_box> -</panel> diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp index acbf019034..3e2e5e70a2 100644 --- a/indra/newview/tests/lldateutil_test.cpp +++ b/indra/newview/tests/lldateutil_test.cpp @@ -34,16 +34,16 @@ #include "lltrans.h" #include "llui.h" -#include <map> +#include <unordered_map> // Baked-in return values for getString() -std::map< std::string, std::string, std::less<>> gString; +std::unordered_map< std::string, std::string, ll::string_hash, std::equal_to<>> gString; // Baked-in return values for getCountString() // map of pairs of input xml_desc and integer count typedef std::pair< std::string, int > count_string_t; -std::map< count_string_t, std::string > gCountString; +std::map<count_string_t, std::string> gCountString; std::string LLTrans::getString(const std::string_view xml_desc, const LLStringUtil::format_map_t& args, bool def_string) { |
