diff --git a/doc/contributions.txt b/doc/contributions.txt index 02fafe6291..947fe19cfb 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -364,6 +364,8 @@ Chaser Zaks BUG-227485 Cherry Cheevers ChickyBabes Zuzu +Chorazin Allen + BUG-229753 Christopher Organiser Ciaran Laval Cinder Roxley diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index d74ee0bc85..259ed22d0c 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,6 +34,10 @@ #include #include "apr_base64.h" +// Add non-allocating variants of unzip_llsd +#include +#include +// #ifdef LL_USESYSTEMLIBS # include #else @@ -2177,60 +2181,223 @@ std::string zip_llsd(LLSD& data) // not very efficient -- creats a copy of decompressed LLSD block in memory // and deserializes from that copy using LLSDSerialize LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size) +{ + // Add non-allocating variants of unzip_llsd + // U8* result = NULL; + // U32 cur_size = 0; + // z_stream strm; + + // const U32 CHUNK = 65536; + + // U8 *in = new(std::nothrow) U8[size]; + // if (!in) + // { + // return ZR_MEM_ERROR; + // } + // is.read((char*) in, size); + + // U8 out[CHUNK]; + + // strm.zalloc = Z_NULL; + // strm.zfree = Z_NULL; + // strm.opaque = Z_NULL; + // strm.avail_in = size; + // strm.next_in = in; + + // S32 ret = inflateInit(&strm); + + // do + // { + // strm.avail_out = CHUNK; + // strm.next_out = out; + // ret = inflate(&strm, Z_NO_FLUSH); + // if (ret == Z_STREAM_ERROR) + // { + // LL_DEBUGS() << "Unzip error: Z_STREAM_ERROR" << LL_ENDL; // + // inflateEnd(&strm); + // // free(result); + // if( result ) + // free(result); + // delete [] in; + // return ZR_DATA_ERROR; + // } + + // switch (ret) + // { + // case Z_NEED_DICT: + // ret = Z_DATA_ERROR; + // case Z_DATA_ERROR: + // case Z_MEM_ERROR: + // LL_DEBUGS() << "Unzip error: " << ret << LL_ENDL; // + // inflateEnd(&strm); + // // free(result); + // if( result ) + // free(result); + // delete [] in; + // return ZR_MEM_ERROR; + // break; + // } + + // U32 have = CHUNK-strm.avail_out; + + // U8* new_result = (U8*)realloc(result, cur_size + have); + // if (new_result == NULL) + // { + // inflateEnd(&strm); + // if (result) + // { + // free(result); + // } + // delete[] in; + // return ZR_MEM_ERROR; + // } + // result = new_result; + // memcpy(result+cur_size, out, have); + // cur_size += have; + + // } while (ret == Z_OK); + + // inflateEnd(&strm); + // delete [] in; + + // if (ret != Z_STREAM_END) + // { + // LL_DEBUGS() << "Unzip error: !Z_STREAM_END" << LL_ENDL; // + // // free(result); + // if( result ) + // free(result); + // return ZR_DATA_ERROR; + // } + + // //result now points to the decompressed LLSD block + // { + // std::istringstream istr; + // // Since we are using this for meshes, data we are dealing with tend to be large. + // // So string can potentially fail to allocate, make sure this won't cause problems + // try + // { + // std::string res_str((char*)result, cur_size); + + // std::string deprecated_header(""); + + // if (res_str.substr(0, deprecated_header.size()) == deprecated_header) + // { + // res_str = res_str.substr(deprecated_header.size() + 1, cur_size); + // } + // cur_size = res_str.size(); + + // istr.str(res_str); + // } + // #ifdef LL_WINDOWS + // catch (std::length_error) + // { + // // free(result); + // if( result ) + // free(result); + // return ZR_SIZE_ERROR; + // } + // #endif + // catch (std::bad_alloc&) + // { + // // free(result); + // if( result ) + // free(result); + // return ZR_MEM_ERROR; + // } + + // if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) + // { + // // free(result); + // if( result ) + // free(result); + // return ZR_PARSE_ERROR; + // } + // } + + // // free(result); + // if( result ) + // free(result); + // return ZR_OK; + std::unique_ptr in; + try + { + in = std::unique_ptr(new U8[size]); + } + catch(const std::bad_alloc&) + { + return ZR_MEM_ERROR; + } + is.read((char*) in.get(), size); + + return unzip_llsd(data, in.get(), size); +} + +LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size) { U8* result = NULL; U32 cur_size = 0; z_stream strm; - const U32 CHUNK = 65536; + constexpr U32 CHUNK = 1024 * 256; - U8 *in = new(std::nothrow) U8[size]; - if (!in) + static thread_local std::unique_ptr out; + if (!out) { - return ZR_MEM_ERROR; + try + { + out = std::unique_ptr(new U8[CHUNK]); + } + catch (const std::bad_alloc&) + { + return ZR_MEM_ERROR; + } } - is.read((char*) in, size); - - U8 out[CHUNK]; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = size; - strm.next_in = in; + strm.next_in = const_cast(in); S32 ret = inflateInit(&strm); - + switch (ret) + { + case Z_STREAM_ERROR: + return ZR_DATA_ERROR; + case Z_VERSION_ERROR: + return ZR_VERSION_ERROR; + case Z_MEM_ERROR: + return ZR_MEM_ERROR; + } + do { strm.avail_out = CHUNK; - strm.next_out = out; + strm.next_out = out.get(); ret = inflate(&strm, Z_NO_FLUSH); - if (ret == Z_STREAM_ERROR) - { - LL_DEBUGS() << "Unzip error: Z_STREAM_ERROR" << LL_ENDL; // - inflateEnd(&strm); - // free(result); - if( result ) - free(result); - delete [] in; - return ZR_DATA_ERROR; - } - switch (ret) { case Z_NEED_DICT: - ret = Z_DATA_ERROR; case Z_DATA_ERROR: - case Z_MEM_ERROR: - LL_DEBUGS() << "Unzip error: " << ret << LL_ENDL; // + { inflateEnd(&strm); - // free(result); - if( result ) - free(result); - delete [] in; + free(result); + return ZR_DATA_ERROR; + } + case Z_STREAM_ERROR: + case Z_BUF_ERROR: + { + inflateEnd(&strm); + free(result); + return ZR_BUFFER_ERROR; + } + + case Z_MEM_ERROR: + { + inflateEnd(&strm); + free(result); return ZR_MEM_ERROR; - break; + } } U32 have = CHUNK-strm.avail_out; @@ -2243,111 +2410,200 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, { free(result); } - delete[] in; return ZR_MEM_ERROR; } result = new_result; - memcpy(result+cur_size, out, have); + memcpy(result+cur_size, out.get(), have); cur_size += have; - } while (ret == Z_OK); + } while (ret == Z_OK && ret != Z_STREAM_END); inflateEnd(&strm); - delete [] in; if (ret != Z_STREAM_END) { - LL_DEBUGS() << "Unzip error: !Z_STREAM_END" << LL_ENDL; // - // free(result); - if( result ) - free(result); + free(result); return ZR_DATA_ERROR; } //result now points to the decompressed LLSD block { - std::istringstream istr; - // Since we are using this for meshes, data we are dealing with tend to be large. - // So string can potentially fail to allocate, make sure this won't cause problems - try - { - std::string res_str((char*)result, cur_size); + char* result_ptr = strip_deprecated_header((char*)result, cur_size); - std::string deprecated_header(""); - - if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - { - res_str = res_str.substr(deprecated_header.size() + 1, cur_size); - } - cur_size = res_str.size(); - - istr.str(res_str); - } -#ifdef LL_WINDOWS - catch (std::length_error) + boost::iostreams::stream istrm(result_ptr, cur_size); + + if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH)) { - // free(result); - if( result ) - free(result); - return ZR_SIZE_ERROR; - } -#endif - catch (std::bad_alloc&) - { - // free(result); - if( result ) - free(result); - return ZR_MEM_ERROR; - } - - if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) - { - // free(result); - if( result ) - free(result); + free(result); return ZR_PARSE_ERROR; } } - // free(result); - if( result ) - free(result); + free(result); return ZR_OK; } +// //This unzip function will only work with a gzip header and trailer - while the contents //of the actual compressed data is the same for either format (gzip vs zlib ), the headers //and trailers are different for the formats. U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) { +// Add non-allocating variants of unzip_llsd +// if (size == 0) +// { +// LL_WARNS() << "No data to unzip." << LL_ENDL; +// return NULL; +// } + +// U8* result = NULL; +// U32 cur_size = 0; +// z_stream strm; + +// const U32 CHUNK = 0x4000; + +// U8 *in = new(std::nothrow) U8[size]; +// if (in == NULL) +// { +// LL_WARNS() << "Memory allocation failure." << LL_ENDL; +// return NULL; +// } +// is.read((char*) in, size); + +// U8 out[CHUNK]; + +// strm.zalloc = Z_NULL; +// strm.zfree = Z_NULL; +// strm.opaque = Z_NULL; +// strm.avail_in = size; +// strm.next_in = in; + +// valid = true; // Default is all okay. +// S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); +// do +// { +// strm.avail_out = CHUNK; +// strm.next_out = out; +// ret = inflate(&strm, Z_NO_FLUSH); +// if (ret == Z_STREAM_ERROR) +// { +// inflateEnd(&strm); +// // free(result); +// if( result ) +// free(result); +// delete [] in; +// in = NULL; result = NULL;// Or we get a double free aftr the while loop ... +// valid = false; +// } + +// switch (ret) +// { +// case Z_NEED_DICT: +// ret = Z_DATA_ERROR; +// case Z_DATA_ERROR: +// case Z_MEM_ERROR: +// inflateEnd(&strm); +// // free(result); +// if( result ) +// free(result); +// delete [] in; +// valid = false; +// in = NULL; result = NULL;// Or we get a double free aftr the while loop ... +// break; +// } + +// if( valid ) {// in case this stream is invalid, do not pass the already freed buffer to realloc. + +// U32 have = CHUNK-strm.avail_out; + +// U8* new_result = (U8*) realloc(result, cur_size + have); +// if (new_result == NULL) +// { +// LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size +// << " bytes; requested " << cur_size + have +// << " bytes; total syze: ." << size << " bytes." +// << LL_ENDL; +// inflateEnd(&strm); +// if (result) +// { +// free(result); +// } +// delete[] in; +// valid = false; +// return NULL; +// } +// result = new_result; +// memcpy(result+cur_size, out, have); +// cur_size += have; + +// } // + +// } while (ret == Z_OK); + +// inflateEnd(&strm); +// delete [] in; + +// if (ret != Z_STREAM_END) +// { +// // result might have been freed above. And calling free with a null pointer is not defined. +// // free(result); +// if( result ) +// free(result); +// // + +// valid = false; +// return NULL; +// } + +// //result now points to the decompressed LLSD block +// { +// outsize= cur_size; +// valid = true; +// } + +// return result; +// } if (size == 0) { LL_WARNS() << "No data to unzip." << LL_ENDL; - return NULL; + return nullptr; + } + std::unique_ptr in; + try + { + in = std::make_unique(size); + } + catch (const std::bad_alloc&) + { + LL_WARNS() << "Memory allocation failure." << LL_ENDL; + return nullptr; } + is.read((char*) in.get(), size); + return unzip_llsdNavMesh(valid, outsize, in.get(), size); +} + +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 size ) +{ + if (size == 0) + { + LL_WARNS() << "No data to unzip." << LL_ENDL; + return nullptr; + } U8* result = NULL; U32 cur_size = 0; z_stream strm; const U32 CHUNK = 0x4000; - U8 *in = new(std::nothrow) U8[size]; - if (in == NULL) - { - LL_WARNS() << "Memory allocation failure." << LL_ENDL; - return NULL; - } - is.read((char*) in, size); - U8 out[CHUNK]; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = size; - strm.next_in = in; + strm.next_in = const_cast(in); - valid = true; // Default is all okay. + S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); do { @@ -2357,32 +2613,23 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 if (ret == Z_STREAM_ERROR) { inflateEnd(&strm); - // free(result); - if( result ) - free(result); - delete [] in; - in = NULL; result = NULL;// Or we get a double free aftr the while loop ... - valid = false; + free(result); + return NULL; } switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; + // [[fallthrough]]; // TODO when we have C++17 compilation. case Z_DATA_ERROR: case Z_MEM_ERROR: inflateEnd(&strm); - // free(result); - if( result ) - free(result); - delete [] in; + free(result); valid = false; - in = NULL; result = NULL;// Or we get a double free aftr the while loop ... - break; + return NULL; } - if( valid ) {// in case this stream is invalid, do not pass the already freed buffer to realloc. - U32 have = CHUNK-strm.avail_out; U8* new_result = (U8*) realloc(result, cur_size + have); @@ -2397,7 +2644,6 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 { free(result); } - delete[] in; valid = false; return NULL; } @@ -2405,21 +2651,13 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 memcpy(result+cur_size, out, have); cur_size += have; - } // - } while (ret == Z_OK); inflateEnd(&strm); - delete [] in; if (ret != Z_STREAM_END) { - // result might have been freed above. And calling free with a null pointer is not defined. - // free(result); - if( result ) - free(result); - // - + free(result); valid = false; return NULL; } @@ -2433,4 +2671,22 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 return result; } +char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size) +{ + const char* deprecated_header = ""; + constexpr size_t deprecated_header_size = 17; + if (cur_size > deprecated_header_size + && memcmp(in, deprecated_header, deprecated_header_size) == 0) + { + in = in + deprecated_header_size; + cur_size = cur_size - deprecated_header_size; + if (header_size) + { + *header_size = deprecated_header_size + 1; + } + } + + return in; +} +// \ No newline at end of file diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index d6079fd9fa..6df00540bd 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -858,9 +858,14 @@ public: ZR_SIZE_ERROR, ZR_DATA_ERROR, ZR_PARSE_ERROR, +// Add non-allocating variants of unzip_llsd + ZR_BUFFER_ERROR, + ZR_VERSION_ERROR +// } EZipRresult; // return OK or reason for failure static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size); + static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size); // Add non-allocating variants of unzip_llsd }; //dirty little zip functions -- yell at davep @@ -868,4 +873,10 @@ LL_COMMON_API std::string zip_llsd(LLSD& data); LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size); +// Add non-allocating variants of unzip_llsd +LL_COMMON_API U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8* in, S32 size); + +// returns a pointer to the array or past the array if the deprecated header exists +LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr); +// #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp index 9c7688870d..6e77de2735 100644 --- a/indra/llfilesystem/lldiskcache.cpp +++ b/indra/llfilesystem/lldiskcache.cpp @@ -71,6 +71,7 @@ void LLDiskCache::purge() LL_INFOS() << "Total dir size before purge is " << dirFileSize(mCacheDir) << LL_ENDL; } + boost::system::error_code ec; auto start_time = std::chrono::high_resolution_clock::now(); typedef std::pair> file_info_t; @@ -81,19 +82,27 @@ void LLDiskCache::purge() #else std::string cache_path(mCacheDir); #endif - if (boost::filesystem::is_directory(cache_path)) + if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed()) { // Optimize asset simple disk cache - //for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(cache_path), {})) - for (auto& entry : boost::make_iterator_range(boost::filesystem::recursive_directory_iterator(cache_path), {})) + //for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(cache_path, ec), {})) + for (auto& entry : boost::make_iterator_range(boost::filesystem::recursive_directory_iterator(cache_path, ec), {})) { - if (boost::filesystem::is_regular_file(entry)) + if (boost::filesystem::is_regular_file(entry, ec) && !ec.failed()) { if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos) { - uintmax_t file_size = boost::filesystem::file_size(entry); + uintmax_t file_size = boost::filesystem::file_size(entry, ec); + if (ec.failed()) + { + continue; + } const std::string file_path = entry.path().string(); - const std::time_t file_time = boost::filesystem::last_write_time(entry); + const std::time_t file_time = boost::filesystem::last_write_time(entry, ec); + if (ec.failed()) + { + continue; + } file_info.push_back(file_info_t(file_time, { file_size, file_path })); } @@ -119,7 +128,6 @@ void LLDiskCache::purge() action = "DELETE:"; // Do not crash if we cannot delete the file for some reason //boost::filesystem::remove(entry.second.second); - boost::system::error_code ec; boost::filesystem::remove(entry.second.second, ec); if (ec.failed()) { @@ -253,9 +261,15 @@ void LLDiskCache::updateFileAccessTime(const std::string& file_path) // current time const std::time_t cur_time = std::time(nullptr); + boost::system::error_code ec; #if LL_WINDOWS // file last write time - const std::time_t last_write_time = boost::filesystem::last_write_time(utf8str_to_utf16str(file_path)); + const std::time_t last_write_time = boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), ec); + if (ec.failed()) + { + LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; + return; + } // delta between cur time and last time the file was written const std::time_t delta_time = cur_time - last_write_time; @@ -264,11 +278,16 @@ void LLDiskCache::updateFileAccessTime(const std::string& file_path) // before the last one if (delta_time > time_threshold) { - boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), cur_time); + boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), cur_time, ec); } #else // file last write time - const std::time_t last_write_time = boost::filesystem::last_write_time(file_path); + const std::time_t last_write_time = boost::filesystem::last_write_time(file_path, ec); + if (ec.failed()) + { + LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; + return; + } // delta between cur time and last time the file was written const std::time_t delta_time = cur_time - last_write_time; @@ -277,9 +296,14 @@ void LLDiskCache::updateFileAccessTime(const std::string& file_path) // before the last one if (delta_time > time_threshold) { - boost::filesystem::last_write_time(file_path, cur_time); + boost::filesystem::last_write_time(file_path, cur_time, ec); } #endif + + if (ec.failed()) + { + LL_WARNS() << "Failed to update last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; + } } const std::string LLDiskCache::getCacheInfo() @@ -305,24 +329,24 @@ void LLDiskCache::clearCache() * the component files but it's called infrequently so it's * likely just fine */ + boost::system::error_code ec; #if LL_WINDOWS std::wstring cache_path(utf8str_to_utf16str(mCacheDir)); #else std::string cache_path(mCacheDir); #endif - if (boost::filesystem::is_directory(cache_path)) + if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed()) { // Optimize asset simple disk cache - //for (auto& entry : boost::make_iterator_range(boost::filesystem::recursive_directory_iterator(cache_path), {})) - for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(cache_path), {})) + //for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(cache_path, ec), {})) + for (auto& entry : boost::make_iterator_range(boost::filesystem::recursive_directory_iterator(cache_path, ec), {})) { - if (boost::filesystem::is_regular_file(entry)) + if (boost::filesystem::is_regular_file(entry, ec) && !ec.failed()) { if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos) { // Do not crash if we cannot delete the file for some reason //boost::filesystem::remove(entry); - boost::system::error_code ec; boost::filesystem::remove(entry, ec); if (ec.failed()) { @@ -348,22 +372,27 @@ uintmax_t LLDiskCache::dirFileSize(const std::string dir) * so if performance is ever an issue, optimizing this or removing it altogether, * is an easy win. */ + boost::system::error_code ec; #if LL_WINDOWS std::wstring dir_path(utf8str_to_utf16str(dir)); #else std::string dir_path(dir); #endif - if (boost::filesystem::is_directory(dir_path)) + if (boost::filesystem::is_directory(dir_path, ec) && !ec.failed()) { // Optimize asset simple disk cache - //for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dir_path), {})) - for (auto& entry : boost::make_iterator_range(boost::filesystem::recursive_directory_iterator(dir_path), {})) + //for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dir_path, ec), {})) + for (auto& entry : boost::make_iterator_range(boost::filesystem::recursive_directory_iterator(dir_path, ec), {})) { - if (boost::filesystem::is_regular_file(entry)) + if (boost::filesystem::is_regular_file(entry, ec) && !ec.failed()) { if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos) { - total_file_size += boost::filesystem::file_size(entry); + uintmax_t file_size = boost::filesystem::file_size(entry, ec); + if (!ec.failed()) + { + total_file_size += file_size; + } } } } diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 3b39aeb56b..5d08c1f4c6 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -295,7 +295,6 @@ public: void setAllowTerraform(BOOL b){setParcelFlag(PF_ALLOW_TERRAFORM, b); } void setAllowDamage(BOOL b) { setParcelFlag(PF_ALLOW_DAMAGE, b); } void setAllowFly(BOOL b) { setParcelFlag(PF_ALLOW_FLY, b); } - void setAllowLandmark(BOOL b){ setParcelFlag(PF_ALLOW_LANDMARK, b); } void setAllowGroupScripts(BOOL b) { setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, b); } void setAllowOtherScripts(BOOL b) { setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, b); } void setAllowDeedToGroup(BOOL b) { setParcelFlag(PF_ALLOW_DEED_TO_GROUP, b); } @@ -476,11 +475,6 @@ public: BOOL getAllowFly() const { return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; } - // Remove permission restrictions for creating landmarks. - // We should eventually remove this flag completely. - BOOL getAllowLandmark() const - { return TRUE; } - BOOL getAllowGroupScripts() const { return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; } diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h index 25b27a281a..4cffa83cc1 100644 --- a/indra/llinventory/llparcelflags.h +++ b/indra/llinventory/llparcelflags.h @@ -33,7 +33,7 @@ const U32 PF_ALLOW_FLY = 1 << 0;// Can start flying const U32 PF_ALLOW_OTHER_SCRIPTS= 1 << 1;// Scripts by others can run. const U32 PF_FOR_SALE = 1 << 2;// Can buy this land const U32 PF_FOR_SALE_OBJECTS = 1 << 7;// Can buy all objects on this land -const U32 PF_ALLOW_LANDMARK = 1 << 3; +const U32 PF_ALLOW_LANDMARK = 1 << 3;// Always true/deprecated const U32 PF_ALLOW_TERRAFORM = 1 << 4; const U32 PF_ALLOW_DAMAGE = 1 << 5; const U32 PF_CREATE_OBJECTS = 1 << 6; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 1ebd42babd..7c6a5a46c4 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2403,7 +2403,27 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; return false; } - +// Add non-allocating variants of of unpackVolumeFaces + return unpackVolumeFacesInternal(mdl); +} + +bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) +{ + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); + if (uzip_result != LLUZipHelper::ZR_OK) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; + return false; + } + return unpackVolumeFacesInternal(mdl); +} + +bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) +{ +// { U32 face_count = mdl.size(); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c9b12a9e97..c745a202db 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1099,7 +1099,13 @@ protected: void createVolumeFaces(); public: virtual bool unpackVolumeFaces(std::istream& is, S32 size); +// Add non-allocating variants of of unpackVolumeFaces + bool unpackVolumeFaces(U8* in_data, S32 size); +private: + bool unpackVolumeFacesInternal(const LLSD& mdl); +public: +// virtual void setMeshAssetLoaded(BOOL loaded); virtual BOOL isMeshAssetLoaded(); diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 3ff8f19b87..e99ac87d88 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -124,6 +124,7 @@ set(llui_SOURCE_FILES lluictrl.cpp lluictrlfactory.cpp lluistring.cpp + lluiusage.cpp llundo.cpp llurlaction.cpp llurlentry.cpp @@ -245,6 +246,7 @@ set(llui_HEADER_FILES llui.h lluicolor.h lluistring.h + lluiusage.h llundo.h llurlaction.h llurlentry.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index badbb34c71..b896280bb8 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -47,6 +47,7 @@ #include "llnotificationsutil.h" #include "llrender.h" #include "lluictrlfactory.h" +#include "lluiusage.h" #include "llhelp.h" #include "lldockablefloater.h" #include "llviewereventrecorder.h" @@ -494,6 +495,13 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); } + if (!mFunctionName.empty()) + { + LL_DEBUGS("UIUsage") << "calling mouse down function " << mFunctionName << LL_ENDL; + LLUIUsage::instance().logCommand(mFunctionName); + LLUIUsage::instance().logControl(getPathname()); + } + /* * ATTENTION! This call fires another mouse down callback. * If you wish to remove this call emit that signal directly diff --git a/indra/llui/llchat.h b/indra/llui/llchat.h index 747a091f4d..6f35eadeb5 100644 --- a/indra/llui/llchat.h +++ b/indra/llui/llchat.h @@ -37,7 +37,8 @@ typedef enum e_chat_source_type CHAT_SOURCE_SYSTEM = 0, CHAT_SOURCE_AGENT = 1, CHAT_SOURCE_OBJECT = 2, - CHAT_SOURCE_UNKNOWN = 3 + CHAT_SOURCE_TELEPORT = 3, + CHAT_SOURCE_UNKNOWN = 4 } EChatSourceType; typedef enum e_chat_type @@ -69,6 +70,7 @@ typedef enum e_chat_style CHAT_STYLE_NORMAL, CHAT_STYLE_IRC, CHAT_STYLE_HISTORY, + CHAT_STYLE_TELEPORT_SEP, CHAT_STYLE_MODERATOR }EChatStyle; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index dcdce439e4..018926c8ad 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -58,6 +58,7 @@ #include "llhelp.h" #include "llmultifloater.h" #include "llsdutil.h" +#include "lluiusage.h" #include @@ -213,6 +214,8 @@ LLFloater::Params::Params() open_callback("open_callback"), close_callback("close_callback"), follows("follows"), + rel_x("rel_x", 0), + rel_y("rel_y", 0), hosted_floater_show_titlebar("hosted_floater_show_titlebar", true) // MultiFloater without titlebar for hosted floater { changeDefault(visible, false); @@ -284,6 +287,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mHasBeenDraggedWhileMinimized(FALSE), mPreviousMinimizedBottom(0), mPreviousMinimizedLeft(0), + mDefaultRelativeX(p.rel_x), + mDefaultRelativeY(p.rel_y), mMinimizeSignal(NULL), mHostedFloaterShowtitlebar(p.hosted_floater_show_titlebar) // MultiFloater without titlebar for hosted floater // mNotificationContext(NULL) @@ -542,7 +547,12 @@ void LLFloater::destroy() // virtual LLFloater::~LLFloater() { - LLFloaterReg::removeInstance(mInstanceName, mKey); + if (!isDead()) + { + // If it's dead, instance is supposed to be already removed, and + // in case of single instance we can remove new one by accident + LLFloaterReg::removeInstance(mInstanceName, mKey); + } if( gFocusMgr.childHasKeyboardFocus(this)) { @@ -1023,6 +1033,15 @@ bool LLFloater::applyRectControl() saved_rect = true; } + else if ((mDefaultRelativeX != 0) && (mDefaultRelativeY != 0)) + { + mPosition.mX = mDefaultRelativeX; + mPosition.mY = mDefaultRelativeY; + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + applyRelativePosition(); + + saved_rect = true; + } // remember updated position if (rect_specified) @@ -1722,6 +1741,7 @@ void LLFloater::bringToFront( S32 x, S32 y ) // virtual void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key) { + LLUIUsage::instance().logFloater(getInstanceName()); LLMultiFloater* hostp = getHost(); if (hostp) { @@ -3527,6 +3547,9 @@ void LLFloater::initFromParams(const LLFloater::Params& p) mSingleInstance = p.single_instance; mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance; + mDefaultRelativeX = p.rel_x; + mDefaultRelativeY = p.rel_y; + mPositioning = p.positioning; mHostedFloaterShowtitlebar = p.hosted_floater_show_titlebar; // MultiFloater without titlebar for hosted floater diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index bf8df7b8ce..e72f79e4ea 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -178,6 +178,9 @@ public: label_v_padding, // Make vertical label padding a per-skin option legacy_header_height; // HACK see initFromXML() + Optional rel_x, + rel_y; + // Images for top-right controls Optional close_image, snooze_image, // FIRE-11724: Snooze group chat @@ -547,6 +550,9 @@ private: S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; + F32 mDefaultRelativeX; + F32 mDefaultRelativeY; + // MultiFloater without titlebar for hosted floater bool mHostedFloaterShowtitlebar; }; diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index a4afa29e7e..cea1e11f07 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -32,6 +32,7 @@ #include "llfloater.h" #include "llmultifloater.h" #include "llfloaterreglistener.h" +#include "lluiusage.h" #include //******************************************************* @@ -73,6 +74,12 @@ void LLFloaterReg::addWithFileCallback(const std::string& name, const LLFloaterF } // [/SL:KB] +//static +bool LLFloaterReg::isRegistered(const std::string& name) +{ + return sBuildMap.find(name) != sBuildMap.end(); +} + //static LLFloater* LLFloaterReg::getLastFloaterInGroup(const std::string& name) { @@ -513,7 +520,6 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD& std::string name = sdname.asString(); LLFloater* instance = getInstance(name, key); - if (!instance) { LL_DEBUGS() << "Unable to get instance of floater '" << name << "'" << LL_ENDL; diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 476dfd8cec..0ab610906b 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -104,6 +104,7 @@ public: static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func, const std::string& groupname = LLStringUtil::null); + static bool isRegistered(const std::string& name); // [SL:KB] - Patch: UI-Base | Checked: 2010-12-01 (Catznip-3.0.0a) | Added: Catznip-2.4.0g static void addWithFileCallback(const std::string& name, const LLFloaterFileFunc& fileFunc, const LLFloaterBuildFunc& func, diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 28c6bf88d9..ff536840d2 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -292,6 +292,9 @@ public: void resetContextMenu() { setContextMenu(NULL); }; + void setBgImage(LLPointer image) { mBgImage = image; } + void setBgImageFocused(LLPointer image) { mBgImageFocused = image; } + // Make these protected void removeChar(); void removeWord(bool prev); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 2b57bea98e..e914bbdae2 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -80,7 +80,7 @@ const U32 LEFT_PAD_PIXELS = 3; const U32 LEFT_WIDTH_PIXELS = 15; const U32 LEFT_PLAIN_PIXELS = LEFT_PAD_PIXELS + LEFT_WIDTH_PIXELS; -const U32 RIGHT_PAD_PIXELS = 2; +const U32 RIGHT_PAD_PIXELS = 7; const U32 RIGHT_WIDTH_PIXELS = 15; const U32 RIGHT_PLAIN_PIXELS = RIGHT_PAD_PIXELS + RIGHT_WIDTH_PIXELS; @@ -96,7 +96,7 @@ const std::string SEPARATOR_NAME("separator"); const std::string VERTICAL_SEPARATOR_LABEL( "|" ); const std::string LLMenuGL::BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK -const std::string LLMenuGL::BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE +const std::string LLMenuGL::BRANCH_SUFFIX( "\xe2\x96\xb8" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE const std::string LLMenuGL::ARROW_UP ("^^^^^^^"); const std::string LLMenuGL::ARROW_DOWN("vvvvvvv"); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d7df19f5cb..34d8ed6fef 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -77,6 +77,7 @@ LLNotificationForm::FormButton::FormButton() text("text"), ignore("ignore"), is_default("default"), + width("width", 0), type("type") { // set type here so it gets serialized diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index c884933bbf..8ec04d2bd5 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -191,6 +191,7 @@ public: Mandatory text; Optional ignore; Optional is_default; + Optional width; Mandatory type; diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index 1fdd05a11c..bafeef41fb 100644 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -34,7 +34,11 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p) : LLUICtrl(p), mSearchButton(NULL), - mClearButton(NULL) + mClearButton(NULL), + mEditorImage(p.background_image), + mEditorImageFocused(p.background_image_focused), + mEditorSearchImage(p.background_image_highlight), + mHighlightTextField(p.highlight_text_field) { S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height; S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad; @@ -57,6 +61,8 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p) // Set up line editor. LLLineEditor::Params line_editor_params(p); line_editor_params.name("filter edit box"); + line_editor_params.background_image(p.background_image); + line_editor_params.background_image_focused(p.background_image_focused); line_editor_params.rect(getLocalRect()); line_editor_params.follows.flags(FOLLOWS_ALL); line_editor_params.text_pad_left(text_pad_left); @@ -104,6 +110,20 @@ void LLSearchEditor::draw() if (mClearButton) mClearButton->setVisible(!mSearchEditor->getWText().empty()); + if (mHighlightTextField) + { + if (!mSearchEditor->getWText().empty()) + { + mSearchEditor->setBgImage(mEditorSearchImage); + mSearchEditor->setBgImageFocused(mEditorSearchImage); + } + else + { + mSearchEditor->setBgImage(mEditorImage); + mSearchEditor->setBgImageFocused(mEditorImageFocused); + } + } + LLUICtrl::draw(); } diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index 3b12868225..c0f3c1d60c 100644 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -47,14 +47,23 @@ public: Optional search_button, clear_button; Optional search_button_visible, - clear_button_visible; + clear_button_visible, + highlight_text_field; Optional keystroke_callback; + Optional background_image, + background_image_focused, + background_image_highlight; + Params() : search_button("search_button"), search_button_visible("search_button_visible"), clear_button("clear_button"), - clear_button_visible("clear_button_visible") + clear_button_visible("clear_button_visible"), + highlight_text_field("highlight_text_field"), + background_image("background_image"), + background_image_focused("background_image_focused"), + background_image_highlight("background_image_highlight") {} }; @@ -93,6 +102,13 @@ protected: LLLineEditor* mSearchEditor; LLButton* mSearchButton; LLButton* mClearButton; + + LLPointer mEditorImage; + LLPointer mEditorImageFocused; + LLPointer mEditorSearchImage; + LLPointer mEditorSearchImageFocused; + + bool mHighlightTextField; }; #endif // LL_SEARCHEDITOR_H diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 17db7f9213..cc6b4a6beb 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -38,6 +38,7 @@ #include "llrender.h" #include "llfloater.h" #include "lltrans.h" +#include "lluiusage.h" //---------------------------------------------------------------------------- @@ -1716,6 +1717,8 @@ BOOL LLTabContainer::setTab(S32 which) if (is_selected) { + LLUIUsage::instance().logPanel(tuple->mTabPanel->getName()); + // Make sure selected tab is within scroll region if (mIsVertical) { diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 122597ecb7..3b46cdf95a 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2153,6 +2153,14 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("FS.LeaveGroup", boost::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupleave", true)); registrar.add("FS.ActivateGroup", boost::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupactivate", true)); + // hook up moderation tools + // if someone knows how to pass a parameter to these, let me know! - Zi + // also, I wish I could pass the group session id through these calls, but LLTextBase does not know it - Zi + registrar.add("FS.AllowGroupChat", boost::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupchatallow", true)); + registrar.add("FS.ForbidGroupChat", boost::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupchatforbid", true)); + registrar.add("FS.EjectGroupMember", boost::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupeject", true)); + registrar.add("FS.BanGroupMember", boost::bind(&LLUrlAction::executeSLURL, "secondlife:///app/firestorm/" + target_id_str + "/groupban", true)); + enable_registrar.add("FS.WaitingForGroupData", boost::bind(&FSRegistrarUtils::checkIsEnabled, gFSRegistrarUtils, target_id, FS_RGSTR_CHK_WAITING_FOR_GROUP_DATA)); enable_registrar.add("FS.HaveGroupData", boost::bind(&FSRegistrarUtils::checkIsEnabled, gFSRegistrarUtils, target_id, FS_RGSTR_CHK_HAVE_GROUP_DATA)); enable_registrar.add("FS.EnableJoinGroup", boost::bind(&FSRegistrarUtils::checkIsEnabled, gFSRegistrarUtils, target_id, FS_RGSTR_CHK_CAN_JOIN_GROUP)); @@ -2200,6 +2208,16 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) unblockButton->setVisible(is_blocked); } } + + // hide the moderation tools in the context menu unless we are in a group IM floater + LLFloater* parent_floater = getParentByType(); + if (!parent_floater || parent_floater->getName() != "panel_im") + { + menu->getChild("GroupModerationSubmenu")->setVisible(false); + menu->getChild("GroupModerationSeparator")->setVisible(false); + } + // + menu->show(x, y); LLMenuGL::showPopup(this, menu, x, y); } diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index b608bddd27..ee5873885b 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -1167,6 +1167,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id) executeStopParam.function_name = executeStopFunction; executeStopParam.parameter = commandp->executeStopParameters(); LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam); + button->setFunctionName(commandp->executeFunctionName()); + LL_DEBUGS("UIUsage") << "button function name a -> " << commandp->executeFunctionName() << LL_ENDL; LLUICtrl::commit_callback_t stop_func = initCommitCallback(executeStopParam); button->setMouseDownCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2)); @@ -1174,7 +1176,8 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id) } else { - // Check enabled state of button before executing! + button->setFunctionName(commandp->executeFunctionName()); + LL_DEBUGS("UIUsage") << "button function name b -> " << commandp->executeFunctionName() << LL_ENDL; // Check enabled state of button before executing! //button->setCommitCallback(executeParam); LLUICtrl::commit_callback_t execute_func = initCommitCallback(executeParam); button->setCommitCallback(boost::bind(&LLToolBarButton::callIfEnabled, button, execute_func, _1, _2)); diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 98f06ee29f..ec80eff451 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -35,6 +35,7 @@ #include "lluictrlfactory.h" #include "lltabcontainer.h" #include "llaccordionctrltab.h" +#include "lluiusage.h" static LLDefaultChildRegistry::Register r("ui_ctrl"); @@ -290,6 +291,7 @@ LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCa else { std::string function_name = cb.function_name; + setFunctionName(function_name); commit_callback_t* func = (CommitCallbackRegistry::getValue(function_name)); if (func) { @@ -430,7 +432,19 @@ BOOL LLUICtrl::canFocusChildren() const void LLUICtrl::onCommit() { if (mCommitSignal) - (*mCommitSignal)(this, getValue()); + { + if (!mFunctionName.empty()) + { + LL_DEBUGS("UIUsage") << "calling commit function " << mFunctionName << LL_ENDL; + LLUIUsage::instance().logCommand(mFunctionName); + LLUIUsage::instance().logControl(getPathname()); + } + else + { + //LL_DEBUGS("UIUsage") << "calling commit function " << "UNKNOWN" << LL_ENDL; + } + (*mCommitSignal)(this, getValue()); + } } //virtual @@ -615,6 +629,12 @@ void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control) // } } + +void LLUICtrl::setFunctionName(const std::string& function_name) +{ + mFunctionName = function_name; +} + // static bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle handle, std::string type) { diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 7a63e660cd..847e75a1aa 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -197,6 +197,8 @@ public: void setMakeVisibleControlVariable(LLControlVariable* control); void setMakeInvisibleControlVariable(LLControlVariable* control); + void setFunctionName(const std::string& function_name); + virtual void setTentative(BOOL b); virtual BOOL getTentative() const; virtual void setValue(const LLSD& value); @@ -326,6 +328,8 @@ protected: LLControlVariable* mMakeInvisibleControlVariable; boost::signals2::connection mMakeInvisibleControlConnection; + std::string mFunctionName; + static F32 sActiveControlTransparency; static F32 sInactiveControlTransparency; diff --git a/indra/llui/lluiusage.cpp b/indra/llui/lluiusage.cpp new file mode 100644 index 0000000000..ccae6643b9 --- /dev/null +++ b/indra/llui/lluiusage.cpp @@ -0,0 +1,146 @@ +/** +* @file lluiuisage.cpp +* @brief Source file for LLUIUsage +* +* $LicenseInfo:firstyear=2021&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2021, 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 "linden_common.h" +#include "lluiusage.h" +#include + +LLUIUsage::LLUIUsage() +{ +} + +LLUIUsage::~LLUIUsage() +{ +} + +// static +std::string LLUIUsage::sanitized(const std::string& s) +{ + // Remove characters that make the ViewerStats db unhappy + std::string result(s); + std::replace(result.begin(), result.end(), '.', '_'); + std::replace(result.begin(), result.end(), ' ', '_'); + return result; +} + +// static +void LLUIUsage::setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val) +{ + // Keep the last max_elts components of the specified path + std::vector fields; + boost::split(fields, path, boost::is_any_of("/")); + auto first_pos = std::max(fields.begin(), fields.end() - max_elts); + auto end_pos = fields.end(); + std::vector last_fields(first_pos,end_pos); + + setLLSDNested(sd, last_fields, val); +} + +// setLLSDNested() +// Accomplish the equivalent of +// sd[fields[0]][fields[1]]... = val; +// for an arbitrary number of fields. +// This might be useful as an LLSD utility function; is not specific to LLUIUsage +// +// static +void LLUIUsage::setLLSDNested(LLSD& sd, const std::vector& fields, const LLSD& val) +{ + LLSD* fsd = &sd; + for (auto it=fields.begin(); it!=fields.end(); ++it) + { + if (it == fields.end()-1) + { + (*fsd)[*it] = val; + } + else + { + if (!(*fsd)[*it].isMap()) + { + (*fsd)[*it] = LLSD::emptyMap(); + } + fsd = &(*fsd)[*it]; + } + } +} + +void LLUIUsage::logCommand(const std::string& command) +{ + mCommandCounts[sanitized(command)]++; + LL_DEBUGS("UIUsage") << "command " << command << LL_ENDL; +} + +void LLUIUsage::logControl(const std::string& control) +{ + mControlCounts[sanitized(control)]++; + LL_DEBUGS("UIUsage") << "control " << control << LL_ENDL; +} + + +void LLUIUsage::logFloater(const std::string& floater) +{ + mFloaterCounts[sanitized(floater)]++; + LL_DEBUGS("UIUsage") << "floater " << floater << LL_ENDL; +} + +void LLUIUsage::logPanel(const std::string& p) +{ + mPanelCounts[sanitized(p)]++; + LL_DEBUGS("UIUsage") << "panel " << p << LL_ENDL; +} + +LLSD LLUIUsage::asLLSD() const +{ + LLSD result; + for (auto const& it : mCommandCounts) + { + result["commands"][it.first] = LLSD::Integer(it.second); + } + for (auto const& it : mControlCounts) + { + setLLSDPath(result["controls"], it.first, 2, LLSD::Integer(it.second)); + } + for (auto const& it : mFloaterCounts) + { + result["floaters"][it.first] = LLSD::Integer(it.second); + } + for (auto const& it : mPanelCounts) + { + result["panels"][it.first] = LLSD::Integer(it.second); + } + return result; +} + +// Clear up some junk content generated during initial login/UI initialization +void LLUIUsage::clear() +{ + + LL_DEBUGS("UIUsage") << "clear" << LL_ENDL; + mCommandCounts.clear(); + mControlCounts.clear(); + mFloaterCounts.clear(); + mPanelCounts.clear(); +} + diff --git a/indra/llui/lluiusage.h b/indra/llui/lluiusage.h new file mode 100644 index 0000000000..a30cd80db3 --- /dev/null +++ b/indra/llui/lluiusage.h @@ -0,0 +1,57 @@ +/** +* @file lluiuisage.h +* @brief Header file for LLUIUsage +* +* $LicenseInfo:firstyear=2021&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2021, 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_LLUIUSAGE_H +#define LL_LLUIUSAGE_H + +#include +#include "llsd.h" +#include "llsingleton.h" + +// UIUsage tracking to see which operations and UI elements are most popular in a session +class LLUIUsage : public LLSingleton +{ +public: + LLSINGLETON(LLUIUsage); + ~LLUIUsage(); +public: + static std::string sanitized(const std::string& s); + static void setLLSDPath(LLSD& sd, const std::string& path, S32 max_elts, const LLSD& val); + static void setLLSDNested(LLSD& sd, const std::vector& fields, const LLSD& val); + void logCommand(const std::string& command); + void logControl(const std::string& control); + void logFloater(const std::string& floater); + void logPanel(const std::string& p); + LLSD asLLSD() const; + void clear(); +private: + std::map mCommandCounts; + std::map mControlCounts; + std::map mFloaterCounts; + std::map mPanelCounts; +}; + +#endif // LLUIUIUSAGE.h diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp index 90ba766332..5b6f57c6b8 100644 --- a/indra/llui/llvirtualtrackball.cpp +++ b/indra/llui/llvirtualtrackball.cpp @@ -348,6 +348,42 @@ LLQuaternion LLVirtualTrackball::getRotation() const return mValue; } +// static +void LLVirtualTrackball::getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation) +{ + // LLQuaternion has own function to get azimuth, but it doesn't appear to return correct values (meant for 2d?) + LLVector3 point = VectorZero * quat; + + if (!is_approx_zero(point.mV[VX]) || !is_approx_zero(point.mV[VY])) + { + azimuth = atan2f(point.mV[VX], point.mV[VY]); + } + else + { + azimuth = 0; + } + + azimuth -= F_PI_BY_TWO; + + if (azimuth < 0) + { + azimuth += F_PI * 2; + } + + // while vector is '1', F32 is not sufficiently precise and we can get + // values like 1.0000012 which will result in -90deg angle instead of 90deg + F32 z = llclamp(point.mV[VZ], -1.f, 1.f); + elevation = asin(z); // because VectorZero's length is '1' +} + +// static +void LLVirtualTrackball::getAzimuthAndElevationDeg(const LLQuaternion &quat, F32 &azimuth, F32 &elevation) +{ + getAzimuthAndElevation(quat, azimuth, elevation); + azimuth *= RAD_TO_DEG; + elevation *= RAD_TO_DEG; +} + BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask) { if (hasMouseCapture()) @@ -409,6 +445,10 @@ BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask) mValue *= az_quat; } + // we are doing a lot of F32 mathematical operations with loss of precision, + // re-normalize to compensate + mValue.normalize(); + mPrevX = x; mPrevY = y; onCommit(); diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h index 2d4b1ece17..c7a893877b 100644 --- a/indra/llui/llvirtualtrackball.h +++ b/indra/llui/llvirtualtrackball.h @@ -96,6 +96,9 @@ public: void setRotation(const LLQuaternion &value); LLQuaternion getRotation() const; + static void getAzimuthAndElevation(const LLQuaternion &quat, F32 &azimuth, F32 &elevation); + static void getAzimuthAndElevationDeg(const LLQuaternion &quat, F32 &azimuth, F32 &elevation); + protected: friend class LLUICtrlFactory; LLVirtualTrackball(const Params&); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8b19c4c715..61780dd48a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -316,6 +316,7 @@ set(viewer_SOURCE_FILES llflexibleobject.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp + llfloateraddpaymentmethod.cpp llfloaterauction.cpp llfloaterautoreplacesettings.cpp llfloateravatar.cpp @@ -339,6 +340,7 @@ set(viewer_SOURCE_FILES llfloatercolorpicker.cpp llfloaterconversationlog.cpp llfloaterconversationpreview.cpp + llfloatercreatelandmark.cpp llfloaterdeleteprefpreset.cpp llfloaterdestinations.cpp llfloaterdisplayname.cpp @@ -362,6 +364,7 @@ set(viewer_SOURCE_FILES llfloaterhandler.cpp llfloaterhelpbrowser.cpp llfloaterhoverheight.cpp + llfloaterhowto.cpp llfloaterhud.cpp llfloaterimagepreview.cpp llfloaterimsessiontab.cpp @@ -653,7 +656,7 @@ set(viewer_SOURCE_FILES llregionposition.cpp llremoteparcelrequest.cpp #llsavedsettingsglue.cpp # Unused - llsaveoutfitcombobtn.cpp + #llsaveoutfitcombobtn.cpp # Unused llscenemonitor.cpp llsceneview.cpp llscreenchannel.cpp @@ -746,6 +749,7 @@ set(viewer_SOURCE_FILES llurl.cpp llurldispatcher.cpp llurldispatcherlistener.cpp + llurlfloaterdispatchhandler.cpp llurlhistory.cpp llurllineeditorctrl.cpp llurlwhitelist.cpp @@ -1088,6 +1092,7 @@ set(viewer_HEADER_FILES llflexibleobject.h llfloaterabout.h llfloaterbvhpreview.h + llfloateraddpaymentmethod.h llfloaterauction.h llfloaterautoreplacesettings.h llfloateravatar.h @@ -1111,6 +1116,7 @@ set(viewer_HEADER_FILES llfloatercolorpicker.h llfloaterconversationlog.h llfloaterconversationpreview.h + llfloatercreatelandmark.h llfloaterdeleteprefpreset.h llfloaterdestinations.h llfloaterdisplayname.h @@ -1134,6 +1140,7 @@ set(viewer_HEADER_FILES llfloaterhandler.h llfloaterhelpbrowser.h llfloaterhoverheight.h + llfloaterhowto.h llfloaterhud.h llfloaterimagepreview.h llfloaterimnearbychat.h @@ -1415,7 +1422,7 @@ set(viewer_HEADER_FILES llresourcedata.h llrootview.h #llsavedsettingsglue.h # Unused - llsaveoutfitcombobtn.h + #llsaveoutfitcombobtn.h # Unused llscenemonitor.h llsceneview.h llscreenchannel.h @@ -1511,6 +1518,7 @@ set(viewer_HEADER_FILES llurl.h llurldispatcher.h llurldispatcherlistener.h + llurlfloaterdispatchhandler.h llurlhistory.h llurllineeditorctrl.h llurlwhitelist.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index e786022da5..22beed373e 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.4.20 +6.4.21 diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 52d58cea89..a13da0b23a 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -94,8 +94,10 @@ icon="Command_HowTo_Icon" label_ref="Command_HowTo_Label" tooltip_ref="Command_HowTo_Tooltip" - execute_function="Help.ToggleHowTo" - is_running_function="Help.HowToVisible" + execute_function="Floater.ToggleOrBringToFront" + execute_parameters="guidebook" + is_running_function="Floater.IsOpen" + is_running_parameters="guidebook" /> https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD] --> + GuidebookURL + + Comment + URL for Guidebook content + Persist + 1 + Type + String + Value + http://guidebooks.secondlife.io/welcome/index.html + HighResSnapshot Comment @@ -10776,9 +10787,9 @@ Change of this parameter will affect the layout of buttons in notification toast Color4 Value - 0.0 - 0.0 - 0.0 + 0.3 + 0.3 + 0.3 1.0 @@ -18080,7 +18091,8 @@ Change of this parameter will affect the layout of buttons in notification toast VivoxVadSensitivity Comment - A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether + + A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether Persist 1 Type @@ -25701,7 +25713,7 @@ Change of this parameter will affect the layout of buttons in notification toast Type U32 Value - 1 + 0 FSAutoUnmuteSounds diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp index b154ac17ef..d2d0dd8b08 100644 --- a/indra/newview/fschathistory.cpp +++ b/indra/newview/fschathistory.cpp @@ -140,6 +140,7 @@ public: mMinUserNameWidth(0), mUserNameFont(NULL), mUserNameTextBox(NULL), + mNeedsTimeBox(true), mTimeBoxTextBox(NULL), mHeaderLayoutStack(NULL), mAvatarNameCacheConnection() @@ -459,10 +460,15 @@ public: { LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagTextChat); } - else if (param == "toggle_allow_text_chat") + else if (param == "allow_text_chat") { LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); - speaker_mgr->toggleAllowTextChat(getAvatarId()); + speaker_mgr->allowTextChat(getAvatarId(), true); + } + else if (param == "forbid_text_chat") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + speaker_mgr->allowTextChat(getAvatarId(), false); } else if (param == "group_mute") { @@ -482,7 +488,15 @@ public: } else if (param == "ban_member") { - banGroupMember(getAvatarId()); + // don't do safety checks as participant list is broken, just ban + // banGroupMember(getAvatarId()); + std::vector ids; + ids.push_back(getAvatarId()); + + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mSessionID, LLGroupMgr::BAN_CREATE, ids); + LLGroupMgr::getInstance()->sendGroupMemberEjects(mSessionID, ids); + LLGroupMgr::getInstance()->sendGroupMembersRequest(mSessionID); + // } } @@ -689,7 +703,18 @@ public: // Make sure we use the correct font style for everything after the display name mNameStyleParams.font.style = style_params.font.style; - if (chat.mFromName.empty() + if (mSourceType == CHAT_SOURCE_TELEPORT + && chat.mChatStyle == CHAT_STYLE_TELEPORT_SEP) + { + mFrom = chat.mFromName; + mNeedsTimeBox = false; + mUserNameTextBox->setValue(mFrom); + updateMinUserNameWidth(); + LLColor4 sep_color = LLUIColorTable::instance().getColor("ChatTeleportSeparatorColor"); + setTransparentColor(sep_color); + mTimeBoxTextBox->setVisible(FALSE); + } + else if (chat.mFromName.empty() //|| mSourceType == CHAT_SOURCE_SYSTEM // FS:LO FIRE-1439 - Clickable avatar names on local chat radar crossing reports || (mSourceType == CHAT_SOURCE_SYSTEM && mType != CHAT_TYPE_RADAR) @@ -822,8 +847,12 @@ public: } // FS:LO FIRE-1439 - Clickable avatar names on local chat radar crossing reports break; - case CHAT_SOURCE_UNKNOWN: + case CHAT_SOURCE_TELEPORT: + icon->setValue(LLSD("Command_Destinations_Icon")); + break; + case CHAT_SOURCE_UNKNOWN: icon->setValue(LLSD("Unknown_Icon")); + break; } // In case the message came from an object, save the object info @@ -857,7 +886,7 @@ public: S32 user_name_width = user_name_rect.getWidth(); S32 time_box_width = mTimeBoxTextBox->getRect().getWidth(); - if (!mTimeBoxTextBox->getVisible() && user_name_width > mMinUserNameWidth) + if (mNeedsTimeBox && !mTimeBoxTextBox->getVisible() && user_name_width > mMinUserNameWidth) { user_name_rect.mRight -= time_box_width; mUserNameTextBox->reshape(user_name_rect.getWidth(), user_name_rect.getHeight()); @@ -1135,6 +1164,8 @@ protected: LLStyle::Params mNameStyleParams; + bool mNeedsTimeBox; + private: boost::signals2::connection mAvatarNameCacheConnection; }; @@ -1359,6 +1390,7 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; + bool teleport_separator = chat.mSourceType == CHAT_SOURCE_TELEPORT; // We graying out chat history by graying out messages that contains full date in a time string if (message_from_log && !is_conversation_log) { @@ -1423,7 +1455,7 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLStyle::Params timestamp_style(body_message_params); // out of the timestamp - if (args["show_time"].asBoolean()) + if (args["show_time"].asBoolean() && !teleport_separator) { LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); timestamp_style.color(timestamp_color); @@ -1533,6 +1565,13 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } prependNewLineState = false; } + else if (teleport_separator) + { + std::string tp_text = LLTrans::getString("teleport_preamble_compact_chat"); + appendText(tp_text + " " + chat.mFromName + "", + prependNewLineState, body_message_params); + prependNewLineState = false; + } else { appendText("" + chat.mFromName + "" + delimiter, @@ -1553,7 +1592,8 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLDate new_message_time = LLDate::now(); bool needs_header_text = false; - if (mLastFromName == chat.mFromName + if (!teleport_separator + && mLastFromName == chat.mFromName && mLastFromID == chat.mFromID && mLastMessageTime.notNull() && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 @@ -1577,7 +1617,14 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL p.top_pad = 0; else p.top_pad = mTopHeaderPad; - p.bottom_pad = mBottomHeaderPad; + if (teleport_separator) + { + p.bottom_pad = mBottomSeparatorPad; + } + else + { + p.bottom_pad = mBottomHeaderPad; + } if (!view) { LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL; @@ -1663,7 +1710,7 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } // usual messages showing - else + else if (!teleport_separator) { std::string message = irc_me ? chat.mText.substr(3) : chat.mText; diff --git a/indra/newview/fsfloaterplacedetails.cpp b/indra/newview/fsfloaterplacedetails.cpp index ed459a5d81..12c025f537 100644 --- a/indra/newview/fsfloaterplacedetails.cpp +++ b/indra/newview/fsfloaterplacedetails.cpp @@ -318,8 +318,9 @@ void FSFloaterPlaceDetails::onOpen(const LLSD& key) mGlobalPos = gAgent.getPositionGlobal(); } + LLUUID dest_folder = key["dest_folder"]; mPanelLandmarkInfo->resetLocation(); - mPanelLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK); + mPanelLandmarkInfo->setInfoAndCreateLandmark(dest_folder); mPanelLandmarkInfo->setHeaderVisible(FALSE); mPanelLandmarkInfo->displayParcelInfo(LLUUID(), mGlobalPos); diff --git a/indra/newview/fsfloaterteleporthistory.cpp b/indra/newview/fsfloaterteleporthistory.cpp index 1cd6930645..f9ec067f38 100644 --- a/indra/newview/fsfloaterteleporthistory.cpp +++ b/indra/newview/fsfloaterteleporthistory.cpp @@ -33,6 +33,7 @@ #include "llpanelteleporthistory.h" #include "llbutton.h" #include "llfiltereditor.h" +#include "llmenubutton.h" FSFloaterTeleportHistory::FSFloaterTeleportHistory(const LLSD& seed) : LLFloater(seed), @@ -53,14 +54,6 @@ BOOL FSFloaterTeleportHistory::postBuild() { mHistoryPanel->setIsStandAlone(true); - mHistoryPanel->mTeleportBtn = getChild("teleport_btn"); - mHistoryPanel->mShowOnMapBtn = getChild("map_btn"); - mHistoryPanel->mShowProfile = getChild("profile_btn"); - - mHistoryPanel->mTeleportBtn->setClickedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleport, mHistoryPanel)); - mHistoryPanel->mShowProfile->setClickedCallback(boost::bind(&LLTeleportHistoryPanel::onShowProfile, mHistoryPanel)); - mHistoryPanel->mShowOnMapBtn->setClickedCallback(boost::bind(&LLTeleportHistoryPanel::onShowOnMap, mHistoryPanel)); - mFilterEditor = getChild("Filter"); if (mFilterEditor) { @@ -74,6 +67,12 @@ BOOL FSFloaterTeleportHistory::postBuild() getChildView("history_placeholder")->addChild(mHistoryPanel); mHistoryPanel->onSearchEdit(""); + + mGearMenuButton = getChild("options_gear_btn"); + mGearMenuButton->setMouseDownCallback(boost::bind(&FSFloaterTeleportHistory::onGearMenuClick, this)); + + mSortingMenuButton = getChild("sorting_menu_btn"); + mSortingMenuButton->setMouseDownCallback(boost::bind(&FSFloaterTeleportHistory::onSortingMenuClick, this)); } else { @@ -117,3 +116,13 @@ BOOL FSFloaterTeleportHistory::handleKeyHere(KEY key, MASK mask) return LLFloater::handleKeyHere(key, mask); } + +void FSFloaterTeleportHistory::onGearMenuClick() +{ + mGearMenuButton->setMenu(mHistoryPanel->getSelectionMenu(), LLMenuButton::MP_BOTTOM_LEFT); +} + +void FSFloaterTeleportHistory::onSortingMenuClick() +{ + mSortingMenuButton->setMenu(mHistoryPanel->getSortingMenu(), LLMenuButton::MP_BOTTOM_LEFT); +} diff --git a/indra/newview/fsfloaterteleporthistory.h b/indra/newview/fsfloaterteleporthistory.h index dbdb915719..f75f8d4ba9 100644 --- a/indra/newview/fsfloaterteleporthistory.h +++ b/indra/newview/fsfloaterteleporthistory.h @@ -32,6 +32,7 @@ class LLFilterEditor; class LLTeleportHistoryPanel; +class LLMenuButton; class FSFloaterTeleportHistory : public LLFloater { @@ -47,9 +48,13 @@ public: private: void onFilterEdit(const std::string& search_string, bool force_filter); + void onGearMenuClick(); + void onSortingMenuClick(); LLTeleportHistoryPanel* mHistoryPanel; LLFilterEditor* mFilterEditor; + LLMenuButton* mGearMenuButton; + LLMenuButton* mSortingMenuButton; }; #endif // FS_FLOATERTELEPORTHISTORY_H diff --git a/indra/newview/fsparticipantlist.cpp b/indra/newview/fsparticipantlist.cpp index b4b6c20caa..e292d67a11 100644 --- a/indra/newview/fsparticipantlist.cpp +++ b/indra/newview/fsparticipantlist.cpp @@ -703,7 +703,7 @@ LLContextMenu* FSParticipantList::FSParticipantListMenu::createMenu() LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; registrar.add("ParticipantList.Sort", boost::bind(&FSParticipantList::FSParticipantListMenu::sortParticipantList, this, _2)); - registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&FSParticipantList::FSParticipantListMenu::toggleAllowTextChat, this, _2)); + registrar.add("ParticipantList.AllowTextChat", boost::bind(&FSParticipantList::FSParticipantListMenu::allowTextChat, this, _2)); registrar.add("ParticipantList.ToggleMuteText", boost::bind(&FSParticipantList::FSParticipantListMenu::toggleMuteText, this, _2)); // [SL:KB] - Patch: Chat-GroupSessionEject | Checked: 2012-02-04 (Catznip-3.2.1) | Added: Catznip-3.2.1 registrar.add("ParticipantList.Eject", boost::bind(&LLGroupActions::ejectFromGroup, mParent.mSpeakerMgr->getSessionID(), mUUIDs.front())); @@ -780,14 +780,13 @@ void FSParticipantList::FSParticipantListMenu::sortParticipantList(const LLSD& u } } -void FSParticipantList::FSParticipantListMenu::toggleAllowTextChat(const LLSD& userdata) +void FSParticipantList::FSParticipantListMenu::allowTextChat(const LLSD& userdata) { - LLIMSpeakerMgr* mgr = dynamic_cast(mParent.mSpeakerMgr); if (mgr) { const LLUUID speaker_id = mUUIDs.front(); - mgr->toggleAllowTextChat(speaker_id); + mgr->allowTextChat(speaker_id, userdata.asString() == "allow"); } } diff --git a/indra/newview/fsparticipantlist.h b/indra/newview/fsparticipantlist.h index 5f7f9c0b91..c5221c2e02 100644 --- a/indra/newview/fsparticipantlist.h +++ b/indra/newview/fsparticipantlist.h @@ -179,7 +179,7 @@ protected: bool checkContextMenuItem(const LLSD& userdata); void sortParticipantList(const LLSD& userdata); - void toggleAllowTextChat(const LLSD& userdata); + void allowTextChat(const LLSD& userdata); void toggleMute(const LLSD& userdata, U32 flags); void toggleMuteText(const LLSD& userdata); void toggleMuteVoice(const LLSD& userdata); diff --git a/indra/newview/fsregioncross.cpp b/indra/newview/fsregioncross.cpp index 737427a087..f957269ad8 100644 --- a/indra/newview/fsregioncross.cpp +++ b/indra/newview/fsregioncross.cpp @@ -148,7 +148,7 @@ bool RegionCrossExtrapolate::ifsaton(const LLViewerObject& vo) // true if root } LLViewerObject::const_child_list_t& children = vo.getChildren(); - for (const auto child : children) + for (const auto &child : children) { if (child->isAvatar()) { diff --git a/indra/newview/fsslurlcommand.cpp b/indra/newview/fsslurlcommand.cpp index b53041d829..f0a8427c00 100644 --- a/indra/newview/fsslurlcommand.cpp +++ b/indra/newview/fsslurlcommand.cpp @@ -32,9 +32,13 @@ #include "llcommandhandler.h" #include "llfloatersettingsdebug.h" #include "llgroupactions.h" +#include "llgroupmgr.h" #include "lllogchat.h" #include "llnotificationsutil.h" +#include "llspeakers.h" +#include "fsfloaterimcontainer.h" +#include "fsfloaterim.h" class FSSlurlCommandHandler : public LLCommandHandler { @@ -138,19 +142,101 @@ public: if (verb == "groupjoin") { - LLGroupActions::join(LLUUID(target_id)); + LLGroupActions::join(target_id); return true; } if (verb == "groupleave") { - LLGroupActions::leave(LLUUID(target_id)); + LLGroupActions::leave(target_id); return true; } if (verb == "groupactivate") { - LLGroupActions::activate(LLUUID(target_id)); + LLGroupActions::activate(target_id); + return true; + } + + // please someone tell me there is an easier way to get the group UUID of the + // currently focused group, or transfer the UUID through the context menu somehow - Zi + LLFloater* focused_floater = gFloaterView->getFocusedFloater(); + + FSFloaterIM* floater_im; + + // let's guess that the user has tabbed IMs + FSFloaterIMContainer* floater_container = dynamic_cast(focused_floater); + + if (floater_container) + { + // get the active sub-floater inside the tabbed IMs + floater_im = dynamic_cast(floater_container->getActiveFloater()); + } + else + { + // no tabbed IMs or torn-off group floater, try if this is already what we wanted + floater_im = dynamic_cast(focused_floater); + } + + // still not an IM floater, give up + if (!floater_im) + { + return true; + } + + // get the group's UUID + LLUUID group_id = floater_im->getKey(); + + // is this actually a valid IM session? + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(group_id); + if (!session) + { + return true; + } + + // is this actually a valid group IM session? + if (!session->isGroupSessionType()) + { + return true; + } + + // finally! let's see what we came here to do + + if (verb == "groupchatallow") + { + // no safety checks, just allow + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(group_id); + speaker_mgr->allowTextChat(target_id, true); + + return true; + } + + if (verb == "groupchatforbid") + { + // no safety checks, just mute + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(group_id); + speaker_mgr->allowTextChat(target_id, false); + + return true; + } + + if (verb == "groupeject") + { + // no safety checks, just eject + LLGroupActions::ejectFromGroup(group_id, target_id); + return true; + } + + if (verb == "groupban") + { + std::vector ids; + ids.push_back(target_id); + + // no safety checks, just ban + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_id, LLGroupMgr::BAN_CREATE, ids); + LLGroupMgr::getInstance()->sendGroupMemberEjects(group_id, ids); + LLGroupMgr::getInstance()->sendGroupMembersRequest(group_id); + return true; } diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 683dad312c..e9f1a469b1 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -110,6 +110,7 @@ // [/RLVa:KB] // Firestorm includes +#include "fsfloaternearbychat.h" #include "fslslbridge.h" #include "llpresetsmanager.h" #include "NACLantispam.h" @@ -425,6 +426,7 @@ LLAgent::LLAgent() : mTeleportFinishedSlot(), mTeleportFailedSlot(), mIsMaturityRatingChangingDuringTeleport(false), + mTPNeedsNeabyChatSeparator(false), mMaturityRatingChange(0U), mIsDoSendMaturityPreferenceToServer(false), mMaturityPreferenceRequestId(0U), @@ -4758,6 +4760,7 @@ void LLAgent::clearTeleportRequest() LLVoiceClient::getInstance()->setHidden(FALSE); } mTeleportRequest.reset(); + mTPNeedsNeabyChatSeparator = false; } void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange) @@ -4766,6 +4769,12 @@ void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange) mMaturityRatingChange = pMaturityRatingChange; } +void LLAgent::sheduleTeleportIM() +{ + // is supposed to be called during teleport so we are still waiting for parcel + mTPNeedsNeabyChatSeparator = true; +} + bool LLAgent::hasPendingTeleportRequest() { return ((mTeleportRequest != NULL) && @@ -4813,6 +4822,12 @@ void LLAgent::startTeleportRequest() void LLAgent::handleTeleportFinished() { LL_INFOS("Teleport") << "Agent handling teleport finished." << LL_ENDL; + if (mTPNeedsNeabyChatSeparator) + { + // parcel is ready at this point + addTPNearbyChatSeparator(); + mTPNeedsNeabyChatSeparator = false; + } clearTeleportRequest(); mTeleportCanceled.reset(); if (mIsMaturityRatingChangingDuringTeleport) @@ -4875,6 +4890,47 @@ void LLAgent::handleTeleportFailed() LLNotificationsUtil::add("PreferredMaturityChanged", args); mIsMaturityRatingChangingDuringTeleport = false; } + + mTPNeedsNeabyChatSeparator = false; +} + +/*static*/ +void LLAgent::addTPNearbyChatSeparator() +{ + LLViewerRegion* agent_region = gAgent.getRegion(); + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!agent_region || !agent_parcel) + { + return; + } + + // [FS communication UI] + //LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat"); + FSFloaterNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("fs_nearby_chat"); + // [FS communication UI] + if (nearby_chat) + { + std::string location_name; + LLAgentUI::ELocationFormat format = LLAgentUI::LOCATION_FORMAT_NO_MATURITY; + + // Might be better to provide slurl to chat + if (!LLAgentUI::buildLocationString(location_name, format)) + { + location_name = "Teleport to new region"; // Shouldn't happen + } + + LLChat chat; + chat.mFromName = location_name; + chat.mMuted = FALSE; + chat.mFromID = LLUUID::null; + chat.mSourceType = CHAT_SOURCE_TELEPORT; + chat.mChatStyle = CHAT_STYLE_TELEPORT_SEP; + chat.mText = ""; + + LLSD args; + args["do_not_log"] = TRUE; + nearby_chat->addMessage(chat, true, args); + } } /*static*/ @@ -5166,10 +5222,16 @@ void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global) // In SL we have uniform region size. This is normal. // In opensim the handle will resolve to a 256m quantised world tile which the server maps back to a region // it "should" also compensate for the local coords. Handle has been "correctly" determined already so we use global % 256 - static const auto width{LLWorld::getInstance()->getRegionWidthInMeters()}; + static const F32 width = REGION_WIDTH_METERS;// Note: reverted back to previous hardcode 256 for non-local. Whilst this appears incorrect server side logic expects %256 and will overshoot otherwise. pos_local.set( fmod((F32)pos_global.mdV[VX], width), fmod((F32)pos_global.mdV[VY], width), (F32)pos_global.mdV[VZ] ); + LL_INFOS("Teleport") << "Non-local TP:" + << " pos_global " << pos_global + << " region " << region_origin + << " local " << pos_local + << " region_handle " << handle + << LL_ENDL; } if(teleportCore(is_local)) // Rather a pointless if as teleportCore currently always returns true diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 586c7b03bb..839fb68eaa 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -753,6 +753,7 @@ public: void restartFailedTeleportRequest(); void clearTeleportRequest(); void setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange); + void sheduleTeleportIM(); private: @@ -769,6 +770,7 @@ private: boost::signals2::connection mTeleportFailedSlot; bool mIsMaturityRatingChangingDuringTeleport; + bool mTPNeedsNeabyChatSeparator; U8 mMaturityRatingChange; bool hasPendingTeleportRequest(); @@ -791,6 +793,7 @@ private: void handleTeleportFinished(); void handleTeleportFailed(); + static void addTPNearbyChatSeparator(); static void onCapabilitiesReceivedAfterTeleport(); //-------------------------------------------------------------------- diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8f4c026458..c55af419d4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -59,6 +59,7 @@ #include "llslurl.h" #include "llstartup.h" #include "llfocusmgr.h" +#include "llurlfloaterdispatchhandler.h" #include "llviewerjoystick.h" #include "llallocator.h" #include "llcalc.h" @@ -1093,6 +1094,7 @@ bool LLAppViewer::init() // Load translations for tooltips LLFloater::initClass(); + LLUrlFloaterDispatchHandler::registerInDispatcher(); ///////////////////////////////////////////////// diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 30da025acf..887256c9f6 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -253,6 +253,19 @@ std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_ return LLTrans::getString(payment_text); } +//static +bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avatar_data) +{ + // Special accounts like M Linden don't have payment info revealed. + if (!avatar_data->caption_text.empty()) return true; + + // Linden employees don't have payment info revealed + const S32 LINDEN_EMPLOYEE_INDEX = 3; + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return true; + + return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED)); +} + void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**) { LLAvatarData avatar_data; diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 7eff1de051..7a96bc896f 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -252,6 +252,8 @@ public: // Used for profiles, inspectors. static std::string paymentInfo(const LLAvatarData* avatar_data); + static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data); + static void processAvatarPropertiesReply(LLMessageSystem* msg, void**); static void processAvatarInterestsReply(LLMessageSystem* msg, void**); diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 5a596bb29b..8cf40652b7 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -59,6 +59,7 @@ #include "llmultigesture.h" #include "llui.h" #include "lluictrlfactory.h" +#include "lluiusage.h" // // Globals @@ -567,6 +568,8 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL // as soon as we say something, we no longer care about teaching the user // how to chat gWarningSettings.setBOOL("FirstOtherChatBeforeUser", FALSE); + + LLUIUsage::instance().logCommand("Chat.Send"); // Pseudo-command // Look for "/20 foo" channel chats. S32 channel = 0; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index ad59fcc4d2..679765863b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -136,6 +136,7 @@ public: mUserNameFont(NULL), mUserNameTextBox(NULL), mTimeBoxTextBox(NULL), + mNeedsTimeBox(true), mAvatarNameCacheConnection() {} @@ -667,8 +668,19 @@ public: user_name->setReadOnlyColor(style_params.readonly_color()); user_name->setColor(style_params.color()); - if (chat.mFromName.empty() - || mSourceType == CHAT_SOURCE_SYSTEM) + if (mSourceType == CHAT_SOURCE_TELEPORT + && chat.mChatStyle == CHAT_STYLE_TELEPORT_SEP) + { + mFrom = chat.mFromName; + mNeedsTimeBox = false; + user_name->setValue(mFrom); + updateMinUserNameWidth(); + LLColor4 sep_color = LLUIColorTable::instance().getColor("ChatTeleportSeparatorColor"); + setTransparentColor(sep_color); + mTimeBoxTextBox->setVisible(FALSE); + } + else if (chat.mFromName.empty() + || mSourceType == CHAT_SOURCE_SYSTEM) { mFrom = LLTrans::getString("SECOND_LIFE"); if(!chat.mFromName.empty() && (mFrom != chat.mFromName)) @@ -777,6 +789,9 @@ public: case CHAT_SOURCE_SYSTEM: icon->setValue(LLSD("SL_Logo")); break; + case CHAT_SOURCE_TELEPORT: + icon->setValue(LLSD("Command_Destinations_Icon")); + break; case CHAT_SOURCE_UNKNOWN: icon->setValue(LLSD("Unknown_Icon")); } @@ -815,7 +830,7 @@ public: S32 user_name_width = user_name_rect.getWidth(); S32 time_box_width = time_box->getRect().getWidth(); - if (!time_box->getVisible() && user_name_width > mMinUserNameWidth) + if (mNeedsTimeBox && !time_box->getVisible() && user_name_width > mMinUserNameWidth) { user_name_rect.mRight -= time_box_width; user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight()); @@ -1028,6 +1043,8 @@ protected: LLTextBox* mUserNameTextBox; LLTextBox* mTimeBoxTextBox; + bool mNeedsTimeBox; + private: boost::signals2::connection mAvatarNameCacheConnection; }; @@ -1262,6 +1279,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } bool message_from_log = chat.mChatStyle == CHAT_STYLE_HISTORY; + bool teleport_separator = chat.mSourceType == CHAT_SOURCE_TELEPORT; // We graying out chat history by graying out messages that contains full date in a time string if (message_from_log) { @@ -1282,14 +1300,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL LLStyle::Params timestamp_style(body_message_params); // out of the timestamp - if (args["show_time"].asBoolean()) + if (args["show_time"].asBoolean() && !teleport_separator) { - if (!message_from_log) - { - LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); - timestamp_style.color(timestamp_color); - timestamp_style.readonly_color(timestamp_color); - } + if (!message_from_log) + { + LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor"); + timestamp_style.color(timestamp_color); + timestamp_style.readonly_color(timestamp_color); + } mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style); prependNewLineState = false; } @@ -1345,6 +1363,13 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL prependNewLineState, link_params); prependNewLineState = false; } + else if (teleport_separator) + { + std::string tp_text = LLTrans::getString("teleport_preamble_compact_chat"); + mEditor->appendText(tp_text + " " + chat.mFromName + "", + prependNewLineState, body_message_params); + prependNewLineState = false; + } else { mEditor->appendText("" + chat.mFromName + "" + delimiter, @@ -1363,8 +1388,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL p.right_pad = mRightWidgetPad; LLDate new_message_time = LLDate::now(); - - if (mLastFromName == chat.mFromName + if (!teleport_separator + && mLastFromName == chat.mFromName && mLastFromID == chat.mFromID && mLastMessageTime.notNull() && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 @@ -1387,7 +1412,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL p.top_pad = 0; else p.top_pad = mTopHeaderPad; - p.bottom_pad = mBottomHeaderPad; + if (teleport_separator) + { + p.bottom_pad = mBottomSeparatorPad; + } + else + { + p.bottom_pad = mBottomHeaderPad; + } if (!view) { LL_WARNS() << "Failed to create header from " << mMessageHeaderFilename << ": can't append to history" << LL_ENDL; @@ -1465,9 +1497,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } } } - // usual messages showing - else + else if(!teleport_separator) { std::string message = irc_me ? chat.mText.substr(3) : chat.mText; @@ -1500,7 +1531,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL if (square_brackets) { message += "]"; - } + } mEditor->appendText(message, prependNewLineState, body_message_params); prependNewLineState = false; diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index bbce2568f9..c9378ea67f 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -463,7 +463,7 @@ void LLCurrencyUIManager::Impl::updateUI() if (!mUserEnteredCurrencyBuy) { - if (!mZeroMessage.empty() && mUserCurrencyBuy == 0) + if (mUserCurrencyBuy == 0) { lindenAmount->setText(LLStringUtil::null); } @@ -476,8 +476,9 @@ void LLCurrencyUIManager::Impl::updateUI() } } - mPanel.getChild("currency_est")->setTextArg("[LOCALAMOUNT]", getLocalEstimate()); - mPanel.getChildView("currency_est")->setVisible( hasEstimate() && mUserCurrencyBuy > 0); + std::string estimated = (mUserCurrencyBuy == 0) ? mPanel.getString("estimated_zero") : getLocalEstimate(); + mPanel.getChild("currency_est")->setTextArg("[LOCALAMOUNT]", estimated); + mPanel.getChildView("currency_est")->setVisible( hasEstimate() || mUserCurrencyBuy == 0); mPanel.getChildView("currency_links")->setVisible( mSupportsInternationalBilling); mPanel.getChildView("exchange_rate_note")->setVisible( mSupportsInternationalBilling); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 68d5c53b80..d7ebf28354 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -918,9 +918,15 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) // MAINT-7926 Handle volumes in an animated object as a special case // SL-937: add dynamic box handling for rigged mesh on regular avatars. //if (volume->getAvatar() && volume->getAvatar()->isControlAvatar()) - if (volume->getAvatar()) + // reduce recursive calls. + // if (volume->getAvatar()) + // { + // const LLVector3* av_box = volume->getAvatar()->getLastAnimExtents(); + LLVOAvatar* avatarp = volume->getAvatar(); + if (avatarp) { - const LLVector3* av_box = volume->getAvatar()->getLastAnimExtents(); + const LLVector3* av_box = avatarp->getLastAnimExtents(); + // LLVector3 cam_pos_from_agent = LLViewerCamera::getInstance()->getOrigin(); LLVector3 cam_to_box_offset = point_to_box_offset(cam_pos_from_agent, av_box); mDistanceWRTCamera = llmax(0.01f, ll_round(cam_to_box_offset.magVec(), 0.01f)); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index d1b1da2b5e..991fb813bb 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -334,7 +334,7 @@ namespace std::istringstream llsdData(llsdRaw); if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) { - LL_WARNS() << "LLExperienceLogDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; + LL_WARNS() << "LLEnvironmentPushDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; } } @@ -792,11 +792,11 @@ namespace } //========================================================================= -const F32Seconds LLEnvironment::TRANSITION_INSTANT(0.0f); -const F32Seconds LLEnvironment::TRANSITION_FAST(1.0f); -const F32Seconds LLEnvironment::TRANSITION_DEFAULT(5.0f); -const F32Seconds LLEnvironment::TRANSITION_SLOW(10.0f); -const F32Seconds LLEnvironment::TRANSITION_ALTITUDE(5.0f); +const F64Seconds LLEnvironment::TRANSITION_INSTANT(0.0f); +const F64Seconds LLEnvironment::TRANSITION_FAST(1.0f); +const F64Seconds LLEnvironment::TRANSITION_DEFAULT(5.0f); +const F64Seconds LLEnvironment::TRANSITION_SLOW(10.0f); +const F64Seconds LLEnvironment::TRANSITION_ALTITUDE(5.0f); const LLUUID LLEnvironment::KNOWN_SKY_SUNRISE("01e41537-ff51-2f1f-8ef7-17e4df760bfb"); const LLUUID LLEnvironment::KNOWN_SKY_MIDDAY("6c83e853-e7f8-cad7-8ee6-5f31c453721c"); @@ -1361,51 +1361,34 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe } } -void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version) -{ - setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET); -} - // FIRE-29926 - allow manually selected environments to have a user defined transition time. void LLEnvironment::setManualEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version) { LLSettingsBase::Seconds transitionTime(static_cast(gSavedSettings.getF32("FSEnvironmentManualTransitionTime"))); - setEnvironmentWithTransition(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, transitionTime); -} -void LLEnvironment::setEnvironmentWithTransition( - EnvSelection_t env, - const LLUUID &assetId, - LLSettingsDay::Seconds daylength, - LLSettingsDay::Seconds dayoffset, - LLSettingsBase::Seconds transition, - S32 env_version) -{ - LLSettingsVOBase::getSettingsAsset(assetId, - [this, env, daylength, dayoffset, transition, env_version](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) - { - onSetEnvAssetLoaded(env, asset_id, settings, daylength, dayoffset, transition, status, env_version); - }); + setEnvironment(env, assetId, transitionTime, env_version); } // -void LLEnvironment::setEnvironment( - EnvSelection_t env, - const LLUUID &assetId, - LLSettingsDay::Seconds daylength, - LLSettingsDay::Seconds dayoffset, - S32 env_version) + +void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version) +{ + setEnvironment(env, assetId, TRANSITION_DEFAULT, env_version); +} + +void LLEnvironment::setEnvironment(EnvSelection_t env, + const LLUUID &assetId, + LLSettingsBase::Seconds transition, + S32 env_version) { LLSettingsVOBase::getSettingsAsset(assetId, - [this, env, daylength, dayoffset, env_version](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) + [this, env, env_version, transition](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { - onSetEnvAssetLoaded(env, asset_id, settings, daylength, dayoffset, TRANSITION_DEFAULT, status, env_version); + onSetEnvAssetLoaded(env, asset_id, settings, transition, status, env_version); }); } void LLEnvironment::onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, - LLSettingsDay::Seconds daylength, - LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 status, S32 env_version) @@ -1882,9 +1865,9 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI clearEnvironment(ENV_PARCEL); // opensim legacy windlight. Nothing we can do here as the default assets do not exist in OpenSim LL_WARNS("ENVIRONMENT") << "No DayCycle specified - setting default" << LL_ENDL; - if(LLGridManager::getInstance()->isInSecondLife()) + if (LLGridManager::getInstance()->isInSecondLife()) { - setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, envinfo->mEnvVersion); + setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), TRANSITION_DEFAULT, envinfo->mEnvVersion); updateEnvironment(); } // @@ -1894,7 +1877,7 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI { LL_WARNS("ENVIRONMENT") << "Invalid day cycle for region" << LL_ENDL; clearEnvironment(ENV_PARCEL); - setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, envinfo->mEnvVersion); + setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), TRANSITION_DEFAULT, envinfo->mEnvVersion); updateEnvironment(); } else @@ -3168,17 +3151,15 @@ bool LLEnvironment::loadFromSettings() if (env_data.has("day_id")) { - LLSettingsDay::Seconds length = LLSettingsDay::Seconds(env_data["day_length"].asInteger()); - LLSettingsDay::Seconds offset = LLSettingsDay::Seconds(env_data["day_offset"].asInteger()); LLUUID assetId = env_data["day_id"].asUUID(); LLSettingsVOBase::getSettingsAsset(assetId, - [this, length, offset, env_data](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) + [this, env_data](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { // Day should be always applied first, // otherwise it will override sky or water that was set earlier // so wait for asset to load before applying sky/water - onSetEnvAssetLoaded(ENV_LOCAL, asset_id, settings, length, offset, TRANSITION_DEFAULT, status, NO_VERSION); + onSetEnvAssetLoaded(ENV_LOCAL, asset_id, settings, TRANSITION_DEFAULT, status, NO_VERSION); bool valid = false, has_assets = false; loadSkyWaterFromSettings(env_data, valid, has_assets); if (!has_assets && valid) diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index 49c2ba337e..21ca9db50c 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -52,11 +52,11 @@ class LLEnvironment : public LLSingleton LOG_CLASS(LLEnvironment); public: - static const F32Seconds TRANSITION_INSTANT; - static const F32Seconds TRANSITION_FAST; - static const F32Seconds TRANSITION_DEFAULT; - static const F32Seconds TRANSITION_SLOW; - static const F32Seconds TRANSITION_ALTITUDE; + static const F64Seconds TRANSITION_INSTANT; + static const F64Seconds TRANSITION_FAST; + static const F64Seconds TRANSITION_DEFAULT; + static const F64Seconds TRANSITION_SLOW; + static const F64Seconds TRANSITION_ALTITUDE; static const LLUUID KNOWN_SKY_SUNRISE; static const LLUUID KNOWN_SKY_MIDDAY; @@ -144,13 +144,10 @@ public: void setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixed, LLSettingsWater::ptr_t()), env_version); } void setEnvironment(EnvSelection_t env, const LLSettingsWater::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(LLSettingsSky::ptr_t(), fixed), env_version); } void setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixeds, const LLSettingsWater::ptr_t & fixedw, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixeds, fixedw), env_version); } - void setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version = NO_VERSION); + void setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version); + void setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, S32 env_version = NO_VERSION); // FIRE-29926 - Allow configurable transition times - void setEnvironmentWithTransition(EnvSelection_t env, const LLUUID &assetId, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 env_version = NO_VERSION); void setManualEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version = NO_VERSION); - // - void setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version = NO_VERSION); - void setSharedEnvironment(); void clearEnvironment(EnvSelection_t env); @@ -461,7 +458,7 @@ private: void onAgentPositionHasChanged(const LLVector3 &localpos); - void onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 status, S32 env_version); + void onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, LLSettingsBase::Seconds transition, S32 status, S32 env_version); void onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, S32 parcel_id, S32 day_length, S32 day_offset, altitudes_vect_t altitudes); void handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index f69f75e6d3..4a3f7192aa 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -38,6 +38,7 @@ #include "lltooltip.h" #include "llagent.h" +#include "llagentpicksinfo.h" #include "llavatarnamecache.h" #include "llclipboard.h" #include "llinventorybridge.h" @@ -533,6 +534,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) //mMoreTextBox = LLUICtrlFactory::create (more_button_params); //mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::onMoreTextBoxClicked, this)); //addChild(mMoreTextBox); + //LLRect rect = mMoreTextBox->getRect(); + //mMoreTextBox->setRect(LLRect(rect.mLeft - rect.getWidth(), rect.mTop, rect.mRight, rect.mBottom)); if (p.chevron_button.isProvided()) { LLButton::Params chevron_button_params(p.chevron_button); @@ -546,6 +549,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) mMoreCtrl = LLUICtrlFactory::create (more_button_params); ((LLTextBox*)mMoreCtrl)->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::onMoreTextBoxClicked, this)); addChild(mMoreCtrl); + LLRect rect = mMoreCtrl->getRect(); + mMoreCtrl->setRect(LLRect(rect.mLeft - rect.getWidth(), rect.mTop, rect.mRight, rect.mBottom)); } // @@ -1371,6 +1376,10 @@ bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata) { return isClipboardPasteable(); } + else if (param == "create_pick") + { + return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); + } return false; } @@ -1422,6 +1431,13 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLFloaterReg::showInstance("world_map", "center"); } } + else if (action == "create_pick") + { + LLSD args; + args["type"] = "create_pick"; + args["item_id"] = item->getUUID(); + LLFloaterSidePanelContainer::showPanel("places", args); + } else if (action == "cut") { } @@ -1437,6 +1453,20 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) { gInventory.removeItem(mSelectedItemID); } + else if (action == "rename") + { + LLSD args; + args["NAME"] = item->getName(); + + LLSD payload; + payload["id"] = mSelectedItemID; + + LLNotificationsUtil::add("RenameLandmark", args, payload, boost::bind(onRenameCommit, _1, _2)); + } + else if (action == "move_to_landmarks") + { + change_item_parent(mSelectedItemID, gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); + } // Pop-up the overflow menu again (it gets hidden whenever the user clicks a context menu item). // See EXT-4217 and STORM-207. @@ -1449,6 +1479,28 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) } } +bool LLFavoritesBarCtrl::onRenameCommit(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LLUUID id = notification["payload"]["id"].asUUID(); + LLInventoryItem *item = gInventory.getItem(id); + std::string landmark_name = response["new_name"].asString(); + LLStringUtil::trim(landmark_name); + + if (!landmark_name.empty() && item && item->getName() != landmark_name) + { + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->rename(landmark_name); + new_item->updateServer(FALSE); + gInventory.updateItem(new_item); + } + } + + return false; +} + BOOL LLFavoritesBarCtrl::isClipboardPasteable() const { if (!LLClipboard::instance().hasContents()) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 50bca11ecc..93b8b8714f 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -94,6 +94,7 @@ protected: bool enableSelected(const LLSD& userdata); void doToSelected(const LLSD& userdata); + static bool onRenameCommit(const LLSD& notification, const LLSD& response); BOOL isClipboardPasteable() const; void pasteFromClipboard() const; diff --git a/indra/newview/llfloateraddpaymentmethod.cpp b/indra/newview/llfloateraddpaymentmethod.cpp new file mode 100644 index 0000000000..3952b48229 --- /dev/null +++ b/indra/newview/llfloateraddpaymentmethod.cpp @@ -0,0 +1,81 @@ +/** + * @file llfloateraddpaymentmethod.cpp + * @brief LLFloaterAddPaymentMethod class implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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 "llfloateraddpaymentmethod.h" +#include "llnotificationsutil.h" +#include "lluictrlfactory.h" +#include "llweb.h" + + +LLFloaterAddPaymentMethod::LLFloaterAddPaymentMethod(const LLSD& key) + : LLFloater(key) +{ +} + +LLFloaterAddPaymentMethod::~LLFloaterAddPaymentMethod() +{ +} + +BOOL LLFloaterAddPaymentMethod::postBuild() +{ + setCanDrag(FALSE); + getChild("continue_btn")->setCommitCallback(boost::bind(&LLFloaterAddPaymentMethod::onContinueBtn, this)); + getChild("close_btn")->setCommitCallback(boost::bind(&LLFloaterAddPaymentMethod::onCloseBtn, this)); + return TRUE; +} + +void LLFloaterAddPaymentMethod::onOpen(const LLSD& key) +{ + centerOnScreen(); +} + +void LLFloaterAddPaymentMethod::onContinueBtn() +{ + closeFloater(); + LLNotificationsUtil::add("AddPaymentMethod", LLSD(), LLSD(), + [this](const LLSD¬if, const LLSD&resp) + { + S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp); + if (opt == 0) + { + LLWeb::loadURL(this->getString("continue_url")); + } + }); +} + +void LLFloaterAddPaymentMethod::onCloseBtn() +{ + closeFloater(); +} + +void LLFloaterAddPaymentMethod::centerOnScreen() +{ + LLVector2 window_size = LLUI::getInstance()->getWindowSize(); + centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY]))); +} + diff --git a/indra/newview/llfloateraddpaymentmethod.h b/indra/newview/llfloateraddpaymentmethod.h new file mode 100644 index 0000000000..b3bb624484 --- /dev/null +++ b/indra/newview/llfloateraddpaymentmethod.h @@ -0,0 +1,52 @@ +/** + * @file llfloateraddpaymentmethod.h + * @brief LLFloaterAddPaymentMethod class definition + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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_FLOATER_ADDPAYMENTMETHOD_H +#define LL_FLOATER_ADDPAYMENTMETHOD_H + +#include "llfloater.h" + +class LLFloaterAddPaymentMethod: + public LLFloater +{ + friend class LLFloaterReg; +public: + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + +private: + LLFloaterAddPaymentMethod(const LLSD& key); + + void centerOnScreen(); + + void onCloseBtn(); + void onContinueBtn(); + + /*virtual*/ ~LLFloaterAddPaymentMethod(); + +}; + +#endif diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 0ff3cb417d..81f662d2b8 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -32,6 +32,8 @@ #include "llcurrencyuimanager.h" #include "llfloater.h" #include "llfloaterreg.h" +#include "lllayoutstack.h" +#include "lliconctrl.h" #include "llnotificationsutil.h" #include "llstatusbar.h" #include "lltextbox.h" @@ -45,7 +47,6 @@ #include "fsgridhandler.h" // FIRE-30481 open sim buy floater fixup #endif -static const S32 STANDARD_BUY_AMOUNT = 2000; static const S32 MINIMUM_BALANCE_AMOUNT = 0; class LLFloaterBuyCurrencyUI @@ -61,8 +62,8 @@ public: LLCurrencyUIManager mManager; bool mHasTarget; - std::string mTargetName; S32 mTargetPrice; + S32 mRequiredAmount; public: void noTarget(); @@ -71,6 +72,7 @@ public: virtual BOOL postBuild(); void updateUI(); + void collapsePanels(bool collapse); virtual void draw(); virtual BOOL canClose(); @@ -95,7 +97,9 @@ LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key) LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI(const LLSD& key) : LLFloater(key), mChildren(*this), - mManager(*this) + mManager(*this), + mHasTarget(false), + mTargetPrice(0) { } @@ -107,15 +111,20 @@ LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI() void LLFloaterBuyCurrencyUI::noTarget() { mHasTarget = false; - mManager.setAmount(STANDARD_BUY_AMOUNT); + mTargetPrice = 0; + mManager.setAmount(0); } void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price) { mHasTarget = true; - mTargetName = name; mTargetPrice = price; + if (!name.empty()) + { + getChild("target_price_label")->setValue(name); + } + S32 balance = gStatusBar->getBalance(); S32 need = price - balance; if (need < 0) @@ -123,7 +132,8 @@ void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price) need = 0; } - mManager.setAmount(need + MINIMUM_BALANCE_AMOUNT); + mRequiredAmount = need + MINIMUM_BALANCE_AMOUNT; + mManager.setAmount(0); } @@ -134,6 +144,13 @@ BOOL LLFloaterBuyCurrencyUI::postBuild() getChild("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this)); getChild("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this)); + +#ifdef OPENSIM + if (LLGridManager::instance().isInOpenSim()) + { + getChild("currency_links")->setText(LLStringExplicit("")); + } +#endif center(); @@ -178,7 +195,6 @@ void LLFloaterBuyCurrencyUI::updateUI() getChildView("purchase_warning_repurchase")->setVisible(FALSE); getChildView("purchase_warning_notenough")->setVisible(FALSE); getChildView("contacting")->setVisible(FALSE); - getChildView("buy_action")->setVisible(FALSE); if (hasError) { @@ -222,8 +238,8 @@ void LLFloaterBuyCurrencyUI::updateUI() { if (mHasTarget) { - getChildView("buy_action")->setVisible( true); - getChild("buy_action")->setTextArg("[ACTION]", mTargetName); + getChild("target_price")->setTextArg("[AMT]", llformat("%d", mTargetPrice)); + getChild("required_amount")->setTextArg("[AMT]", llformat("%d", mRequiredAmount)); } } @@ -244,18 +260,40 @@ void LLFloaterBuyCurrencyUI::updateUI() if (mHasTarget) { - if (total >= mTargetPrice) - { - getChildView("purchase_warning_repurchase")->setVisible( true); - } - else - { - getChildView("purchase_warning_notenough")->setVisible( true); - } + getChildView("purchase_warning_repurchase")->setVisible( !getChildView("currency_links")->getVisible()); } } - getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError); + getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError && !getChildView("currency_est")->getVisible()); +} + +void LLFloaterBuyCurrencyUI::collapsePanels(bool collapse) +{ + LLLayoutPanel* price_panel = getChild("layout_panel_price"); + + if (price_panel->isCollapsed() == collapse) + return; + + LLLayoutStack* outer_stack = getChild("outer_stack"); + LLLayoutPanel* required_panel = getChild("layout_panel_required"); + LLLayoutPanel* msg_panel = getChild("layout_panel_msg"); + + S32 delta_height = price_panel->getRect().getHeight() + required_panel->getRect().getHeight() + msg_panel->getRect().getHeight(); + delta_height *= (collapse ? -1 : 1); + + LLIconCtrl* icon = getChild("normal_background"); + LLRect rect = icon->getRect(); + icon->setRect(rect.setOriginAndSize(rect.mLeft, rect.mBottom - delta_height, rect.getWidth(), rect.getHeight() + delta_height)); + + outer_stack->collapsePanel(price_panel, collapse); + outer_stack->collapsePanel(required_panel, collapse); + outer_stack->collapsePanel(msg_panel, collapse); + + outer_stack->updateLayout(); + + LLRect floater_rect = getRect(); + floater_rect.mBottom -= delta_height; + setShape(floater_rect, false); } void LLFloaterBuyCurrencyUI::onClickBuy() @@ -278,25 +316,109 @@ void LLFloaterBuyCurrencyUI::onClickCancel() LLStatusBar::sendMoneyBalanceRequest(); } +LLFetchAvatarPaymentInfo* LLFloaterBuyCurrency::sPropertiesRequest = NULL; + // static void LLFloaterBuyCurrency::buyCurrency() { - LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance("buy_currency"); - ui->noTarget(); - ui->updateUI(); + // OpenSim support + //delete sPropertiesRequest; + //sPropertiesRequest = new LLFetchAvatarPaymentInfo(false); +#if OPENSIM + if (LLGridManager::instance().isInOpenSim()) + { + LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance("buy_currency"); + ui->noTarget(); + ui->updateUI(); + } + else +#endif + { + delete sPropertiesRequest; + sPropertiesRequest = new LLFetchAvatarPaymentInfo(false); + } + // } // static void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price) { - LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance("buy_currency"); - // - // Not wrapping name here because according to llfloaterbuycurrency.h - // name should not include currency symbols as the price will be appended to the string. - // If an "L$" is ever included in a name, then we should call Tea::wrapCurrency on it here. - // > - ui->target(name, price); - ui->updateUI(); + // OpenSim support + //delete sPropertiesRequest; + //sPropertiesRequest = new LLFetchAvatarPaymentInfo(true, name, price); +#if OPENSIM + if (LLGridManager::instance().isInOpenSim()) + { + LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance("buy_currency"); + // + // Not wrapping name here because according to llfloaterbuycurrency.h + // name should not include currency symbols as the price will be appended to the string. + // If an "L$" is ever included in a name, then we should call Tea::wrapCurrency on it here. + // > + ui->target(name, price); + ui->updateUI(); + } + else +#endif + { + delete sPropertiesRequest; + sPropertiesRequest = new LLFetchAvatarPaymentInfo(true, name, price); + } + // +} + +// static +void LLFloaterBuyCurrency::handleBuyCurrency(bool has_piof, bool has_target, const std::string name, S32 price) +{ + delete sPropertiesRequest; + sPropertiesRequest = NULL; + + if (has_piof) + { + LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance("buy_currency"); + if (has_target) + { + ui->target(name, price); + } + else + { + ui->noTarget(); + } + ui->updateUI(); + ui->collapsePanels(!has_target); + } + else + { + LLFloaterReg::showInstance("add_payment_method"); + } +} + +LLFetchAvatarPaymentInfo::LLFetchAvatarPaymentInfo(bool has_target, const std::string& name, S32 price) +: mAvatarID(gAgent.getID()), + mHasTarget(has_target), + mPrice(price), + mName(name) +{ + LLAvatarPropertiesProcessor* processor = LLAvatarPropertiesProcessor::getInstance(); + // register ourselves as an observer + processor->addObserver(mAvatarID, this); + // send a request (duplicates will be suppressed inside the avatar + // properties processor) + processor->sendAvatarPropertiesRequest(mAvatarID); +} + +LLFetchAvatarPaymentInfo::~LLFetchAvatarPaymentInfo() +{ + LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarID, this); +} + +void LLFetchAvatarPaymentInfo::processProperties(void* data, EAvatarProcessorType type) +{ + if (data && type == APT_PROPERTIES) + { + LLAvatarData* avatar_data = static_cast(data); + LLFloaterBuyCurrency::handleBuyCurrency(LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(avatar_data), mHasTarget, mName, mPrice); + } } // @@ -311,7 +433,8 @@ void LLFloaterBuyCurrency::updateCurrencySymbols() // update all text boxes with currency symbols. LLTextBox* tb = NULL; - static const std::list sctb = { "info_need_more", "info_buying", "currency_label", "purchase_warning_repurchase", "purchase_warning_notenough" }; + static const std::list sctb = { "info_need_more", "info_buying", "target_price", "balance_amount", + "required_amount", "currency_label", "total_amount", "purchase_warning_repurchase" }; // Do not include balance_amount and total_amount because they are updated on every display when amounts are replaced. for (std::list::const_iterator iter = sctb.begin(); iter != sctb.end(); ++iter) { @@ -324,3 +447,4 @@ void LLFloaterBuyCurrency::updateCurrencySymbols() } } // + diff --git a/indra/newview/llfloaterbuycurrency.h b/indra/newview/llfloaterbuycurrency.h index 3fdacea4de..ab41b0c973 100644 --- a/indra/newview/llfloaterbuycurrency.h +++ b/indra/newview/llfloaterbuycurrency.h @@ -27,15 +27,34 @@ #ifndef LL_LLFLOATERBUYCURRENCY_H #define LL_LLFLOATERBUYCURRENCY_H +#include "llavatarpropertiesprocessor.h" #include "stdtypes.h" - +#include "llagent.h" class LLFloater; +class LLFetchAvatarPaymentInfo : public LLAvatarPropertiesObserver +{ +public: + LLFetchAvatarPaymentInfo(bool has_target, const std::string& name = std::string(), S32 price = 0); + ~LLFetchAvatarPaymentInfo(); + + void processProperties(void* data, EAvatarProcessorType type); + +private: + LLUUID mAvatarID; + bool mHasTarget; + std::string mName; + S32 mPrice; +}; + + class LLFloaterBuyCurrency { public: static void buyCurrency(); static void buyCurrency(const std::string& name, S32 price); + + static void handleBuyCurrency(bool has_piof, bool has_target, const std::string name, S32 price); /* name should be a noun phrase of the object or service being bought: "That object costs" "Trying to give" @@ -45,6 +64,8 @@ public: static LLFloater* buildFloater(const LLSD& key); + static LLFetchAvatarPaymentInfo* sPropertiesRequest; + // // Necessary because floater was designed to build only on first display. // Forces refresh of all currency symbols in floater when called. @@ -52,5 +73,4 @@ public: // }; - #endif diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp new file mode 100644 index 0000000000..eb93a6a75a --- /dev/null +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -0,0 +1,323 @@ +/** + * @file llfloatercreatelandmark.cpp + * @brief LLFloaterCreateLandmark class implementation + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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 "llfloatercreatelandmark.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llcombobox.h" +#include "llinventoryfunctions.h" +#include "llinventoryobserver.h" +#include "lllandmarkactions.h" +#include "llnotificationsutil.h" +#include "llpanellandmarkinfo.h" +#include "llparcel.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "lluictrlfactory.h" +#include "llviewermessage.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" + +typedef std::pair folder_pair_t; + +class LLLandmarksInventoryObserver : public LLInventoryAddedObserver +{ +public: + LLLandmarksInventoryObserver(LLFloaterCreateLandmark* create_landmark_floater) : + mFloater(create_landmark_floater) + {} + +protected: + /*virtual*/ void done() + { + mFloater->setItem(gInventory.getAddedIDs()); + } + +private: + LLFloaterCreateLandmark* mFloater; +}; + +LLFloaterCreateLandmark::LLFloaterCreateLandmark(const LLSD& key) + : LLFloater("add_landmark"), + mItem(NULL) +{ + mInventoryObserver = new LLLandmarksInventoryObserver(this); +} + +LLFloaterCreateLandmark::~LLFloaterCreateLandmark() +{ + removeObserver(); +} + +BOOL LLFloaterCreateLandmark::postBuild() +{ + mFolderCombo = getChild("folder_combo"); + mLandmarkTitleEditor = getChild("title_editor"); + mNotesEditor = getChild("notes_editor"); + + getChild("new_folder_textbox")->setURLClickedCallback(boost::bind(&LLFloaterCreateLandmark::onCreateFolderClicked, this)); + getChild("ok_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onSaveClicked, this)); + getChild("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterCreateLandmark::onCancelClicked, this)); + + mLandmarksID = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + + return TRUE; +} + +void LLFloaterCreateLandmark::removeObserver() +{ + if (gInventory.containsObserver(mInventoryObserver)) + gInventory.removeObserver(mInventoryObserver); +} + +void LLFloaterCreateLandmark::onOpen(const LLSD& key) +{ + LLUUID dest_folder = LLUUID(); + if (key.has("dest_folder")) + { + dest_folder = key["dest_folder"].asUUID(); + } + mItem = NULL; + gInventory.addObserver(mInventoryObserver); + setLandmarkInfo(dest_folder); + populateFoldersList(dest_folder); +} + +void LLFloaterCreateLandmark::setLandmarkInfo(const LLUUID &folder_id) +{ + LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); + LLParcel* parcel = parcel_mgr->getAgentParcel(); + std::string name = parcel->getName(); + LLVector3 agent_pos = gAgent.getPositionAgent(); + + if (name.empty()) + { + S32 region_x = ll_round(agent_pos.mV[VX]); + S32 region_y = ll_round(agent_pos.mV[VY]); + S32 region_z = ll_round(agent_pos.mV[VZ]); + + std::string region_name; + LLViewerRegion* region = parcel_mgr->getSelectionRegion(); + if (region) + { + region_name = region->getName(); + } + else + { + std::string desc; + LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos); + region_name = desc; + } + + mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)", + region_name.c_str(), region_x, region_y, region_z)); + } + else + { + mLandmarkTitleEditor->setText(name); + } + + LLLandmarkActions::createLandmarkHere(name, "", folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)); +} + +bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) +{ + return left.second < right.second; +} + +void LLFloaterCreateLandmark::populateFoldersList(const LLUUID &folder_id) +{ + // Collect all folders that can contain landmarks. + LLInventoryModel::cat_array_t cats; + LLPanelLandmarkInfo::collectLandmarkFolders(cats); + + mFolderCombo->removeall(); + + // Put the "My Favorites" folder first in list. + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id); + if (!favorites_cat) + { + LL_WARNS() << "Cannot find the favorites folder" << LL_ENDL; + } + else + { + mFolderCombo->add(getString("favorites_bar"), favorites_cat->getUUID()); + } + + // Add the "Landmarks" category. + const LLViewerInventoryCategory* lmcat = gInventory.getCategory(mLandmarksID); + if (!lmcat) + { + LL_WARNS() << "Cannot find the landmarks folder" << LL_ENDL; + } + else + { + std::string cat_full_name = LLPanelLandmarkInfo::getFullFolderName(lmcat); + mFolderCombo->add(cat_full_name, lmcat->getUUID()); + } + + typedef std::vector folder_vec_t; + folder_vec_t folders; + // Sort the folders by their full name. + for (S32 i = 0; i < cats.size(); i++) + { + const LLViewerInventoryCategory* cat = cats.at(i); + std::string cat_full_name = LLPanelLandmarkInfo::getFullFolderName(cat); + folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name)); + } + sort(folders.begin(), folders.end(), cmp_folders); + + // Finally, populate the combobox. + for (folder_vec_t::const_iterator it = folders.begin(); it != folders.end(); it++) + mFolderCombo->add(it->second, LLSD(it->first)); + + if (folder_id.notNull()) + { + mFolderCombo->setCurrentByID(folder_id); + } +} + +void LLFloaterCreateLandmark::onCreateFolderClicked() +{ + LLNotificationsUtil::add("CreateLandmarkFolder", LLSD(), LLSD(), + [this](const LLSD¬if, const LLSD&resp) + { + S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp); + if (opt == 0) + { + std::string folder_name = resp["message"].asString(); + if (!folder_name.empty()) + { + inventory_func_type func = boost::bind(&LLFloaterCreateLandmark::folderCreatedCallback, this, _1); + gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, func); + gInventory.notifyObservers(); + } + } + }); +} + +void LLFloaterCreateLandmark::folderCreatedCallback(LLUUID folder_id) +{ + populateFoldersList(folder_id); +} + +void LLFloaterCreateLandmark::onSaveClicked() +{ + if (mItem.isNull()) + { + closeFloater(); + return; + } + + + std::string current_title_value = mLandmarkTitleEditor->getText(); + std::string item_title_value = mItem->getName(); + std::string current_notes_value = mNotesEditor->getText(); + std::string item_notes_value = mItem->getDescription(); + + LLStringUtil::trim(current_title_value); + LLStringUtil::trim(current_notes_value); + + LLUUID item_id = mItem->getUUID(); + LLUUID folder_id = mFolderCombo->getValue().asUUID(); + bool change_parent = folder_id != mItem->getParentUUID(); + + LLPointer new_item = new LLViewerInventoryItem(mItem); + + if (!current_title_value.empty() && + (item_title_value != current_title_value || item_notes_value != current_notes_value)) + { + new_item->rename(current_title_value); + new_item->setDescription(current_notes_value); + LLPointer cb; + if (change_parent) + { + cb = new LLUpdateLandmarkParent(new_item, folder_id); + } + LLInventoryModel::LLCategoryUpdate up(mItem->getParentUUID(), 0); + gInventory.accountForUpdate(up); + update_inventory_item(new_item, cb); + } + else if (change_parent) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + new_item->setParent(folder_id); + new_item->updateParentOnServer(FALSE); + } + + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + + closeFloater(); +} + +void LLFloaterCreateLandmark::onCancelClicked() +{ + if (!mItem.isNull()) + { + LLUUID item_id = mItem->getUUID(); + remove_inventory_item(item_id, NULL); + } + closeFloater(); +} + + +void LLFloaterCreateLandmark::setItem(const uuid_set_t& items) +{ + for (uuid_set_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + const LLUUID& item_id = (*item_iter); + if(!highlight_offered_object(item_id)) + { + continue; + } + + LLInventoryItem* item = gInventory.getItem(item_id); + + llassert(item); + if (item && (LLAssetType::AT_LANDMARK == item->getType()) ) + { + if(!getItem()) + { + removeObserver(); + mItem = item; + break; + } + } + } +} \ No newline at end of file diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h new file mode 100644 index 0000000000..74ac5e651c --- /dev/null +++ b/indra/newview/llfloatercreatelandmark.h @@ -0,0 +1,74 @@ +/** + * @file llfloatercreatelandmark.h + * @brief LLFloaterCreateLandmark class definition + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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_LLFLOATERCREATELANDMARK_H +#define LL_LLFLOATERCREATELANDMARK_H + +#include "llfloater.h" + +class LLComboBox; +class LLInventoryItem; +class LLLineEditor; +class LLTextEditor; +class LLLandmarksInventoryObserver; + +class LLFloaterCreateLandmark: + public LLFloater +{ + friend class LLFloaterReg; + +public: + + LLFloaterCreateLandmark(const LLSD& key); + ~LLFloaterCreateLandmark(); + + BOOL postBuild(); + void onOpen(const LLSD& key); + + void setItem(const uuid_set_t& items); + + LLInventoryItem* getItem() { return mItem; } + +private: + void setLandmarkInfo(const LLUUID &folder_id); + void removeObserver(); + void populateFoldersList(const LLUUID &folder_id = LLUUID::null); + void onCreateFolderClicked(); + void onSaveClicked(); + void onCancelClicked(); + + void folderCreatedCallback(LLUUID folder_id); + + LLComboBox* mFolderCombo; + LLLineEditor* mLandmarkTitleEditor; + LLTextEditor* mNotesEditor; + LLUUID mLandmarksID; + + LLLandmarksInventoryObserver* mInventoryObserver; + LLPointer mItem; +}; + +#endif diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp index 4eb5e03603..95d6a2d652 100644 --- a/indra/newview/llfloaterenvironmentadjust.cpp +++ b/indra/newview/llfloaterenvironmentadjust.cpp @@ -53,11 +53,15 @@ namespace const std::string FIELD_SKY_CLOUD_SCALE("cloud_scale"); const std::string FIELD_SKY_SCENE_GAMMA("scene_gamma"); const std::string FIELD_SKY_SUN_ROTATION("sun_rotation"); + const std::string FIELD_SKY_SUN_AZIMUTH("sun_azimuth"); + const std::string FIELD_SKY_SUN_ELEVATION("sun_elevation"); const std::string FIELD_SKY_SUN_SCALE("sun_scale"); const std::string FIELD_SKY_GLOW_FOCUS("glow_focus"); const std::string FIELD_SKY_GLOW_SIZE("glow_size"); const std::string FIELD_SKY_STAR_BRIGHTNESS("star_brightness"); const std::string FIELD_SKY_MOON_ROTATION("moon_rotation"); + const std::string FIELD_SKY_MOON_AZIMUTH("moon_azimuth"); + const std::string FIELD_SKY_MOON_ELEVATION("moon_elevation"); const std::string BTN_RESET("btn_reset"); const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f); @@ -96,9 +100,13 @@ BOOL LLFloaterEnvironmentAdjust::postBuild() getChild(FIELD_SKY_GLOW_SIZE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); }); getChild(FIELD_SKY_STAR_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onStarBrightnessChanged(); }); getChild(FIELD_SKY_SUN_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunRotationChanged(); }); + getChild(FIELD_SKY_SUN_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); }); + getChild(FIELD_SKY_SUN_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); }); getChild(FIELD_SKY_SUN_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunScaleChanged(); }); getChild(FIELD_SKY_MOON_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonRotationChanged(); }); + getChild(FIELD_SKY_MOON_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); }); + getChild(FIELD_SKY_MOON_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); }); getChild(BTN_RESET)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onButtonReset(); }); getChild(FIELD_SKY_CLOUD_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudMapChanged(); }); @@ -169,10 +177,25 @@ void LLFloaterEnvironmentAdjust::refresh() getChild(FIELD_SKY_GLOW_SIZE)->setValue(2.0 - (glow.mV[0] / SLIDER_SCALE_GLOW_R)); getChild(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B); getChild(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mLiveSky->getStarBrightness()); - getChild(FIELD_SKY_SUN_ROTATION)->setRotation(mLiveSky->getSunRotation()); getChild(FIELD_SKY_SUN_SCALE)->setValue(mLiveSky->getSunScale()); - getChild(FIELD_SKY_MOON_ROTATION)->setRotation(mLiveSky->getMoonRotation()); + // Sun rotation + LLQuaternion quat = mLiveSky->getSunRotation(); + F32 azimuth; + F32 elevation; + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + + getChild(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_SUN_ELEVATION)->setValue(elevation); + getChild(FIELD_SKY_SUN_ROTATION)->setRotation(quat); + + // Moon rotation + quat = mLiveSky->getMoonRotation(); + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + + getChild(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_MOON_ELEVATION)->setValue(elevation); + getChild(FIELD_SKY_MOON_ROTATION)->setRotation(quat); } @@ -325,10 +348,45 @@ void LLFloaterEnvironmentAdjust::onStarBrightnessChanged() void LLFloaterEnvironmentAdjust::onSunRotationChanged() { - if (!mLiveSky) - return; - mLiveSky->setSunRotation(getChild(FIELD_SKY_SUN_ROTATION)->getRotation()); - mLiveSky->update(); + LLQuaternion quat = getChild(FIELD_SKY_SUN_ROTATION)->getRotation(); + F32 azimuth; + F32 elevation; + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + getChild(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_SUN_ELEVATION)->setValue(elevation); + if (mLiveSky) + { + mLiveSky->setSunRotation(quat); + mLiveSky->update(); + } +} + +void LLFloaterEnvironmentAdjust::onSunAzimElevChanged() +{ + F32 azimuth = getChild(FIELD_SKY_SUN_AZIMUTH)->getValue().asReal(); + F32 elevation = getChild(FIELD_SKY_SUN_ELEVATION)->getValue().asReal(); + LLQuaternion quat; + + azimuth *= DEG_TO_RAD; + elevation *= DEG_TO_RAD; + + if (is_approx_zero(elevation)) + { + elevation = F_APPROXIMATELY_ZERO; + } + + quat.setAngleAxis(-elevation, 0, 1, 0); + LLQuaternion az_quat; + az_quat.setAngleAxis(F_TWO_PI - azimuth, 0, 0, 1); + quat *= az_quat; + + getChild(FIELD_SKY_SUN_ROTATION)->setRotation(quat); + + if (mLiveSky) + { + mLiveSky->setSunRotation(quat); + mLiveSky->update(); + } } void LLFloaterEnvironmentAdjust::onSunScaleChanged() @@ -341,10 +399,45 @@ void LLFloaterEnvironmentAdjust::onSunScaleChanged() void LLFloaterEnvironmentAdjust::onMoonRotationChanged() { - if (!mLiveSky) - return; - mLiveSky->setMoonRotation(getChild(FIELD_SKY_MOON_ROTATION)->getRotation()); - mLiveSky->update(); + LLQuaternion quat = getChild(FIELD_SKY_MOON_ROTATION)->getRotation(); + F32 azimuth; + F32 elevation; + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + getChild(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_MOON_ELEVATION)->setValue(elevation); + if (mLiveSky) + { + mLiveSky->setMoonRotation(quat); + mLiveSky->update(); + } +} + +void LLFloaterEnvironmentAdjust::onMoonAzimElevChanged() +{ + F32 azimuth = getChild(FIELD_SKY_MOON_AZIMUTH)->getValue().asReal(); + F32 elevation = getChild(FIELD_SKY_MOON_ELEVATION)->getValue().asReal(); + LLQuaternion quat; + + azimuth *= DEG_TO_RAD; + elevation *= DEG_TO_RAD; + + if (is_approx_zero(elevation)) + { + elevation = F_APPROXIMATELY_ZERO; + } + + quat.setAngleAxis(-elevation, 0, 1, 0); + LLQuaternion az_quat; + az_quat.setAngleAxis(F_TWO_PI - azimuth, 0, 0, 1); + quat *= az_quat; + + getChild(FIELD_SKY_MOON_ROTATION)->setRotation(quat); + + if (mLiveSky) + { + mLiveSky->setMoonRotation(quat); + mLiveSky->update(); + } } void LLFloaterEnvironmentAdjust::onCloudMapChanged() diff --git a/indra/newview/llfloaterenvironmentadjust.h b/indra/newview/llfloaterenvironmentadjust.h index cb38dbcfa8..05ff011be5 100644 --- a/indra/newview/llfloaterenvironmentadjust.h +++ b/indra/newview/llfloaterenvironmentadjust.h @@ -73,9 +73,11 @@ private: void onGlowChanged(); void onStarBrightnessChanged(); void onSunRotationChanged(); + void onSunAzimElevChanged(); void onSunScaleChanged(); void onMoonRotationChanged(); + void onMoonAzimElevChanged(); void onCloudMapChanged(); void onWaterMapChanged(); diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp index 41bbd5e8f9..4f2c36f45b 100644 --- a/indra/newview/llfloaterfixedenvironment.cpp +++ b/indra/newview/llfloaterfixedenvironment.cpp @@ -128,7 +128,7 @@ void LLFloaterFixedEnvironment::onOpen(const LLSD& key) updateEditEnvironment(); syncronizeTabs(); refresh(); - LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT); } @@ -180,7 +180,7 @@ void LLFloaterFixedEnvironment::setEditSettingsAndUpdate(const LLSettingsBase::p updateEditEnvironment(); syncronizeTabs(); refresh(); - LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST); + LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT); } void LLFloaterFixedEnvironment::syncronizeTabs() @@ -460,7 +460,7 @@ void LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile(const std::vector< setDirtyFlag(); LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, legacywater); setEditSettings(legacywater); - LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST, true); + LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT, true); } //========================================================================= @@ -548,7 +548,7 @@ void LLFloaterFixedEnvironmentSky::loadSkySettingFromFile(const std::vector("stack1"); + LLRect stack_rect = stack->getRect(); + stack->reshape(STACK_WIDTH, STACK_HEIGHT); + stack->setOrigin(stack_rect.mLeft, stack_rect.mTop - STACK_HEIGHT); + stack->updateLayout(); + } +} + +LLFloaterHowTo* LLFloaterHowTo::getInstance() +{ + return LLFloaterReg::getTypedInstance("guidebook"); +} + +BOOL LLFloaterHowTo::handleKeyHere(KEY key, MASK mask) +{ + BOOL handled = FALSE; + + if (KEY_F1 == key ) + { + closeFloater(); + handled = TRUE; + } + + return handled; +} diff --git a/indra/newview/llfloaterhowto.h b/indra/newview/llfloaterhowto.h new file mode 100644 index 0000000000..d8da355600 --- /dev/null +++ b/indra/newview/llfloaterhowto.h @@ -0,0 +1,58 @@ +/** + * @file llfloaterhowto.h + * @brief A variant of web floater meant to open guidebook + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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_LLFLOATERHOWTO_H +#define LL_LLFLOATERHOWTO_H + +#include "llfloaterwebcontent.h" + +class LLMediaCtrl; + + +class LLFloaterHowTo : + public LLFloaterWebContent +{ +public: + LOG_CLASS(LLFloaterHowTo); + + typedef LLFloaterWebContent::Params Params; + + LLFloaterHowTo(const Params& key); + + void onOpen(const LLSD& key) override; + + BOOL handleKeyHere(KEY key, MASK mask) override; + + static LLFloaterHowTo* getInstance(); + + bool matchesKey(const LLSD& key) override { return true; /*single instance*/ }; + +private: + BOOL postBuild() override; +}; + +#endif // LL_LLFLOATERHOWTO_H + diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 5225473cf6..3291e744d3 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -69,6 +69,7 @@ #include "llviewerchat.h" #include "lltranslate.h" #include "llautoreplace.h" +#include "lluiusage.h" // [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0b) #include "rlvactions.h" #include "rlvcommon.h" @@ -707,6 +708,7 @@ void LLFloaterIMNearbyChat::sendChatFromViewer(const std::string &utf8text, ECha void LLFloaterIMNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) { + LLUIUsage::instance().logCommand("Chat.Send"); // pseuo-command // Look for "/20 foo" channel chats. S32 channel = 0; LLWString out_text = stripChannelNumber(wtext, &channel); diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp index f34760a6bf..749a3d2686 100644 --- a/indra/newview/llfloaterlandholdings.cpp +++ b/indra/newview/llfloaterlandholdings.cpp @@ -51,6 +51,9 @@ #include "llgroupactions.h" +const std::string LINDEN_HOMES_SKU = "131"; +bool LLFloaterLandHoldings::sHasLindenHome = false; + // protected LLFloaterLandHoldings::LLFloaterLandHoldings(const LLSD& key) : LLFloater(key), @@ -148,10 +151,24 @@ void LLFloaterLandHoldings::refresh() void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**) { LLFloaterLandHoldings* self = LLFloaterReg::findTypedInstance("land_holdings"); - - // Is this packet from an old, closed window? + S32 count = msg->getNumberOfBlocks("QueryData"); + std::string land_sku; + sHasLindenHome = false; if (!self) { + for (S32 i = 0; i < count; i++) + { + if ( msg->getSizeFast(_PREHASH_QueryData, i, _PREHASH_ProductSKU) > 0 ) + { + msg->getStringFast( _PREHASH_QueryData, _PREHASH_ProductSKU, land_sku, i); + + if (LINDEN_HOMES_SKU == land_sku) + { + sHasLindenHome = true; + return; + } + } + } return; } @@ -174,12 +191,9 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**) F32 global_x; F32 global_y; std::string sim_name; - std::string land_sku; std::string land_type; - S32 i; - S32 count = msg->getNumberOfBlocks("QueryData"); - for (i = 0; i < count; i++) + for (S32 i = 0; i < count; i++) { msg->getUUID("QueryData", "OwnerID", owner_id, i); msg->getString("QueryData", "Name", name, i); @@ -196,6 +210,10 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**) msg->getStringFast( _PREHASH_QueryData, _PREHASH_ProductSKU, land_sku, i); LL_INFOS() << "Land sku: " << land_sku << LL_ENDL; land_type = LLProductInfoRequestManager::instance().getDescriptionForSku(land_sku); + if (LINDEN_HOMES_SKU == land_sku) + { + sHasLindenHome = true; + } } else { diff --git a/indra/newview/llfloaterlandholdings.h b/indra/newview/llfloaterlandholdings.h index d1d510bb40..90e75b1062 100644 --- a/indra/newview/llfloaterlandholdings.h +++ b/indra/newview/llfloaterlandholdings.h @@ -57,6 +57,8 @@ public: static void onGrantList(void* data); + static bool sHasLindenHome; + protected: void refreshAggregates(); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index b410be19a1..4948039dc8 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -701,7 +701,7 @@ void LLFloaterWorldMap::processParcelInfo(const LLParcelData& parcel_data, const LLTracker::trackLocation(pos_global, parcel_data.name.empty() ? getString("UnnamedParcel") : parcel_data.name, full_name); } -void LLFloaterWorldMap::requestParcelInfo(const LLVector3d& pos_global) +void LLFloaterWorldMap::requestParcelInfo(const LLVector3d& pos_global, const LLVector3d& region_origin) { if (pos_global == mRequestedGlobalPos) { @@ -713,16 +713,8 @@ void LLFloaterWorldMap::requestParcelInfo(const LLVector3d& pos_global) { return; } - // VarRegion slurl shenanigans - // agent_x = ll_round(region_pos.mV[VX]); - // agent_y = ll_round(region_pos.mV[VY]); - // agent_z = ll_round(region_pos.mV[VZ]); - // LLVector3 pos_region((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS), - // (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS), - // (F32)pos_global.mdV[VZ]); - auto region_origin = region->getOriginGlobal(); + auto pos_region = LLVector3(pos_global - region_origin); - // LLSD body; std::string url = region->getCapability("RemoteParcelRequest"); @@ -739,7 +731,6 @@ void LLFloaterWorldMap::requestParcelInfo(const LLVector3d& pos_global) region->getRegionID(), pos_region, pos_global, mParcelInfoObserver->getObserverHandle() ); - } else { @@ -903,7 +894,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) { mShowParcelInfo = true; - requestParcelInfo(pos_global); + requestParcelInfo(pos_global, sim_info->getGlobalOrigin()); } else { diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 924098435b..ae77b86d22 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -179,7 +179,7 @@ protected: void cacheLandmarkPosition(); // Parcel details on map - void requestParcelInfo(const LLVector3d& pos_global); + void requestParcelInfo(const LLVector3d& pos_global, const LLVector3d& region_origin); LLVector3d mRequestedGlobalPos; bool mShowParcelInfo; FSWorldMapParcelInfoObserver* mParcelInfoObserver; diff --git a/indra/newview/llflyoutcombobtn.h b/indra/newview/llflyoutcombobtn.h index e41cd0cecb..be9113f558 100644 --- a/indra/newview/llflyoutcombobtn.h +++ b/indra/newview/llflyoutcombobtn.h @@ -1,5 +1,5 @@ /** - * @file llsaveoutfitcombobtn.h + * @file llflyoutcombobtn.h * @brief Represents outfit save/save as combo button. * * $LicenseInfo:firstyear=2010&license=viewerlgpl$ diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h index 06a908cccc..51b98339c4 100644 --- a/indra/newview/llfolderviewmodelinventory.h +++ b/indra/newview/llfolderviewmodelinventory.h @@ -45,6 +45,7 @@ public: virtual LLFolderType::EType getPreferredType() const = 0; virtual void showProperties(void) = 0; virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. + virtual BOOL isAgentInventory() const { return FALSE; } virtual BOOL isUpToDate() const = 0; virtual bool hasChildren() const = 0; virtual LLInventoryType::EType getInventoryType() const = 0; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1e43d7b737..50cdc45252 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2046,31 +2046,11 @@ void LLItemBridge::restoreToWorld() void LLItemBridge::gotoItem() { - LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); - // Optional hiding of Received Items folder aka Inbox - //if (gInventory.isObjectDescendentOf(obj->getLinkedUUID(), inbox_id)) - if (gInventory.isObjectDescendentOf(obj->getLinkedUUID(), inbox_id) && !gSavedSettings.getBOOL("FSShowInboxFolder")) - // - { - LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); - if (sidepanel_inventory && sidepanel_inventory->getInboxPanel()) - { - sidepanel_inventory->getInboxPanel()->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); - } - } - else - { - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); - if (active_panel) - { - active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); - } - } - - } + LLInventoryObject *obj = getInventoryObject(); + if (obj && obj->getIsLinkType()) + { + show_item_original(obj->getUUID()); + } } LLUIImagePtr LLItemBridge::getIcon() const @@ -4527,6 +4507,12 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items items.push_back(std::string("New Body Parts")); items.push_back(std::string("New Settings")); items.push_back(std::string("upload_def")); + + if (!LLEnvironment::instance().isInventoryEnabled()) + { + disabled_items.push_back("New Settings"); + } + } } getClipboardEntries(false, items, disabled_items, flags); @@ -7822,7 +7808,8 @@ void LLSettingsBridge::performAction(LLInventoryModel* model, std::string action return; LLUUID asset_id = item->getAssetUUID(); // FIRE-30701 - Allow crossfade time to apply when using EEP from inventory. - // LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id); + //LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id, LLEnvironment::TRANSITION_INSTANT); + //LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setManualEnvironment(LLEnvironment::ENV_LOCAL, asset_id); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); } @@ -7996,21 +7983,17 @@ void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string acti } void LLLinkFolderBridge::gotoItem() { - const LLUUID &cat_uuid = getFolderID(); - if (!cat_uuid.isNull()) - { - LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid); - if (base_folder) - { - if (LLInventoryModel* model = getInventoryModel()) - { - model->fetchDescendentsOf(cat_uuid); - } - base_folder->setOpen(TRUE); - mRoot->setSelection(base_folder,TRUE); - mRoot->scrollToShowSelection(); - } - } + LLItemBridge::gotoItem(); + + const LLUUID &cat_uuid = getFolderID(); + if (!cat_uuid.isNull()) + { + LLFolderViewItem *base_folder = LLInventoryPanel::getActiveInventoryPanel()->getItemByID(cat_uuid); + if (base_folder) + { + base_folder->setOpen(TRUE); + } + } } const LLUUID &LLLinkFolderBridge::getFolderID() const { diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index e84fbeb577..21a2c5cbbf 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -69,7 +69,8 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p) mPermissions(p.permissions), mFilterTypes(p.types), mFilterUUID(p.uuid), - mFilterLinks(p.links) + mFilterLinks(p.links), + mSearchVisibility(p.search_visibility) { } @@ -171,6 +172,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item) passed = passed && checkAgainstPermissions(listener); passed = passed && checkAgainstFilterLinks(listener); passed = passed && checkAgainstCreator(listener); + passed = passed && checkAgainstSearchVisibility(listener); return passed; } @@ -625,6 +627,27 @@ bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory } } +bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItemInventory* listener) const +{ + if (!listener || !hasFilterString()) return TRUE; + + const LLUUID object_id = listener->getUUID(); + const LLInventoryObject *object = gInventory.getObject(object_id); + if (!object) return TRUE; + + const BOOL is_link = object->getIsLinkType(); + if (is_link && ((mFilterOps.mSearchVisibility & VISIBILITY_LINKS) == 0)) + return FALSE; + + if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0)) + return FALSE; + + if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0)) + return FALSE; + + return TRUE; +} + const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const { return mFilterSubString; @@ -796,6 +819,61 @@ void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_list } } + +void LLInventoryFilter::toggleSearchVisibilityLinks() +{ + bool hide_links = mFilterOps.mSearchVisibility & VISIBILITY_LINKS; + if (hide_links) + { + mFilterOps.mSearchVisibility &= ~VISIBILITY_LINKS; + } + else + { + mFilterOps.mSearchVisibility |= VISIBILITY_LINKS; + } + + if (hasFilterString()) + { + setModified(hide_links ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); + } +} + +void LLInventoryFilter::toggleSearchVisibilityTrash() +{ + bool hide_trash = mFilterOps.mSearchVisibility & VISIBILITY_TRASH; + if (hide_trash) + { + mFilterOps.mSearchVisibility &= ~VISIBILITY_TRASH; + } + else + { + mFilterOps.mSearchVisibility |= VISIBILITY_TRASH; + } + + if (hasFilterString()) + { + setModified(hide_trash ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); + } +} + +void LLInventoryFilter::toggleSearchVisibilityLibrary() +{ + bool hide_library = mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY; + if (hide_library) + { + mFilterOps.mSearchVisibility &= ~VISIBILITY_LIBRARY; + } + else + { + mFilterOps.mSearchVisibility |= VISIBILITY_LIBRARY; + } + + if (hasFilterString()) + { + setModified(hide_library ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE); + } +} + void LLInventoryFilter::setFilterNoMarketplaceFolder() { mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS; @@ -919,6 +997,44 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) } } +void LLInventoryFilter::setSearchVisibilityTypes(U32 types) +{ + if (mFilterOps.mSearchVisibility != types) + { + // keep current items only if no perm bits getting turned off + BOOL fewer_bits_set = (mFilterOps.mSearchVisibility & ~types); + BOOL more_bits_set = (~mFilterOps.mSearchVisibility & types); + mFilterOps.mSearchVisibility = types; + + if (more_bits_set && fewer_bits_set) + { + setModified(FILTER_RESTART); + } + else if (more_bits_set) + { + // target must have all requested permission bits, so more bits == more restrictive + setModified(FILTER_MORE_RESTRICTIVE); + } + else if (fewer_bits_set) + { + setModified(FILTER_LESS_RESTRICTIVE); + } + } +} + +void LLInventoryFilter::setSearchVisibilityTypes(const Params& params) +{ + if (!params.validateBlock()) + { + return; + } + + if (params.filter_ops.search_visibility.isProvided()) + { + setSearchVisibilityTypes(params.filter_ops.search_visibility); + } +} + void LLInventoryFilter::setFilterPermissions(PermissionMask perms) { if (mFilterOps.mPermissions != perms) @@ -1346,6 +1462,18 @@ const std::string& LLInventoryFilter::getFilterText() filtered_by_all_types = FALSE; } + if (isFilterObjectTypesWith(LLInventoryType::IT_SETTINGS)) + { + filtered_types += LLTrans::getString("Settings"); + filtered_by_type = TRUE; + num_filter_types++; + } + else + { + not_filtered_types += LLTrans::getString("Settings"); + filtered_by_all_types = FALSE; + } + if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() && filtered_by_type && !filtered_by_all_types) @@ -1437,6 +1565,7 @@ void LLInventoryFilter::toParams(Params& params) const params.filter_ops.show_folder_state = getShowFolderState(); params.filter_ops.creator_type = getFilterCreatorType(); params.filter_ops.permissions = getFilterPermissions(); + params.filter_ops.search_visibility = getSearchVisibilityTypes(); params.substring = getFilterSubString(); params.since_logoff = isSinceLogoff(); } @@ -1458,6 +1587,7 @@ void LLInventoryFilter::fromParams(const Params& params) //setFilterCreator(params.filter_ops.creator_type); //setShowFolderState(params.filter_ops.show_folder_state); //setFilterPermissions(params.filter_ops.permissions); + //setSearchVisibilityTypes(params.filter_ops.search_visibility); //setFilterSubString(params.substring); //setDateRangeLastLogoff(params.since_logoff); if (params.filter_ops.types.isProvided()) @@ -1496,6 +1626,10 @@ void LLInventoryFilter::fromParams(const Params& params) { setFilterPermissions(params.filter_ops.permissions); } + if (params.filter_ops.search_visibility.isProvided()) + { + setSearchVisibilityTypes(params.filter_ops.search_visibility); + } // FIRE-8947: Don't restore filter string on relog //if (params.substring.isProvided()) //{ @@ -1533,6 +1667,11 @@ U64 LLInventoryFilter::getFilterSettingsTypes() const return mFilterOps.mFilterSettingsTypes; } +U64 LLInventoryFilter::getSearchVisibilityTypes() const +{ + return mFilterOps.mSearchVisibility; +} + bool LLInventoryFilter::hasFilterString() const { return mFilterSubString.size() > 0; diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index d2ebda7149..6f244c43d6 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -100,6 +100,14 @@ public: FILTERCREATOR_OTHERS }; + enum ESearchVisibility + { + VISIBILITY_NONE = 0, + VISIBILITY_TRASH = 0x1 << 0, + VISIBILITY_LIBRARY = 0x1 << 1, + VISIBILITY_LINKS = 0x1 << 2 + }; + struct FilterOps { struct DateRange : public LLInitParam::Block @@ -117,11 +125,13 @@ public: struct Params : public LLInitParam::Block { - Optional types; + Optional types, + search_visibility; Optional object_types, wearable_types, settings_types, category_types; + Optional links; Optional uuid; Optional date_range; @@ -138,6 +148,7 @@ public: settings_types("settings_types", 0xffffFFFFffffFFFFULL), category_types("category_types", 0xffffFFFFffffFFFFULL), links("links", FILTERLINK_INCLUDE_LINKS), + search_visibility("search_visibility", 0xFFFFFFFF), uuid("uuid"), date_range("date_range"), hours_ago("hours_ago", 0), @@ -150,7 +161,8 @@ public: FilterOps(const Params& = Params()); - U32 mFilterTypes; + U32 mFilterTypes, + mSearchVisibility; U64 mFilterObjectTypes, // For _OBJECT mFilterWearableTypes, mFilterSettingsTypes, // for _SETTINGS @@ -194,7 +206,8 @@ public: U64 getFilterObjectTypes() const; U64 getFilterCategoryTypes() const; U64 getFilterWearableTypes() const; - U64 getFilterSettingsTypes() const; + U64 getFilterSettingsTypes() const; + U64 getSearchVisibilityTypes() const; bool isFilterObjectTypesWith(LLInventoryType::EType t) const; void setFilterObjectTypes(U64 types); @@ -215,6 +228,12 @@ public: ESearchType getSearchType() { return mSearchType; } void setFilterCreator(EFilterCreatorType type); + void toggleSearchVisibilityLinks(); + void toggleSearchVisibilityTrash(); + void toggleSearchVisibilityLibrary(); + void setSearchVisibilityTypes(U32 types); + void setSearchVisibilityTypes(const Params& params); + void setFilterSubString(const std::string& string); const std::string& getFilterSubString(BOOL trim = FALSE) const; const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; } @@ -323,6 +342,7 @@ private: bool checkAgainstPermissions(const LLInventoryItem* item) const; bool checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const; bool checkAgainstCreator(const class LLFolderViewModelItemInventory* listener) const; + bool checkAgainstSearchVisibility(const class LLFolderViewModelItemInventory* listener) const; bool checkAgainstClipboard(const LLUUID& object_id) const; FilterOps mFilterOps; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 02b97924d2..c67c7e49f1 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -884,69 +884,48 @@ void show_item_profile(const LLUUID& item_uuid) void show_item_original(const LLUUID& item_uuid) { - // FIRE-19493: "Show Original" should open main inventory panel - //LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory"); - //if (!floater_inventory) - //{ - // LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL; - // return; - //} + LLFloater* floater_inventory = LLFloaterReg::getInstance("inventory"); + if (!floater_inventory) + { + LL_WARNS() << "Could not find My Inventory floater" << LL_ENDL; + return; + } + LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); + if (sidepanel_inventory) + { + LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + if (main_inventory) + { + main_inventory->resetFilters(); + } + reset_inventory_filter(); - ////sidetray inventory panel - //LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); + if (!LLFloaterReg::getTypedInstance("inventory")->isInVisibleChain()) + { + LLFloaterReg::toggleInstanceOrBringToFront("inventory"); + } - //bool do_reset_inventory_filter = !floater_inventory->isInVisibleChain(); - - //LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(); - //if (!active_panel) - //{ - // //this may happen when there is no floatera and other panel is active in inventory tab - - // if (sidepanel_inventory) - // { - // sidepanel_inventory->showInventoryPanel(); - // } - //} - // - //active_panel = LLInventoryPanel::getActiveInventoryPanel(); - //if (!active_panel) - //{ - // return; - //} - //active_panel->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES); - // - //if(do_reset_inventory_filter) - //{ - // reset_inventory_filter(); - //} - - LLFloaterReg::showInstance("inventory"); - LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); - sidepanel_inventory->showInventoryPanel(); - LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); - main_inventory->showAllItemsPanel(); - main_inventory->resetFilters(); - main_inventory->onFilterEdit(""); - LLUUID linked_item_id = gInventory.getLinkedItemID(item_uuid); - bool in_inbox = (gInventory.isObjectDescendentOf(linked_item_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX))); - bool show_inbox = gSavedSettings.getBOOL("FSShowInboxFolder"); // Optional hiding of Received Items folder aka Inbox - - if (in_inbox && !show_inbox) - { - LLInventoryPanel * inventory_panel = NULL; - sidepanel_inventory->openInbox(); - inventory_panel = sidepanel_inventory->getInboxPanel(); - - if (inventory_panel) - { - inventory_panel->setSelection(linked_item_id, TAKE_FOCUS_YES); - } - } - else - { - main_inventory->getActivePanel()->setSelection(linked_item_id, TAKE_FOCUS_YES); - } - // + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); + // Optional hiding of Received Items folder aka Inbox + // if (gInventory.isObjectDescendentOf(gInventory.getLinkedItemID(item_uuid), inbox_id)) + if (gInventory.isObjectDescendentOf(gInventory.getLinkedItemID(item_uuid), inbox_id) && !gSavedSettings.getBOOL("FSShowInboxFolder")) + // + { + if (sidepanel_inventory->getInboxPanel()) + { + sidepanel_inventory->openInbox(); + sidepanel_inventory->getInboxPanel()->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES); + } + } + else + { + sidepanel_inventory->selectAllItemsPanel(); + if (sidepanel_inventory->getActivePanel()) + { + sidepanel_inventory->getActivePanel()->setSelection(gInventory.getLinkedItemID(item_uuid), TAKE_FOCUS_YES); + } + } + } } @@ -1985,6 +1964,26 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_ return result && !has_bad_items; } +void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id) +{ + LLInventoryItem* inv_item = gInventory.getItem(item_id); + if (inv_item) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + LLPointer new_item = new LLViewerInventoryItem(inv_item); + new_item->setParent(new_parent_id); + new_item->updateParentOnServer(FALSE); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + } +} + ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 65771c35e9..01a9757305 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -99,6 +99,8 @@ S32 depth_nesting_in_marketplace(LLUUID cur_uuid); LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); +void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id); + /** Miscellaneous global functions ** ** *******************************************************************************/ diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 8db53f313a..01b856e685 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -165,7 +165,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mViewsInitialized(VIEWS_UNINITIALIZED), mInvFVBridgeBuilder(NULL), mInventoryViewModel(p.name), - mGroupedItemBridge(new LLFolderViewGroupedItemBridge) + mGroupedItemBridge(new LLFolderViewGroupedItemBridge), + mFocusSelection(false) { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; @@ -1338,6 +1339,7 @@ void LLInventoryPanel::setSelectCallback(const boost::functiongetViewModelItem()) + if(itemp && itemp->getViewModelItem() && itemp->passedFilter()) { itemp->arrangeAndSet(TRUE, take_keyboard_focus); mSelectThisID.setNull(); + mFocusSelection = false; return; } else { // save the desired item to be selected later (if/when ready) + mFocusSelection = take_keyboard_focus; mSelectThisID = obj_id; } } @@ -1934,7 +1938,7 @@ void LLInventoryPanel::updateSelection() { if (mSelectThisID.notNull()) { - setSelectionByID(mSelectThisID, false); + setSelectionByID(mSelectThisID, mFocusSelection); } } diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index dabb027981..141c6ad72b 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -281,6 +281,7 @@ protected: LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; LLInvPanelComplObserver* mCompletionObserver; + bool mFocusSelection; bool mAcceptsDragAndDrop; bool mAllowMultiSelect; bool mAllowDrag; @@ -379,27 +380,6 @@ private: EViewsInitializationState mViewsInitialized; // Whether views have been generated }; - -class LLInventoryFavoriteItemsPanel : public LLInventoryPanel -{ -public: - struct Params : public LLInitParam::Block - {}; - - void initFromParams(const Params& p); - bool isSelectionRemovable() { return false; } - void setSelectCallback(const boost::function& items, BOOL user_action)>& cb); - -protected: - LLInventoryFavoriteItemsPanel(const Params& params); - ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); } - void updateFavoritesRootFolder(); - - boost::signals2::connection mFolderChangedSignal; - boost::function& items, BOOL user_action)> mSelectionCallback; - friend class LLUICtrlFactory; -}; - /************************************************************************/ /* Asset Pre-Filtered Inventory Panel related class */ /* Exchanges filter's flexibility for speed of generation and */ diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index 436b25ffe4..968513662b 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -228,23 +228,6 @@ LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos() return findLandmarkForGlobalPos(gAgent.getPositionGlobal()); } -bool LLLandmarkActions::canCreateLandmarkHere() -{ - LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if(!agent_parcel) - { - LL_WARNS() << "No agent region" << LL_ENDL; - return false; - } - if (agent_parcel->getAllowLandmark() - || LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) - { - return true; - } - - return false; -} - void LLLandmarkActions::createLandmarkHere( const std::string& name, const std::string& desc, @@ -261,11 +244,6 @@ void LLLandmarkActions::createLandmarkHere( LL_WARNS() << "No agent parcel" << LL_ENDL; return; } - if (!canCreateLandmarkHere()) - { - LLNotificationsUtil::add("CannotCreateLandmarkNotOwner"); - return; - } create_inventory_item(gAgent.getID(), gAgent.getSessionID(), folder_id, LLTransactionID::tnull, diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h index a153ac9403..1b1d50b927 100644 --- a/indra/newview/lllandmarkactions.h +++ b/indra/newview/lllandmarkactions.h @@ -72,12 +72,6 @@ public: */ static LLViewerInventoryItem* findLandmarkForAgentPos(); - - /** - * @brief Checks whether agent has rights to create landmark for current parcel. - */ - static bool canCreateLandmarkHere(); - /** * @brief Creates landmark for current parcel. */ diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index de802f6275..a6b51555a8 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -44,6 +44,7 @@ // newview includes #include "llagent.h" +#include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llinventoryobserver.h" #include "lllandmarkactions.h" @@ -695,10 +696,7 @@ void LLLocationInputCtrl::onAddLandmarkButtonClicked() } else { - // FIRE-817: Separate place details floater - //LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark")); - FSFloaterPlaceDetails::showPlaceDetails(LLSD().with("type", "create_landmark")); - // + LLFloaterReg::showInstance("add_landmark"); } } @@ -1225,10 +1223,7 @@ void LLLocationInputCtrl::onLocationContextMenuItemClicked(const LLSD& userdata) if(!landmark) { - // FIRE-817: Separate place details floater - //LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark")); - FSFloaterPlaceDetails::showPlaceDetails(LLSD().with("type", "create_landmark")); - // + LLFloaterReg::showInstance("add_landmark"); } else { diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index c3e39429a2..7c942e8b53 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -105,7 +105,10 @@ void LLManipRotate::handleSelect() { // *FIX: put this in mouseDown? LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - gFloaterTools->setStatusText("rotate"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("rotate"); + } LLManip::handleSelect(); } diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 1459ede50e..a4434c8a3e 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -182,7 +182,10 @@ void LLManipScale::handleSelect() LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); updateSnapGuides(bbox); LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - gFloaterTools->setStatusText("scale"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("scale"); + } LLManip::handleSelect(); } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 1b47d16f9d..74dc0be83c 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -291,7 +291,10 @@ LLManipTranslate::~LLManipTranslate() void LLManipTranslate::handleSelect() { LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - gFloaterTools->setStatusText("move"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("move"); + } LLManip::handleSelect(); } diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 099fdadd86..f5218ee4c6 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -477,7 +477,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL std::istringstream content_stream(content_string); LLSD response_data; - U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + // Use new variant unzip_llsd + // U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); + // if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index da4637e7dc..0c5cc892ae 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -78,6 +78,10 @@ #include "llfloaterreg.h" #include "boost/lexical_cast.hpp" +// Reduce temporaries and copes in decoding mesh headers +#include +#include +// #ifndef LL_WINDOWS #include "netdb.h" @@ -1901,27 +1905,35 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes U32 header_size = 0; if (data_size > 0) { - std::istringstream stream; - try - { - std::string res_str((char*)data, data_size); + // Reduce temporaries and copes in decoding mesh headers + // std::istringstream stream; + // try + // { + // std::string res_str((char*)data, data_size); - std::string deprecated_header(""); + // std::string deprecated_header(""); - if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - { - res_str = res_str.substr(deprecated_header.size() + 1, data_size); - header_size = deprecated_header.size() + 1; - } - data_size = res_str.size(); + // if (res_str.substr(0, deprecated_header.size()) == deprecated_header) + // { + // res_str = res_str.substr(deprecated_header.size() + 1, data_size); + // header_size = deprecated_header.size() + 1; + // } + // data_size = res_str.size(); - stream.str(res_str); - } - catch (std::bad_alloc&) - { - // out of memory, we won't be able to process this mesh - return MESH_OUT_OF_MEMORY; - } + // stream.str(res_str); + // } + // catch (std::bad_alloc&) + // { + // // out of memory, we won't be able to process this mesh + // return MESH_OUT_OF_MEMORY; + // } + U32 dsize = data_size; + char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size); + + data_size = dsize; + + boost::iostreams::stream stream(result_ptr, data_size); + // if (!LLSDSerialize::fromBinary(header, stream, data_size)) { @@ -1990,19 +2002,22 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p } LLPointer volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); - std::istringstream stream; - try - { - std::string mesh_string((char*)data, data_size); - stream.str(mesh_string); - } - catch (std::bad_alloc&) - { - // out of memory, we won't be able to process this mesh - return MESH_OUT_OF_MEMORY; - } + // Reduce temporaries and copes in decoding mesh headers + // std::istringstream stream; + // try + // { + // std::string mesh_string((char*)data, data_size); + // stream.str(mesh_string); + // } + // catch (std::bad_alloc&) + // { + // // out of memory, we won't be able to process this mesh + // return MESH_OUT_OF_MEMORY; + // } - if (volume->unpackVolumeFaces(stream, data_size)) + // if (volume->unpackVolumeFaces(stream, data_size)) + if (volume->unpackVolumeFaces(data, data_size)) + // { if (volume->getNumFaces() > 0) { @@ -2032,10 +2047,13 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat { try { - std::string res_str((char*)data, data_size); - std::istringstream stream(res_str); + // Reduce temporaries and copes in decoding mesh headers + // std::string res_str((char*)data, data_size); + // std::istringstream stream(res_str); - U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size); + // U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size); + U32 uzip_result = LLUZipHelper::unzip_llsd(skin, data, data_size); + // if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id @@ -2073,10 +2091,13 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 { try { - std::string res_str((char*)data, data_size); - std::istringstream stream(res_str); + // Reduce temporaries and copes in decoding mesh headers + // std::string res_str((char*)data, data_size); + // std::istringstream stream(res_str); - U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size); + // U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size); + U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, data, data_size); + // if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id @@ -2085,7 +2106,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 return false; } } - catch (std::bad_alloc&) + catch (const std::bad_alloc&) // const cos const! { LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL; return false; @@ -2122,20 +2143,22 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_ volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); LLPointer volume = new LLVolume(volume_params,0); - std::istringstream stream; - try - { - std::string mesh_string((char*)data, data_size); - stream.str(mesh_string); - } - catch (std::bad_alloc&) - { - // out of memory, we won't be able to process this mesh - delete d; - return MESH_OUT_OF_MEMORY; - } + // Reduce temporaries and copes in decoding mesh headers + // std::istringstream stream; + // try + // { + // std::string mesh_string((char*)data, data_size); + // stream.str(mesh_string); + // } + // catch (std::bad_alloc&) + // { + // // out of memory, we won't be able to process this mesh + // delete d; + // return MESH_OUT_OF_MEMORY; + // } - if (volume->unpackVolumeFaces(stream, data_size)) + // if (volume->unpackVolumeFaces(stream, data_size)) + if (volume->unpackVolumeFaces(data, data_size)) { //load volume faces into decomposition buffer S32 vertex_count = 0; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 83e4fe3326..51b79c3cc2 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -378,14 +378,14 @@ bool LLModelPreview::matchMaterialOrder(LLModel* lod, LLModel* ref, int& refFace //1. ref = a,b,c lod1 = d,e => This is not permitted //2. ref = a,b,c lod1 = c => This would be permitted - LL_INFOS("MESHSKININFO") << "In matchMaterialOrder." << LL_ENDL; + LL_DEBUGS("MESHSKININFO") << "In matchMaterialOrder." << LL_ENDL; bool isASubset = lod->isMaterialListSubset( ref ); if ( !isASubset ) { - LL_INFOS("MESHSKININFO")<<"Material of model is not a subset of reference."<getName() << "'s materials are not a subset of the High LOD (reference) model " << ref->getName(); - LL_INFOS() << out.str() << LL_ENDL; + LL_DEBUGS() << out.str() << LL_ENDL; LLFloaterModelPreview::addStringToLog(out, true); return false; } @@ -471,7 +471,7 @@ bool LLModelPreview::matchMaterialOrder(LLModel* lod, LLModel* ref, int& refFace // if (reorder && (base_mat == cur_mat)) //don't reorder if material name sets don't match if ( reorder ) { - LL_INFOS("MESHSKININFO") << "re-ordering." << LL_ENDL; + LL_DEBUGS("MESHSKININFO") << "re-ordering." << LL_ENDL; lod->sortVolumeFacesByMaterialName(); lod->mMaterialList = ref->mMaterialList; } diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 8ee616ad80..37d8957a7f 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -787,7 +787,20 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id) msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_MuteData); msg->addU32Fast(_PREHASH_MuteCRC, crc.getCRC()); - gAgent.sendReliableMessage(); + + if (gDisconnected) + { + LL_WARNS() << "Trying to request mute list when disconnected!" << LL_ENDL; + return; + } + if (!gAgent.getRegion()) + { + LL_WARNS() << "No region for agent yet, skipping mute list request!" << LL_ENDL; + return; + } + // Double amount of retries due to this request happening during busy stage + // Ideally this should be turned into a capability + gMessageSystem->sendReliable(gAgent.getRegionHost(), LL_DEFAULT_RELIABLE_RETRIES * 2, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 34b5853bb9..9357292eea 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -59,6 +59,7 @@ #include "llweb.h" #include "llhints.h" +#include "llfloatersidepanelcontainer.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" @@ -312,6 +313,7 @@ void LLNavigationBar::setupPanel() // mBtnBack = getChild("back_btn"); // mBtnForward = getChild("forward_btn"); // mBtnHome = getChild("home_btn"); + // mBtnLandmarks = getChild("landmarks_btn"); // mCmbLocation= getChild("location_combo"); @@ -320,6 +322,7 @@ void LLNavigationBar::setupPanel() mBtnBack = mView->getChild("back_btn"); mBtnForward = mView->getChild("forward_btn"); mBtnHome = mView->getChild("home_btn"); + //mBtnLandmarks = mView->getChild("landmarks_btn"); // We don't use that right now... mCmbLocation = mView->getChild("location_combo"); mSearchComboBox = mView->getChild("search_combo_box"); @@ -350,6 +353,8 @@ void LLNavigationBar::setupPanel() //mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this)); mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this, _1)); + //mBtnLandmarks->setClickedCallback(boost::bind(&LLNavigationBar::onLandmarksButtonClicked, this)); // We don't use that right now... + mCmbLocation->setCommitCallback(boost::bind(&LLNavigationBar::onLocationSelection, this)); mSearchComboBox->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); @@ -490,6 +495,12 @@ void LLNavigationBar::onHomeButtonClicked(LLUICtrl* ctrl) gFocusMgr.releaseFocusIfNeeded(ctrl); // [FS:CR] FIRE-12333 } +void LLNavigationBar::onLandmarksButtonClicked() +{ + LLFloaterReg::toggleInstanceOrBringToFront("places"); + LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "open_landmark_tab")); +} + void LLNavigationBar::onSearchCommit() { std::string search_query = mSearchComboBox->getSimple(); diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index bf82e270bd..bb5952e9f1 100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -137,6 +137,7 @@ private: //void onHomeButtonClicked(); void onForwardButtonClicked(LLUICtrl* ctrl); void onHomeButtonClicked(LLUICtrl* ctrl); + void onLandmarksButtonClicked(); void onLocationSelection(); void onLocationPrearrange(const LLSD& data); void onSearchCommit(); @@ -173,6 +174,7 @@ private: LLPullButton* mBtnBack; LLPullButton* mBtnForward; LLButton* mBtnHome; + LLButton* mBtnLandmarks; LLSearchComboBox* mSearchComboBox; LLLocationInputCtrl* mCmbLocation; // No size calculations in code please. XUI handles it all now with visibility_control diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp index 2e26b69144..a169712bd8 100644 --- a/indra/newview/llpaneleditsky.cpp +++ b/indra/newview/llpaneleditsky.cpp @@ -69,11 +69,15 @@ namespace const std::string FIELD_SKY_GLOW_SIZE("glow_size"); const std::string FIELD_SKY_STAR_BRIGHTNESS("star_brightness"); const std::string FIELD_SKY_SUN_ROTATION("sun_rotation"); + const std::string FIELD_SKY_SUN_AZIMUTH("sun_azimuth"); + const std::string FIELD_SKY_SUN_ELEVATION("sun_elevation"); const std::string FIELD_SKY_SUN_IMAGE("sun_image"); const std::string FIELD_SKY_SUN_SCALE("sun_scale"); const std::string FIELD_SKY_SUN_BEACON("sunbeacon"); const std::string FIELD_SKY_MOON_BEACON("moonbeacon"); const std::string FIELD_SKY_MOON_ROTATION("moon_rotation"); + const std::string FIELD_SKY_MOON_AZIMUTH("moon_azimuth"); + const std::string FIELD_SKY_MOON_ELEVATION("moon_elevation"); const std::string FIELD_SKY_MOON_IMAGE("moon_image"); const std::string FIELD_SKY_MOON_SCALE("moon_scale"); const std::string FIELD_SKY_MOON_BRIGHTNESS("moon_brightness"); @@ -473,12 +477,16 @@ BOOL LLPanelSettingsSkySunMoonTab::postBuild() getChild(FIELD_SKY_GLOW_SIZE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); }); getChild(FIELD_SKY_STAR_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onStarBrightnessChanged(); }); getChild(FIELD_SKY_SUN_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunRotationChanged(); }); + getChild(FIELD_SKY_SUN_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); }); + getChild(FIELD_SKY_SUN_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunAzimElevChanged(); }); getChild(FIELD_SKY_SUN_IMAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunImageChanged(); }); getChild(FIELD_SKY_SUN_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunScaleChanged(); }); getChild(FIELD_SKY_SUN_IMAGE)->setBlankImageAssetID(LLSettingsSky::GetBlankSunTextureId()); getChild(FIELD_SKY_SUN_IMAGE)->setDefaultImageAssetID(LLSettingsSky::GetBlankSunTextureId()); getChild(FIELD_SKY_SUN_IMAGE)->setAllowNoTexture(TRUE); getChild(FIELD_SKY_MOON_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonRotationChanged(); }); + getChild(FIELD_SKY_MOON_AZIMUTH)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); }); + getChild(FIELD_SKY_MOON_ELEVATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonAzimElevChanged(); }); getChild(FIELD_SKY_MOON_IMAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonImageChanged(); }); getChild(FIELD_SKY_MOON_IMAGE)->setDefaultImageAssetID(LLSettingsSky::GetDefaultMoonTextureId()); getChild(FIELD_SKY_MOON_IMAGE)->setBlankImageAssetID(LLSettingsSky::GetDefaultMoonTextureId()); @@ -537,13 +545,29 @@ void LLPanelSettingsSkySunMoonTab::refresh() getChild(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B); getChild(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mSkySettings->getStarBrightness()); - getChild(FIELD_SKY_SUN_ROTATION)->setRotation(mSkySettings->getSunRotation()); getChild(FIELD_SKY_SUN_IMAGE)->setValue(mSkySettings->getSunTextureId()); getChild(FIELD_SKY_SUN_SCALE)->setValue(mSkySettings->getSunScale()); - getChild(FIELD_SKY_MOON_ROTATION)->setRotation(mSkySettings->getMoonRotation()); getChild(FIELD_SKY_MOON_IMAGE)->setValue(mSkySettings->getMoonTextureId()); getChild(FIELD_SKY_MOON_SCALE)->setValue(mSkySettings->getMoonScale()); getChild(FIELD_SKY_MOON_BRIGHTNESS)->setValue(mSkySettings->getMoonBrightness()); + + // Sun rotation values + F32 azimuth, elevation; + LLQuaternion quat = mSkySettings->getSunRotation(); + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + + getChild(FIELD_SKY_SUN_ROTATION)->setRotation(quat); + getChild(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_SUN_ELEVATION)->setValue(elevation); + + // Moon rotation values + quat = mSkySettings->getMoonRotation(); + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + + getChild(FIELD_SKY_MOON_ROTATION)->setRotation(quat); + getChild(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_MOON_ELEVATION)->setValue(elevation); + } //------------------------------------------------------------------------- @@ -583,10 +607,47 @@ void LLPanelSettingsSkySunMoonTab::onStarBrightnessChanged() void LLPanelSettingsSkySunMoonTab::onSunRotationChanged() { - if (!mSkySettings) return; - mSkySettings->setSunRotation(getChild(FIELD_SKY_SUN_ROTATION)->getRotation()); - mSkySettings->update(); - setIsDirty(); + LLQuaternion quat = getChild(FIELD_SKY_SUN_ROTATION)->getRotation(); + + F32 azimuth, elevation; + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + getChild(FIELD_SKY_SUN_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_SUN_ELEVATION)->setValue(elevation); + if (mSkySettings) + { + mSkySettings->setSunRotation(quat); + mSkySettings->update(); + setIsDirty(); + } +} + +void LLPanelSettingsSkySunMoonTab::onSunAzimElevChanged() +{ + F32 azimuth = getChild(FIELD_SKY_SUN_AZIMUTH)->getValue().asReal(); + F32 elevation = getChild(FIELD_SKY_SUN_ELEVATION)->getValue().asReal(); + LLQuaternion quat; + + azimuth *= DEG_TO_RAD; + elevation *= DEG_TO_RAD; + + if (is_approx_zero(elevation)) + { + elevation = F_APPROXIMATELY_ZERO; + } + + quat.setAngleAxis(-elevation, 0, 1, 0); + LLQuaternion az_quat; + az_quat.setAngleAxis(F_TWO_PI - azimuth, 0, 0, 1); + quat *= az_quat; + + getChild(FIELD_SKY_SUN_ROTATION)->setRotation(quat); + + if (mSkySettings) + { + mSkySettings->setSunRotation(quat); + mSkySettings->update(); + setIsDirty(); + } } void LLPanelSettingsSkySunMoonTab::onSunScaleChanged() @@ -607,10 +668,48 @@ void LLPanelSettingsSkySunMoonTab::onSunImageChanged() void LLPanelSettingsSkySunMoonTab::onMoonRotationChanged() { - if (!mSkySettings) return; - mSkySettings->setMoonRotation(getChild(FIELD_SKY_MOON_ROTATION)->getRotation()); - mSkySettings->update(); - setIsDirty(); + LLQuaternion quat = getChild(FIELD_SKY_MOON_ROTATION)->getRotation(); + + F32 azimuth, elevation; + LLVirtualTrackball::getAzimuthAndElevationDeg(quat, azimuth, elevation); + getChild(FIELD_SKY_MOON_AZIMUTH)->setValue(azimuth); + getChild(FIELD_SKY_MOON_ELEVATION)->setValue(elevation); + + if (mSkySettings) + { + mSkySettings->setMoonRotation(quat); + mSkySettings->update(); + setIsDirty(); + } +} + +void LLPanelSettingsSkySunMoonTab::onMoonAzimElevChanged() +{ + F32 azimuth = getChild(FIELD_SKY_MOON_AZIMUTH)->getValue().asReal(); + F32 elevation = getChild(FIELD_SKY_MOON_ELEVATION)->getValue().asReal(); + LLQuaternion quat; + + azimuth *= DEG_TO_RAD; + elevation *= DEG_TO_RAD; + + if (is_approx_zero(elevation)) + { + elevation = F_APPROXIMATELY_ZERO; + } + + quat.setAngleAxis(-elevation, 0, 1, 0); + LLQuaternion az_quat; + az_quat.setAngleAxis(F_TWO_PI- azimuth, 0, 0, 1); + quat *= az_quat; + + getChild(FIELD_SKY_MOON_ROTATION)->setRotation(quat); + + if (mSkySettings) + { + mSkySettings->setMoonRotation(quat); + mSkySettings->update(); + setIsDirty(); + } } void LLPanelSettingsSkySunMoonTab::onMoonImageChanged() diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h index 801fb8b9b2..cb63d40b0c 100644 --- a/indra/newview/llpaneleditsky.h +++ b/indra/newview/llpaneleditsky.h @@ -124,9 +124,11 @@ private: void onGlowChanged(); void onStarBrightnessChanged(); void onSunRotationChanged(); + void onSunAzimElevChanged(); void onSunScaleChanged(); void onSunImageChanged(); void onMoonRotationChanged(); + void onMoonAzimElevChanged(); void onMoonScaleChanged(); void onMoonBrightnessChanged(); void onMoonImageChanged(); diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 6751c25fb9..880323ce16 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -52,7 +52,6 @@ typedef std::pair folder_pair_t; static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right); -static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); static LLPanelInjector t_landmark_info("panel_landmark_info"); @@ -106,6 +105,18 @@ void LLPanelLandmarkInfo::resetLocation() // virtual void LLPanelLandmarkInfo::setInfoType(EInfoType type) +{ + LLUUID dest_folder; + setInfoType(type, dest_folder); +} + +// Sets CREATE_LANDMARK infotype and creates landmark at desired folder +void LLPanelLandmarkInfo::setInfoAndCreateLandmark(const LLUUID& fodler_id) +{ + setInfoType(CREATE_LANDMARK, fodler_id); +} + +void LLPanelLandmarkInfo::setInfoType(EInfoType type, const LLUUID &folder_id) { LLPanel* landmark_info_panel = getChild("landmark_info_panel"); @@ -183,7 +194,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) // remote parcel request to complete. if (!LLLandmarkActions::landmarkAlreadyExists()) { - createLandmark(LLUUID()); + createLandmark(folder_id); } } break; @@ -504,7 +515,7 @@ static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) return left.second < right.second; } -static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) +void LLPanelLandmarkInfo::collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) { LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); @@ -517,16 +528,20 @@ static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) items, LLInventoryModel::EXCLUDE_TRASH, is_category); - - // Add the "My Favorites" category. - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id); - if (!favorites_cat) - { - LL_WARNS() << "Cannot find the favorites folder" << LL_ENDL; - } - else - { - cats.push_back(favorites_cat); - } +} + +/* virtual */ void LLUpdateLandmarkParent::fire(const LLUUID& inv_item_id) +{ + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + mItem->setParent(mNewParentId); + mItem->updateParentOnServer(FALSE); + + gInventory.updateItem(mItem); + gInventory.notifyObservers(); } diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index 9712736182..f727f286b5 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -28,6 +28,7 @@ #define LL_LLPANELLANDMARKINFO_H #include "llpanelplaceinfo.h" +#include "llinventorymodel.h" class LLComboBox; class LLLineEditor; @@ -43,8 +44,12 @@ public: /*virtual*/ void resetLocation(); + // If landmark doesn't exists, will create it at default folder /*virtual*/ void setInfoType(EInfoType type); + // Sets CREATE_LANDMARK infotype and creates landmark at desired folder + void setInfoAndCreateLandmark(const LLUUID& fodler_id); + /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); // Displays landmark owner, creator and creation date info. @@ -59,13 +64,19 @@ public: // Select current landmark folder in combobox. BOOL setLandmarkFolder(const LLUUID& id); - // Create a landmark for the current location - // in a folder specified by folder_id. - void createLandmark(const LLUUID& folder_id); - + typedef std::vector > cat_array_t; static std::string getFullFolderName(const LLViewerInventoryCategory* cat); + static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); private: + // Create a landmark for the current location + // in a folder specified by folder_id. + // Expects title and description to be initialized + void createLandmark(const LLUUID& folder_id); + + // If landmark doesn't exists, will create it at specified folder + void setInfoType(EInfoType type, const LLUUID &folder_id); + void populateFoldersList(); LLTextBox* mOwner; @@ -77,4 +88,17 @@ private: LLComboBox* mFolderCombo; }; +class LLUpdateLandmarkParent : public LLInventoryCallback +{ +public: + LLUpdateLandmarkParent(LLPointer item, LLUUID new_parent) : + mItem(item), + mNewParentId(new_parent) + {}; + /* virtual */ void fire(const LLUUID& inv_item_id); + +private: + LLPointer mItem; + LLUUID mNewParentId; +}; #endif // LL_LLPANELLANDMARKINFO_H diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 0ecb448259..c3a20f45f2 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -36,12 +36,11 @@ #include "llregionhandle.h" #include "llaccordionctrl.h" -#include "llaccordionctrltab.h" #include "llagent.h" #include "llagentpicksinfo.h" #include "llagentui.h" +#include "llavataractions.h" #include "llcallbacklist.h" -#include "lldndbutton.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterworldmap.h" #include "llfolderviewitem.h" @@ -64,15 +63,8 @@ // Not yet implemented; need to remove buildPanel() from constructor when we switch //static LLPanelInjector t_landmarks("panel_landmarks"); -static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn"; -static const std::string ADD_BUTTON_NAME = "add_btn"; -//static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn"; // Doesn't exist as of 18-11-2017 -static const std::string TRASH_BUTTON_NAME = "trash_btn"; - - // helper functions static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string); -static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list); static void collapse_all_folders(LLFolderView* root_folder); static void expand_all_folders(LLFolderView* root_folder); static bool has_expanded_folders(LLFolderView* root_folder); @@ -153,70 +145,37 @@ void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder) } } -/** - * Bridge to support knowing when the inventory has changed to update Landmarks tab - * ShowFolderState filter setting to show all folders when the filter string is empty and - * empty folder message when Landmarks inventory category has no children. - * Ensures that "Landmarks" folder in the Library is open on strart up. - */ -class LLLandmarksPanelObserver : public LLInventoryObserver -{ -public: - LLLandmarksPanelObserver(LLLandmarksPanel* lp) - : mLP(lp), - mIsLibraryLandmarksOpen(false) - {} - virtual ~LLLandmarksPanelObserver() {} - /*virtual*/ void changed(U32 mask); - -private: - LLLandmarksPanel* mLP; - bool mIsLibraryLandmarksOpen; -}; - -void LLLandmarksPanelObserver::changed(U32 mask) -{ - mLP->updateShowFolderState(); - - LLPlacesInventoryPanel* library = mLP->getLibraryInventoryPanel(); - if (!mIsLibraryLandmarksOpen && library) - { - // Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827. - const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - if (landmarks_cat.notNull()) - { - LLOpenFolderByID opener(landmarks_cat); - library->getRootFolder()->applyFunctorRecursively(opener); - mIsLibraryLandmarksOpen = opener.isFolderOpen(); - } - } -} - LLLandmarksPanel::LLLandmarksPanel() : LLPanelPlacesTab() - , mFavoritesInventoryPanel(NULL) , mLandmarksInventoryPanel(NULL) - , mMyInventoryPanel(NULL) - , mLibraryInventoryPanel(NULL) , mCurrentSelectedList(NULL) - , mListCommands(NULL) - , mGearButton(NULL) , mGearFolderMenu(NULL) , mGearLandmarkMenu(NULL) - , mMyLandmarksAccordionTab(NULL) // Fix warnings log spam + , mSortingMenu(NULL) + , mAddMenu(NULL) + , isLandmarksPanel(true) { - mInventoryObserver = new LLLandmarksPanelObserver(this); - gInventory.addObserver(mInventoryObserver); + buildFromFile("panel_landmarks.xml"); +} - buildFromFile( "panel_landmarks.xml"); +LLLandmarksPanel::LLLandmarksPanel(bool is_landmark_panel) + : LLPanelPlacesTab() + , mLandmarksInventoryPanel(NULL) + , mCurrentSelectedList(NULL) + , mGearFolderMenu(NULL) + , mGearLandmarkMenu(NULL) + , mSortingMenu(NULL) + , mAddMenu(NULL) + , isLandmarksPanel(is_landmark_panel) +{ + if (is_landmark_panel) + { + buildFromFile("panel_landmarks.xml"); + } } LLLandmarksPanel::~LLLandmarksPanel() { - if (gInventory.containsObserver(mInventoryObserver)) - { - gInventory.removeObserver(mInventoryObserver); - } } BOOL LLLandmarksPanel::postBuild() @@ -226,21 +185,7 @@ BOOL LLLandmarksPanel::postBuild() // mast be called before any other initXXX methods to init Gear menu initListCommandsHandlers(); - - initFavoritesInventoryPanel(); initLandmarksInventoryPanel(); - initMyInventoryPanel(); - initLibraryInventoryPanel(); - - // Fix warnings log spam - //LLAccordionCtrl* accordion = getChild("landmarks_accordion"); - LLView* accordion_view = findChildView("landmarks_accordion"); - LLAccordionCtrl* accordion = dynamic_cast(accordion_view); - // - if (accordion) - { - accordion->setSkipScrollToChild(true); - } return TRUE; } @@ -248,47 +193,10 @@ BOOL LLLandmarksPanel::postBuild() // virtual void LLLandmarksPanel::onSearchEdit(const std::string& string) { - // Fix for landmark search (FIRE-6611): We don't have - // accordion tabs but normal tabs! - // give FolderView a chance to be refreshed. So, made all accordions visible - //for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) - //{ - // LLAccordionCtrlTab* tab = *iter; - // tab->setVisible(TRUE); - - // // expand accordion to see matched items in each one. See EXT-2014. - // if (string != "") - // { - // tab->changeOpenClose(false); - // } - - // LLPlacesInventoryPanel* inventory_list = dynamic_cast(tab->getAccordionView()); - // if (NULL == inventory_list) continue; - - if (mFavoritesInventoryPanel) - { - filter_list(mFavoritesInventoryPanel, string); - } - if (mLandmarksInventoryPanel) - { - filter_list(mLandmarksInventoryPanel, string); - } - if (mMyInventoryPanel) - { - filter_list(mMyInventoryPanel, string); - } - if (mLibraryInventoryPanel) - { - filter_list(mLibraryInventoryPanel, string); - } - // Fix for landmark search (FIRE-6611) + filter_list(mCurrentSelectedList, string); if (sFilterSubString != string) sFilterSubString = string; - - // show all folders in Landmarks Accordion for empty filter - // only if Landmarks inventory folder is not empty - updateShowFolderState(); } // virtual @@ -300,11 +208,6 @@ void LLLandmarksPanel::onShowOnMap() return; } - // Disable the "Map" button because loading landmark can take some time. - // During this time the button is useless. It will be enabled on callback finish - // or upon switching to other item. - mShowOnMapBtn->setEnabled(FALSE); - doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doShowOnMap, this, _1)); } @@ -329,6 +232,12 @@ void LLLandmarksPanel::onTeleport() } } +/*virtual*/ +void LLLandmarksPanel::onRemoveSelected() +{ + onClipboardAction("delete"); +} + // virtual bool LLLandmarksPanel::isSingleItemSelected() { @@ -348,89 +257,55 @@ bool LLLandmarksPanel::isSingleItemSelected() } // virtual +LLToggleableMenu* LLLandmarksPanel::getSelectionMenu() +{ + LLToggleableMenu* menu = mGearFolderMenu; + + if (mCurrentSelectedList) + { + LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem(); + if (!listenerp) + return menu; + + if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + menu = mGearLandmarkMenu; + } + } + return menu; +} + +// virtual +LLToggleableMenu* LLLandmarksPanel::getSortingMenu() +{ + return mSortingMenu; +} + +// virtual +LLToggleableMenu* LLLandmarksPanel::getCreateMenu() +{ + return mAddMenu; +} + void LLLandmarksPanel::updateVerbs() { - if (!isTabVisible()) - return; - - bool landmark_selected = isLandmarkSelected(); - mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport")); - mShowProfile->setEnabled(landmark_selected && isActionEnabled("more_info")); - mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map")); - - // TODO: mantipov: Uncomment when mShareBtn is supported - // Share button should be enabled when neither a folder nor a landmark is selected - //mShareBtn->setEnabled(NULL != current_item); - - updateListCommands(); -} - -void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque &items, BOOL user_action) -{ - if (user_action && (items.size() > 0)) + if (sRemoveBtn) { - deselectOtherThan(inventory_list); - mCurrentSelectedList = inventory_list; + sRemoveBtn->setEnabled(isActionEnabled("delete") && (isFolderSelected() || isLandmarkSelected())); } - updateVerbs(); -} - -void LLLandmarksPanel::onSelectorButtonClicked() -{ - // TODO: mantipov: update getting of selected item - // TODO: bind to "i" button - LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); - if (!cur_item) return; - - LLFolderViewModelItemInventory* listenerp = static_cast(cur_item->getViewModelItem()); - if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) - { - LLSD key; - key["type"] = "landmark"; - key["id"] = listenerp->getUUID(); - - // FIRE-817: Separate place details floater - //LLFloaterSidePanelContainer::showPanel("places", key); - FSFloaterPlaceDetails::showPlaceDetails(key); - // - } -} - -void LLLandmarksPanel::updateShowFolderState() -{ - bool show_all_folders = mLandmarksInventoryPanel->getFilterSubString().empty(); - if (show_all_folders) - { - show_all_folders = category_has_descendents(mLandmarksInventoryPanel); - } - - mLandmarksInventoryPanel->setShowFolderState(show_all_folders ? - LLInventoryFilter::SHOW_ALL_FOLDERS : - LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS - ); } void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus) { - if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus)) - { + if (!mCurrentSelectedList) return; - } - if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus)) - { + LLFolderView* root = mCurrentSelectedList->getRootFolder(); + LLFolderViewItem* item = mCurrentSelectedList->getItemByID(obj_id); + if (!item) return; - } - - if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus)) - { - return; - } - - if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus)) - { - return; - } + root->setSelection(item, FALSE, take_keyboard_focus); + root->scrollToShowSelection(); } ////////////////////////////////////////////////////////////////////////// @@ -449,18 +324,6 @@ bool LLLandmarksPanel::isFolderSelected() const return current_item && (current_item->getInventoryType() == LLInventoryType::IT_CATEGORY); } -bool LLLandmarksPanel::isReceivedFolderSelected() const -{ - // Received Folder can be only in Landmarks accordion - if (mCurrentSelectedList != mLandmarksInventoryPanel) return false; - - // *TODO: it should be filled with logic when EXT-976 is done. - - LL_WARNS() << "Not implemented yet until EXT-976 is done." << LL_ENDL; - - return false; -} - void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb) { LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); @@ -490,61 +353,6 @@ LLFolderViewModelItemInventory* LLLandmarksPanel::getCurSelectedViewModelItem() } -LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, - const std::string& tab_name, - const LLUUID& obj_id, - BOOL take_keyboard_focus) const -{ - if (!inventory_list) - return NULL; - - LLFolderView* root = inventory_list->getRootFolder(); - - LLFolderViewItem* item = inventory_list->getItemByID(obj_id); - if (!item) - return NULL; - - // Fix warnings log spam - //LLAccordionCtrlTab* tab = getChild(tab_name); - //if (!tab->isExpanded()) - LLView* tab_view = findChildView(tab_name); - LLAccordionCtrlTab* tab = dynamic_cast(tab_view); - if (tab && !tab->isExpanded()) - // - { - tab->changeOpenClose(false); - } - // Fix warnings log spam - else - { - LLPanel* panel = dynamic_cast(tab_view); - if (panel) - { - panel->getParentByType()->selectTabPanel(panel); - } - } - // - - root->setSelection(item, FALSE, take_keyboard_focus); - - // Fix warnings log spam - //LLAccordionCtrl* accordion = getChild("landmarks_accordion"); - //LLRect screen_rc; - //localRectToScreen(item->getRect(), &screen_rc); - //accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); - LLView* accordion_view = findChildView("landmarks_accordion"); - LLAccordionCtrl* accordion = dynamic_cast(accordion_view); - if (accordion) - { - LLRect screen_rc; - localRectToScreen(item->getRect(), &screen_rc); - accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue())); - } - // - - return item; -} - void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate) { if(!panel) return; @@ -560,19 +368,29 @@ void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate) } } +void LLLandmarksPanel::resetSelection() +{ +} + // virtual void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data) { //this function will be called after user will try to create a pick for selected landmark. // We have to make request to sever to get parcel_id and snaption_id. - if(isLandmarkSelected()) + if(mCreatePickItemId.notNull()) { - LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); - if (!cur_item) return; - LLUUID id = cur_item->getUUID(); - LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id); - doActionOnCurSelectedLandmark(boost::bind( - &LLLandmarksPanel::doProcessParcelInfo, this, _1, getCurSelectedItem(), inv_item, parcel_data)); + LLInventoryItem* inv_item = gInventory.getItem(mCreatePickItemId); + + if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_LANDMARK) + { + // we are processing response for doCreatePick, landmark should be already loaded + LLLandmark* landmark = LLLandmarkActions::getLandmark(inv_item->getUUID()); + if (landmark) + { + doProcessParcelInfo(landmark, inv_item, parcel_data); + } + } + mCreatePickItemId.setNull(); } } @@ -597,16 +415,6 @@ void LLLandmarksPanel::setErrorStatus(S32 status, const std::string& reason) // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// -void LLLandmarksPanel::initFavoritesInventoryPanel() -{ - mFavoritesInventoryPanel = getChild("favorites_list"); - - initLandmarksPanel(mFavoritesInventoryPanel); - mFavoritesInventoryPanel->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems"); - - initAccordion("tab_favorites", mFavoritesInventoryPanel, true); -} - void LLLandmarksPanel::initLandmarksInventoryPanel() { mLandmarksInventoryPanel = getChild("landmarks_list"); @@ -618,40 +426,14 @@ void LLLandmarksPanel::initLandmarksInventoryPanel() // subscribe to have auto-rename functionality while creating New Folder mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2)); - mMyLandmarksAccordionTab = initAccordion("tab_landmarks", mLandmarksInventoryPanel, true); -} - -void LLLandmarksPanel::initMyInventoryPanel() -{ - mMyInventoryPanel= getChild("my_inventory_list"); - - initLandmarksPanel(mMyInventoryPanel); - - initAccordion("tab_inventory", mMyInventoryPanel, false); -} - -void LLLandmarksPanel::initLibraryInventoryPanel() -{ - mLibraryInventoryPanel = getChild("library_list"); - - initLandmarksPanel(mLibraryInventoryPanel); - - // We want to fetch only "Landmarks" category from the library. - const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - if (landmarks_cat.notNull()) - { - LLInventoryModelBackgroundFetch::instance().start(landmarks_cat); - } - - // Expanding "Library" tab for new users who have no landmarks in "My Inventory". - initAccordion("tab_library", mLibraryInventoryPanel, true); + mCurrentSelectedList = mLandmarksInventoryPanel; } void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list) { inventory_list->getFilter().setEmptyLookupMessage("PlacesNoMatchingItems"); inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); - inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); + inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::updateVerbs, this)); inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); bool sorting_order = gSavedSettings.getBOOL("LandmarksSortedByDate"); @@ -669,94 +451,10 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list inventory_list->saveFolderState(); } -LLAccordionCtrlTab* LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list, bool expand_tab) -{ - // Fix warnings log spam - //LLAccordionCtrlTab* accordion_tab = getChild(accordion_tab_name); - LLView* accordion_tab_view = findChildView(accordion_tab_name); - LLAccordionCtrlTab* accordion_tab = dynamic_cast(accordion_tab_view); - if (!accordion_tab) - { - return NULL; - } - // - - mAccordionTabs.push_back(accordion_tab); - accordion_tab->setDropDownStateChangedCallback( - boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list)); - accordion_tab->setDisplayChildren(expand_tab); - return accordion_tab; -} - -void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list) -{ - bool expanded = param.asBoolean(); - - if(!expanded && (mCurrentSelectedList == inventory_list)) - { - inventory_list->getRootFolder()->clearSelection(); - - mCurrentSelectedList = NULL; - updateVerbs(); - } - - // Start background fetch, mostly for My Inventory and Library - if (expanded) - { - const LLUUID &cat_id = inventory_list->getRootFolderID(); - // Just because the category itself has been fetched, doesn't mean its child folders have. - /* - if (!gInventory.isCategoryComplete(cat_id)) - */ - { - LLInventoryModelBackgroundFetch::instance().start(cat_id); - } - - // Apply filter substring because it might have been changed - // while accordion was closed. See EXT-3714. - filter_list(inventory_list, sFilterSubString); - } -} - -void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list) -{ - if (inventory_list != mFavoritesInventoryPanel) - { - mFavoritesInventoryPanel->clearSelection(); - } - - if (inventory_list != mLandmarksInventoryPanel) - { - mLandmarksInventoryPanel->clearSelection(); - } - if (inventory_list != mMyInventoryPanel) - { - mMyInventoryPanel->clearSelection(); - } - if (inventory_list != mLibraryInventoryPanel) - { - mLibraryInventoryPanel->clearSelection(); - } -} // List Commands Handlers void LLLandmarksPanel::initListCommandsHandlers() { - mListCommands = getChild("bottom_panel"); - - mGearButton = getChild(OPTIONS_BUTTON_NAME); - mGearButton->setMouseDownCallback(boost::bind(&LLLandmarksPanel::onActionsButtonClick, this)); - - mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this)); - - LLDragAndDropButton* trash_btn = mListCommands->getChild(TRASH_BUTTON_NAME); - trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this - , _4 // BOOL drop - , _5 // EDragAndDropType cargo_type - , _6 // void* cargo_data - , _7 // EAcceptance* accept - )); - mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2)); mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2)); mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2)); @@ -765,23 +463,16 @@ void LLLandmarksPanel::initListCommandsHandlers() mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2)); mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_places_gear_sorting.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mAddMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2)); mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2)); - mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME)); -} - - -void LLLandmarksPanel::updateListCommands() -{ - //bool add_folder_enabled = isActionEnabled("category"); // Doesn't exist as of 18-11-2017 - bool trash_enabled = isActionEnabled("delete") && (isFolderSelected() || isLandmarkSelected()); - - // keep Options & Add Landmark buttons always enabled - //mListCommands->getChildView(ADD_FOLDER_BUTTON_NAME)->setEnabled(add_folder_enabled); // Doesn't exist as of 18-11-2017 - mListCommands->getChildView(TRASH_BUTTON_NAME)->setEnabled(trash_enabled); + // show menus even if all items are disabled + mGearLandmarkMenu->setAlwaysShowMenu(TRUE); + mGearFolderMenu->setAlwaysShowMenu(TRUE); + mAddMenu->setAlwaysShowMenu(TRUE); } void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu) @@ -789,43 +480,6 @@ void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu) onMenuVisibilityChange(menu, LLSD().with("visibility", true)); } -void LLLandmarksPanel::onActionsButtonClick() -{ - LLToggleableMenu* menu = mGearFolderMenu; - - if(mCurrentSelectedList) - { - LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem(); - if(!listenerp) - return; - - if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) - { - menu = mGearLandmarkMenu; - } - } - - mGearButton->setMenu(menu); -} - -void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) -{ - if (menu) - { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - menu->arrangeAndClear(); - - LLView* spawning_view = getChild(spawning_view_name); - - S32 menu_x, menu_y; - //show menu in co-ordinates of panel - spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this); - menu_y += menu->getRect().getHeight(); - LLMenuGL::showPopup(this, menu, menu_x, menu_y); - } -} - void LLLandmarksPanel::onTrashButtonClick() const { onClipboardAction("delete"); @@ -837,7 +491,8 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const LLFolderViewItem* item = getCurSelectedItem(); std::string command_name = userdata.asString(); - if("add_landmark" == command_name) + if("add_landmark" == command_name + || "add_landmark_root" == command_name) { // [RLVa:KB] - Checked: 2012-02-08 (RLVa-1.4.5) | Added: RLVa-1.4.5 if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) @@ -850,10 +505,20 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const } else { - // FIRE-817: Separate place details floater - //LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark")); - FSFloaterPlaceDetails::showPlaceDetails(LLSD().with("type", "create_landmark")); - // + LLSD args; + args["type"] = "create_landmark"; + if ("add_landmark" == command_name + && view_model->getInventoryType() == LLInventoryType::IT_CATEGORY) + { + args["dest_folder"] = view_model->getUUID(); + } + if ("add_landmark_root" == command_name + && mCurrentSelectedList == mLandmarksInventoryPanel) + { + args["dest_folder"] = mLandmarksInventoryPanel->getRootFolderID(); + } + // else will end up in favorites + LLFloaterReg::showInstance("add_landmark", args); } // [RLVa:KB] - Checked: 2012-02-08 (RLVa-1.4.5) | Added: RLVa-1.4.5 } @@ -888,13 +553,14 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const //in case My Landmarks tab is completely empty (thus cannot be determined as being selected) menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"), gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); - - if (mMyLandmarksAccordionTab) - { - mMyLandmarksAccordionTab->changeOpenClose(false); - } } } + else if ("category_root" == command_name) + { + //in case My Landmarks tab is completely empty (thus cannot be determined as being selected) + menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"), + gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); + } } void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const @@ -928,27 +594,11 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) if ("expand_all" == command_name) { - expand_all_folders(mFavoritesInventoryPanel->getRootFolder()); - expand_all_folders(mLandmarksInventoryPanel->getRootFolder()); - expand_all_folders(mMyInventoryPanel->getRootFolder()); - expand_all_folders(mLibraryInventoryPanel->getRootFolder()); - - for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) - { - (*iter)->changeOpenClose(false); - } + expand_all_folders(mCurrentSelectedList->getRootFolder()); } else if ("collapse_all" == command_name) { - collapse_all_folders(mFavoritesInventoryPanel->getRootFolder()); - collapse_all_folders(mLandmarksInventoryPanel->getRootFolder()); - collapse_all_folders(mMyInventoryPanel->getRootFolder()); - collapse_all_folders(mLibraryInventoryPanel->getRootFolder()); - - for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) - { - (*iter)->changeOpenClose(true); - } + collapse_all_folders(mCurrentSelectedList->getRootFolder()); } else if ("sort_by_date" == command_name) { @@ -956,8 +606,6 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) sorting_order=!sorting_order; gSavedSettings.setBOOL("LandmarksSortedByDate",sorting_order); updateSortOrder(mLandmarksInventoryPanel, sorting_order); - updateSortOrder(mMyInventoryPanel, sorting_order); - updateSortOrder(mLibraryInventoryPanel, sorting_order); } else { @@ -989,51 +637,21 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const ? mCurrentSelectedList->getRootFolder() : NULL; + bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1; + if ("collapse_all" == command_name) { - bool disable_collapse_all = !has_expanded_folders(mFavoritesInventoryPanel->getRootFolder()) - && !has_expanded_folders(mLandmarksInventoryPanel->getRootFolder()) - && !has_expanded_folders(mMyInventoryPanel->getRootFolder()) - && !has_expanded_folders(mLibraryInventoryPanel->getRootFolder()); - if (disable_collapse_all) - { - for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) - { - if ((*iter)->isExpanded()) - { - disable_collapse_all = false; - break; - } - } - } - - return !disable_collapse_all; + return has_expanded_folders(mCurrentSelectedList->getRootFolder()); } else if ("expand_all" == command_name) { - bool disable_expand_all = !has_collapsed_folders(mFavoritesInventoryPanel->getRootFolder()) - && !has_collapsed_folders(mLandmarksInventoryPanel->getRootFolder()) - && !has_collapsed_folders(mMyInventoryPanel->getRootFolder()) - && !has_collapsed_folders(mLibraryInventoryPanel->getRootFolder()); - if (disable_expand_all) - { - for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter) - { - if (!(*iter)->isExpanded()) - { - disable_expand_all = false; - break; - } - } - } - - return !disable_expand_all; + return has_collapsed_folders(mCurrentSelectedList->getRootFolder()); } else if ("sort_by_date" == command_name) { - // disable "sort_by_date" for Favorites accordion because + // disable "sort_by_date" for Favorites tab because // it has its own items order. EXT-1758 - if (mCurrentSelectedList == mFavoritesInventoryPanel) + if (!isLandmarksPanel) { return false; } @@ -1050,6 +668,11 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const std::set selected_uuids = root_folder_view->getSelectionList(); + if (selected_uuids.empty()) + { + return false; + } + // Allow to execute the command only if it can be applied to all selected items. for (std::set::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) { @@ -1070,7 +693,6 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const ) { // disable some commands for multi-selection. EXT-1757 - bool is_single_selection = root_folder_view && root_folder_view->getSelectedCount() == 1; if (!is_single_selection) { return false; @@ -1100,35 +722,10 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const return true; } - else if ("category" == command_name) - { - // FIRE-29367: Available actions in "Add" button menu in places window are incorrect - //// we can add folder only in Landmarks Accordion - //if (mCurrentSelectedList == mLandmarksInventoryPanel) - //{ - // // ... but except Received folder - // return !isReceivedFolderSelected(); - //} - ////"Add a folder" is enabled by default (case when My Landmarks is empty) - //else return true; - std::string current_tabname; - LLView* accordion_view = findChildView("landmarks_accordion"); - LLAccordionCtrl* accordion = dynamic_cast(accordion_view); - if (accordion) - { - current_tabname = accordion->getSelectedTab()->getName(); - } - else - { - LLTabContainer* tabcontainer = dynamic_cast(accordion_view); - if (tabcontainer) - { - current_tabname = tabcontainer->getCurrentPanel()->getName(); - } - } - - return current_tabname == "tab_landmarks"; - // + if ("category_root" == command_name || "category" == command_name) + { + // we can add folder only in Landmarks tab + return isLandmarksPanel; } else if("create_pick" == command_name) { @@ -1142,28 +739,84 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const } return false; } -// [RLVa:KB] - Checked: 2012-02-08 (RLVa-1.4.5) | Added: RLVa-1.4.5 - else if("add_landmark" == command_name) + else if ("add_landmark" == command_name) + { + if (!is_single_selection) + { + return false; + } + + LLFolderViewModelItemInventory* view_model = getCurSelectedViewModelItem(); + if (!view_model || view_model->getInventoryType() != LLInventoryType::IT_CATEGORY) + { + return false; + } + LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos(); + if (landmark) + { + //already exists + return false; + } + // RLVa check + //return true; + return !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC); + // + } + else if ("add_landmark_root" == command_name) + { + LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos(); + if (landmark) + { + //already exists + return false; + } + // RLVa check + //return true; + return !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC); + // + } + else if ("share" == command_name) + { + if (!mCurrentSelectedList) + { + return false; + } + if (!LLAvatarActions::canShareSelectedItems(mCurrentSelectedList)) + { + return false; + } + return true; + } + else if (command_name == "move_to_landmarks" || command_name == "move_to_favorites") { - std::string current_tabname; - LLView* accordion_view = findChildView("landmarks_accordion"); - LLAccordionCtrl* accordion = dynamic_cast(accordion_view); - if (accordion) + LLFolderViewModelItemInventory* cur_item_model = getCurSelectedViewModelItem(); + if (cur_item_model) { - current_tabname = accordion->getSelectedTab()->getName(); - } - else - { - LLTabContainer* tabcontainer = dynamic_cast(accordion_view); - if (tabcontainer) + LLFolderType::EType folder_type = command_name == "move_to_landmarks" ? LLFolderType::FT_FAVORITE : LLFolderType::FT_LANDMARK; + if (!gInventory.isObjectDescendentOf(cur_item_model->getUUID(), gInventory.findCategoryUUIDForType(folder_type))) { - current_tabname = tabcontainer->getCurrentPanel()->getName(); + return false; + } + + if (root_folder_view) + { + std::set selected_uuids = root_folder_view->getSelectionList(); + for (std::set::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + { + LLFolderViewItem* item = *iter; + if (!item) return false; + + cur_item_model = static_cast(item->getViewModelItem()); + if (!cur_item_model || cur_item_model->getInventoryType() != LLInventoryType::IT_LANDMARK) + { + return false; + } + } + return true; } } - - return !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC) && current_tabname != "tab_library"; + return false; } -// [/RLVa:KB] else { LL_WARNS() << "Unprocessed command has come: " << command_name << LL_ENDL; @@ -1189,12 +842,42 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata) } else if ("create_pick" == command_name) { - doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1)); + LLFolderViewModelItemInventory* cur_item = getCurSelectedViewModelItem(); + if (cur_item) + { + doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1, cur_item->getUUID())); + } } + else if ("share" == command_name && mCurrentSelectedList) + { + LLAvatarActions::shareWithAvatars(mCurrentSelectedList); + } else if ("restore" == command_name && mCurrentSelectedList) { mCurrentSelectedList->doToSelected(userdata); } + else if (command_name == "move_to_landmarks" || command_name == "move_to_favorites") + { + LLFolderView* root_folder_view = mCurrentSelectedList ? mCurrentSelectedList->getRootFolder() : NULL; + if (root_folder_view) + { + LLFolderType::EType folder_type = command_name == "move_to_landmarks" ? LLFolderType::FT_LANDMARK : LLFolderType::FT_FAVORITE; + std::set selected_uuids = root_folder_view->getSelectionList(); + for (std::set::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + { + LLFolderViewItem* item = *iter; + if (item) + { + LLFolderViewModelItemInventory* item_model = static_cast(item->getViewModelItem()); + if (item_model) + { + change_item_parent(item_model->getUUID(), gInventory.findCategoryUUIDForType(folder_type)); + } + } + } + } + + } } void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param) @@ -1261,29 +944,17 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold if (!item) return false; - // nothing can be modified in Library - if (mLibraryInventoryPanel == mCurrentSelectedList) return false; - bool can_be_modified = false; // landmarks can be modified in any other accordion... if (static_cast(item->getViewModelItem())->getInventoryType() == LLInventoryType::IT_LANDMARK) { can_be_modified = true; - - // we can modify landmarks anywhere except paste to My Inventory - if ("paste" == command_name) - { - can_be_modified = (mCurrentSelectedList != mMyInventoryPanel); - } } else { // ...folders only in the Landmarks accordion... - can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList; - - // ...except "Received" folder - can_be_modified &= !isReceivedFolderSelected(); + can_be_modified = isLandmarksPanel; } // then ask LLFolderView permissions @@ -1400,12 +1071,10 @@ void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark) LLFloaterReg::showInstance("world_map", "center"); } - mShowOnMapBtn->setEnabled(TRUE); mGearLandmarkMenu->setItemEnabled("show_on_map", TRUE); } void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark, - LLFolderViewItem* cur_item, LLInventoryItem* inv_item, const LLParcelData& parcel_data) { @@ -1434,7 +1103,7 @@ void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark, LLPickData data; data.pos_global = landmark_global_pos; - data.name = cur_item->getName(); + data.name = inv_item->getName(); data.desc = inv_item->getDescription(); data.snapshot_id = parcel_data.snapshot_id; data.parcel_id = parcel_data.parcel_id; @@ -1454,11 +1123,13 @@ void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark, panel_pick, panel_places,params)); } -void LLLandmarksPanel::doCreatePick(LLLandmark* landmark) +void LLLandmarksPanel::doCreatePick(LLLandmark* landmark, const LLUUID &item_id) { LLViewerRegion* region = gAgent.getRegion(); if (!region) return; + mCreatePickItemId = item_id; + LLGlobalVec pos_global; LLUUID region_id; landmark->getGlobalPos(pos_global); @@ -1511,28 +1182,12 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin inventory_list->setFilterSubString(string); } -static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list) -{ - LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getRootFolderID()); - if (category) - { - return category->getDescendentCount() > 0; - } - - return false; -} - static void collapse_all_folders(LLFolderView* root_folder) { if (!root_folder) return; root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); - - // The top level folder is invisible, it must be open to - // display its sub-folders. - // Also collapse top level folders on Firestorm - we don't have accordions (FIRE-3961) - //root_folder->openTopLevelFolders(); root_folder->arrangeAll(); } @@ -1599,4 +1254,31 @@ void toggle_restore_menu(LLMenuGL *menu, BOOL visible, BOOL enabled) } } } + +LLFavoritesPanel::LLFavoritesPanel() + : LLLandmarksPanel(false) +{ + buildFromFile("panel_favorites.xml"); +} + +BOOL LLFavoritesPanel::postBuild() +{ + if (!gInventory.isInventoryUsable()) + return FALSE; + + // mast be called before any other initXXX methods to init Gear menu + LLLandmarksPanel::initListCommandsHandlers(); + + initFavoritesInventoryPanel(); + + return TRUE; +} + +void LLFavoritesPanel::initFavoritesInventoryPanel() +{ + mCurrentSelectedList = getChild("favorites_list"); + + LLLandmarksPanel::initLandmarksPanel(mCurrentSelectedList); + mCurrentSelectedList->getFilter().setEmptyLookupMessage("FavoritesNoMatchingItems"); +} // EOF diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index c11cbe05ae..d7408269b5 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -50,81 +50,69 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver { public: LLLandmarksPanel(); + LLLandmarksPanel(bool is_landmark_panel); virtual ~LLLandmarksPanel(); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onSearchEdit(const std::string& string); - /*virtual*/ void onShowOnMap(); - /*virtual*/ void onShowProfile(); - /*virtual*/ void onTeleport(); - /*virtual*/ void updateVerbs(); - /*virtual*/ bool isSingleItemSelected(); + BOOL postBuild() override; + void onSearchEdit(const std::string& string) override; + void onShowOnMap() override; + void onShowProfile() override; + void onTeleport() override; + void onRemoveSelected() override; + void updateVerbs() override; + bool isSingleItemSelected() override; + + LLToggleableMenu* getSelectionMenu() override; + LLToggleableMenu* getSortingMenu() override; + LLToggleableMenu* getCreateMenu() override; + + /** + * Processes drag-n-drop of the Landmarks and folders into trash button. + */ + bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override; - void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque &items, BOOL user_action); - void onSelectorButtonClicked(); void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list) { mCurrentSelectedList = inventory_list; } - /** - * Update filter ShowFolderState setting to show empty folder message - * if Landmarks inventory folder is empty. - */ - void updateShowFolderState(); - /** * Selects item with "obj_id" in one of accordion tabs. */ void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus); - LLPlacesInventoryPanel* getLibraryInventoryPanel() { return mLibraryInventoryPanel; } - void updateMenuVisibility(LLUICtrl* menu); + void doCreatePick(LLLandmark* landmark, const LLUUID &item_id ); + + void resetSelection(); + protected: /** * @return true - if current selected panel is not null and selected item is a landmark */ bool isLandmarkSelected() const; bool isFolderSelected() const; - bool isReceivedFolderSelected() const; void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb); LLFolderViewItem* getCurSelectedItem() const; LLFolderViewModelItemInventory* getCurSelectedViewModelItem() const; - /** - * Selects item with "obj_id" in "inventory_list" and scrolls accordion - * scrollbar to show the item. - * Returns pointer to the item if it is found in "inventory_list", otherwise NULL. - */ - LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list, - const std::string& tab_name, - const LLUUID& obj_id, - BOOL take_keyboard_focus) const; - void updateSortOrder(LLInventoryPanel* panel, bool byDate); //LLRemoteParcelInfoObserver interface - /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); - /*virtual*/ void setParcelID(const LLUUID& parcel_id); - /*virtual*/ void setErrorStatus(S32 status, const std::string& reason); - -private: - void initFavoritesInventoryPanel(); - void initLandmarksInventoryPanel(); - void initMyInventoryPanel(); - void initLibraryInventoryPanel(); - void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list); - LLAccordionCtrlTab* initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list, bool expand_tab); - void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list); - void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list); + void processParcelInfo(const LLParcelData& parcel_data) override; + void setParcelID(const LLUUID& parcel_id) override; + void setErrorStatus(S32 status, const std::string& reason) override; // List Commands Handlers void initListCommandsHandlers(); - void updateListCommands(); - void onActionsButtonClick(); - void showActionMenu(LLMenuGL* menu, std::string spawning_view_name); + void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list); + + LLPlacesInventoryPanel* mCurrentSelectedList; + +private: + void initLandmarksInventoryPanel(); + void onTrashButtonClick() const; void onAddAction(const LLSD& command_name) const; void onClipboardAction(const LLSD& command_name) const; @@ -150,39 +138,34 @@ private: bool canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const; void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params); - /** - * Processes drag-n-drop of the Landmarks and folders into trash button. - */ - bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept); - /** * Landmark actions callbacks. Fire when a landmark is loaded from the list. */ void doShowOnMap(LLLandmark* landmark); void doProcessParcelInfo(LLLandmark* landmark, - LLFolderViewItem* cur_item, LLInventoryItem* inv_item, const LLParcelData& parcel_data); - void doCreatePick(LLLandmark* landmark); private: - LLPlacesInventoryPanel* mFavoritesInventoryPanel; LLPlacesInventoryPanel* mLandmarksInventoryPanel; - LLPlacesInventoryPanel* mMyInventoryPanel; - LLPlacesInventoryPanel* mLibraryInventoryPanel; - LLMenuButton* mGearButton; LLToggleableMenu* mGearLandmarkMenu; LLToggleableMenu* mGearFolderMenu; - LLMenuGL* mMenuAdd; - LLPlacesInventoryPanel* mCurrentSelectedList; - LLInventoryObserver* mInventoryObserver; + LLToggleableMenu* mSortingMenu; + LLToggleableMenu* mAddMenu; - LLPanel* mListCommands; + bool isLandmarksPanel; - typedef std::vector accordion_tabs_t; - accordion_tabs_t mAccordionTabs; + LLUUID mCreatePickItemId; // item we requested a pick for +}; - LLAccordionCtrlTab* mMyLandmarksAccordionTab; + +class LLFavoritesPanel : public LLLandmarksPanel +{ +public: + LLFavoritesPanel(); + + BOOL postBuild() override; + void initFavoritesInventoryPanel(); }; #endif //LL_LLPANELLANDMARKS_H diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index dff97f0523..636efef275 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -129,6 +129,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mSavedFolderState(NULL), mFilterText(""), mMenuGearDefault(NULL), + mMenuVisibility(NULL), mMenuAddHandle(), mNeedUploadCost(true), mSearchTypeCombo(NULL) // Properly initialize this @@ -320,6 +321,18 @@ BOOL LLPanelMainInventory::postBuild() // } } + if(mActivePanel) + { + if(savedFilterState.has(mActivePanel->getFilter().getName())) + { + LLSD items = savedFilterState.get(mActivePanel->getFilter().getName()); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(items, p); + mActivePanel->getFilter().setSearchVisibilityTypes(p); + } + } + } mFilterEditor = getChild("inventory search editor"); @@ -334,6 +347,7 @@ BOOL LLPanelMainInventory::postBuild() // Filter dropdown mGearMenuButton = getChild("options_gear_btn"); + mVisibilityMenuButton = getChild("options_visibility_btn"); initListCommandsHandlers(); const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); @@ -358,6 +372,9 @@ BOOL LLPanelMainInventory::postBuild() LLPanelMainInventory::~LLPanelMainInventory( void ) { // Save the filters state. + // Some params types cannot be saved this way + // for example, LLParamSDParser doesn't know about U64, + // so some FilterOps params should be revised. LLSD filterRoot; LLInventoryPanel* all_items_panel = getChild("All Items"); if (all_items_panel) @@ -1611,6 +1628,10 @@ void LLPanelMainInventory::initListCommandsHandlers() LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mMenuAddHandle = menu->getHandle(); + mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mVisibilityMenuButton->setMenu(mMenuVisibility); + mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT); + // Update the trash button when selected item(s) get worn or taken off. LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); } @@ -1808,6 +1829,21 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } LLFloaterReg::showInstance("linkreplace", params); } + + if (command_name == "toggle_search_trash") + { + mActivePanel->getFilter().toggleSearchVisibilityTrash(); + } + + if (command_name == "toggle_search_library") + { + mActivePanel->getFilter().toggleSearchVisibilityLibrary(); + } + + if (command_name == "include_links") + { + mActivePanel->getFilter().toggleSearchVisibilityLinks(); + } } void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) @@ -1962,6 +1998,21 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata) return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; } + if (command_name == "toggle_search_trash") + { + return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0; + } + + if (command_name == "toggle_search_library") + { + return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0; + } + + if (command_name == "include_links") + { + return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0; + } + if (command_name == "add_objects_on_double_click") { return gSavedSettings.getBOOL("FSDoubleClickAddInventoryObjects"); diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 5affeb1c2d..ce264784c9 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -86,7 +86,6 @@ public: void selectAllItemsPanel(); // FIRE-19493: "Show Original" should open main inventory panel void showAllItemsPanel(); - void resetFilters(); // const std::string& getFilterText() const { return mFilterText; } @@ -101,6 +100,8 @@ public: void toggleFindOptions(); + void resetFilters(); + // Filter dropdown void onFilterTypeSelected(const std::string& filter_type_name); void updateFilterDropdown(const LLInventoryFilter* filter); @@ -135,8 +136,6 @@ protected: void doToSelected(const LLSD& userdata); void closeAllFolders(); void doCreate(const LLSD& userdata); - // FIRE-19493: "Show Original" should open main inventory panel - //void resetFilters(); // Moved to public // Sort By menu handlers void setSortBy(const LLSD& userdata); @@ -218,7 +217,9 @@ protected: private: LLDragAndDropButton* mTrashButton; LLToggleableMenu* mMenuGearDefault; + LLToggleableMenu* mMenuVisibility; LLMenuButton* mGearMenuButton; + LLMenuButton* mVisibilityMenuButton; LLHandle mMenuAddHandle; // Inventory Collapse and Expand Buttons diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 799e0fb412..a670abf086 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1439,6 +1439,7 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this)); mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&do_nothing)); mCommitCallbackRegistrar.add("Inventory.SetFavoritesFolder", boost::bind(&do_nothing)); // Prevent warning "No callback found for: 'Inventory.SetFavoritesFolder' in control: Set Favorites folder" + mCommitCallbackRegistrar.add("Inventory.ResetFavoritesFolder", boost::bind(&do_nothing)); // Prevent warning "No callback found for: 'Inventory.ResetFavoritesFolder' in control: Reset Favorites folder" mCommitCallbackRegistrar.add("Inventory.CustomAction", boost::bind(&do_nothing)); // Prevent warning "No callback found for: 'Inventory.CustomAction' in control: Find Links" } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 532d24126c..57abb245c7 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -58,7 +58,6 @@ #include "llmenubutton.h" #include "llpaneloutfitsinventory.h" #include "lluiconstants.h" -#include "llsaveoutfitcombobtn.h" #include "llscrolllistctrl.h" #include "lltextbox.h" #include "lltoggleablemenu.h" @@ -84,6 +83,8 @@ const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LL const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK; static const std::string REVERT_BTN("revert_btn"); +static const std::string SAVE_AS_BTN("save_as_btn"); +static const std::string SAVE_BTN("save_btn"); /////////////////////////////////////////////////////////////////////////////// @@ -569,12 +570,13 @@ BOOL LLPanelOutfitEdit::postBuild() mGearMenu = LLPanelOutfitEditGearMenu::create(); mGearMenuBtn->setMenu(mGearMenu); + getChild(SAVE_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false)); + getChild(SAVE_AS_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true)); + // Show avatar complexity in appearance floater mAvatarComplexityLabel = getChild("avatar_complexity_label"); mAvatarComplexityAddingLabel = getChild("avatar_complexity_adding_label"); - mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); - onOutfitChanging(gAgentWearables.isCOFChangeInProgress()); return TRUE; } @@ -1254,11 +1256,9 @@ void LLPanelOutfitEdit::updateVerbs() bool outfit_locked = LLAppearanceMgr::getInstance()->isOutfitLocked(); bool has_baseoutfit = LLAppearanceMgr::getInstance()->getBaseOutfitUUID().notNull(); - mSaveComboBtn->setSaveBtnEnabled(!outfit_locked && outfit_is_dirty); + getChildView(SAVE_BTN)->setEnabled(!outfit_locked && outfit_is_dirty); getChildView(REVERT_BTN)->setEnabled(outfit_is_dirty && has_baseoutfit); - mSaveComboBtn->setMenuItemEnabled("save_outfit", !outfit_locked && outfit_is_dirty); - mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing")); updateCurrentOutfitName(); @@ -1444,6 +1444,15 @@ void LLPanelOutfitEdit::saveListSelection() } } +void LLPanelOutfitEdit::saveOutfit(bool as_new) +{ + LLPanelOutfitsInventory* panel_outfits_inventory = LLPanelOutfitsInventory::findInstance(); + if (panel_outfits_inventory) + { + panel_outfits_inventory->saveOutfit(as_new); + } +} + // Show avatar complexity in appearance floater void LLPanelOutfitEdit::updateAvatarComplexity(U32 complexity) { diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 2bfce93ee9..6920d41e2d 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -58,7 +58,6 @@ class LLMenuButton; class LLMenuGL; class LLFindNonLinksByMask; class LLFindWearablesOfType; -class LLSaveOutfitComboBtn; class LLWearableItemTypeNameComparator; class LLPanelOutfitEdit : public LLPanel @@ -198,6 +197,7 @@ private: void getSelectedItemsUUID(uuid_vec_t& uuid_list); void getCurrentItemUUID(LLUUID& selected_id); void onCOFChanged(); + void saveOutfit(bool as_new = false); /** * Method preserves selection while switching between folder/list view modes @@ -243,7 +243,6 @@ private: LLToggleableMenu* mGearMenu; LLToggleableMenu* mAddWearablesGearMenu; bool mInitialized; - std::auto_ptr mSaveComboBtn; LLMenuButton* mWearablesGearMenuBtn; LLMenuButton* mGearMenuBtn; diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index fe4fcacd37..798cbc9923 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -40,7 +40,6 @@ #include "lloutfitgallery.h" #include "lloutfitslist.h" #include "llpanelwearing.h" -#include "llsaveoutfitcombobtn.h" #include "llsidepanelappearance.h" #include "llviewercontrol.h" #include "llviewerfoldertype.h" @@ -49,6 +48,9 @@ static const std::string OUTFITS_TAB_NAME = "outfitslist_tab"; static const std::string OUTFIT_GALLERY_TAB_NAME = "outfit_gallery_tab"; static const std::string COF_TAB_NAME = "cof_tab"; +static const std::string SAVE_AS_BTN("save_as_btn"); +static const std::string SAVE_BTN("save_btn"); + static LLPanelInjector t_inventory("panel_outfits_inventory"); LLPanelOutfitsInventory::LLPanelOutfitsInventory() : @@ -101,8 +103,9 @@ BOOL LLPanelOutfitsInventory::postBuild() { LLInventoryModelBackgroundFetch::instance().start(outfits_cat); } - - mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this, true)); + + getChild(SAVE_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::saveOutfit, this, false)); + getChild(SAVE_AS_BTN)->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::saveOutfit, this, true)); return TRUE; } @@ -286,6 +289,12 @@ LLPanelOutfitsInventory* LLPanelOutfitsInventory::findInstance() return dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfits_inventory")); } +void LLPanelOutfitsInventory::openApearanceTab(const std::string& tab_name) +{ + if (!mAppearanceTabs) return; + mAppearanceTabs->selectTabByName(tab_name); +} + ////////////////////////////////////////////////////////////////////////////////// // List Commands // @@ -309,7 +318,7 @@ void LLPanelOutfitsInventory::updateListCommands() mOutfitGalleryPanel->childSetEnabled("trash_btn", trash_enabled); wear_btn->setEnabled(wear_enabled); wear_btn->setVisible(wear_visible); - mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled); + getChild(SAVE_BTN)->setEnabled(make_outfit_enabled); wear_btn->setToolTip(getString((!isOutfitsGalleryPanelActive() && mMyOutfitsPanel->hasItemSelected()) ? "wear_items_tooltip" : "wear_outfit_tooltip")); } @@ -409,6 +418,18 @@ LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP() return panel_appearance; } +void LLPanelOutfitsInventory::saveOutfit(bool as_new) +{ + if (!as_new && LLAppearanceMgr::getInstance()->updateBaseOutfit()) + { + // we don't need to ask for an outfit name, and updateBaseOutfit() successfully saved. + // If updateBaseOutfit fails, ask for an outfit name anyways + return; + } + + onSave(); +} + // Show avatar complexity in appearance floater void LLPanelOutfitsInventory::updateAvatarComplexity(U32 complexity, const std::map& item_complexity, const std::map& temp_item_complexity, U32 body_parts_complexity) { @@ -417,4 +438,3 @@ void LLPanelOutfitsInventory::updateAvatarComplexity(U32 complexity, const std:: mCurrentOutfitPanel->updateAvatarComplexity(complexity, item_complexity, temp_item_complexity, body_parts_complexity); } // - diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index e8534311d8..349cc5ea81 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -38,7 +38,6 @@ class LLPanelWearing; class LLMenuGL; class LLSidepanelAppearance; class LLTabContainer; -class LLSaveOutfitComboBtn; class LLInventoryCategoriesObserver; // FIRE-17626: Attachment count in appearance floater class LLPanelOutfitsInventory : public LLPanel @@ -53,6 +52,7 @@ public: void onSearchEdit(const std::string& string); void onSave(); + void saveOutfit(bool as_new = false); bool onSaveCommit(const LLSD& notification, const LLSD& response); @@ -66,6 +66,8 @@ public: static LLPanelOutfitsInventory* findInstance(); + void openApearanceTab(const std::string& tab_name); + // Show avatar complexity in appearance floater void updateAvatarComplexity(U32 complexity, const std::map& item_complexity, const std::map& temp_item_complexity, U32 body_parts_complexity); @@ -75,7 +77,6 @@ protected: private: LLTabContainer* mAppearanceTabs; std::string mFilterSubString; - std::auto_ptr mSaveComboBtn; // FIRE-17626: Attachment count in appearance floater LLInventoryCategoriesObserver* mCategoriesObserver; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f7768f372f..17e0053309 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -742,6 +742,7 @@ BOOL LLPanelPeople::postBuild() mRecentList->setShowIcons("RecentListShowIcons"); mGroupList = getChild("group_list"); + mGroupList->setNoItemsCommentText(getString("no_groups_msg")); mGroupList->setNoItemsMsg(getString("no_groups_msg")); mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg")); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 8294158870..de8688fc5d 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -54,6 +54,7 @@ #include "llagentpicksinfo.h" #include "llavatarpropertiesprocessor.h" #include "llcommandhandler.h" +#include "lldndbutton.h" #include "llfloaterworldmap.h" #include "llinventorybridge.h" #include "llinventoryobserver.h" @@ -83,6 +84,7 @@ static const F32 PLACE_INFO_UPDATE_INTERVAL = 3.0; static const std::string AGENT_INFO_TYPE = "agent"; static const std::string CREATE_LANDMARK_INFO_TYPE = "create_landmark"; +static const std::string CREATE_PICK_TYPE = "create_pick"; static const std::string LANDMARK_INFO_TYPE = "landmark"; static const std::string REMOTE_PLACE_INFO_TYPE = "remote_place"; static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history"; @@ -305,8 +307,25 @@ BOOL LLPanelPlaces::postBuild() mOverflowBtn = getChild("overflow_btn"); mOverflowBtn->setMouseDownCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this)); - mPlaceInfoBtn = getChild("profile_btn"); - mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this)); + mGearMenuButton = getChild("options_gear_btn"); + mGearMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onGearMenuClick, this)); + + mSortingMenuButton = getChild("sorting_menu_btn"); + mSortingMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onSortingMenuClick, this)); + + mAddMenuButton = getChild("add_menu_btn"); + mAddMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onAddMenuClick, this)); + + mRemoveSelectedBtn = getChild("trash_btn"); + mRemoveSelectedBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onRemoveButtonClicked, this)); + + LLDragAndDropButton* trash_btn = (LLDragAndDropButton*)mRemoveSelectedBtn; + trash_btn->setDragAndDropHandler(boost::bind(&LLPanelPlaces::handleDragAndDropToTrash, this + , _4 // BOOL drop + , _5 // EDragAndDropType cargo_type + , _6 // void* cargo_data + , _7 // EAcceptance* accept + )); LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Places.OverflowMenu.Action", boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2)); @@ -335,6 +354,10 @@ BOOL LLPanelPlaces::postBuild() mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this)); } + mButtonsContainer = getChild("button_layout_panel"); + mButtonsContainer->setVisible(FALSE); + mFilterContainer = getChild("top_menu_panel"); + mFilterEditor = getChild("Filter"); if (mFilterEditor) { @@ -400,6 +423,21 @@ void LLPanelPlaces::onOpen(const LLSD& key) // Update the buttons at the bottom of the panel updateVerbs(); } + else if (key_type == CREATE_PICK_TYPE) + { + LLUUID item_id = key["item_id"]; + + LLLandmarksPanel* landmarks_panel = + dynamic_cast(mTabContainer->getPanelByName("Landmarks")); + if (landmarks_panel && item_id.notNull()) + { + LLLandmark* landmark = LLLandmarkActions::getLandmark(item_id, boost::bind(&LLLandmarksPanel::doCreatePick, landmarks_panel, _1, item_id)); + if (landmark) + { + landmarks_panel->doCreatePick(landmark, item_id); + } + } + } // Toggle teleport history panel directly else if (key_type == TELEPORT_HISTORY_TAB_INFO_TYPE) { @@ -423,7 +461,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) updateVerbs(); } // Toggle teleport history panel directly - else + else // "create_landmark" { mFilterEditor->clear(); onFilterEdit("", false); @@ -444,7 +482,8 @@ void LLPanelPlaces::onOpen(const LLSD& key) } else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE) { - mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK); + LLUUID dest_folder = key["dest_folder"]; + mLandmarkInfo->setInfoAndCreateLandmark(dest_folder); if (key.has("x") && key.has("y") && key.has("z")) { @@ -655,6 +694,26 @@ void LLPanelPlaces::onTabSelected() onFilterEdit(mActivePanel->getFilterSubString(), true); mActivePanel->updateVerbs(); + + // History panel does not support deletion nor creation + // Hide menus + bool supports_create = mActivePanel->getCreateMenu() != NULL; + childSetVisible("add_btn_panel", supports_create); + + // favorites and inventory can remove items, history can clear history + // Trashcan icon clearing everything? No way! + //childSetVisible("trash_btn_panel", TRUE); + + //if (supports_create) + //{ + // mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_items")); + //} + //else + //{ + // mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_history")); + //} + childSetVisible("trash_btn_panel", supports_create); + // } void LLPanelPlaces::onTeleportButtonClicked() @@ -771,34 +830,6 @@ void LLPanelPlaces::onEditButtonClicked() updateVerbs(); } -class LLUpdateLandmarkParent : public LLInventoryCallback -{ -public: - LLUpdateLandmarkParent(LLPointer item, LLUUID new_parent) : - mItem(item), - mNewParentId(new_parent) - {}; - /* virtual */ void fire(const LLUUID& inv_item_id) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - mItem->setParent(mNewParentId); - mItem->updateParentOnServer(FALSE); - - gInventory.updateItem(mItem); - gInventory.notifyObservers(); - } - -private: - LLPointer mItem; - LLUUID mNewParentId; -}; - void LLPanelPlaces::onSaveButtonClicked() { if (!mLandmarkInfo || mItem.isNull()) @@ -932,14 +963,6 @@ void LLPanelPlaces::onOverflowButtonClicked() mOverflowBtn->setMenu(menu, LLMenuButton::MP_TOP_RIGHT); } -void LLPanelPlaces::onProfileButtonClicked() -{ - if (!mActivePanel) - return; - - mActivePanel->onShowProfile(); -} - bool LLPanelPlaces::onOverflowMenuItemEnable(const LLSD& param) { std::string value = param.asString(); @@ -1028,6 +1051,50 @@ void LLPanelPlaces::onBackButtonClicked() updateVerbs(); } +void LLPanelPlaces::onGearMenuClick() +{ + if (mActivePanel) + { + LLToggleableMenu* menu = mActivePanel->getSelectionMenu(); + mGearMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT); + } +} + +void LLPanelPlaces::onSortingMenuClick() +{ + if (mActivePanel) + { + LLToggleableMenu* menu = mActivePanel->getSortingMenu(); + mSortingMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT); + } +} + +void LLPanelPlaces::onAddMenuClick() +{ + if (mActivePanel) + { + LLToggleableMenu* menu = mActivePanel->getCreateMenu(); + mAddMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT); + } +} + +void LLPanelPlaces::onRemoveButtonClicked() +{ + if (mActivePanel) + { + mActivePanel->onRemoveSelected(); + } +} + +bool LLPanelPlaces::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) +{ + if (mActivePanel) + { + return mActivePanel->handleDragAndDropToTrash(drop, cargo_type, cargo_data, accept); + } + return false; +} + void LLPanelPlaces::togglePickPanel(BOOL visible) { if (mPickPanel) @@ -1044,8 +1111,9 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) if (!mPlaceProfile || !mLandmarkInfo) return; - mFilterEditor->setVisible(!visible); mTabContainer->setVisible(!visible); + mButtonsContainer->setVisible(visible); + mFilterContainer->setVisible(!visible); if (mPlaceInfoType == AGENT_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE || @@ -1061,10 +1129,6 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) // to avoid text blinking. mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL); - LLRect rect = getRect(); - LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom); - mPlaceProfile->reshape(new_rect.getWidth(), new_rect.getHeight()); - mLandmarkInfo->setVisible(FALSE); } else if (mPlaceInfoType == AGENT_INFO_TYPE) @@ -1085,15 +1149,19 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) if (visible) { mLandmarkInfo->resetLocation(); - - LLRect rect = getRect(); - LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom); - mLandmarkInfo->reshape(new_rect.getWidth(), new_rect.getHeight()); } else { - LLLandmarksPanel* landmarks_panel = - dynamic_cast(mTabContainer->getPanelByName("Landmarks")); + std::string tab_panel_name("Landmarks"); + if (mItem.notNull()) + { + if (gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))) + { + tab_panel_name = "Favorites"; + } + } + + LLLandmarksPanel* landmarks_panel = dynamic_cast(mTabContainer->getPanelByName(tab_panel_name)); if (landmarks_panel) { // If a landmark info is being closed we open the landmarks tab @@ -1103,6 +1171,10 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) { landmarks_panel->setItemSelected(mItem->getUUID(), TRUE); } + else + { + landmarks_panel->resetSelection(); + } } } } @@ -1170,11 +1242,19 @@ void LLPanelPlaces::createTabs() if (!(gInventory.isInventoryUsable() && LLTeleportHistory::getInstance() && !mTabsCreated)) return; + LLFavoritesPanel* favorites_panel = new LLFavoritesPanel(); + if (favorites_panel) + { + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(favorites_panel). + label(getString("favorites_tab_title")). + insert_at(LLTabContainer::END)); + } + LLLandmarksPanel* landmarks_panel = new LLLandmarksPanel(); if (landmarks_panel) { - landmarks_panel->setPanelPlacesButtons(this); - mTabContainer->addTabPanel( LLTabContainer::TabPanelParams(). panel(landmarks_panel). @@ -1185,8 +1265,6 @@ void LLPanelPlaces::createTabs() LLTeleportHistoryPanel* teleport_history_panel = new LLTeleportHistoryPanel(); if (teleport_history_panel) { - teleport_history_panel->setPanelPlacesButtons(this); - mTabContainer->addTabPanel( LLTabContainer::TabPanelParams(). panel(teleport_history_panel). @@ -1198,9 +1276,34 @@ void LLPanelPlaces::createTabs() mActivePanel = dynamic_cast(mTabContainer->getCurrentPanel()); - // Filter applied to show all items. - if (mActivePanel) - mActivePanel->onSearchEdit(mActivePanel->getFilterSubString()); + if (mActivePanel) + { + // Filter applied to show all items. + mActivePanel->onSearchEdit(mActivePanel->getFilterSubString()); + + // History panel does not support deletion nor creation + // Hide menus + bool supports_create = mActivePanel->getCreateMenu() != NULL; + childSetVisible("add_btn_panel", supports_create); + + // favorites and inventory can remove items, history can clear history + // Trashcan icon clearing everything? No way! + //childSetVisible("trash_btn_panel", TRUE); + + //if (supports_create) + //{ + // mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_items")); + //} + //else + //{ + // mRemoveSelectedBtn->setToolTip(getString("tooltip_trash_history")); + //} + childSetVisible("trash_btn_panel", supports_create); + // + + mActivePanel->setRemoveBtn(mRemoveSelectedBtn); + mActivePanel->updateVerbs(); + } mTabsCreated = true; } @@ -1266,15 +1369,12 @@ void LLPanelPlaces::updateVerbs() mSaveBtn->setVisible(isLandmarkEditModeOn); mCancelBtn->setVisible(isLandmarkEditModeOn); mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn); - mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); bool show_options_btn = is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn; mOverflowBtn->setVisible(show_options_btn); getChild("lp_options")->setVisible(show_options_btn); getChild("lp2")->setVisible(!show_options_btn); - mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos); - if (is_place_info_visible) { mShowOnMapBtn->setEnabled(have_3d_pos); diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index c4281cfdf9..24b7605fd6 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -48,6 +48,7 @@ class LLRemoteParcelInfoObserver; class LLTabContainer; class LLToggleableMenu; class LLMenuButton; +class LLLayoutStack; typedef std::pair folder_pair_t; @@ -103,7 +104,12 @@ private: bool onOverflowMenuItemEnable(const LLSD& param); void onCreateLandmarkButtonClicked(const LLUUID& folder_id); void onBackButtonClicked(); - void onProfileButtonClicked(); + void onGearMenuClick(); + void onSortingMenuClick(); + void onAddMenuClick(); + void onRemoveButtonClicked(); + bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept); + void toggleMediaPanel(); void togglePickPanel(BOOL visible); @@ -118,6 +124,8 @@ private: LLFilterEditor* mFilterEditor; LLPanelPlacesTab* mActivePanel; LLTabContainer* mTabContainer; + LLPanel* mButtonsContainer; + LLLayoutStack* mFilterContainer; LLPanelPlaceProfile* mPlaceProfile; LLPanelLandmarkInfo* mLandmarkInfo; @@ -132,7 +140,12 @@ private: LLButton* mCancelBtn; LLButton* mCloseBtn; LLMenuButton* mOverflowBtn; - LLButton* mPlaceInfoBtn; + + // Top menu + LLMenuButton* mGearMenuButton; + LLMenuButton* mSortingMenuButton; + LLMenuButton* mAddMenuButton; + LLButton* mRemoveSelectedBtn; LLPlacesInventoryObserver* mInventoryObserver; LLPlacesParcelObserver* mParcelObserver; diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp index 34a36b186e..1594cac817 100644 --- a/indra/newview/llpanelplacestab.cpp +++ b/indra/newview/llpanelplacestab.cpp @@ -38,6 +38,7 @@ #include "llworldmap.h" std::string LLPanelPlacesTab::sFilterSubString = LLStringUtil::null; +LLButton* LLPanelPlacesTab::sRemoveBtn = NULL; bool LLPanelPlacesTab::isTabVisible() { @@ -47,13 +48,6 @@ bool LLPanelPlacesTab::isTabVisible() return true; } -void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel) -{ - mTeleportBtn = panel->getChild("teleport_btn"); - mShowOnMapBtn = panel->getChild("map_btn"); - mShowProfile = panel->getChild("profile_btn"); -} - void LLPanelPlacesTab::onRegionResponse(const LLVector3d& landmark_global_pos, U64 region_handle, const std::string& url, diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h index 367ce46e2e..aab1c130c1 100644 --- a/indra/newview/llpanelplacestab.h +++ b/indra/newview/llpanelplacestab.h @@ -30,6 +30,7 @@ #include "llpanel.h" class LLPanelPlaces; +class LLToggleableMenu; class LLPanelPlacesTab : public LLPanel { @@ -42,11 +43,21 @@ public: virtual void onShowOnMap() = 0; virtual void onShowProfile() = 0; virtual void onTeleport() = 0; + virtual void onRemoveSelected() = 0; virtual bool isSingleItemSelected() = 0; + // returns menu for current selection + virtual LLToggleableMenu* getSelectionMenu() = 0; + virtual LLToggleableMenu* getSortingMenu() = 0; + virtual LLToggleableMenu* getCreateMenu() = 0; + + /** + * Processes drag-n-drop of the Landmarks and folders into trash button. + */ + virtual bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) = 0; + bool isTabVisible(); // Check if parent TabContainer is visible. - void setPanelPlacesButtons(LLPanelPlaces* panel); void onRegionResponse(const LLVector3d& landmark_global_pos, U64 region_handle, const std::string& url, @@ -56,13 +67,12 @@ public: const std::string& getFilterSubString() { return sFilterSubString; } void setFilterSubString(const std::string& string) { sFilterSubString = string; } -protected: - LLButton* mTeleportBtn; - LLButton* mShowOnMapBtn; - LLButton* mShowProfile; + void setRemoveBtn(LLButton* trash_btn) { sRemoveBtn = trash_btn; } +protected: // Search string for filtering landmarks and teleport history locations static std::string sFilterSubString; + static LLButton* sRemoveBtn; }; #endif //LL_LLPANELPLACESTAB_H diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index e45ca2dfc2..7b0cbe45e0 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -62,7 +62,7 @@ static const std::string COLLAPSED_BY_USER = "collapsed_by_user"; class LLTeleportHistoryFlatItem : public LLPanel { public: - LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, + LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string ®ion_name, // Extended TP history // LLDate date, const std::string &hl); LLDate date, const LLVector3& local_pos, const std::string &hl); @@ -98,12 +98,13 @@ public: private: void onProfileBtnClick(); + void showMenu(S32 x, S32 y); LLButton* mProfileBtn; LLTextBox* mTitle; LLTextBox* mTimeTextBox; - LLTeleportHistoryPanel::ContextMenu *mContextMenu; + LLToggleableMenu *mMenu; S32 mIndex; std::string mRegionName; @@ -130,7 +131,7 @@ protected: public: LLTeleportHistoryFlatItem* getFlatItemForPersistentItem ( - LLTeleportHistoryPanel::ContextMenu *context_menu, + LLToggleableMenu *menu, const LLTeleportHistoryPersistentItem& persistent_item, const S32 cur_item_index, const std::string &hl); @@ -148,14 +149,14 @@ private: //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string ®ion_name, +LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string ®ion_name, // Extended TP history // LLDate date, const std::string &hl) LLDate date, const LLVector3& local_pos, const std::string &hl) // : LLPanel(), mIndex(index), - mContextMenu(context_menu), + mMenu(menu), mRegionName(region_name), mDate(date), // Extended TP history @@ -163,7 +164,7 @@ LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistor // mHighlight(hl) { - buildFromFile( "panel_teleport_history_item.xml"); + buildFromFile("panel_teleport_history_item.xml"); } LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem() @@ -321,10 +322,9 @@ void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask) // virtual BOOL LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (mContextMenu) - mContextMenu->show(this, mIndex, x, y); - - return LLPanel::handleRightMouseDown(x, y, mask); + LLPanel::handleRightMouseDown(x, y, mask); + showMenu(x, y); + return TRUE; } void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index) @@ -344,13 +344,23 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick() LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex); } +void LLTeleportHistoryFlatItem::showMenu(S32 x, S32 y) +{ + mMenu->setButtonRect(this); + mMenu->buildDrawLabels(); + mMenu->arrangeAndClear(); + mMenu->updateParent(LLMenuGL::sMenuContainer); + + LLMenuGL::showPopup(this, mMenu, x, y); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// LLTeleportHistoryFlatItem* LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem ( - LLTeleportHistoryPanel::ContextMenu *context_menu, + LLToggleableMenu *menu, const LLTeleportHistoryPersistentItem& persistent_item, const S32 cur_item_index, const std::string &hl) @@ -388,7 +398,7 @@ LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem ( if ( !item ) { item = new LLTeleportHistoryFlatItem(cur_item_index, - context_menu, + menu, persistent_item.mTitle, persistent_item.mDate, // Extended TP history @@ -435,74 +445,6 @@ void LLTeleportHistoryFlatItemStorage::purge() //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -LLTeleportHistoryPanel::ContextMenu::ContextMenu() : - mMenu(NULL), mIndex(0) -{ -} - -void LLTeleportHistoryPanel::ContextMenu::show(LLView* spawning_view, S32 index, S32 x, S32 y) -{ - if (mMenu) - { - //preventing parent (menu holder) from deleting already "dead" context menus on exit - LLView* parent = mMenu->getParent(); - if (parent) - { - parent->removeChild(mMenu); - } - delete mMenu; - } - - mIndex = index; - mMenu = createMenu(); - - mMenu->show(x, y); - LLMenuGL::showPopup(spawning_view, mMenu, x, y); -} - -LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu() -{ - // set up the callbacks for all of the avatar menu items - // (N.B. callbacks don't take const refs as mID is local scope) - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - - registrar.add("TeleportHistory.Teleport", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this)); - registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this)); - registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this)); - - // create the context menu from the XUI - llassert(LLMenuGL::sMenuContainer != NULL); - return LLUICtrlFactory::getInstance()->createFromFile( - "menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); -} - -void LLTeleportHistoryPanel::ContextMenu::onTeleport() -{ - confirmTeleport(mIndex); -} - -void LLTeleportHistoryPanel::ContextMenu::onInfo() -{ - LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex); -} - -//static -void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl) -{ - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size()); - - LLSD args; - args["SLURL"] = slurl; - - LLNotificationsUtil::add("CopySLURL", args); -} - -void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard() -{ - LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos; - LLLandmarkActions::getSLURLfromPosGlobal(globalPos, - boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1)); -} // Not yet implemented; need to remove buildPanel() from constructor when we switch //static LLPanelInjector t_teleport_history("panel_teleport_history"); @@ -515,9 +457,10 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel() mHistoryAccordion(NULL), mAccordionTabMenu(NULL), mLastSelectedFlatlList(NULL), - // Separate search filter for standalone TP history - //mLastSelectedItemIndex(-1) mLastSelectedItemIndex(-1), + mGearItemMenu(NULL), + mSortingMenu(NULL), + // Separate search filter for standalone TP history mIsStandAlone(false) // { @@ -531,12 +474,19 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel() LLTeleportHistoryPanel::~LLTeleportHistoryPanel() { LLTeleportHistoryFlatItemStorage::instance().purge(); - if (mGearMenuHandle.get()) mGearMenuHandle.get()->die(); mTeleportHistoryChangedConnection.disconnect(); } BOOL LLTeleportHistoryPanel::postBuild() { + mCommitCallbackRegistrar.add("TeleportHistory.GearMenu.Action", boost::bind(&LLTeleportHistoryPanel::onGearMenuAction, this, _2)); + mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2)); + + // init menus before list, since menus are passed to list + mGearItemMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_teleport_history_item.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mGearItemMenu->setAlwaysShowMenu(TRUE); // all items can be disabled if nothing is selected, show anyway + mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mTeleportHistory = LLTeleportHistoryStorage::getInstance(); if (mTeleportHistory) { @@ -588,24 +538,6 @@ BOOL LLTeleportHistoryPanel::postBuild() } } - getChild("bottom_panel")->childSetAction("gear_btn",boost::bind(&LLTeleportHistoryPanel::onGearButtonClicked, this)); - - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - - registrar.add("TeleportHistory.ExpandAllFolders", boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders, this)); - registrar.add("TeleportHistory.CollapseAllFolders", boost::bind(&LLTeleportHistoryPanel::onCollapseAllFolders, this)); - registrar.add("TeleportHistory.ClearTeleportHistory", boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory, this)); - mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2)); -// mMenuGearButton = getChild("gear_btn"); - -// LLToggleableMenu* gear_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());; - LLMenuGL* gear_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(gear_menu) - { - mGearMenuHandle = gear_menu->getHandle(); -// mMenuGearButton->setMenu(gear_menu); - } - return TRUE; } @@ -689,6 +621,12 @@ void LLTeleportHistoryPanel::onTeleport() confirmTeleport(itemp->getIndex()); } +// virtual +void LLTeleportHistoryPanel::onRemoveSelected() +{ + LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2)); +} + /* // virtual void LLTeleportHistoryPanel::onCopySLURL() @@ -719,19 +657,28 @@ void LLTeleportHistoryPanel::updateVerbs() if (!isTabVisible()) return; - if (!mLastSelectedFlatlList) + if (sRemoveBtn) { - mTeleportBtn->setEnabled(false); - mShowProfile->setEnabled(false); - mShowOnMapBtn->setEnabled(false); - return; + sRemoveBtn->setEnabled(true); } +} - LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedFlatlList->getSelectedItem()); +// virtual +LLToggleableMenu* LLTeleportHistoryPanel::getSelectionMenu() +{ + return mGearItemMenu; +} - mTeleportBtn->setEnabled(NULL != itemp); - mShowProfile->setEnabled(NULL != itemp); - mShowOnMapBtn->setEnabled(NULL != itemp); +// virtual +LLToggleableMenu* LLTeleportHistoryPanel::getSortingMenu() +{ + return mSortingMenu; +} + +// virtual +LLToggleableMenu* LLTeleportHistoryPanel::getCreateMenu() +{ + return NULL; } void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date) @@ -918,7 +865,7 @@ void LLTeleportHistoryPanel::refresh() { LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance() - .getFlatItemForPersistentItem(&mContextMenu, + .getFlatItemForPersistentItem(mGearItemMenu, items[mCurrentItem], mCurrentItem, filter_string); @@ -997,7 +944,7 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index) const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems(); LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance() - .getFlatItemForPersistentItem(&mContextMenu, + .getFlatItemForPersistentItem(mGearItemMenu, history_items[history_items.size() - 1], // Most recent item, it was added instead of removed history_items.size(), // index will be decremented inside loop below // Separate search filter for standalone TP history @@ -1173,33 +1120,6 @@ void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab) mHistoryAccordion->arrange(); } -void LLTeleportHistoryPanel::onExpandAllFolders() -{ - S32 tabs_cnt = mItemContainers.size(); - - for (S32 n = 0; n < tabs_cnt; n++) - { - mItemContainers.at(n)->setDisplayChildren(true); - } - mHistoryAccordion->arrange(); -} - -void LLTeleportHistoryPanel::onCollapseAllFolders() -{ - S32 tabs_cnt = mItemContainers.size(); - - for (S32 n = 0; n < tabs_cnt; n++) - { - mItemContainers.at(n)->setDisplayChildren(false); - } - mHistoryAccordion->arrange(); - - if (mLastSelectedFlatlList) - { - mLastSelectedFlatlList->resetSelection(); - } -} - // [timezone support for teleport history] void LLTeleportHistoryPanel::onTimeZoneChecked(const LLSD& userdata) { @@ -1216,11 +1136,6 @@ bool LLTeleportHistoryPanel::isTimeZoneChecked(const LLSD& userdata) } // -void LLTeleportHistoryPanel::onClearTeleportHistory() -{ - LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2)); -} - bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response) { @@ -1252,66 +1167,137 @@ LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTa return NULL; } -void LLTeleportHistoryPanel::onGearButtonClicked() +void LLTeleportHistoryPanel::gotSLURLCallback(const std::string& slurl) { - LLMenuGL* menu = (LLMenuGL*)mGearMenuHandle.get(); - if (!menu) - return; + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, slurl.size()); - // Shows the menu at the top of the button bar. + LLSD args; + args["SLURL"] = slurl; - // Calculate its coordinates. - LLPanel* bottom_panel = getChild("bottom_panel"); - menu->arrangeAndClear(); - S32 menu_height = menu->getRect().getHeight(); - S32 menu_x = -2; // *HACK: compensates HPAD in showPopup() - S32 menu_y = bottom_panel->getRect().mTop + menu_height; + LLNotificationsUtil::add("CopySLURL", args); +} - // Actually show the menu. - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, menu, menu_x, menu_y); +void LLTeleportHistoryPanel::onGearMenuAction(const LLSD& userdata) +{ + std::string command_name = userdata.asString(); + + if ("expand_all" == command_name) + { + S32 tabs_cnt = mItemContainers.size(); + + for (S32 n = 0; n < tabs_cnt; n++) + { + mItemContainers.at(n)->setDisplayChildren(true); + } + mHistoryAccordion->arrange(); + } + else if ("collapse_all" == command_name) + { + S32 tabs_cnt = mItemContainers.size(); + + for (S32 n = 0; n < tabs_cnt; n++) + { + mItemContainers.at(n)->setDisplayChildren(false); + } + mHistoryAccordion->arrange(); + + if (mLastSelectedFlatlList) + { + mLastSelectedFlatlList->resetSelection(); + } + } + + S32 index = -1; + if (mLastSelectedFlatlList) + { + LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedFlatlList->getSelectedItem()); + if (itemp) + { + index = itemp->getIndex(); + } + } + + if ("teleport" == command_name) + { + confirmTeleport(index); + } + else if ("view" == command_name) + { + LLTeleportHistoryFlatItem::showPlaceInfoPanel(index); + } + else if ("show_on_map" == command_name) + { + LLTeleportHistoryStorage::getInstance()->showItemOnMap(index); + } + else if ("copy_slurl" == command_name) + { + LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[index].mGlobalPos; + LLLandmarkActions::getSLURLfromPosGlobal(globalPos, + boost::bind(&LLTeleportHistoryPanel::gotSLURLCallback, _1)); + } } bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const { - S32 tabs_cnt = mItemContainers.size(); + std::string command_name = userdata.asString(); - bool has_expanded_tabs = false; - bool has_collapsed_tabs = false; + if (command_name == "collapse_all" + || command_name == "expand_all") + { + S32 tabs_cnt = mItemContainers.size(); - for (S32 n = 0; n < tabs_cnt; n++) - { - LLAccordionCtrlTab* tab = mItemContainers.at(n); - if (!tab->getVisible()) - continue; + bool has_expanded_tabs = false; + bool has_collapsed_tabs = false; - if (tab->getDisplayChildren()) - { - has_expanded_tabs = true; - } - else - { - has_collapsed_tabs = true; - } + for (S32 n = 0; n < tabs_cnt; n++) + { + LLAccordionCtrlTab* tab = mItemContainers.at(n); + if (!tab->getVisible()) + continue; - if (has_expanded_tabs && has_collapsed_tabs) - { - break; - } - } + if (tab->getDisplayChildren()) + { + has_expanded_tabs = true; + } + else + { + has_collapsed_tabs = true; + } - std::string command_name = userdata.asString(); + if (has_expanded_tabs && has_collapsed_tabs) + { + break; + } + } - if (has_expanded_tabs && command_name == "collapse_all") - { - return true; - } + if (command_name == "collapse_all") + { + return has_expanded_tabs; + } - if (has_collapsed_tabs && command_name == "expand_all") - { - return true; - } + if (command_name == "expand_all") + { + return has_collapsed_tabs; + } + } + + if (command_name == "clear_history") + { + return mTeleportHistory->getItems().size() > 0; + } + + if ("teleport" == command_name + || "view" == command_name + || "show_on_map" == command_name + || "copy_slurl" == command_name) + { + if (!mLastSelectedFlatlList) + { + return false; + } + LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedFlatlList->getSelectedItem()); + return itemp != NULL; + } return false; } diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index 8fe1e32436..02872966ad 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -45,38 +45,26 @@ class LLTeleportHistoryPanel : public LLPanelPlacesTab friend class FSFloaterTeleportHistory; public: - // *TODO: derive from LLListContextMenu? - class ContextMenu - { - public: - ContextMenu(); - void show(LLView* spawning_view, S32 index, S32 x, S32 y); - - private: - LLContextMenu* createMenu(); - void onTeleport(); - void onInfo(); - void onCopyToClipboard(); - - static void gotSLURLCallback(const std::string& slurl); - - LLContextMenu* mMenu; - S32 mIndex; - }; - LLTeleportHistoryPanel(); virtual ~LLTeleportHistoryPanel(); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); + BOOL postBuild() override; + void draw() override; - /*virtual*/ void onSearchEdit(const std::string& string); - /*virtual*/ void onShowOnMap(); - /*virtual*/ void onShowProfile(); - /*virtual*/ void onTeleport(); - ///*virtual*/ void onCopySLURL(); - /*virtual*/ void updateVerbs(); - /*virtual*/ bool isSingleItemSelected(); + void onSearchEdit(const std::string& string) override; + void onShowOnMap() override; + void onShowProfile() override; + void onTeleport() override; + ///*virtual*/ void onCopySLURL(); + void onRemoveSelected() override; + void updateVerbs() override; + bool isSingleItemSelected() override; + + LLToggleableMenu* getSelectionMenu() override; + LLToggleableMenu* getSortingMenu() override; + LLToggleableMenu* getCreateMenu() override; + + bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override { return false; } // Separate search filter for standalone TP history void setIsStandAlone(bool standalone) { mIsStandAlone = standalone; } @@ -99,14 +87,15 @@ private: void onClearTeleportHistory(); bool onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response); - void refresh(); + void refresh() override; void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date); void onTeleportHistoryChange(S32 removed_index); void replaceItem(S32 removed_index); void showTeleportHistory(); void handleItemSelect(LLFlatListView* ); LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *); - void onGearButtonClicked(); + static void gotSLURLCallback(const std::string& slurl); + void onGearMenuAction(const LLSD& userdata); bool isActionEnabled(const LLSD& userdata) const; void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed); @@ -127,9 +116,10 @@ private: typedef std::vector item_containers_t; item_containers_t mItemContainers; - ContextMenu mContextMenu; LLContextMenu* mAccordionTabMenu; - LLHandle mGearMenuHandle; + + LLToggleableMenu* mGearItemMenu; + LLToggleableMenu* mSortingMenu; boost::signals2::connection mTeleportHistoryChangedConnection; diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index b377a20dd4..5c81bb458e 100644 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llagentui.h" #include "llclipboard.h" +#include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "lllandmarkactions.h" #include "lllocationinputctrl.h" @@ -476,10 +477,7 @@ void LLPanelTopInfoBar::onContextMenuItemClicked(const LLSD::String& item) if(landmark == NULL) { - // FIRE-817: Separate place details floater - //LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark")); - FSFloaterPlaceDetails::showPlaceDetails(LLSD().with("type", "create_landmark")); - // + LLFloaterReg::showInstance("add_landmark"); } else { diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp index 0287c07f96..41976674a7 100644 --- a/indra/newview/llpathfindingnavmesh.cpp +++ b/indra/newview/llpathfindingnavmesh.cpp @@ -140,12 +140,17 @@ void LLPathfindingNavMesh::handleNavMeshResult(const LLSD &pContent, U32 pNavMes if ( pContent.has(NAVMESH_DATA_FIELD) ) { const LLSD::Binary &value = pContent.get(NAVMESH_DATA_FIELD).asBinary(); - unsigned int binSize = value.size(); - std::string newStr(reinterpret_cast(&value[0]), binSize); - std::istringstream streamdecomp( newStr ); + // Use new variants of unzip_llsd calls + // unsigned int binSize = value.size(); + // std::string newStr(reinterpret_cast(&value[0]), binSize); + // std::istringstream streamdecomp( newStr ); + // unsigned int decompBinSize = 0; bool valid = false; - U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ; + // Use new variants of unzip_llsd calls + // U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ; + U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, value.data(), value.size() ) ; + // if ( !valid ) { LL_WARNS() << "Unable to decompress the navmesh llsd." << LL_ENDL; diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 0729979208..2fc50132d2 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -169,8 +169,12 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) std::string type = key["type"].asString(); if (type == "my_outfits") { - showOutfitsInventoryPanel(); + showOutfitsInventoryPanel("outfitslist_tab"); } + else if (type == "now_wearing") + { + showOutfitsInventoryPanel("cof_tab"); + } else if (type == "edit_outfit") { showOutfitEditPanel(); @@ -292,7 +296,14 @@ void LLSidepanelAppearance::showOutfitsInventoryPanel() { toggleWearableEditPanel(FALSE); toggleOutfitEditPanel(FALSE); - toggleMyOutfitsPanel(TRUE); + toggleMyOutfitsPanel(TRUE, ""); +} + +void LLSidepanelAppearance::showOutfitsInventoryPanel(const std::string &tab_name) +{ + toggleWearableEditPanel(FALSE); + toggleOutfitEditPanel(FALSE); + toggleMyOutfitsPanel(TRUE, tab_name); } void LLSidepanelAppearance::showOutfitEditPanel() @@ -317,37 +328,42 @@ void LLSidepanelAppearance::showOutfitEditPanel() return; } - toggleMyOutfitsPanel(FALSE); + toggleMyOutfitsPanel(FALSE, ""); toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode toggleOutfitEditPanel(TRUE); } void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch) { - toggleMyOutfitsPanel(FALSE); + toggleMyOutfitsPanel(FALSE, ""); toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode toggleWearableEditPanel(TRUE, wearable, disable_camera_switch); } -void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible) +void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible, const std::string& tab_name) { - if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible) - { - // visibility isn't changing, hence nothing to do - return; - } + if (!mPanelOutfitsInventory + || (mPanelOutfitsInventory->getVisible() == visible && tab_name.empty())) + { + // visibility isn't changing, hence nothing to do + return; + } - mPanelOutfitsInventory->setVisible(visible); + mPanelOutfitsInventory->setVisible(visible); - // *TODO: Move these controls to panel_outfits_inventory.xml - // so that we don't need to toggle them explicitly. - mFilterEditor->setVisible(visible); - mCurrOutfitPanel->setVisible(visible); + // *TODO: Move these controls to panel_outfits_inventory.xml + // so that we don't need to toggle them explicitly. + mFilterEditor->setVisible(visible); + mCurrOutfitPanel->setVisible(visible); - if (visible) - { - mPanelOutfitsInventory->onOpen(LLSD()); - } + if (visible) + { + mPanelOutfitsInventory->onOpen(LLSD()); + if (!tab_name.empty()) + { + mPanelOutfitsInventory->openApearanceTab(tab_name); + } + } } void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch) diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 90025d9619..75c6cc8edf 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -63,7 +63,8 @@ public: void fetchInventory(); void inventoryFetched(); - void showOutfitsInventoryPanel(); + void showOutfitsInventoryPanel(); // last selected + void showOutfitsInventoryPanel(const std::string& tab_name); void showOutfitEditPanel(); void showWearableEditPanel(LLViewerWearable *wearable = NULL, BOOL disable_camera_switch = FALSE); void setWearablesLoading(bool val); @@ -90,7 +91,7 @@ private: void onOpenOutfitButtonClicked(); void onEditAppearanceButtonClicked(); - void toggleMyOutfitsPanel(BOOL visible); + void toggleMyOutfitsPanel(BOOL visible, const std::string& tab_name); void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE); void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 62e2658044..b56979da76 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -819,10 +819,15 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) } } -void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) +// make text chat block in groups not a toggle to prevent accidental unmuting +// void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) +void LLIMSpeakerMgr::allowTextChat(const LLUUID& speaker_id, bool allow) { - LLPointer speakerp = findSpeaker(speaker_id); - if (!speakerp) return; + // Don't test for presence in the group participants list, as the list + // is unreliable and this leads to situations where people can't be + // chat muted at all anymore + // LLPointer speakerp = findSpeaker(speaker_id); + // if (!speakerp) return; std::string url = gAgent.getRegionCapability("ChatSessionRequest"); LLSD data; @@ -831,8 +836,10 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) data["params"] = LLSD::emptyMap(); data["params"]["agent_id"] = speaker_id; data["params"]["mute_info"] = LLSD::emptyMap(); + // make text chat block in groups not a toggle to prevent accidental unmuting //current value represents ability to type, so invert - data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText; + // data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText; + data["params"]["mute_info"]["text"] = !allow; LLCoros::instance().launch("LLIMSpeakerMgr::moderationActionCoro", boost::bind(&LLIMSpeakerMgr::moderationActionCoro, this, url, data)); diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index d1dbf72fe9..0d19bf9fcf 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -297,7 +297,9 @@ public: void updateSpeakers(const LLSD& update); void setSpeakers(const LLSD& speakers); - void toggleAllowTextChat(const LLUUID& speaker_id); + // make text chat block in groups not a toggle to prevent accidental unmuting + // void toggleAllowTextChat(const LLUUID& speaker_id); + void allowTextChat(const LLUUID& speaker_id, bool allow); /** * Mutes/Unmutes avatar for current group voice chat. diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1f2c33557b..9343e9b707 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -131,10 +131,12 @@ #include "llpanelpick.h" #include "llpanelgrouplandmoney.h" #include "llpanelgroupnotices.h" +#include "llparcel.h" #include "llpreview.h" #include "llpreviewscript.h" #include "llproxy.h" #include "llproductinforequest.h" +#include "llqueryflags.h" #include "llselectmgr.h" #include "llsky.h" #include "llstatview.h" @@ -145,6 +147,7 @@ #include "lltoolmgr.h" #include "lltrans.h" #include "llui.h" +#include "lluiusage.h" #include "llurldispatcher.h" #include "llurlentry.h" #include "llslurl.h" @@ -273,7 +276,6 @@ extern std::string gWindowTitle; static bool gGotUseCircuitCodeAck = false; static std::string sInitialOutfit; static std::string sInitialOutfitGender; // "male" or "female" -static boost::signals2::connection sWearablesLoadedCon; static bool gUseCircuitCallbackCalled = false; @@ -2392,28 +2394,26 @@ bool idle_startup() //--------------------------------------------------------------------- if (STATE_INVENTORY_SEND == LLStartUp::getStartupState()) { - // Moved before inventory creation. Otherwise the responses - // from the money balance request and mutelist request - // seem to get lost under certain conditions - // request mute list - LL_INFOS() << "Requesting Mute List" << LL_ENDL; - LLMuteList::getInstance()->requestFromServer(gAgent.getID()); - display_startup(); - // Get L$ and ownership credit information - LL_INFOS() << "Requesting Money Balance" << LL_ENDL; - LLStatusBar::sendMoneyBalanceRequest(); - display_startup(); + // request mute list + LL_INFOS() << "Requesting Mute List" << LL_ENDL; + LLMuteList::getInstance()->requestFromServer(gAgent.getID()); + + // Get L$ and ownership credit information + LL_INFOS() << "Requesting Money Balance" << LL_ENDL; + LLStatusBar::sendMoneyBalanceRequest(); + + display_startup(); + // Moved before inventory creation. // request all group information LL_INFOS("Agent_GroupData") << "GROUPDEBUG: Requesting Agent Data during startup" << LL_ENDL; gAgent.sendAgentDataUpdateRequest(); display_startup(); // - - display_startup(); // Inform simulator of our language preference LLAgentLanguage::update(); + display_startup(); // unpack thin inventory LLSD response = LLLoginInstance::getInstance()->getResponse(); @@ -2592,17 +2592,7 @@ bool idle_startup() LLLandmark::registerCallbacks(msg); display_startup(); - // Moved before inventory creation. Otherwise the responses - // from the money balance request and mutelist request - // seem to get lost under certain conditions - //// request mute list - //LL_INFOS() << "Requesting Mute List" << LL_ENDL; - //LLMuteList::getInstance()->requestFromServer(gAgent.getID()); - //display_startup(); - //// Get L$ and ownership credit information - //LL_INFOS() << "Requesting Money Balance" << LL_ENDL; - //LLStatusBar::sendMoneyBalanceRequest(); - //display_startup(); + // Moved before inventory creation. //// request all group information //LL_INFOS() << "Requesting Agent Data" << LL_ENDL; //gAgent.sendAgentDataUpdateRequest(); @@ -2670,9 +2660,7 @@ bool idle_startup() // on with this install. gSavedSettings.setBOOL("ShowStartLocation", TRUE); - // Open Conversation floater on first login. // [FS Communication UI] - //LLFloaterReg::toggleInstanceOrBringToFront("im_container"); LLFloaterReg::toggleInstanceOrBringToFront("fs_im_container"); // [FS Communication UI] @@ -3131,6 +3119,16 @@ bool idle_startup() gAgentAvatarp->sendHoverHeight(); + // look for parcels we own + send_places_query(LLUUID::null, + LLUUID::null, + "", + DFQ_AGENT_OWNED, + LLParcel::C_ANY, + ""); + + LLUIUsage::instance().clear(); + // FIRE-6643 Display MOTD when login screens are disabled if (gSavedSettings.getBOOL("FSDisableLoginScreens")) { @@ -3617,11 +3615,6 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, } else { - // FIXME SH-3860 - this creates a race condition, where COF - // changes (base outfit link added) after appearance update - // request has been submitted. - sWearablesLoadedCon = gAgentWearables.addLoadedCallback(LLStartUp::saveInitialOutfit); - bool do_copy = true; bool do_append = false; LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); @@ -3640,23 +3633,6 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, gAgentWearables.sendDummyAgentWearablesUpdate(); } -//static -void LLStartUp::saveInitialOutfit() -{ - if (sInitialOutfit.empty()) { - LL_DEBUGS() << "sInitialOutfit is empty" << LL_ENDL; - return; - } - - if (sWearablesLoadedCon.connected()) - { - LL_DEBUGS("Avatar") << "sWearablesLoadedCon is connected, disconnecting" << LL_ENDL; - sWearablesLoadedCon.disconnect(); - } - LL_DEBUGS("Avatar") << "calling makeNewOutfitLinks( \"" << sInitialOutfit << "\" )" << LL_ENDL; - LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false); -} - std::string& LLStartUp::getInitialOutfitName() { return sInitialOutfit; diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index f5b18d7626..4bb76a92da 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -121,9 +121,6 @@ public: static void loadInitialOutfit( const std::string& outfit_folder_name, const std::string& gender_name ); - //save loaded initial outfit into My Outfits category - static void saveInitialOutfit(); - static std::string& getInitialOutfitName(); static std::string getUserId(); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 0ce7258e59..c1fdd85996 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -805,7 +805,20 @@ void LLStatusBar::sendMoneyBalanceRequest() msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_MoneyData); msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); - gAgent.sendReliableMessage(); + + if (gDisconnected) + { + LL_DEBUGS() << "Trying to send message when disconnected, skipping balance request!" << LL_ENDL; + return; + } + if (!gAgent.getRegion()) + { + LL_DEBUGS() << "LLAgent::sendReliableMessage No region for agent yet, skipping balance request!" << LL_ENDL; + return; + } + // Double amount of retries due to this request initially happening during busy stage + // Ideally this should be turned into a capability + gMessageSystem->sendReliable(gAgent.getRegionHost(), LL_DEFAULT_RELIABLE_RETRIES * 2, TRUE, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL); } diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp index 679662829a..35f5c99a9d 100644 --- a/indra/newview/llteleporthistorystorage.cpp +++ b/indra/newview/llteleporthistorystorage.cpp @@ -33,6 +33,8 @@ #include "lldir.h" #include "llteleporthistory.h" #include "llagent.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" // [RLVa:KB] - Checked: 2010-09-03 (RLVa-1.2.1b) #include "rlvactions.h" // [/RLVa:KB] @@ -276,3 +278,23 @@ void LLTeleportHistoryStorage::goToItem(S32 idx) gAgent.teleportViaLocation(mItems[idx].mGlobalPos); } +void LLTeleportHistoryStorage::showItemOnMap(S32 idx) +{ + // Validate specified index. + if (idx < 0 || idx >= (S32)mItems.size()) + { + LL_WARNS() << "Invalid teleport history index (" << idx << ") specified" << LL_ENDL; + dump(); + return; + } + + LLVector3d landmark_global_pos = mItems[idx].mGlobalPos; + + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if (!landmark_global_pos.isExactlyZero() && worldmap_instance) + { + worldmap_instance->trackLocation(landmark_global_pos); + LLFloaterReg::showInstance("world_map", "center"); + } +} + diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h index c646bb7edf..95ca6075d1 100644 --- a/indra/newview/llteleporthistorystorage.h +++ b/indra/newview/llteleporthistorystorage.h @@ -107,6 +107,13 @@ public: */ void goToItem(S32 idx); + /** + * Show specific item on map. + * + * The item is specified by its index (starting from 0). + */ + void showItemOnMap(S32 idx); + //private: // [RLVa:KB] - Checked: 2010-09-03 (RLVa-1.2.1b) | Added: RLVa-1.2.1b protected: diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index d3470351c5..457226d2f2 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -125,6 +125,11 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal data.mURLExternal = mNotification->getURLOpenExternally(); } + if((*it).has("width")) + { + data.mWidth = (*it)["width"].asInteger(); + } + mButtonData.push_back(data); option_index++; } @@ -165,15 +170,29 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal // Calc total width of buttons S32 button_width = 0; S32 sp = font->getWidth(std::string("OO")); + S32 btn_total_width = 0; + S32 default_size_btns = 0; for( S32 i = 0; i < num_options; i++ ) - { + { S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD; - button_width = llmax( w, button_width ); + if (mButtonData[i].mWidth > w) + { + btn_total_width += mButtonData[i].mWidth; + } + else + { + button_width = llmax(w, button_width); + default_size_btns++; + } } - S32 btn_total_width = button_width; + if( num_options > 1 ) { - btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD); + btn_total_width = btn_total_width + (button_width * default_size_btns) + ((num_options - 1) * BTN_HPAD); + } + else + { + btn_total_width = llmax(btn_total_width, button_width); } // Message: create text box using raw string, as text has been structure deliberately @@ -278,7 +297,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLineEditor->setText(edit_text_contents); std::string notif_name = mNotification->getName(); - if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name)) + if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name) || ("CreateLandmarkFolder" == notif_name)) { mLineEditor->setPrevalidate(&LLTextValidate::validateASCII); } @@ -339,7 +358,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal if(btn) { btn->setName(options[i].first); - btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT )); + btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, (mButtonData[i].mWidth == 0) ? button_width : mButtonData[i].mWidth, BTN_HEIGHT )); btn->setLabel(options[i].second); btn->setFont(font); @@ -354,7 +373,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal btn->setFocus(TRUE); } } - button_left += button_width + BTN_HPAD; + button_left += ((mButtonData[i].mWidth == 0) ? button_width : mButtonData[i].mWidth) + BTN_HPAD; } if(defaultText) diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 9b4e054bf1..71b0bc32b5 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -82,9 +82,16 @@ private: struct ButtonData { + ButtonData() + // Linux compile fix + // : mWidth(0) + : mWidth(0), mButton(nullptr) + {} + LLButton* mButton; std::string mURL; U32 mURLExternal; + S32 mWidth; }; std::vector mButtonData; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 8aac9796a4..e509b94c71 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -412,9 +412,9 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) if (mIsScriptDialog) { // we are using default width for script buttons so we can determinate button_rows - //to get a number of rows we divide the required width of the buttons to button_panel_width - S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); - //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; + // to get a number of rows we divide the required width of the buttons to button_panel_width + // buttons.size() is reduced by -2 due to presence of ignore button which is calculated independently a bit lower + S32 button_rows = llceil(F32(buttons.size() - 2) * (BUTTON_WIDTH + h_pad) / (button_panel_width + h_pad)); //reserve one row for the ignore_btn button_rows++; //calculate required panel height for scripdialog notification. diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp new file mode 100644 index 0000000000..6b1a373beb --- /dev/null +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -0,0 +1,214 @@ +/** + * @file llurlfloaterdispatchhandler.cpp + * @brief Handles URLFloater generic message from server + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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 "llurlfloaterdispatchhandler.h" + +#include "llfloaterreg.h" +#include "llfloaterhowto.h" +#include "llfloaterwebcontent.h" +#include "llsdserialize.h" +#include "llviewercontrol.h" +#include "llviewergenericmessage.h" +#include "llweb.h" + +// Example: +// llOpenFloater("guidebook", "http://page.com", []); + +// values specified by server side's dispatcher +// for llopenfloater +const std::string MESSAGE_URL_FLOATER("URLFloater"); +const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL" +const std::string VALUE_OPEN_URL("OpenURL"); +const std::string KEY_DATA("action_data"); +const std::string KEY_FLOATER("floater_title"); // name of the floater, not title +const std::string KEY_URL("floater_url"); +const std::string KEY_PARAMS("floater_params"); + +// Supported floaters +const std::string FLOATER_GUIDEBOOK("guidebook"); +const std::string FLOATER_HOW_TO("how_to"); // alias for guidebook +const std::string FLOATER_WEB_CONTENT("web_content"); + +// All arguments are palceholders! Server side will need to add validation first. +// Web content universal argument +const std::string KEY_TRUSTED_CONTENT("trusted_content"); + +// Guidebook specific arguments +const std::string KEY_WIDTH("width"); +const std::string KEY_HEGHT("height"); +const std::string KEY_CAN_CLOSE("can_close"); +const std::string KEY_TITLE("title"); + +// web_content specific arguments +const std::string KEY_SHOW_PAGE_TITLE("show_page_title"); +const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed + + +LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler; + +LLUrlFloaterDispatchHandler::LLUrlFloaterDispatchHandler() +{ +} + +LLUrlFloaterDispatchHandler::~LLUrlFloaterDispatchHandler() +{ +} + +void LLUrlFloaterDispatchHandler::registerInDispatcher() +{ + if (!gGenericDispatcher.isHandlerPresent(MESSAGE_URL_FLOATER)) + { + gGenericDispatcher.addHandler(MESSAGE_URL_FLOATER, &sUrlDispatchhandler); + } +} + +//virtual +bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings) +{ + // invoice - transaction id + + LLSD message; + sparam_t::const_iterator it = strings.begin(); + + if (it != strings.end()) + { + const std::string& llsdRaw = *it++; + std::istringstream llsdData(llsdRaw); + if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) + { + LL_WARNS("URLFloater") << "Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; + return false; + } + } + + // At the moment command_params is a placeholder and code treats it as map + // Once server side adds argument validation this will be either a map or an array + std::string floater; + LLSD command_params; + std::string url; + + if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL) + { + LLSD &action_data = message[KEY_DATA]; + if (action_data.isMap()) + { + floater = action_data[KEY_FLOATER].asString(); + command_params = action_data[KEY_PARAMS]; + url = action_data[KEY_URL].asString(); + } + } + else if (message.has(KEY_FLOATER)) + { + floater = message[KEY_FLOATER].asString(); + command_params = message[KEY_PARAMS]; + url = message[KEY_URL].asString(); + } + else + { + LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with unexpected data format: " << message << LL_ENDL; + return false; + } + + if (url.find("://") == std::string::npos) + { + // try unescaping + url = LLURI::unescape(url); + } + + LLFloaterWebContent::Params params; + params.url = url; + + if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO) + { + LL_DEBUGS("URLFloater") << "Opening how_to floater with parameters: " << message << LL_ENDL; + if (command_params.isMap()) // by default is undefines + { + params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; + + // Script's side argument list can't include other lists, neither + // there is a LLRect type, so expect just width and height + if (command_params.has(KEY_WIDTH) && command_params.has(KEY_HEGHT)) + { + LLRect rect(0, command_params[KEY_HEGHT].asInteger(), command_params[KEY_WIDTH].asInteger(), 0); + params.preferred_media_size.setValue(rect); + } + } + + // Some locations will have customized guidebook, which this function easists for + // only one instance of guidebook can exist at a time, so if this command arrives, + // we need to close previous guidebook then reopen it. + + LLFloater* instance = LLFloaterReg::findInstance("guidebook"); + if (instance) + { + instance->closeHostedFloater(); + } + + LLFloaterReg::toggleInstanceOrBringToFront("guidebook", params); + + if (command_params.isMap()) + { + LLFloater* instance = LLFloaterReg::findInstance("guidebook"); + if (command_params.has(KEY_CAN_CLOSE)) + { + instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); + } + if (command_params.has(KEY_TITLE)) + { + instance->setTitle(command_params[KEY_TITLE].asString()); + } + } + } + else if (floater == FLOATER_WEB_CONTENT) + { + LL_DEBUGS("URLFloater") << "Opening web_content floater with parameters: " << message << LL_ENDL; + if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params + { + params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; + params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true; + params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true; + } + LLFloaterReg::showInstance("web_content", params); + } + else + { + LL_DEBUGS("URLFloater") << "Unknow floater with parameters: " << message << LL_ENDL; + if (LLFloaterReg::isRegistered(floater)) + { + // A valid floater + LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL; + } + else + { + // A valid message, but no such flaoter + LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL; + } + } + + return true; +} diff --git a/indra/newview/llurlfloaterdispatchhandler.h b/indra/newview/llurlfloaterdispatchhandler.h new file mode 100644 index 0000000000..1dff52c66f --- /dev/null +++ b/indra/newview/llurlfloaterdispatchhandler.h @@ -0,0 +1,49 @@ +/** + * @file llurlfloaterdispatchhandler.h + * @brief Handles URLFloater generic message from server + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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_LLURLFLOATERDISPATCHHANDLER_H +#define LL_LLURLFLOATERDISPATCHHANDLER_H + +#include "lldispatcher.h" + +class LLUrlFloaterDispatchHandler : public LLDispatchHandler +{ +public: + LOG_CLASS(LLUrlFloaterDispatchHandler); + + LLUrlFloaterDispatchHandler(); + virtual ~LLUrlFloaterDispatchHandler(); + + virtual bool operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override; + + static void registerInDispatcher(); + +private: + static LLUrlFloaterDispatchHandler sUrlDispatchhandler; +}; + +#endif // LL_LLURLFLOATERDISPATCHHANDLER_H + diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index b494549e16..9c857bbcd9 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -79,6 +79,7 @@ #include "llslurl.h" #include "llstartup.h" // [RLVa:KB] - Checked: 2015-12-27 (RLVa-1.5.0) +#include "llvisualeffect.h" #include "rlvactions.h" #include "rlvcommon.h" // [/RLVa:KB] @@ -216,15 +217,15 @@ static bool handleAvatarHoverOffsetChanged(const LLSD& newvalue) bool handleSetShaderChanged(const LLSD& newvalue) // { -// [RLVa:KB] - @setenv - if ( (!RlvActions::canChangeEnvironment()) && (LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) && (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ) +// [RLVa:KB] - @setenv and @setsphere + if ( (RlvActions::isRlvEnabled()) && (!RlvActions::canChangeEnvironment() || (LLVfxManager::instance().hasEffect(EVisualEffect::RlvSphere))) && + (LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))&& (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ) { gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE); return true; } // [/RLVa:KB] - // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache gBumpImageList.destroyGL(); gBumpImageList.restoreGL(); @@ -521,21 +522,9 @@ static bool handleRenderLocalLightsChanged(const LLSD& newvalue) return true; } -// [RLVa:KB] - @setsphere -static bool handleWindLightAtmosShadersChanged(const LLSD& newvalue) -{ - LLRenderTarget::sUseFBO = newvalue.asBoolean() && LLPipeline::sUseDepthTexture; - handleSetShaderChanged(LLSD()); - return true; -} -// [/RLVa:KB] - static bool handleRenderDeferredChanged(const LLSD& newvalue) { -// LLRenderTarget::sUseFBO = newvalue.asBoolean(); -// [RLVa:KB] - @setsphere - LLRenderTarget::sUseFBO = newvalue.asBoolean() || (gSavedSettings.getBOOL("WindLightUseAtmosShaders") && LLPipeline::sUseDepthTexture); -// [/RLVa:KB] + LLRenderTarget::sUseFBO = newvalue.asBoolean(); if (gPipeline.isInit()) { LLPipeline::refreshCachedSettings(); @@ -557,10 +546,7 @@ static bool handleRenderDeferredChanged(const LLSD& newvalue) // static bool handleRenderBumpChanged(const LLSD& newval) { -// LLRenderTarget::sUseFBO = newval.asBoolean(); -// [RLVa:KB] - @setsphere - LLRenderTarget::sUseFBO = newval.asBoolean() || (gSavedSettings.getBOOL("WindLightUseAtmosShaders") && LLPipeline::sUseDepthTexture); -// [/RLVa:KB] + LLRenderTarget::sUseFBO = newval.asBoolean(); if (gPipeline.isInit()) { gPipeline.updateRenderBump(); @@ -1099,10 +1085,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderAvatarCloth")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -// gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); -// [RLVa:KB] - @setsphere - gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleWindLightAtmosShadersChanged, _2)); -// [/RLVa:KB] + gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 99b7e090b9..e23d990184 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -541,6 +541,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); + gAgent.sheduleTeleportIM(); gTextureList.mForceResetTextureStats = TRUE; if(!gSavedSettings.getBOOL("FSDisableTeleportScreens")) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index de0a59d108..393b62d61a 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -34,6 +34,7 @@ #include "llcompilequeue.h" #include "llfasttimerview.h" #include "llfloaterabout.h" +#include "llfloateraddpaymentmethod.h" #include "llfloaterauction.h" #include "llfloaterautoreplacesettings.h" #include "llfloateravatar.h" @@ -57,6 +58,7 @@ #include "llfloaterchatvoicevolume.h" #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" +#include "llfloatercreatelandmark.h" #include "llfloaterdeleteprefpreset.h" #include "llfloaterdestinations.h" #include "llfloatereditextdaycycle.h" @@ -74,6 +76,7 @@ #include "llfloatergroups.h" #include "llfloaterhelpbrowser.h" #include "llfloaterhoverheight.h" +#include "llfloaterhowto.h" #include "llfloaterhud.h" #include "llfloaterimagepreview.h" #include "llfloaterimsession.h" @@ -245,6 +248,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterAboutUtil::registerFloater(); LLFloaterReg::add("block_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("add_payment_method", "floater_add_payment_method.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -277,6 +281,7 @@ void LLViewerFloaterReg::registerFloaters() // [FS communication UI] LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("add_landmark", "floater_create_landmark.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("delete_pref_preset", "floater_delete_pref_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -443,7 +448,7 @@ void LLViewerFloaterReg::registerFloaters() //LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create); - LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create); + LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 0e20f9fc54..34c3b7c5ee 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1654,6 +1654,7 @@ void remove_inventory_category( LLNotificationsUtil::add("CannotRemoveProtectedCategories"); return; } + // [UDP-Msg] if (AISAPI::isAvailable()) { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f988ac3cd5..ed2cc3e4ad 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -68,6 +68,7 @@ #include "llfloaterimcontainer.h" #include "llfloaterland.h" #include "llfloaterimnearbychat.h" +#include "llfloaterlandholdings.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" #include "llfloaterpay.h" @@ -233,11 +234,15 @@ const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents" LLMenuGL* gAttachSubMenu = NULL; LLMenuGL* gDetachSubMenu = NULL; LLMenuGL* gTakeOffClothes = NULL; +LLMenuGL* gDetachAvatarMenu = NULL; +LLMenuGL* gDetachHUDAvatarMenu = NULL; LLContextMenu* gAttachScreenPieMenu = NULL; LLContextMenu* gAttachPieMenu = NULL; LLContextMenu* gAttachBodyPartPieMenus[9]; LLContextMenu* gDetachPieMenu = NULL; LLContextMenu* gDetachScreenPieMenu = NULL; +LLContextMenu* gDetachAttSelfMenu = NULL; +LLContextMenu* gDetachHUDAttSelfMenu = NULL; LLContextMenu* gDetachBodyPartPieMenus[9]; // Pie menu @@ -532,6 +537,9 @@ void init_menus() gMenuAttachmentOther = LLUICtrlFactory::createFromFile( "menu_attachment_other.xml", gMenuHolder, registry); + gDetachHUDAttSelfMenu = gMenuHolder->getChild("Detach Self HUD", true); + gDetachAttSelfMenu = gMenuHolder->getChild("Detach Self", true); + gMenuLand = LLUICtrlFactory::createFromFile( "menu_land.xml", gMenuHolder, registry); @@ -642,6 +650,9 @@ void init_menus() gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE); + gDetachAvatarMenu = gMenuHolder->getChild("Avatar Detach", true); + gDetachHUDAvatarMenu = gMenuHolder->getChild("Avatar Detach HUD", true); + // Don't display the Memory console menu if the feature is turned off LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild("Memory", TRUE); if (memoryMenu) @@ -825,6 +836,7 @@ class LLAdvancedCheckHUDInfo : public view_listener_t }; +// Keep this for menu check item ////////////// // FLYING // ////////////// @@ -836,6 +848,7 @@ class LLAdvancedAgentFlyingInfo : public view_listener_t return gAgent.getFlying(); } }; +// /////////////////////// @@ -4615,6 +4628,35 @@ bool enable_sitdown_self() // return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying(); } +class LLSelfToggleSitStand : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + if (isAgentAvatarValid()) + { + if (gAgentAvatarp->isSitting()) + { + gAgent.standUp(); + } + else + { + gAgent.sitDown(); + } + } + return true; + } +}; + +bool enable_sit_stand() +{ + return enable_sitdown_self() || enable_standup_self(); +} + +bool enable_fly_land() +{ + return gAgent.getFlying() || LLAgent::enableFlying(); +} + // Force sit -KC class FSSelfForceSit : public view_listener_t { @@ -6184,7 +6226,7 @@ void handle_buy_or_take() { LLStringUtil::format_map_t args; args["AMOUNT"] = llformat("%d", total_price); - LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "BuyingCosts", args ), total_price ); + LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price ); } } else @@ -6213,13 +6255,6 @@ bool tools_visible_take_object() return !is_selection_buy_not_take(); } -bool enable_how_to_visible(const LLSD& param) -{ - LLFloaterWebContent::Params p; - p.target = "__help_how_to"; - return LLFloaterReg::instanceVisible("how_to", p); -} - class LLToolsEnableBuyOrTake : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -7205,6 +7240,16 @@ class LLWorldSetHomeLocation : public view_listener_t } }; +class LLWorldLindenHome : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url"); + LLWeb::loadURL(url); + return true; + } +}; + class LLWorldTeleportHome : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -7456,10 +7501,7 @@ class LLWorldCreateLandmark : public view_listener_t return true; // [/RLVa:KB] - // FIRE-817: Separate place details floater - //LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "create_landmark")); - FSFloaterPlaceDetails::showPlaceDetails(LLSD().with("type", "create_landmark")); - // + LLFloaterReg::showInstance("add_landmark"); return true; } @@ -7892,6 +7934,11 @@ void handle_edit_outfit() LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); } +void handle_now_wearing() +{ + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "now_wearing")); +} + void handle_edit_shape() { LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape")); @@ -9730,15 +9777,7 @@ class LLToggleHowTo : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLFloaterWebContent::Params p; - std::string url = gSavedSettings.getString("HowToHelpURL"); - p.url = LLWeb::expandURLSubstitutions(url, LLSD()); - p.show_chrome = false; - p.target = "__help_how_to"; - p.show_page_title = false; - p.preferred_media_size = LLRect(0, 460, 335, 0); - - LLFloaterReg::toggleInstanceOrBringToFront("how_to", p); + LLFloaterReg::toggleInstanceOrBringToFront("guidebook"); return true; } }; @@ -10978,49 +11017,46 @@ class LLWorldEnvSettings : public view_listener_t if (event_name == "sunrise") { - // FIRE-29926 - allow manually selected environments to have a user defined transition time. - // LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE); + // FIRE-29926 - allow manually selected environments to have a user defined transition time. + //LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_INSTANT); + //LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setManualEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE); - // LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().updateEnvironment(); + // defocusEnvFloaters(); } else if (event_name == "noon") { - // FIRE-29926 - allow manually selected environments to have a user defined transition time. - // LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY); + // FIRE-29926 - allow manually selected environments to have a user defined transition time. + //LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_INSTANT); + //LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setManualEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY); - // LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().updateEnvironment(); + // defocusEnvFloaters(); } else if (event_name == "sunset") { - // FIRE-29926 - allow manually selected environments to have a user defined transition time. - // LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET); + // FIRE-29926 - allow manually selected environments to have a user defined transition time. + //LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_INSTANT); + //LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setManualEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET); - // - LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().updateEnvironment(); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); // defocusEnvFloaters(); } else if (event_name == "midnight") { - // FIRE-29926 - allow manually selected environments to have a user defined transition time. - // LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT); + // FIRE-29926 - allow manually selected environments to have a user defined transition time. + //LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_INSTANT); + //LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setManualEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT); - // - LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().updateEnvironment(); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); // defocusEnvFloaters(); } else if (event_name == "region") { LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().updateEnvironment(); + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } else if (event_name == "pause_clouds") @@ -11193,6 +11229,20 @@ public: } }; +class LLUpdateMembershipLabel : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + const std::string label_str = LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText"); + gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str); + + // OpenSim check + //return true; + return LLGridManager::instance().isInSecondLife(); + // + } +}; + void handle_voice_morphing_subscribe() { LLWeb::loadURL(LLTrans::getString("voice_morphing_url")); @@ -11540,6 +11590,8 @@ void initialize_menus() view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts"); + view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel"); + // [FS communication UI] //enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); @@ -11549,7 +11601,8 @@ void initialize_menus() // Agent commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying)); - enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying)); + enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land)); + enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying)); // Keep this commit.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2)); commit.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2)); commit.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2)); @@ -11565,6 +11618,7 @@ void initialize_menus() view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight"); view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics"); commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar)); + commit.add("NowWearing", boost::bind(&handle_now_wearing)); commit.add("EditOutfit", boost::bind(&handle_edit_outfit)); commit.add("EditShape", boost::bind(&handle_edit_shape)); commit.add("HoverHeight", boost::bind(&handle_hover_height)); @@ -11609,9 +11663,9 @@ void initialize_menus() view_listener_t::addMenu(new FSCheckCameraFloater(), "View.CheckCameraFloater"); // + // Keep this for menu check item // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); - //Communicate Nearby chat // [FS Communication UI] //view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat"); @@ -11634,6 +11688,8 @@ void initialize_menus() view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome"); view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway"); view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb"); + view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome"); + view_listener_t::addMenu(new LLWorldGetAway(), "World.GetAway"); //[SJ FIRE-2177] view_listener_t::addMenu(new LLWorldGetBusy(), "World.GetBusy"); //[SJ FIRE-2177] view_listener_t::addMenu(new LLWorldSetAutorespond(), "World.SetAutorespond"); @@ -11712,7 +11768,6 @@ void initialize_menus() // Help menu // most items use the ShowFloater method view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo"); - enable.add("Help.HowToVisible", boost::bind(&enable_how_to_visible, _2)); // Advanced menu view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole"); @@ -11918,11 +11973,15 @@ void initialize_menus() view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState"); // Self context menu + view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand"); + enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand)); + // Keep this for menu check item view_listener_t::addMenu(new LLSelfStandUp(), "Self.StandUp"); enable.add("Self.EnableStandUp", boost::bind(&enable_standup_self)); view_listener_t::addMenu(new LLSelfSitDown(), "Self.SitDown"); enable.add("Self.EnableSitDown", boost::bind(&enable_sitdown_self)); enable.add("Self.ShowSitDown", boost::bind(&show_sitdown_self)); + // view_listener_t::addMenu(new FSSelfForceSit(), "Self.ForceSit"); //KC enable.add("Self.EnableForceSit", boost::bind(&enable_forcesit_self)); //KC view_listener_t::addMenu(new FSSelfCheckForceSit(), "Self.getForceSit"); //KC diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 85388a8149..b13e38e561 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -224,10 +224,14 @@ extern LLContextMenu *gMenuMuteParticle; extern LLMenuGL* gAttachSubMenu; extern LLMenuGL* gDetachSubMenu; extern LLMenuGL* gTakeOffClothes; +extern LLMenuGL* gDetachAvatarMenu; +extern LLMenuGL* gDetachHUDAvatarMenu; extern LLContextMenu* gAttachScreenPieMenu; extern LLContextMenu* gDetachScreenPieMenu; +extern LLContextMenu* gDetachHUDAttSelfMenu; extern LLContextMenu* gAttachPieMenu; extern LLContextMenu* gDetachPieMenu; +extern LLContextMenu* gDetachAttSelfMenu; extern LLContextMenu* gAttachBodyPartPieMenus[9]; extern LLContextMenu* gDetachBodyPartPieMenus[9]; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 5b8c6e5849..d8dd0cea82 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -867,10 +867,7 @@ void upload_done_callback( if(!(can_afford_transaction(expected_upload_cost))) { - LLStringUtil::format_map_t args; - args["NAME"] = data->mAssetInfo.getName(); - args["AMOUNT"] = llformat("%d", expected_upload_cost); - LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("UploadingCosts", args), expected_upload_cost ); + LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost ); is_balance_sufficient = FALSE; } else if(region) @@ -1004,10 +1001,7 @@ void upload_new_resource( if (balance < uploadInfo->getExpectedUploadCost()) { // insufficient funds, bail on this upload - LLStringUtil::format_map_t args; - args["NAME"] = uploadInfo->getName(); - args["AMOUNT"] = llformat("%d", uploadInfo->getExpectedUploadCost()); - LLBuyCurrencyHTML::openCurrencyFloater(LLTrans::getString("UploadingCosts", args), uploadInfo->getExpectedUploadCost()); + LLBuyCurrencyHTML::openCurrencyFloater("", uploadInfo->getExpectedUploadCost()); return; } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d37d84b188..52540d59b0 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -126,7 +126,6 @@ #include "rlvui.h" // [/RLVa:KB] -#include // #include #include "llnotificationmanager.h" // @@ -859,7 +858,6 @@ void response_group_invitation_coro(std::string url, LLUUID group_id, bool notif LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL; if (notify_and_update) { - LLNotificationsUtil::add("JoinGroupSuccess"); gAgent.sendAgentDataUpdateRequest(); LLGroupMgr::getInstance()->clearGroupData(group_id); @@ -6339,6 +6337,15 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) // notification was specified using the new mechanism, so we can just handle it here std::string notificationID; msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID); + + //SL-13824 skip notification when both joining a group and leaving a group + //remove this after server stops sending these messages + if (notificationID == "JoinGroupSuccess" || + notificationID == "GroupDepart") + { + return true; + } + if (!LLNotifications::getInstance()->templateExists(notificationID)) { return false; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index de86f2f106..3423ac0837 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1802,6 +1802,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use } parcel->setParcelEnvironmentVersion(parcel_environment_version); LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL; + // Notify anything that wants to know when the agent changes parcels gAgent.changeParcels(); instance->mTeleportInProgress = FALSE; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 2f1eb06ecf..adf09bed17 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -62,6 +62,7 @@ #include "llsdutil.h" #include "llcorehttputil.h" #include "llvoicevivox.h" +#include "lluiusage.h" namespace LLStatViewer { @@ -580,6 +581,8 @@ void send_viewer_stats(bool include_preferences) fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets; fail["missing_updater"] = (S32) LLAppViewer::instance()->isUpdaterMissing(); + body["ui"] = LLUIUsage::instance().asLLSD(); + body["stats"]["voice"] = LLVoiceVivoxStats::getInstance()->read(); // Misc stats, two strings and two ints diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index af5a1c7250..acb78bedc2 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -7200,10 +7200,15 @@ void LLPickInfo::fetchResults() // [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay) if ( (RlvActions::hasBehaviour(RLV_BHVR_SETOVERLAY)) && (hit_object) && (!hit_object->isHUDAttachment()) ) { - if (auto* pOverlayEffect = LLVfxManager::instance().getEffect(EVisualEffect::RlvOverlay)) + std::list effects; + LLVfxManager::instance().getEffects(effects); + for (const LLVisualEffect* pEffect : effects) { - if (pOverlayEffect->hitTest(mMousePt)) + if (pEffect->getEnabled() && static_cast(pEffect)->hitTest(mMousePt)) + { hit_object = nullptr; + break; + } } } // [/RLVa:KB] diff --git a/indra/newview/llvisualeffect.cpp b/indra/newview/llvisualeffect.cpp index af68a57413..3a4594ff09 100644 --- a/indra/newview/llvisualeffect.cpp +++ b/indra/newview/llvisualeffect.cpp @@ -70,35 +70,43 @@ LLVector4 LLTweenableValueLerp::get() LLVfxManager::LLVfxManager() { - } bool LLVfxManager::addEffect(LLVisualEffect* pEffectInst) { - if (m_Effects.end() != m_Effects.find(pEffectInst)) + // Effect IDs can be reused across effects but should be unique for all effect instances sharing the same effect code + auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [pEffectInst](const LLVisualEffect* pEffect) { return pEffect->getCode() == pEffectInst->getCode() && pEffect->getId() == pEffectInst->getId(); }); + llassert(m_Effects.end() == itEffect); + if (m_Effects.end() != itEffect) return false; - m_Effects.insert(pEffectInst); - + m_Effects.insert(std::upper_bound(m_Effects.begin(), m_Effects.end(), pEffectInst, cmpEffect), pEffectInst); return true; } -LLVisualEffect* LLVfxManager::getEffect(const LLUUID& idEffect) const +LLVisualEffect* LLVfxManager::getEffect(EVisualEffect eCode, const LLUUID& idEffect) const { - auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [&idEffect](const LLVisualEffect* pEffect) { return pEffect->getId() == idEffect; }); + auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [eCode, &idEffect](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode && pEffect->getId() == idEffect; }); return (m_Effects.end() != itEffect) ? *itEffect : nullptr; } -LLVisualEffect* LLVfxManager::getEffect(EVisualEffect eCode) const +bool LLVfxManager::getEffects(std::list& effectList, std::function fnFilter) { - // NOTE: returns the first found but there could be more - auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [eCode](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode; }); - return (m_Effects.end() != itEffect) ? *itEffect : nullptr; + effectList.clear(); + + auto itEffect = boost::make_filter_iterator(fnFilter, m_Effects.begin(), m_Effects.end()), + endEffect = boost::make_filter_iterator(fnFilter, m_Effects.end(), m_Effects.end()); + while (itEffect != endEffect) + { + effectList.push_back(*itEffect++); + } + + return effectList.size(); } -bool LLVfxManager::removeEffect(const LLUUID& idEffect) +bool LLVfxManager::removeEffect(EVisualEffect eCode, const LLUUID& idEffect) { - auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [&idEffect](const LLVisualEffect* pEffect) { return pEffect->getId() == idEffect; }); + auto itEffect = std::find_if(m_Effects.begin(), m_Effects.end(), [eCode, &idEffect](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode && pEffect->getId() == idEffect; }); if (m_Effects.end() == itEffect) return false; @@ -109,32 +117,54 @@ bool LLVfxManager::removeEffect(const LLUUID& idEffect) void LLVfxManager::runEffect(EVisualEffect eCode, LLVisualEffectParams* pParams) { - // *TODO-Catz: once we're done, check whether iterating over the entire list still has negliable impact - auto pred = [eCode](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode; }; - - auto itEffect = boost::make_filter_iterator(pred, m_Effects.begin(), m_Effects.end()), - endEffect = boost::make_filter_iterator(pred, m_Effects.end(), m_Effects.end()); - for (; itEffect != endEffect; ++itEffect) - { - if (pParams) - pParams->step(itEffect == endEffect); - (*itEffect)->run(pParams); - } + runEffect([eCode](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode; }, pParams); } void LLVfxManager::runEffect(EVisualEffectType eType, LLVisualEffectParams* pParams) { - // *TODO-Catz: once we're done, check whether iterating over the entire list still has negliable impact - auto pred = [eType](const LLVisualEffect* pEffect) { return pEffect->getType() == eType; }; + runEffect([eType](const LLVisualEffect* pEffect) { return pEffect->getType() == eType; }, pParams); +} - auto itEffect = boost::make_filter_iterator(pred, m_Effects.begin(), m_Effects.end()), - endEffect = boost::make_filter_iterator(pred, m_Effects.end(), m_Effects.end()); - for (; itEffect != endEffect; ++itEffect) +void LLVfxManager::runEffect(std::function predicate, LLVisualEffectParams* pParams) +{ + // *TODO-Catz: once we're done, check whether iterating over the entire list still has negliable impact + auto itEffect = boost::make_filter_iterator(predicate, m_Effects.begin(), m_Effects.end()), + endEffect = boost::make_filter_iterator(predicate, m_Effects.end(), m_Effects.end()); + while (itEffect != endEffect) { - if (pParams) - pParams->step(itEffect == endEffect); - (*itEffect)->run(pParams); + LLVisualEffect* pEffect = *itEffect++; + if (pEffect->getEnabled()) + { + if (pParams) + pParams->step(itEffect == endEffect); + pEffect->run(pParams); + } } } +void LLVfxManager::updateEffect(LLVisualEffect* pEffect, bool fEnabled, U32 nPriority) +{ + llassert(m_Effects.end() != std::find(m_Effects.begin(), m_Effects.end(), pEffect)); + + if ( (pEffect->getEnabled() != fEnabled) || (pEffect->getPriority() != nPriority) ) + { + pEffect->setEnabled(fEnabled); + pEffect->setPriority(nPriority); + std::sort(m_Effects.begin(), m_Effects.end(), cmpEffect); + } +} + +// static +bool LLVfxManager::cmpEffect(const LLVisualEffect* pLHS, const LLVisualEffect* pRHS) +{ + if (pLHS && pRHS) + { + // Sort by code, then priority, then memory address + return (pLHS->getCode() == pRHS->getCode()) ? (pLHS->getPriority() == pRHS->getPriority() ? pLHS < pRHS + : pLHS->getPriority() > pRHS->getPriority()) + : pLHS->getCode() < pRHS->getCode(); + } + return (pLHS); +} + // ============================================================================ diff --git a/indra/newview/llvisualeffect.h b/indra/newview/llvisualeffect.h index 41d10bda90..ab8f1e5aa0 100644 --- a/indra/newview/llvisualeffect.h +++ b/indra/newview/llvisualeffect.h @@ -73,6 +73,7 @@ struct LLShaderEffectParams : LLVisualEffectParams class LLVisualEffect { + friend class LLVfxManager; public: LLVisualEffect(LLUUID id, EVisualEffect eCode, EVisualEffectType eType) : m_id(id), m_eCode(eCode), m_eType(eType) @@ -80,12 +81,17 @@ public: virtual ~LLVisualEffect() {} EVisualEffect getCode() const { return m_eCode;} + bool getEnabled() const { return m_fEnabled; } const LLUUID& getId() const { return m_id;} U32 getPriority() const { return m_nPriority; } EVisualEffectType getType() const { return m_eType;} + void setEnabled(bool enable) { m_fEnabled = enable; } virtual void run(const LLVisualEffectParams* pParams) = 0; +protected: + void setPriority(U32 priority) { m_nPriority = priority; } + /* * Member variables */ @@ -93,7 +99,8 @@ protected: LLUUID m_id; EVisualEffect m_eCode; EVisualEffectType m_eType; - U32 m_nPriority; + bool m_fEnabled = true; + U32 m_nPriority = 0; }; // ============================================================================ @@ -160,20 +167,34 @@ protected: */ public: bool addEffect(LLVisualEffect* pEffectInst); - LLVisualEffect* getEffect(const LLUUID& idEffect) const; - template T* getEffect(const LLUUID& idEffect) const { return dynamic_cast(getEffect(idEffect)); } - LLVisualEffect* getEffect(EVisualEffect eCode) const; - template T* getEffect(EVisualEffect eCode) const { return dynamic_cast(getEffect(eCode)); } - bool removeEffect(const LLUUID& idEffect); + LLVisualEffect* getEffect(EVisualEffect eCode, const LLUUID& idEffect) const; + template T* getEffect(const LLUUID& idEffect) const { return dynamic_cast(getEffect(T::EffectCode, idEffect)); } + bool getEffects(std::list& effectList, std::function fnFilter); + template bool getEffects(std::list& effectList) { return getEffects(effectList, [](const LLVisualEffect* pEffect) { return pEffect->getCode() == T::EffectCode; }); } + bool hasEffect(EVisualEffect eCode) const; + bool removeEffect(EVisualEffect eCode, const LLUUID& idEffect); + template bool removeEffect(const LLUUID& idEffect) { return removeEffect(T::EffectCode, idEffect); } void runEffect(EVisualEffect eCode, LLVisualEffectParams* pParams = nullptr); void runEffect(EVisualEffectType eType, LLVisualEffectParams* pParams = nullptr); + void updateEffect(LLVisualEffect* pEffect, bool fEnabled, U32 nPriority); protected: + void runEffect(std::function fnFilter, LLVisualEffectParams* pParams); + static bool cmpEffect(const LLVisualEffect* pLHS, const LLVisualEffect* pRHS); /* * Member variables */ protected: - std::set m_Effects; + std::vector m_Effects; }; // ============================================================================ +// Inlined member functions +// + +inline bool LLVfxManager::hasEffect(EVisualEffect eCode) const +{ + return m_Effects.end() != std::find_if(m_Effects.begin(), m_Effects.end(), [eCode](const LLVisualEffect* pEffect) { return pEffect->getCode() == eCode; }); +} + +// ============================================================================ diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 434d3d587d..113e6a053d 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -583,6 +583,8 @@ BOOL LLVOAvatarSelf::buildMenus() if (gDetachBodyPartPieMenus[i]) { gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] ); + gDetachAttSelfMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]); + gDetachAvatarMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]); // FIRE-7893: "Detach" sub-menu on inspect menu without function gInspectSelfDetachMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] ); } @@ -613,7 +615,8 @@ BOOL LLVOAvatarSelf::buildMenus() LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); gDetachPieMenu->addChild(item); - + gDetachAttSelfMenu->addChild(LLUICtrlFactory::create(item_params)); + gDetachAvatarMenu->addChild(LLUICtrlFactory::create(item_params)); // FIRE-7893: "Detach" sub-menu on inspect menu without function gInspectSelfDetachMenu->addChild(item); @@ -622,6 +625,7 @@ BOOL LLVOAvatarSelf::buildMenus() } } } + // Pie menu for (S32 i = 0; i < PIE_MAX_SLICES; i++) @@ -759,6 +763,8 @@ BOOL LLVOAvatarSelf::buildMenus() item_params.on_enable.parameter = iter->first; item = LLUICtrlFactory::create(item_params); gDetachScreenPieMenu->addChild(item); + gDetachHUDAttSelfMenu->addChild(LLUICtrlFactory::create(item_params)); + gDetachHUDAvatarMenu->addChild(LLUICtrlFactory::create(item_params)); // FIRE-7893: "Detach" sub-menu on inspect menu without function gInspectSelfDetachScreenMenu->addChild(LLUICtrlFactory::create(item_params)); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index f463ae8677..2f10015fa1 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -749,7 +749,7 @@ void LLVivoxVoiceClient::voiceControlCoro() gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this)); gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this)); - if (mTuningMode) + if (mTuningMode) { performMicTuning(); } diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 11fa19cc76..3c2fc1d29e 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1687,6 +1687,11 @@ public: virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const { + if (LLApp::isExiting()) + { + return; + } + if (!input["body"].has("agent-id") || !input["body"].has("sim-ip-and-port") || !input["body"].has("seed-capability")) diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 3a657780b5..32c2a4a2fe 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -201,6 +201,8 @@ LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 //LL_INFOS("WorldMap") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LL_INFOS("MAPURL") << "fetching map tile from " << imageurl << LL_ENDL; + img->setBoostLevel(LLGLTexture::BOOST_MAP); // Return the smart pointer diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ad0db03658..8e64265bf2 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1176,6 +1176,14 @@ void LLPipeline::updateRenderDeferred() (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); exoPostProcess::instance().ExodusRenderPostUpdate(); // Import Vignette from Exodus + +// [RLVa:KB] - @setsphere + if (!sRenderDeferred && RlvActions::hasBehaviour(RLV_BHVR_SETSPHERE) && WindLightUseAtmosShaders) + { + LLRenderTarget::sUseFBO = true; + LLPipeline::sUseDepthTexture = true; + } +// [/RLVa:KB] } // static @@ -4597,7 +4605,7 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate) gGL.loadMatrix(gGLModelView); LLGLSLShader::bindNoShader(); // [RLVa:KB] - @setsphere - if (LLPipeline::RenderDeferred || !LLRenderTarget::sUseFBO || !LLPipeline::sUseDepthTexture) + if (LLPipeline::sRenderDeferred || !LLRenderTarget::sUseFBO || !LLPipeline::sUseDepthTexture) { doOcclusion(camera); } diff --git a/indra/newview/qtoolalign.cpp b/indra/newview/qtoolalign.cpp index d959da87f5..e22e7215d0 100644 --- a/indra/newview/qtoolalign.cpp +++ b/indra/newview/qtoolalign.cpp @@ -24,7 +24,6 @@ const F32 MANIPULATOR_SIZE = 5.0f; const F32 MANIPULATOR_SELECT_SIZE = 20.0f; -const F32 FUDGE = 0.001f; // because of SL precision/rounding QToolAlign::QToolAlign() : LLTool(std::string("Align")) @@ -45,12 +44,13 @@ BOOL QToolAlign::handleMouseDown(S32 x, S32 y, MASK mask) { gViewerWindow->pickAsync(x, y, mask, pickCallback); } - + return TRUE; } void QToolAlign::pickCallback(const LLPickInfo& pick_info) { + LLSelectMgr* select_mgr = LLSelectMgr::getInstance(); LLViewerObject* object = pick_info.getObject(); if (object) @@ -63,31 +63,30 @@ void QToolAlign::pickCallback(const LLPickInfo& pick_info) if (pick_info.mKeyMask & MASK_SHIFT) { // If object not selected, select it - if ( !object->isSelected() ) + if (!object->isSelected()) { - LLSelectMgr::getInstance()->selectObjectAndFamily(object); + select_mgr->selectObjectAndFamily(object); } else { - LLSelectMgr::getInstance()->deselectObjectAndFamily(object); + select_mgr->deselectObjectAndFamily(object); } } else { - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->selectObjectAndFamily(object); + select_mgr->deselectAll(); + select_mgr->selectObjectAndFamily(object); } - } else { if (pick_info.mKeyMask != MASK_SHIFT) { - LLSelectMgr::getInstance()->deselectAll(); + select_mgr->deselectAll(); } } - LLSelectMgr::getInstance()->promoteSelectionToRoot(); + select_mgr->promoteSelectionToRoot(); } void QToolAlign::handleSelect() @@ -182,7 +181,7 @@ BOOL QToolAlign::handleHover(S32 x, S32 y, MASK mask) { mForce = TRUE; } - + gViewerWindow->setCursor(UI_CURSOR_ARROW); return findSelectedManipulator(x, y); } @@ -235,15 +234,16 @@ void render_cone_bbox(LLBBox bbox) // should this be cached in the selection manager? yes. LLBBox get_selection_axis_aligned_bbox() { - LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + LLSelectMgr* select_mgr = LLSelectMgr::getInstance(); + LLBBox selection_bbox = select_mgr->getBBoxOfSelection(); LLVector3 position = selection_bbox.getPositionAgent(); - + LLBBox axis_aligned_bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3()); axis_aligned_bbox.addPointLocal(LLVector3()); // cycle over the nodes in selection - for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin(); - selection_iter != LLSelectMgr::getInstance()->getSelection()->end(); + for (LLObjectSelection::iterator selection_iter = select_mgr->getSelection()->begin(); + selection_iter != select_mgr->getSelection()->end(); ++selection_iter) { LLSelectNode *select_node = *selection_iter; @@ -257,7 +257,6 @@ LLBBox get_selection_axis_aligned_bbox() } } - return axis_aligned_bbox; } @@ -274,7 +273,7 @@ void QToolAlign::computeManipulatorSize() { F32 distance = dist_vec(gAgentCamera.getCameraPositionAgent(), mBBox.getCenterAgent()); - if (distance > FUDGE) + if (distance > F_ALMOST_ZERO) { // range != zero F32 fraction_of_fov = MANIPULATOR_SIZE / camera->getViewHeightInPixels(); @@ -304,7 +303,7 @@ void QToolAlign::renderManipulators() computeManipulatorSize(); LLVector3 bbox_center = mBBox.getCenterAgent(); LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal(); - + for (S32 axis = VX; axis <= VZ; axis++) { for (F32 direction = -1.0f; direction <= 1.0f; direction += 2.0f) @@ -355,7 +354,8 @@ BOOL QToolAlign::canAffectSelection() // and it does not have any sitting agents. In case of editing linked parts, // the object itself has to be modifiable. static LLCachedControl edit_linked_parts(gSavedSettings, "EditLinkedParts"); - BOOL can_scale = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0; + LLSelectMgr* select_mgr = LLSelectMgr::getInstance(); + BOOL can_scale = select_mgr->getSelection()->getObjectCount() != 0; if (can_scale) { struct f : public LLSelectedObjectFunctor @@ -365,7 +365,7 @@ BOOL QToolAlign::canAffectSelection() return (!edit_linked_parts || objectp->permModify()) && objectp->permMove() && !objectp->isSeat(); } } func; - can_scale = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func); + can_scale = select_mgr->getSelection()->applyToObjects(&func); } return can_scale; } @@ -399,9 +399,9 @@ BOOL bbox_overlap(LLBBox bbox1, LLBBox bbox2) LLVector3 half_extent = (bbox1.getExtentLocal() + bbox2.getExtentLocal()) / 2.0f; - return ((fabs(delta.mV[VX]) < half_extent.mV[VX] - FUDGE) && - (fabs(delta.mV[VY]) < half_extent.mV[VY] - FUDGE) && - (fabs(delta.mV[VZ]) < half_extent.mV[VZ] - FUDGE)); + return ((fabs(delta.mV[VX]) < half_extent.mV[VX] - F_ALMOST_ZERO) && + (fabs(delta.mV[VY]) < half_extent.mV[VY] - F_ALMOST_ZERO) && + (fabs(delta.mV[VZ]) < half_extent.mV[VZ] - F_ALMOST_ZERO)); } // used to sort bboxes before packing @@ -430,15 +430,17 @@ public: void QToolAlign::align() { + LLSelectMgr* select_mgr = LLSelectMgr::getInstance(); + // no linkset parts, please - LLSelectMgr::getInstance()->promoteSelectionToRoot(); - + select_mgr->promoteSelectionToRoot(); + std::vector > objects; std::map, LLBBox > original_bboxes; - + // cycle over the nodes in selection and collect them into an array - for (LLObjectSelection::root_iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - selection_iter != LLSelectMgr::getInstance()->getSelection()->root_end(); + for (LLObjectSelection::root_iterator selection_iter = select_mgr->getSelection()->root_begin(); + selection_iter != select_mgr->getSelection()->root_end(); ++selection_iter) { LLSelectNode *select_node = *selection_iter; @@ -448,7 +450,7 @@ void QToolAlign::align() if (object) { LLVector3 position = object->getPositionAgent(); - + LLBBox bbox = LLBBox(position, LLQuaternion(), LLVector3(), LLVector3()); bbox.addPointLocal(LLVector3()); @@ -463,7 +465,7 @@ void QToolAlign::align() LLViewerObject* child = *it; bbox.addBBoxAgent(child->getBoundingBoxAgent()); } - + objects.push_back(object); original_bboxes[object] = bbox; } @@ -486,7 +488,7 @@ void QToolAlign::align() LLBBox target_bbox = mBBox; LLVector3 target_corner = target_bbox.getCenterAgent() - direction * target_bbox.getExtentLocal() / 2.0f; - + LLViewerObject* object = objects[i]; LLBBox this_bbox = original_bboxes[object]; @@ -573,7 +575,6 @@ void QToolAlign::align() object->setPosition(new_position); } - - - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); + + select_mgr->sendMultipleUpdate(UPD_POSITION); } diff --git a/indra/newview/qtoolalign.h b/indra/newview/qtoolalign.h index ab198bd429..ca3da4fa56 100644 --- a/indra/newview/qtoolalign.h +++ b/indra/newview/qtoolalign.h @@ -13,8 +13,7 @@ class LLViewerObject; class LLPickInfo; class LLToolSelectRect; -class QToolAlign -: public LLTool, public LLSingleton +class QToolAlign : public LLTool, public LLSingleton { LLSINGLETON(QToolAlign); virtual ~QToolAlign(); @@ -30,16 +29,16 @@ public: static void pickCallback(const LLPickInfo& pick_info); private: - void align(); - void computeManipulatorSize(); - void renderManipulators(); - BOOL findSelectedManipulator(S32 x, S32 y); - - LLBBox mBBox; - F32 mManipulatorSize; - S32 mHighlightedAxis; - F32 mHighlightedDirection; - BOOL mForce; + void align(); + void computeManipulatorSize(); + void renderManipulators(); + BOOL findSelectedManipulator(S32 x, S32 y); + + LLBBox mBBox; + F32 mManipulatorSize; + S32 mHighlightedAxis; + F32 mHighlightedDirection; + BOOL mForce; }; #endif // Q_QTOOLALIGN_H diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index ceefa1c25a..c0e19fe324 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -39,7 +39,7 @@ const S32 RLV_VERSION_BUILD_COMPAT = 0; // Implementation version const S32 RLVa_VERSION_MAJOR = 2; const S32 RLVa_VERSION_MINOR = 4; -const S32 RLVa_VERSION_PATCH = 0; +const S32 RLVa_VERSION_PATCH = 1; const S32 RLVa_IMPL_ID = 13; // Uncomment before a final release diff --git a/indra/newview/rlveffects.cpp b/indra/newview/rlveffects.cpp index 6da6a15825..70e9030144 100644 --- a/indra/newview/rlveffects.cpp +++ b/indra/newview/rlveffects.cpp @@ -40,6 +40,7 @@ RlvOverlayEffect::RlvOverlayEffect(const LLUUID& idRlvObj) , m_fBlockTouch(false) , m_Color(LLColor3(c_DefaultColor)) { + m_fEnabled = false; } RlvOverlayEffect::~RlvOverlayEffect() @@ -50,7 +51,7 @@ RlvOverlayEffect::~RlvOverlayEffect() // static ERlvCmdRet RlvOverlayEffect::onAlphaValueChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvOverlayEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_nAlpha = (newValue) ? boost::get(newValue.value()) : c_DefaultAlpha; } @@ -60,7 +61,7 @@ ERlvCmdRet RlvOverlayEffect::onAlphaValueChanged(const LLUUID& idRlvObj, const b // static ERlvCmdRet RlvOverlayEffect::onBlockTouchValueChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvOverlayEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_fBlockTouch = (newValue) ? boost::get(newValue.value()) : false; } @@ -69,7 +70,7 @@ ERlvCmdRet RlvOverlayEffect::onBlockTouchValueChanged(const LLUUID& idRlvObj, co // static ERlvCmdRet RlvOverlayEffect::onColorValueChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvOverlayEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_Color = LLColor3( (newValue) ? boost::get(newValue.value()).mV : c_DefaultColor); } @@ -79,7 +80,7 @@ ERlvCmdRet RlvOverlayEffect::onColorValueChanged(const LLUUID& idRlvObj, const b // static ERlvCmdRet RlvOverlayEffect::onTextureChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvOverlayEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvOverlayEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { if (newValue) pEffect->setImage(boost::get(newValue.value())); @@ -189,7 +190,7 @@ RlvSphereEffect::~RlvSphereEffect() // static ERlvCmdRet RlvSphereEffect::onModeChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_eMode = (ESphereMode)((newValue) ? boost::get(newValue.value()) : c_SphereDefaultMode); } @@ -199,7 +200,7 @@ ERlvCmdRet RlvSphereEffect::onModeChanged(const LLUUID& idRlvObj, const boost::o // static ERlvCmdRet RlvSphereEffect::onOriginChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_eOrigin = (ESphereOrigin)((newValue) ? boost::get(newValue.value()) : c_SphereDefaultOrigin); } @@ -209,7 +210,7 @@ ERlvCmdRet RlvSphereEffect::onOriginChanged(const LLUUID& idRlvObj, const boost: // static ERlvCmdRet RlvSphereEffect::onColorChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { LLVector4 vecColor = (newValue) ? LLVector4(boost::get(newValue.value()), 1.0f) : LLVector4(c_SphereDefaultColor); if (!pEffect->m_nTweenDuration) @@ -223,7 +224,7 @@ ERlvCmdRet RlvSphereEffect::onColorChanged(const LLUUID& idRlvObj, const boost:: // static ERlvCmdRet RlvSphereEffect::onDistMinChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { float nDistanceMin = (newValue) ? boost::get(newValue.value()) : c_SphereDefaultDistance; if (!pEffect->m_nTweenDuration) @@ -237,7 +238,7 @@ ERlvCmdRet RlvSphereEffect::onDistMinChanged(const LLUUID& idRlvObj, const boost // static ERlvCmdRet RlvSphereEffect::onDistMaxChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { float nDistanceMax = (newValue) ? boost::get(newValue.value()) : c_SphereDefaultDistance; if (!pEffect->m_nTweenDuration) @@ -251,7 +252,7 @@ ERlvCmdRet RlvSphereEffect::onDistMaxChanged(const LLUUID& idRlvObj, const boost // static ERlvCmdRet RlvSphereEffect::onDistExtendChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_eDistExtend = (ESphereDistExtend)((newValue) ? boost::get(newValue.value()) : c_SphereDefaultDistanceExtend); } @@ -261,7 +262,7 @@ ERlvCmdRet RlvSphereEffect::onDistExtendChanged(const LLUUID& idRlvObj, const bo // static ERlvCmdRet RlvSphereEffect::onParamsChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { LLVector4 params = LLVector4((newValue) ? boost::get(newValue.value()).mV : c_SphereDefaultColor); if (!pEffect->m_nTweenDuration) @@ -275,7 +276,7 @@ ERlvCmdRet RlvSphereEffect::onParamsChanged(const LLUUID& idRlvObj, const boost: // static ERlvCmdRet RlvSphereEffect::onTweenDurationChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { pEffect->m_nTweenDuration = (newValue) ? boost::get(newValue.value()) : 0; } @@ -285,7 +286,7 @@ ERlvCmdRet RlvSphereEffect::onTweenDurationChanged(const LLUUID& idRlvObj, const // static ERlvCmdRet RlvSphereEffect::onValueMinChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { float nValueMin = (newValue) ? boost::get(newValue.value()) : c_SphereDefaultAlpha;; if (!pEffect->m_nTweenDuration) @@ -299,7 +300,7 @@ ERlvCmdRet RlvSphereEffect::onValueMinChanged(const LLUUID& idRlvObj, const boos // static ERlvCmdRet RlvSphereEffect::onValueMaxChanged(const LLUUID& idRlvObj, const boost::optional newValue) { - if (RlvSphereEffect* pEffect = dynamic_cast(LLVfxManager::instance().getEffect(idRlvObj))) + if (RlvSphereEffect* pEffect = LLVfxManager::instance().getEffect(idRlvObj)) { float nValueMax = (newValue) ? boost::get(newValue.value()) : c_SphereDefaultAlpha; if (!pEffect->m_nTweenDuration) diff --git a/indra/newview/rlveffects.h b/indra/newview/rlveffects.h index 0b55b2a500..d4378da88f 100644 --- a/indra/newview/rlveffects.h +++ b/indra/newview/rlveffects.h @@ -35,6 +35,7 @@ public: RlvOverlayEffect(const LLUUID& idRlvObj); ~RlvOverlayEffect(); + static const EVisualEffect EffectCode = EVisualEffect::RlvOverlay; public: bool hitTest(const LLCoordGL& ptMouse) const; void run(const LLVisualEffectParams*) override; @@ -70,6 +71,7 @@ public: RlvSphereEffect(const LLUUID& idRlvObj); ~RlvSphereEffect(); + static const EVisualEffect EffectCode = EVisualEffect::RlvSphere; public: void run(const LLVisualEffectParams* pParams) override; static ERlvCmdRet onModeChanged(const LLUUID& idRlvObj, const boost::optional newValue); diff --git a/indra/newview/rlvfloaters.cpp b/indra/newview/rlvfloaters.cpp index b0b089e138..92a5e4efb3 100644 --- a/indra/newview/rlvfloaters.cpp +++ b/indra/newview/rlvfloaters.cpp @@ -19,6 +19,7 @@ #include "llagent.h" #include "llappearancemgr.h" #include "llavatarnamecache.h" +#include #include "llclipboard.h" #include "llcombobox.h" #include "llinventoryfunctions.h" @@ -733,7 +734,7 @@ static const char s_strRlvConsoleDisabled[] = "RLVa is disabled"; static const char s_strRlvConsoleInvalid[] = "Invalid command"; RlvFloaterConsole::RlvFloaterConsole(const LLSD& sdKey) - : LLFloater(sdKey), m_pOutputText(nullptr) + : LLFloater(sdKey) { } @@ -743,11 +744,14 @@ RlvFloaterConsole::~RlvFloaterConsole() BOOL RlvFloaterConsole::postBuild() { - LLLineEditor* pInputEdit = getChild("console_input"); - pInputEdit->setEnableLineHistory(true); - pInputEdit->setCommitCallback(boost::bind(&RlvFloaterConsole::onInput, this, _1, _2)); - pInputEdit->setFocus(true); - pInputEdit->setCommitOnFocusLost(false); + m_pInputEdit = getChild("console_input"); + m_pInputEdit->setCommitCallback(boost::bind(&RlvFloaterConsole::onInput, this, _1, _2)); + m_pInputEdit->setTextExpandedCallback(boost::bind(&RlvFloaterConsole::reshapeLayoutPanel, this)); + m_pInputEdit->setFocus(true); + m_pInputEdit->setCommitOnFocusLost(false); + + m_pInputPanel = getChild("input_panel"); + m_nInputEditPad = m_pInputPanel->getRect().getHeight() - m_pInputEdit->getRect().getHeight(); m_pOutputText = getChild("console_output"); m_pOutputText->appendText(s_strRlvConsolePrompt, false); @@ -769,12 +773,12 @@ void RlvFloaterConsole::addCommandReply(const std::string& strCommand, const std void RlvFloaterConsole::onInput(LLUICtrl* pCtrl, const LLSD& sdParam) { - LLLineEditor* pInputEdit = static_cast(pCtrl); + LLChatEntry* pInputEdit = static_cast(pCtrl); std::string strInput = pInputEdit->getText(); LLStringUtil::trim(strInput); m_pOutputText->appendText(strInput, false); - pInputEdit->clear(); + pInputEdit->setText(LLStringUtil::null); if (!rlv_handler_t::isEnabled()) { @@ -831,4 +835,9 @@ void RlvFloaterConsole::onInput(LLUICtrl* pCtrl, const LLSD& sdParam) m_pOutputText->appendText(s_strRlvConsolePrompt, true); } +void RlvFloaterConsole::reshapeLayoutPanel() +{ + m_pInputPanel->reshape(m_pInputPanel->getRect().getWidth(), m_pInputEdit->getRect().getHeight() + m_nInputEditPad, FALSE); +} + // ============================================================================ diff --git a/indra/newview/rlvfloaters.h b/indra/newview/rlvfloaters.h index f29fa92483..2ca4adc904 100644 --- a/indra/newview/rlvfloaters.h +++ b/indra/newview/rlvfloaters.h @@ -1,21 +1,20 @@ -/** +/** * * Copyright (c) 2009-2011, Kitty Barnett - * - * The source code in this file is provided to you under the terms of the + * + * The source code in this file is provided to you under the terms of the * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt - * + * * By copying, modifying or distributing this software, you acknowledge that - * you have read and understood your obligations described above, and agree to + * you have read and understood your obligations described above, and agree to * abide by those obligations. - * + * */ -#ifndef RLV_FLOATERS_H -#define RLV_FLOATERS_H +#pragma once #include "llfloater.h" @@ -25,7 +24,9 @@ // ============================================================================ // Foward declarations // +class LLChatEntry; class LLComboBox; +class LLLayoutPanel; class LLTextEditor; // ============================================================================ @@ -150,21 +151,23 @@ private: public: BOOL postBuild() override; void onClose(bool fQuitting) override; - + /* * Member functions */ protected: void addCommandReply(const std::string& strCommand, const std::string& strReply); void onInput(LLUICtrl* ctrl, const LLSD& param); + void reshapeLayoutPanel(); /* * Member variables */ protected: - LLTextEditor* m_pOutputText; + LLTextEditor* m_pOutputText = nullptr; + LLLayoutPanel* m_pInputPanel = nullptr; + LLChatEntry* m_pInputEdit = nullptr; + int m_nInputEditPad = 0; }; // ============================================================================ - -#endif // RLV_FLOATERS_H diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 19a8d49739..fd92632ec0 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -2065,14 +2065,44 @@ void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour eBhv } } -// Handles: @setoverlay=n|y toggles +// Handles: @setoverlay=n|y template<> template<> -void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour eBhvr, bool fHasBhvr) +ERlvCmdRet RlvBehaviourHandler::onCommand(const RlvCommand& rlvCmd, bool& fRefCount) { - if (fHasBhvr) - LLVfxManager::instance().addEffect(new RlvOverlayEffect(gRlvHandler.getCurrentObject())); - else - LLVfxManager::instance().removeEffect(gRlvHandler.getCurrentObject()); + ERlvCmdRet eRet = RlvBehaviourGenericHandler::onCommand(rlvCmd, fRefCount); + if ( (RLV_RET_SUCCESS == eRet) && (!rlvCmd.isModifier()) ) + { + if (gRlvHandler.hasBehaviour(rlvCmd.getObjectID(), rlvCmd.getBehaviourType())) + { + LLVfxManager::instance().addEffect(new RlvOverlayEffect(gRlvHandler.getCurrentObject())); + } + else + { + LLVfxManager::instance().removeEffect(gRlvHandler.getCurrentObject()); + } + } + + // Refresh overlay effects according to object hierarchy + std::list effects; + if (LLVfxManager::instance().getEffects(effects)) + { + auto itActiveEffect = std::find_if(effects.begin(), effects.end(), [](const LLVisualEffect* pEffect) { return pEffect->getEnabled(); }); + if (effects.end() == itActiveEffect) + { + // If nothing is active just pick the first one to activate + itActiveEffect = effects.begin(); + } + + const LLUUID idActiveRootObj = (effects.end() != itActiveEffect) ? Rlv::getObjectRootId((*itActiveEffect)->getId()) : LLUUID::null; + for (LLVisualEffect* pEffect : effects) + { + bool isActive = (idActiveRootObj.isNull() && pEffect == effects.front()) || (Rlv::getObjectRootId(pEffect->getId()) == idActiveRootObj); + int nPriority = (isActive) ? 256 - Rlv::getObjectLinkNumber(pEffect->getId()) : pEffect->getPriority(); + LLVfxManager::instance().updateEffect(pEffect, isActive, nPriority); + } + } + + return eRet; } // Handles: @setsphere=n|y @@ -2086,22 +2116,28 @@ ERlvCmdRet RlvBehaviourHandler::onCommand(const RlvCommand& ERlvCmdRet eRet = RlvBehaviourGenericHandler::onCommand(rlvCmd, fRefCount); if ( (RLV_RET_SUCCESS == eRet) && (!rlvCmd.isModifier()) ) { - // If we're not using deferred but are using Windlight shaders we need to force use of FBO and depthmap texture - if ( (!LLPipeline::RenderDeferred) && (LLPipeline::WindLightUseAtmosShaders) && (!LLPipeline::sUseDepthTexture) ) - { - LLRenderTarget::sUseFBO = true; - LLPipeline::sUseDepthTexture = true; - - gPipeline.releaseGLBuffers(); - gPipeline.createGLBuffers(); - gPipeline.resetVertexBuffers(); - LLViewerShaderMgr::instance()->setShaders(); - } - if (gRlvHandler.hasBehaviour(rlvCmd.getObjectID(), rlvCmd.getBehaviourType())) + { + Rlv::forceAtmosphericShadersIfAvailable(); + + // If we're not using deferred but are using Windlight shaders we need to force use of FBO and depthmap texture + if ( (!LLPipeline::sRenderDeferred) && (LLPipeline::WindLightUseAtmosShaders) && (!LLPipeline::sUseDepthTexture) ) + { + LLRenderTarget::sUseFBO = true; + LLPipeline::sUseDepthTexture = true; + + gPipeline.releaseGLBuffers(); + gPipeline.createGLBuffers(); + gPipeline.resetVertexBuffers(); + LLViewerShaderMgr::instance()->setShaders(); + } + LLVfxManager::instance().addEffect(new RlvSphereEffect(rlvCmd.getObjectID())); + } else - LLVfxManager::instance().removeEffect(gRlvHandler.getCurrentObject()); + { + LLVfxManager::instance().removeEffect(gRlvHandler.getCurrentObject()); + } } return eRet; } @@ -2418,11 +2454,10 @@ void RlvBehaviourToggleHandler::onCommandToggle(ERlvBehaviour e } } - // Don't allow toggling "Atmopsheric Shaders" through the debug settings under @setenv=n - gSavedSettings.getControl("WindLightUseAtmosShaders")->setHiddenFromSettingsEditor(fHasBhvr); - if (fHasBhvr) { + Rlv::forceAtmosphericShadersIfAvailable(); + // Usurp the 'edit' environment for RLVa locking so TPV tools like quick prefs and phototools are automatically locked out as well // (these needed per-feature awareness of RLV in the previous implementation which often wasn't implemented) LLEnvironment* pEnv = LLEnvironment::getInstance(); diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 3ca2a4d725..f633d12770 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -17,9 +17,11 @@ #include "llviewerprecompiledheaders.h" #include "llappearancemgr.h" #include "llattachmentsmgr.h" +#include "llfeaturemanager.h" #include "llgesturemgr.h" #include "llnotificationsutil.h" #include "llviewerobjectlist.h" +#include "pipeline.h" // FIRE-4453 bridge detached by the RLV command @remattach=force #include "fslslbridge.h" @@ -223,16 +225,16 @@ RlvBehaviourDictionary::RlvBehaviourDictionary() addEntry(new RlvBehaviourGenericToggleProcessor("camunlock", RlvBehaviourInfo::BHVR_SYNONYM | RlvBehaviourInfo::BHVR_DEPRECATED)); // Overlay - RlvBehaviourInfo* pSetOverlayBhvr = new RlvBehaviourGenericToggleProcessor("setoverlay"); + RlvBehaviourInfo* pSetOverlayBhvr = new RlvBehaviourProcessor("setoverlay"); pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayAlpha, typeid(float), "alpha", &RlvOverlayEffect::onAlphaValueChanged); pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTexture, typeid(LLUUID), "texture", &RlvOverlayEffect::onTextureChanged); pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTint, typeid(LLVector3), "tint", &RlvOverlayEffect::onColorValueChanged); pSetOverlayBhvr->addModifier(ERlvLocalBhvrModifier::OverlayTouch, typeid(LLVector3), "touch", &RlvOverlayEffect::onBlockTouchValueChanged); addEntry(pSetOverlayBhvr); - addEntry(new RlvForceProcessor("setoverlay_tween", RlvBehaviourInfo::BHVR_EXPERIMENTAL)); + addEntry(new RlvForceProcessor("setoverlay_tween")); // Sphere - RlvBehaviourInfo* pSetSphereBhvr = new RlvBehaviourProcessor("setsphere", RlvBehaviourInfo::BHVR_EXPERIMENTAL); + RlvBehaviourInfo* pSetSphereBhvr = new RlvBehaviourProcessor("setsphere"); pSetSphereBhvr->addModifier(ERlvLocalBhvrModifier::SphereMode, typeid(int), "mode", &RlvSphereEffect::onModeChanged); pSetSphereBhvr->addModifier(ERlvLocalBhvrModifier::SphereOrigin, typeid(int), "origin", &RlvSphereEffect::onOriginChanged); pSetSphereBhvr->addModifier(ERlvLocalBhvrModifier::SphereColor, typeid(LLVector3), "color", &RlvSphereEffect::onColorChanged); @@ -2044,3 +2046,40 @@ std::string rlvGetLastParenthesisedText(const std::string& strText, std::string: } // ========================================================================= +// Various helper functions +// + +namespace Rlv +{ + void forceAtmosphericShadersIfAvailable() + { + if ( (LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) && (!LLPipeline::WindLightUseAtmosShaders) ) + { + // Triggers handleSetShaderChanged() which will do the actual work for us + gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE); + } + } + + int getObjectLinkNumber(const LLUUID& idObj) + { + const LLViewerObject* pObj = gObjectList.findObject(idObj); + const LLViewerObject* pRootObj = (pObj) ? pObj->getRootEdit() : nullptr; + if ( (!pRootObj) || (pRootObj->getChildren().empty()) ) + return 0; + else if (pRootObj == pObj) + return 1; + return 2 + std::distance(pRootObj->getChildren().begin(), std::find(pRootObj->getChildren().begin(), pRootObj->getChildren().end(), pObj)); + } + + const LLUUID& getObjectRootId(const LLUUID& idObj) + { + if (const LLViewerObject* pObj = gObjectList.findObject(idObj)) + { + pObj = pObj->getRootEdit(); + return pObj->getID(); + } + return idObj; + } +} + +// ========================================================================= diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 1577510c01..c36cde75b0 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -689,6 +689,14 @@ ERlvAttachGroupType rlvAttachGroupFromString(const std::string& strGroup); std::string rlvGetFirstParenthesisedText(const std::string& strText, std::string::size_type* pidxMatch = NULL); std::string rlvGetLastParenthesisedText(const std::string& strText, std::string::size_type* pidxStart = NULL); +namespace Rlv +{ + void forceAtmosphericShadersIfAvailable(); + + int getObjectLinkNumber(const LLUUID& idObj); + const LLUUID& getObjectRootId(const LLUUID& idObj); +} + // ============================================================================ // Inlined class member functions // diff --git a/indra/newview/skins/ansastorm/colors.xml b/indra/newview/skins/ansastorm/colors.xml index e093b9e68c..1e740bf20c 100644 --- a/indra/newview/skins/ansastorm/colors.xml +++ b/indra/newview/skins/ansastorm/colors.xml @@ -1187,6 +1187,9 @@ + diff --git a/indra/newview/skins/ansastorm/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/ansastorm/textures/widgets/TextField_Search_Highlight.png new file mode 100644 index 0000000000..3aa8ccf8cb Binary files /dev/null and b/indra/newview/skins/ansastorm/textures/widgets/TextField_Search_Highlight.png differ diff --git a/indra/newview/skins/ansastorm/themes/blood/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/ansastorm/themes/blood/textures/widgets/TextField_Search_Highlight.png new file mode 100644 index 0000000000..a467d8f8a4 Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/blood/textures/widgets/TextField_Search_Highlight.png differ diff --git a/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml b/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml index 7b343fc296..44ae95b14e 100644 --- a/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml +++ b/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml @@ -1184,6 +1184,9 @@ + diff --git a/indra/newview/skins/ansastorm/themes/classic_brown/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/ansastorm/themes/classic_brown/textures/widgets/TextField_Search_Highlight.png new file mode 100644 index 0000000000..47bb60389e Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/classic_brown/textures/widgets/TextField_Search_Highlight.png differ diff --git a/indra/newview/skins/ansastorm/themes/ectoplasma/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/ansastorm/themes/ectoplasma/textures/widgets/TextField_Search_Highlight.png new file mode 100644 index 0000000000..32c5c75382 Binary files /dev/null and b/indra/newview/skins/ansastorm/themes/ectoplasma/textures/widgets/TextField_Search_Highlight.png differ diff --git a/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml index 5f4656f7c8..efc8e108cf 100644 --- a/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/de/panel_main_inventory.xml @@ -100,6 +100,7 @@ + diff --git a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml index b1abe688bd..7f7234bc43 100644 --- a/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/ansastorm/xui/en/panel_main_inventory.xml @@ -496,6 +496,7 @@ layout="topleft" left="4" max_length_chars="300" + highlight_text_field="true" name="inventory search editor" tool_tip="Type in one or more words to search for, separated by '+' " top_pad="4" @@ -532,7 +533,7 @@ -