diff --git a/autobuild.xml b/autobuild.xml index eacf11fb0f..a8203bb643 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -244,9 +244,9 @@ archive hash - 471b0b350955152fd87518575057dfc4 + 322dd6c45c384d454ae14ef127984a4e url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60326/566593/bugsplat-1.0.7.542667-darwin64-542667.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65457/612879/bugsplat-1.0.7.546418-darwin64-546418.tar.bz2 name darwin64 @@ -256,9 +256,9 @@ archive hash - 70e8bf46145c4cbae6f93e8b70ba5499 + 010a0e73c0fddaa2316411803fad8e69 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60320/566541/bugsplat-3.6.0.4.542667-windows-542667.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65456/612876/bugsplat-3.6.0.8.546418-windows-546418.tar.bz2 name windows @@ -268,16 +268,16 @@ archive hash - a73696e859fad3f19f835740815a2bd3 + 7e8530762e7b50663708a888c23b8780 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60321/566542/bugsplat-3.6.0.4.542667-windows64-542667.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65455/612874/bugsplat-3.6.0.8.546418-windows64-546418.tar.bz2 name windows64 version - 1.0.7.542667 + 3.6.0.8.546418 colladadom @@ -580,9 +580,9 @@ archive hash - e145f8ea99a21712434e0e868d1885dc + cc26af2ebfa241891caca829a6e46b88 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/62333/588183/dullahan-1.7.0.202006240858_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-544091.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65005/607316/dullahan-1.7.0.202008031101_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-546064.tar.bz2 name darwin64 @@ -592,9 +592,9 @@ archive hash - fdbbbfc377e28cba664f2b1c54ea6086 + 4e5b9e2fe65d94e30a4f3d831c767199 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/62331/588162/dullahan-1.7.0.202006241556_81.3.10_gb223419_chromium-81.0.4044.138-windows-544091.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65004/607304/dullahan-1.7.0.202008031759_81.3.10_gb223419_chromium-81.0.4044.138-windows-546064.tar.bz2 name windows @@ -604,16 +604,16 @@ archive hash - d85a32d905b199534e8feafa34b28e39 + 6f7bf7f915f3d75dbdad08a2d41ca74e url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/62332/588168/dullahan-1.7.0.202006241556_81.3.10_gb223419_chromium-81.0.4044.138-windows64-544091.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65003/607308/dullahan-1.7.0.202008031800_81.3.10_gb223419_chromium-81.0.4044.138-windows64-546064.tar.bz2 name windows64 version - 1.7.0.202006240858_81.3.10_gb223419_chromium-81.0.4044.138 + 1.7.0.202008031800_81.3.10_gb223419_chromium-81.0.4044.138 elfio @@ -748,9 +748,9 @@ archive hash - dc4c9122de8bf77f34cfc8227d10a272 + 89c37441a806ed80c0102d380eec6fd0 url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59038/554626/fmodstudio-2.00.07.541681-darwin64-541681.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65400/612632/fmodstudio-2.00.11.546392-darwin64-546392.tar.bz2 name darwin64 @@ -760,9 +760,9 @@ archive hash - c491bdc1690f3d920c66be509ccc6ef2 + 5283050c22d31877cd9e0afbe6feb9fc url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59039/554632/fmodstudio-2.00.07.541681-linux-541681.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65398/612630/fmodstudio-2.00.11.546392-linux-546392.tar.bz2 name linux @@ -772,9 +772,9 @@ archive hash - ae75cdb1cc9da824c9e270bf97bfdd6c + 5a3c78f4a77ae6477986e33836725e8b url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54589/506866/fmodstudio-2.00.07.538806-linux64-538806.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65399/612631/fmodstudio-2.00.11.546392-linux64-546392.tar.bz2 name linux64 @@ -784,9 +784,9 @@ archive hash - 7f0294b038eab2d89ecc73bbf08b6d94 + 0f44323b0d03b7d0d8a17eec83e103ce url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59042/554668/fmodstudio-2.00.07.541681-windows-541681.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65401/612647/fmodstudio-2.00.11.546392-windows-546392.tar.bz2 name windows @@ -796,16 +796,16 @@ archive hash - da2e8e2b809d8fe635ee437baa2a7386 + 462d28eacf731a5d36ab031e7071c32a url - http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/59041/554656/fmodstudio-2.00.07.541681-windows64-541681.tar.bz2 + http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65402/612648/fmodstudio-2.00.11.546392-windows64-546392.tar.bz2 name windows64 version - 2.00.07.541681 + 2.00.11.546392 fontconfig @@ -2187,16 +2187,18 @@ archive hash - b677ee43822212f0a27c838dc8bf3623 + 9f4687d7d328b0c13a9e651e805e880a + hash_algorithm + md5 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/67622/646614/llca-202009010215.548269-common-548269.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/71501/691487/llca-202011010215.551526-common-551526.tar.bz2 name common version - 202009010215.548269 + 202011010215.551526 llphysicsextensions_source @@ -3495,7 +3497,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors canonical_repo https://bitbucket.org/lindenlab/viewer copyright - Copyright (c) 2014, Linden Research, Inc. + Copyright (c) 2020, Linden Research, Inc. description Second Life Viewer license diff --git a/doc/contributions.txt b/doc/contributions.txt index 07a96d8766..bbdfaf655d 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -223,6 +223,9 @@ Ansariel Hiller MAINT-8723 SL-10385 SL-10891 + SL-13364 + SL-13858 + SL-13697 Aralara Rajal Arare Chantilly CHUIBUG-191 @@ -834,7 +837,9 @@ Khyota Wulluf Kimar Coba Kithrak Kirkorian Kitty Barnett + BUG-228664 BUG-228665 + BUG-228719 VWR-19699 STORM-288 STORM-799 diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 3dab632aef..a90b294550 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -180,7 +180,7 @@ LLApp::~LLApp() if(mExceptionHandler != 0) delete mExceptionHandler; - SUBSYSTEM_CLEANUP(LLCommon); + SUBSYSTEM_CLEANUP_DBG(LLCommon); } // static diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 984e90f376..db94765871 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -68,7 +68,7 @@ void ll_cleanup_apr() { gAPRInitialized = false; - LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; + LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL; LLThreadLocalPointerBase::destroyAllThreadLocalStorage(); diff --git a/indra/llcommon/llcleanup.cpp b/indra/llcommon/llcleanup.cpp index c5283507bf..1f34c2036a 100644 --- a/indra/llcommon/llcleanup.cpp +++ b/indra/llcommon/llcleanup.cpp @@ -20,10 +20,13 @@ #include "llerror.h" #include "llerrorcontrol.h" -void log_subsystem_cleanup(const char* file, int line, const char* function, +void log_subsystem_cleanup(LLError::ELevel level, + const char* file, + int line, + const char* function, const char* classname) { - LL_INFOS("Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): " + LL_VLOGS(level, "Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): " << "calling " << classname << "::cleanupClass() in " << function << LL_ENDL; } diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h index a319171b5f..0f567ed5f6 100644 --- a/indra/llcommon/llcleanup.h +++ b/indra/llcommon/llcleanup.h @@ -21,13 +21,22 @@ // shutdown schemes. #define SUBSYSTEM_CLEANUP(CLASSNAME) \ do { \ - log_subsystem_cleanup(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \ + log_subsystem_cleanup(LLError::LEVEL_INFO, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \ + CLASSNAME::cleanupClass(); \ + } while (0) + +#define SUBSYSTEM_CLEANUP_DBG(CLASSNAME) \ + do { \ + log_subsystem_cleanup(LLError::LEVEL_DEBUG, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \ CLASSNAME::cleanupClass(); \ } while (0) // Use ancient do { ... } while (0) macro trick to permit a block of // statements with the same syntax as a single statement. -void log_subsystem_cleanup(const char* file, int line, const char* function, +void log_subsystem_cleanup(LLError::ELevel level, + const char* file, + int line, + const char* function, const char* classname); #endif /* ! defined(LL_LLCLEANUP_H) */ diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 2d665c611b..96be913d17 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -63,7 +63,7 @@ void LLCommon::cleanupClass() sMasterThreadRecorder = NULL; LLTrace::set_master_thread_recorder(NULL); LLThreadSafeRefCount::cleanupThreadSafeRefCount(); - SUBSYSTEM_CLEANUP(LLTimer); + SUBSYSTEM_CLEANUP_DBG(LLTimer); if (sAprInitialized) { ll_cleanup_apr(); diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 411412c883..f876b8ee4a 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -332,12 +332,9 @@ namespace LLError } // huh, that's odd, we should see one or the other prefix -- but don't // try to log unless logging is already initialized - if (is_available()) - { - // in Python, " or ".join(vector) -- but in C++, a PITB - LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '" - << name << "'" << LL_ENDL; - } + // in Python, " or ".join(vector) -- but in C++, a PITB + LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '" + << name << "'" << LL_ENDL; return name; #else // neither GCC nor Visual Studio @@ -438,9 +435,12 @@ namespace typedef std::vector Recorders; typedef std::vector CallSiteVector; - class Globals : public LLSingleton + class Globals { - LLSINGLETON(Globals); + public: + static Globals* getInstance(); + protected: + Globals(); public: std::ostringstream messageStream; bool messageStreamInUse; @@ -460,6 +460,16 @@ namespace { } + Globals* Globals::getInstance() + { + // According to C++11 Function-Local Initialization + // of static variables is supposed to be thread safe + // without risk of deadlocks. + static Globals inst; + + return &inst; + } + void Globals::addCallSite(LLError::CallSite& site) { callSites.push_back(&site); @@ -512,14 +522,17 @@ namespace LLError typedef LLPointer SettingsConfigPtr; - class Settings : public LLSingleton + class Settings { - LLSINGLETON(Settings); + public: + static Settings* getInstance(); + protected: + Settings(); public: SettingsConfigPtr getSettingsConfig(); void reset(); - SettingsStoragePtr saveAndReset(); + SettingsStoragePtr saveAndReset(); void restore(SettingsStoragePtr pSettingsStorage); private: @@ -553,6 +566,16 @@ namespace LLError { } + Settings* Settings::getInstance() + { + // According to C++11 Function-Local Initialization + // of static variables is supposed to be thread safe + // without risk of deadlocks. + static Settings inst; + + return &inst; + } + SettingsConfigPtr Settings::getSettingsConfig() { return mSettingsConfig; @@ -577,11 +600,6 @@ namespace LLError SettingsConfigPtr newSettingsConfig(dynamic_cast(pSettingsStorage.get())); mSettingsConfig = newSettingsConfig; } - - bool is_available() - { - return Settings::instanceExists() && Globals::instanceExists(); - } } namespace LLError @@ -1028,7 +1046,7 @@ namespace LLError std::pair, Recorders::iterator> findRecorderPos() { - SettingsConfigPtr s = Settings::instance().getSettingsConfig(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); // Since we promise to return an iterator, use a classic iterator // loop. auto end{s->mRecorders.end()}; @@ -1071,7 +1089,7 @@ namespace LLError auto found = findRecorderPos(); if (found.first) { - SettingsConfigPtr s = Settings::instance().getSettingsConfig(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); s->mRecorders.erase(found.second); } return bool(found.first); @@ -1307,14 +1325,6 @@ namespace LLError return false; } - // If we hit a logging request very late during shutdown processing, - // when either of the relevant LLSingletons has already been deleted, - // DO NOT resurrect them. - if (Settings::wasDeleted() || Globals::wasDeleted()) - { - return false; - } - SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); s->mShouldLogCallCounter++; @@ -1353,10 +1363,8 @@ namespace LLError std::ostringstream* Log::out() { LLMutexTrylock lock(getMutex(),5); - // If we hit a logging request very late during shutdown processing, - // when either of the relevant LLSingletons has already been deleted, - // DO NOT resurrect them. - if (lock.isLocked() && ! (Settings::wasDeleted() || Globals::wasDeleted())) + + if (lock.isLocked()) { Globals* g = Globals::getInstance(); @@ -1378,14 +1386,6 @@ namespace LLError return; } - // If we hit a logging request very late during shutdown processing, - // when either of the relevant LLSingletons has already been deleted, - // DO NOT resurrect them. - if (Settings::wasDeleted() || Globals::wasDeleted()) - { - return; - } - if(strlen(out->str().c_str()) < 128) { strcpy(message, out->str().c_str()); @@ -1418,14 +1418,6 @@ namespace LLError return; } - // If we hit a logging request very late during shutdown processing, - // when either of the relevant LLSingletons has already been deleted, - // DO NOT resurrect them. - if (Settings::wasDeleted() || Globals::wasDeleted()) - { - return; - } - Globals* g = Globals::getInstance(); SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index bfa2269025..25786d5457 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -203,11 +203,6 @@ namespace LLError LL_COMMON_API std::string abbreviateFile(const std::string& filePath); LL_COMMON_API int shouldLogCallCount(); - - // Check whether Globals exists. This should only be used by LLSingleton - // infrastructure to avoid trying to log when our internal LLSingleton is - // unavailable -- circularity ensues. - LL_COMMON_API bool is_available(); }; #endif // LL_LLERRORCONTROL_H diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index d3d25201b2..83a4b64e8f 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -28,7 +28,7 @@ #include "llsingleton.h" #include "llerror.h" -#include "llerrorcontrol.h" // LLError::is_available() +#include "llerrorcontrol.h" #include "lldependencies.h" #include "llexception.h" #include "llcoros.h" @@ -41,8 +41,6 @@ namespace { void log(LLError::ELevel level, const char* p1, const char* p2, const char* p3, const char* p4); - -bool oktolog(); } // anonymous namespace // Our master list of all LLSingletons is itself an LLSingleton. We used to @@ -279,8 +277,6 @@ void LLSingletonBase::reset_initializing(list_t::size_type size) void LLSingletonBase::MasterList::LockedInitializing::log(const char* verb, const char* name) { - if (oktolog()) - { LL_DEBUGS("LLSingleton") << verb << ' ' << demangle(name) << ';'; if (mList) { @@ -292,7 +288,6 @@ void LLSingletonBase::MasterList::LockedInitializing::log(const char* verb, cons } } LL_ENDL; - } } void LLSingletonBase::capture_dependency() @@ -455,33 +450,11 @@ void LLSingletonBase::deleteAll() /*---------------------------- Logging helpers -----------------------------*/ namespace { -bool oktolog() -{ - // See comments in log() below. - return LLError::is_available(); -} void log(LLError::ELevel level, const char* p1, const char* p2, const char* p3, const char* p4) { - // The is_available() test below ensures that we'll stop logging once - // LLError has been cleaned up. If we had a similar portable test for - // std::cerr, this would be a good place to use it. - - // Check LLError::is_available() because some of LLError's infrastructure - // is itself an LLSingleton. If that LLSingleton has not yet been - // initialized, trying to log will engage LLSingleton machinery... and - // around and around we go. - if (LLError::is_available()) - { - LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL; - } - else - { - // Caller may be a test program, or something else whose stderr is - // visible to the user. - std::cerr << p1 << p2 << p3 << p4 << std::endl; - } + LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL; } } // anonymous namespace diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 11647c5518..18bc1b5a91 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -41,7 +41,7 @@ /// Exported functions ///---------------------------------------------------------------------------- static const std::string INV_ITEM_ID_LABEL("item_id"); -static const std::string INV_FOLDER_ID_LABEL("folder_id"); +static const std::string INV_FOLDER_ID_LABEL("cat_id"); static const std::string INV_PARENT_ID_LABEL("parent_id"); static const std::string INV_ASSET_TYPE_LABEL("type"); static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type"); @@ -228,22 +228,6 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream) return TRUE; } -// exportFile should be replaced with exportLegacyStream -// not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get icramented... -BOOL LLInventoryObject::exportFile(LLFILE* fp, BOOL) const -{ - std::string uuid_str; - fprintf(fp, "\tinv_object\t0\n\t{\n"); - mUUID.toString(uuid_str); - fprintf(fp, "\t\tobj_id\t%s\n", uuid_str.c_str()); - mParentUUID.toString(uuid_str); - fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); - fprintf(fp,"\t}\n"); - return TRUE; -} - BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) const { std::string uuid_str; @@ -603,215 +587,6 @@ BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 #endif } -// virtual -BOOL LLInventoryItem::importFile(LLFILE* fp) -{ - // *NOTE: Changing the buffer size will require changing the scanf - // calls below. - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - char valuestr[MAX_STRING]; /* Flawfinder: ignore */ - char junk[MAX_STRING]; /* Flawfinder: ignore */ - BOOL success = TRUE; - - keyword[0] = '\0'; - valuestr[0] = '\0'; - - mInventoryType = LLInventoryType::IT_NONE; - mAssetUUID.setNull(); - while(success && (!feof(fp))) - { - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */ - if(0 == strcmp("{",keyword)) - { - continue; - } - if(0 == strcmp("}", keyword)) - { - break; - } - else if(0 == strcmp("item_id", keyword)) - { - mUUID.set(valuestr); - } - else if(0 == strcmp("parent_id", keyword)) - { - mParentUUID.set(valuestr); - } - else if(0 == strcmp("permissions", keyword)) - { - success = mPermissions.importFile(fp); - } - else if(0 == strcmp("sale_info", keyword)) - { - // Sale info used to contain next owner perm. It is now in - // the permissions. Thus, we read that out, and fix legacy - // objects. It's possible this op would fail, but it - // should pick up the vast majority of the tasks. - BOOL has_perm_mask = FALSE; - U32 perm_mask = 0; - success = mSaleInfo.importFile(fp, has_perm_mask, perm_mask); - if(has_perm_mask) - { - if(perm_mask == PERM_NONE) - { - perm_mask = mPermissions.getMaskOwner(); - } - // fair use fix. - if(!(perm_mask & PERM_COPY)) - { - perm_mask |= PERM_TRANSFER; - } - mPermissions.setMaskNext(perm_mask); - } - } - else if(0 == strcmp("shadow_id", keyword)) - { - mAssetUUID.set(valuestr); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(mAssetUUID.mData, UUID_BYTES); - } - else if(0 == strcmp("asset_id", keyword)) - { - mAssetUUID.set(valuestr); - } - else if(0 == strcmp("type", keyword)) - { - mType = LLAssetType::lookup(valuestr); - } - else if(0 == strcmp("inv_type", keyword)) - { - mInventoryType = LLInventoryType::lookup(std::string(valuestr)); - } - else if(0 == strcmp("flags", keyword)) - { - sscanf(valuestr, "%x", &mFlags); - } - else if(0 == strcmp("name", keyword)) - { - //strcpy(valuestr, buffer + strlen(keyword) + 3); - // *NOTE: Not ANSI C, but widely supported. - sscanf( /* Flawfinder: ignore */ - buffer, - " %254s%254[\t]%254[^|]", - keyword, junk, valuestr); - - // IW: sscanf chokes and puts | in valuestr if there's no name - if (valuestr[0] == '|') - { - valuestr[0] = '\000'; - } - - mName.assign(valuestr); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - } - else if(0 == strcmp("desc", keyword)) - { - //strcpy(valuestr, buffer + strlen(keyword) + 3); - // *NOTE: Not ANSI C, but widely supported. - sscanf( /* Flawfinder: ignore */ - buffer, - " %254s%254[\t]%254[^|]", - keyword, junk, valuestr); - - if (valuestr[0] == '|') - { - valuestr[0] = '\000'; - } - - disclaimMem(mDescription); - mDescription.assign(valuestr); - claimMem(mDescription); - LLStringUtil::replaceNonstandardASCII(mDescription, ' '); - /* TODO -- ask Ian about this code - const char *donkey = mDescription.c_str(); - if (donkey[0] == '|') - { - LL_ERRS() << "Donkey" << LL_ENDL; - } - */ - } - else if(0 == strcmp("creation_date", keyword)) - { - S32 date; - sscanf(valuestr, "%d", &date); - mCreationDate = date; - } - else - { - LL_WARNS() << "unknown keyword '" << keyword - << "' in inventory import of item " << mUUID << LL_ENDL; - } - } - - // Need to convert 1.0 simstate files to a useful inventory type - // and potentially deal with bad inventory tyes eg, a landmark - // marked as a texture. - if((LLInventoryType::IT_NONE == mInventoryType) - || !inventory_and_asset_types_match(mInventoryType, mType)) - { - LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL; - mInventoryType = LLInventoryType::defaultForAssetType(mType); - } - - mPermissions.initMasks(mInventoryType); - - return success; -} - -BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const -{ - std::string uuid_str; - fprintf(fp, "\tinv_item\t0\n\t{\n"); - mUUID.toString(uuid_str); - fprintf(fp, "\t\titem_id\t%s\n", uuid_str.c_str()); - mParentUUID.toString(uuid_str); - fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); - mPermissions.exportFile(fp); - - // Check for permissions to see the asset id, and if so write it - // out as an asset id. Otherwise, apply our cheesy encryption. - if(include_asset_key) - { - U32 mask = mPermissions.getMaskBase(); - if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - || (mAssetUUID.isNull())) - { - mAssetUUID.toString(uuid_str); - fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str()); - } - else - { - LLUUID shadow_id(mAssetUUID); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.encrypt(shadow_id.mData, UUID_BYTES); - shadow_id.toString(uuid_str); - fprintf(fp, "\t\tshadow_id\t%s\n", uuid_str.c_str()); - } - } - else - { - LLUUID::null.toString(uuid_str); - fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str()); - } - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); - if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str()); - fprintf(fp, "\t\tflags\t%08x\n", mFlags); - mSaleInfo.exportFile(fp); - fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); - fprintf(fp, "\t\tdesc\t%s|\n", mDescription.c_str()); - fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate); - fprintf(fp,"\t}\n"); - return TRUE; -} - // virtual BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) { @@ -1463,90 +1238,7 @@ void LLInventoryCategory::unpackMessage(LLMessageSystem* msg, msg->getStringFast(block, _PREHASH_Name, mName, block_num); LLStringUtil::replaceNonstandardASCII(mName, ' '); } - -// virtual -BOOL LLInventoryCategory::importFile(LLFILE* fp) -{ - // *NOTE: Changing the buffer size will require changing the scanf - // calls below. - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - char valuestr[MAX_STRING]; /* Flawfinder: ignore */ - keyword[0] = '\0'; - valuestr[0] = '\0'; - while(!feof(fp)) - { - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %254s %254s", - keyword, valuestr); - if(0 == strcmp("{",keyword)) - { - continue; - } - if(0 == strcmp("}", keyword)) - { - break; - } - else if(0 == strcmp("cat_id", keyword)) - { - mUUID.set(valuestr); - } - else if(0 == strcmp("parent_id", keyword)) - { - mParentUUID.set(valuestr); - } - else if(0 == strcmp("type", keyword)) - { - mType = LLAssetType::lookup(valuestr); - } - else if(0 == strcmp("pref_type", keyword)) - { - mPreferredType = LLFolderType::lookup(valuestr); - } - else if(0 == strcmp("name", keyword)) - { - //strcpy(valuestr, buffer + strlen(keyword) + 3); - // *NOTE: Not ANSI C, but widely supported. - sscanf( /* Flawfinder: ignore */ - buffer, - " %254s %254[^|]", - keyword, valuestr); - mName.assign(valuestr); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - } - else - { - LL_WARNS() << "unknown keyword '" << keyword - << "' in inventory import category " << mUUID << LL_ENDL; - } - } - return TRUE; -} - -BOOL LLInventoryCategory::exportFile(LLFILE* fp, BOOL) const -{ - std::string uuid_str; - fprintf(fp, "\tinv_category\t0\n\t{\n"); - mUUID.toString(uuid_str); - fprintf(fp, "\t\tcat_id\t%s\n", uuid_str.c_str()); - mParentUUID.toString(uuid_str); - fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str()); - fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); - fprintf(fp,"\t}\n"); - return TRUE; -} - - // virtual BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream) { @@ -1625,6 +1317,45 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL) return TRUE; } +LLSD LLInventoryCategory::exportLLSD() const +{ + LLSD cat_data; + cat_data[INV_FOLDER_ID_LABEL] = mUUID; + cat_data[INV_PARENT_ID_LABEL] = mParentUUID; + cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); + cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType); + cat_data[INV_NAME_LABEL] = mName; + + return cat_data; +} + +bool LLInventoryCategory::importLLSD(const LLSD& cat_data) +{ + if (cat_data.has(INV_FOLDER_ID_LABEL)) + { + setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID()); + } + if (cat_data.has(INV_PARENT_ID_LABEL)) + { + setParent(cat_data[INV_PARENT_ID_LABEL].asUUID()); + } + if (cat_data.has(INV_ASSET_TYPE_LABEL)) + { + setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString())); + } + if (cat_data.has(INV_PREFERRED_TYPE_LABEL)) + { + setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString())); + } + if (cat_data.has(INV_NAME_LABEL)) + { + mName = cat_data[INV_NAME_LABEL].asString(); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + } + + return true; +} ///---------------------------------------------------------------------------- /// Local function definitions ///---------------------------------------------------------------------------- diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 70b200e139..024afc109c 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -95,8 +95,7 @@ public: // Implemented here so that a minimal information set can be transmitted // between simulator and viewer. //-------------------------------------------------------------------- - // virtual BOOL importFile(LLFILE* fp); - virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const; + virtual BOOL importLegacyStream(std::istream& input_stream); virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; @@ -197,8 +196,6 @@ public: // File Support //-------------------------------------------------------------------- public: - virtual BOOL importFile(LLFILE* fp); - virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const; virtual BOOL importLegacyStream(std::istream& input_stream); virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; @@ -269,11 +266,11 @@ public: // File Support //-------------------------------------------------------------------- public: - virtual BOOL importFile(LLFILE* fp); - virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const; virtual BOOL importLegacyStream(std::istream& input_stream); virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; + LLSD exportLLSD() const; + bool importLLSD(const LLSD& cat_data); //-------------------------------------------------------------------- // Member Variables //-------------------------------------------------------------------- diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp index fdad50e8d4..81485b3a97 100644 --- a/indra/llinventory/llinventorysettings.cpp +++ b/indra/llinventory/llinventorysettings.cpp @@ -33,10 +33,6 @@ #include "llsingleton.h" #include "llinvtranslationbrdg.h" -//========================================================================= -namespace { - LLTranslationBridge::ptr_t sTranslator; -} //========================================================================= struct SettingsEntry : public LLDictionaryEntry @@ -49,7 +45,7 @@ struct SettingsEntry : public LLDictionaryEntry mLabel(name), mIconName(iconName) { - std::string transdname = sTranslator->getString(mLabel); + std::string transdname = LLSettingsType::getInstance()->mTranslator->getString(mLabel); if (!transdname.empty()) { mLabel = transdname; @@ -84,6 +80,16 @@ void LLSettingsDictionary::initSingleton() //========================================================================= +LLSettingsType::LLSettingsType(LLTranslationBridge::ptr_t &trans) +{ + mTranslator = trans; +} + +LLSettingsType::~LLSettingsType() +{ + mTranslator.reset(); +} + LLSettingsType::type_e LLSettingsType::fromInventoryFlags(U32 flags) { return (LLSettingsType::type_e)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK); @@ -104,13 +110,3 @@ std::string LLSettingsType::getDefaultName(LLSettingsType::type_e type) return getDefaultName(ST_INVALID); return entry->mDefaultNewName; } - -void LLSettingsType::initClass(LLTranslationBridge::ptr_t &trans) -{ - sTranslator = trans; -} - -void LLSettingsType::cleanupClass() -{ - sTranslator.reset(); -} diff --git a/indra/llinventory/llinventorysettings.h b/indra/llinventory/llinventorysettings.h index 906540689c..6b6685d088 100644 --- a/indra/llinventory/llinventorysettings.h +++ b/indra/llinventory/llinventorysettings.h @@ -30,9 +30,15 @@ #include "llinventorytype.h" #include "llinvtranslationbrdg.h" +#include "llsingleton.h" -class LLSettingsType +class LLSettingsType : public LLParamSingleton { + LLSINGLETON(LLSettingsType, LLTranslationBridge::ptr_t &trans); + ~LLSettingsType(); + + friend struct SettingsEntry; + public: enum type_e { @@ -48,8 +54,9 @@ public: static LLInventoryType::EIconName getIconName(type_e type); static std::string getDefaultName(type_e type); - static void initClass(LLTranslationBridge::ptr_t &trans); - static void cleanupClass(); +protected: + + LLTranslationBridge::ptr_t mTranslator; }; diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index e79b753514..0359d2f554 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -565,148 +565,6 @@ void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 b } -// -// File support -// - -BOOL LLPermissions::importFile(LLFILE* fp) -{ - init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); - const S32 BUFSIZE = 16384; - - // *NOTE: Changing the buffer size will require changing the scanf - // calls below. - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - char uuid_str[256]; /* Flawfinder: ignore */ - U32 mask; - - keyword[0] = '\0'; - valuestr[0] = '\0'; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("creator_mask", keyword)) - { - // legacy support for "creator" masks - sscanf(valuestr, "%x", &mask); - mMaskBase = mask; - fixFairUse(); - } - else if (!strcmp("base_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskBase = mask; - //fixFairUse(); - } - else if (!strcmp("owner_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskOwner = mask; - } - else if (!strcmp("group_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskGroup = mask; - } - else if (!strcmp("everyone_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskEveryone = mask; - } - else if (!strcmp("next_owner_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskNextOwner = mask; - } - else if (!strcmp("creator_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mCreator.set(uuid_str); - } - else if (!strcmp("owner_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mOwner.set(uuid_str); - } - else if (!strcmp("last_owner_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mLastOwner.set(uuid_str); - } - else if (!strcmp("group_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mGroup.set(uuid_str); - } - else if (!strcmp("group_owned", keyword)) - { - sscanf(valuestr, "%d", &mask); - if(mask) mIsGroupOwned = true; - else mIsGroupOwned = false; - } - else - { - LL_INFOS() << "unknown keyword " << keyword << " in permissions import" << LL_ENDL; - } - } - fix(); - return TRUE; -} - - -BOOL LLPermissions::exportFile(LLFILE* fp) const -{ - std::string uuid_str; - - fprintf(fp, "\tpermissions 0\n"); - fprintf(fp, "\t{\n"); - - fprintf(fp, "\t\tbase_mask\t%08x\n", mMaskBase); - fprintf(fp, "\t\towner_mask\t%08x\n", mMaskOwner); - fprintf(fp, "\t\tgroup_mask\t%08x\n", mMaskGroup); - fprintf(fp, "\t\teveryone_mask\t%08x\n", mMaskEveryone); - fprintf(fp, "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); - - mCreator.toString(uuid_str); - fprintf(fp, "\t\tcreator_id\t%s\n", uuid_str.c_str()); - - mOwner.toString(uuid_str); - fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str()); - - mLastOwner.toString(uuid_str); - fprintf(fp, "\t\tlast_owner_id\t%s\n", uuid_str.c_str()); - - mGroup.toString(uuid_str); - fprintf(fp, "\t\tgroup_id\t%s\n", uuid_str.c_str()); - - if(mIsGroupOwned) - { - fprintf(fp, "\t\tgroup_owned\t1\n"); - } - fprintf(fp,"\t}\n"); - return TRUE; -} - - BOOL LLPermissions::importLegacyStream(std::istream& input_stream) { init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index 89c66f6ebd..27252f7b97 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -311,10 +311,6 @@ public: void packMessage(LLMessageSystem* msg) const; void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); - // Load/save support - BOOL importFile(LLFILE* fp); - BOOL exportFile(LLFILE* fp) const; - BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index 63e34d188e..b7231ee239 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -78,16 +78,6 @@ U32 LLSaleInfo::getCRC32() const return rv; } - -BOOL LLSaleInfo::exportFile(LLFILE* fp) const -{ - fprintf(fp, "\tsale_info\t0\n\t{\n"); - fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType)); - fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice); - fprintf(fp,"\t}\n"); - return TRUE; -} - BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const { output_stream << "\tsale_info\t0\n\t{\n"; @@ -129,69 +119,6 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) return true; } -// Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML() -// because I can't find any non-test code references to it. 2009-05-04 JC - -BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask) -{ - has_perm_mask = FALSE; - - // *NOTE: Changing the buffer size will require changing the scanf - // calls below. - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - char valuestr[MAX_STRING]; /* Flawfinder: ignore */ - BOOL success = TRUE; - - keyword[0] = '\0'; - valuestr[0] = '\0'; - while(success && (!feof(fp))) - { - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %254s %254s", - keyword, valuestr); - if(!keyword[0]) - { - continue; - } - if(0 == strcmp("{",keyword)) - { - continue; - } - if(0 == strcmp("}", keyword)) - { - break; - } - else if(0 == strcmp("sale_type", keyword)) - { - mSaleType = lookup(valuestr); - } - else if(0 == strcmp("sale_price", keyword)) - { - sscanf(valuestr, "%d", &mSalePrice); - mSalePrice = llclamp(mSalePrice, 0, S32_MAX); - } - else if (!strcmp("perm_mask", keyword)) - { - //LL_INFOS() << "found deprecated keyword perm_mask" << LL_ENDL; - has_perm_mask = TRUE; - sscanf(valuestr, "%x", &perm_mask); - } - else - { - LL_WARNS() << "unknown keyword '" << keyword - << "' in sale info import" << LL_ENDL; - } - } - return success; -} - BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask) { has_perm_mask = FALSE; diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index 4e98ccf6ff..3c8952838b 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -84,11 +84,6 @@ public: void setSalePrice(S32 price); //void setNextOwnerPermMask(U32 mask) { mNextOwnerPermMask = mask; } - - // file serialization - BOOL exportFile(LLFILE* fp) const; - BOOL importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask); - BOOL exportLegacyStream(std::ostream& output_stream) const; LLSD asLLSD() const; operator LLSD() const { return asLLSD(); } diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h index 1d118f0789..f7a9d5b7cd 100644 --- a/indra/llinventory/llsettingsbase.h +++ b/indra/llinventory/llsettingsbase.h @@ -359,7 +359,6 @@ protected: virtual parammapping_t getParameterMap() const { return parammapping_t(); } LLSD mSettings; - bool mIsValid; LLSD cloneSettings() const; diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp index 7b15552f24..e8b063bffe 100644 --- a/indra/llinventory/tests/inventorymisc_test.cpp +++ b/indra/llinventory/tests/inventorymisc_test.cpp @@ -28,9 +28,9 @@ #include "linden_common.h" #include "llsd.h" +#include "llsdserialize.h" #include "../llinventory.h" - #include "../test/lltut.h" @@ -320,27 +320,39 @@ namespace tut template<> template<> void inventory_object::test<7>() { - LLFILE* fp = LLFile::fopen("linden_file.dat","w+"); - if(!fp) + std::string filename("linden_file.dat"); + llofstream fileXML(filename.c_str()); + if (!fileXML.is_open()) { LL_ERRS() << "file could not be opened\n" << LL_ENDL; return; } LLPointer src1 = create_random_inventory_item(); - src1->exportFile(fp, TRUE); - fclose(fp); + fileXML << LLSDOStreamer(src1->asLLSD()) << std::endl; + fileXML.close(); - LLPointer src2 = new LLInventoryItem(); - fp = LLFile::fopen("linden_file.dat","r+"); - if(!fp) + + LLPointer src2 = new LLInventoryItem(); + llifstream file(filename.c_str()); + if (!file.is_open()) { LL_ERRS() << "file could not be opened\n" << LL_ENDL; return; } - - src2->importFile(fp); - fclose(fp); + std::string line; + LLPointer parser = new LLSDNotationParser(); + std::getline(file, line); + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) + { + LL_ERRS()<< "Parsing cache failed" << LL_ENDL; + return; + } + src2->fromLLSD(s_item); + + file.close(); ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); @@ -457,27 +469,39 @@ namespace tut template<> template<> void inventory_object::test<13>() { - LLFILE* fp = LLFile::fopen("linden_file.dat","w"); - if(!fp) + std::string filename("linden_file.dat"); + llofstream fileXML(filename.c_str()); + if (!fileXML.is_open()) { - LL_ERRS() << "file coudnt be opened\n" << LL_ENDL; + LL_ERRS() << "file could not be opened\n" << LL_ENDL; return; } - - LLPointer src1 = create_random_inventory_cat(); - src1->exportFile(fp, TRUE); - fclose(fp); - LLPointer src2 = new LLInventoryCategory(); - fp = LLFile::fopen("linden_file.dat","r"); - if(!fp) + LLPointer src1 = create_random_inventory_cat(); + fileXML << LLSDOStreamer(src1->exportLLSD()) << std::endl; + fileXML.close(); + + llifstream file(filename.c_str()); + if (!file.is_open()) { - LL_ERRS() << "file coudnt be opened\n" << LL_ENDL; + LL_ERRS() << "file could not be opened\n" << LL_ENDL; return; } - - src2->importFile(fp); - fclose(fp); + std::string line; + LLPointer parser = new LLSDNotationParser(); + std::getline(file, line); + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) + { + LL_ERRS()<< "Parsing cache failed" << LL_ENDL; + return; + } + + file.close(); + + LLPointer src2 = new LLInventoryCategory(); + src2->importLLSD(s_item); ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index 26684a4d9e..a4fe3a2a8e 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -360,7 +360,7 @@ LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoproced } // The queue should never fill up. - LL_ERRS("CoProcMgr") << "Enqueue failed (" << unsigned(pushed) << ")" << LL_ENDL; + LL_ERRS("CoProcMgr") << "Enqueue into '" << name << "' failed (" << unsigned(pushed) << ")" << LL_ENDL; return {}; // never executed, pacify the compiler } diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 58069afdf9..6d51adc685 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -857,12 +857,12 @@ void LLPluginClassMedia::paste() } void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, - const std::string &user_data_path_cookies, + const std::string &username, const std::string &user_data_path_cef_log) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path"); - message.setValue("cache_path", user_data_path_cache); - message.setValue("cookies_path", user_data_path_cookies); + message.setValue("cache_path", user_data_path_cache); + message.setValue("username", username); // cef shares cache between users but creates user-based contexts message.setValue("cef_log_file", user_data_path_cef_log); bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 9d11ee0421..382f891e0c 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -195,7 +195,7 @@ public: bool canPaste() const { return mCanPaste; }; // These can be called before init(), and they will be queued and sent before the media init message. - void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_cef_log); + void setUserDataPath(const std::string &user_data_path_cache, const std::string &username, const std::string &user_data_path_cef_log); void setLanguageCode(const std::string &language_code); void setPluginsEnabled(const bool enabled); void setJavascriptEnabled(const bool enabled); diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index c5304d2ccf..d93ec8cf4b 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -225,6 +225,18 @@ void LLPluginProcessChild::idle(void) } setState(STATE_UNLOADED); } + + if (mInstance) + { + // Provide some time to the plugin + // example: CEF on "cleanup" sets shutdown request, but it still needs idle loop to actually shutdown + LLPluginMessage message("base", "idle"); + message.setValueReal("time", PLUGIN_IDLE_SECONDS); + sendMessageToPlugin(message); + + mInstance->idle(); + } + break; case STATE_UNLOADED: diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 498dfca1a3..604fb4e946 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -2700,10 +2700,11 @@ LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_w } #if LL_WINDOWS -// Expose desired use of high-performance graphics processor to Optimus driver +// Expose desired use of high-performance graphics processor to Optimus driver and to AMD driver extern "C" -{ - _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +{ + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 6a02cd9c19..7d2b09ca4a 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1193,7 +1193,7 @@ bool LLVertexBuffer::createGLBuffer(U32 size) return true; } - bool sucsess = true; + bool success = true; mEmpty = true; @@ -1215,9 +1215,9 @@ bool LLVertexBuffer::createGLBuffer(U32 size) if (!mMappedData) { - sucsess = false; + success = false; } - return sucsess; + return success; } bool LLVertexBuffer::createGLIndices(U32 size) @@ -1232,7 +1232,7 @@ bool LLVertexBuffer::createGLIndices(U32 size) return true; } - bool sucsess = true; + bool success = true; mEmpty = true; @@ -1257,9 +1257,9 @@ bool LLVertexBuffer::createGLIndices(U32 size) if (!mMappedIndexData) { - sucsess = false; + success = false; } - return sucsess; + return success; } void LLVertexBuffer::destroyGLBuffer() @@ -1306,7 +1306,7 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts) { llassert(nverts >= 0); - bool sucsess = true; + bool success = true; if (nverts > 65536) { @@ -1318,34 +1318,34 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts) if (needed_size > mSize || needed_size <= mSize/2) { - sucsess &= createGLBuffer(needed_size); + success &= createGLBuffer(needed_size); } sVertexCount -= mNumVerts; mNumVerts = nverts; sVertexCount += mNumVerts; - return sucsess; + return success; } bool LLVertexBuffer::updateNumIndices(S32 nindices) { llassert(nindices >= 0); - bool sucsess = true; + bool success = true; U32 needed_size = sizeof(U16) * nindices; if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2) { - sucsess &= createGLIndices(needed_size); + success &= createGLIndices(needed_size); } sIndexCount -= mNumIndices; mNumIndices = nindices; sIndexCount += mNumIndices; - return sucsess; + return success; } bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) @@ -1358,10 +1358,10 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL; } - bool sucsess = true; + bool success = true; - sucsess &= updateNumVerts(nverts); - sucsess &= updateNumIndices(nindices); + success &= updateNumVerts(nverts); + success &= updateNumIndices(nindices); if (create && (nverts || nindices)) { @@ -1377,7 +1377,7 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) } } - return sucsess; + return success; } static LLTrace::BlockTimerStatHandle FTM_SETUP_VERTEX_ARRAY("Setup VAO"); diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 61a119800e..809d72208f 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -55,6 +55,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params) , mTabComparator( NULL ) , mNoVisibleTabsHelpText(NULL) , mNoVisibleTabsOrigString(params.no_visible_tabs_text.initial_value().asString()) + , mSkipScrollToChild(false) { initNoTabsWidget(params.no_matched_tabs_text); @@ -659,7 +660,7 @@ void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) // virtual void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl) { - if (mScrollbar && mScrollbar->getVisible()) + if (mScrollbar && mScrollbar->getVisible() && !mSkipScrollToChild) { // same as scrollToShowRect LLRect rect; diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index b38a76d27f..2828254472 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -138,6 +138,8 @@ public: bool getFitParent() const {return mFitParent;} + void setSkipScrollToChild(bool skip) { mSkipScrollToChild = skip; } + private: void initNoTabsWidget(const LLTextBox::Params& tb_params); void updateNoTabsHelpTextVisibility(); @@ -183,6 +185,8 @@ private: F32 mAutoScrollRate; LLTextBox* mNoVisibleTabsHelpText; + bool mSkipScrollToChild; + std::string mNoMatchedTabsOrigString; std::string mNoVisibleTabsOrigString; diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index e718fcec46..0c1dcc301b 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -342,7 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View"); void LLFolderView::filter( LLFolderViewFilter& filter ) { LL_RECORD_BLOCK_TIME(FTM_FILTER); - filter.resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32(mParentPanel.get()->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100)); + static LLCachedControl filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); + static LLCachedControl filter_hidden(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1); + filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? filter_visible() : filter_hidden(), 1, 100)); // Note: we filter the model, not the view getViewModelItem()->filter(filter); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9a1f7de73b..1c6c7b1b35 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -122,6 +122,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) : LLView(p), mLabelWidth(0), mLabelWidthDirty(false), + mSuffixNeedsRefresh(false), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mParentFolder( NULL ), mIsSelected( FALSE ), @@ -181,11 +182,25 @@ LLFolderViewItem::~LLFolderViewItem() BOOL LLFolderViewItem::postBuild() { - refresh(); + LLFolderViewModelItem& vmi = *getViewModelItem(); + // getDisplayName() is expensive (due to internal getLabelSuffix() and name building) + // it also sets search strings so it requires a filter reset + mLabel = vmi.getDisplayName(); + setToolTip(vmi.getName()); + + // Dirty the filter flag of the model from the view (CHUI-849) + vmi.dirtyFilter(); + + // Don't do full refresh on constructor if it is possible to avoid + // it significantly slows down bulk view creation. + // Todo: Ideally we need to move getDisplayName() out of constructor as well. + // Like: make a logic that will let filter update search string, + // while LLFolderViewItem::arrange() updates visual part + mSuffixNeedsRefresh = true; + mLabelWidthDirty = true; return TRUE; } - LLFolderView* LLFolderViewItem::getRoot() { return mRoot; @@ -280,24 +295,51 @@ BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation) void LLFolderViewItem::refresh() { - LLFolderViewModelItem& vmi = *getViewModelItem(); + LLFolderViewModelItem& vmi = *getViewModelItem(); - mLabel = vmi.getDisplayName(); + mLabel = vmi.getDisplayName(); + setToolTip(vmi.getName()); + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() + mIcon = vmi.getIcon(); + mIconOpen = vmi.getIconOpen(); + mIconOverlay = vmi.getIconOverlay(); - setToolTip(vmi.getName()); - mIcon = vmi.getIcon(); - mIconOpen = vmi.getIconOpen(); - mIconOverlay = vmi.getIconOverlay(); + if (mRoot->useLabelSuffix()) + { + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list + mLabelStyle = vmi.getLabelStyle(); + mLabelSuffix = vmi.getLabelSuffix(); + } + + // Dirty the filter flag of the model from the view (CHUI-849) + vmi.dirtyFilter(); + + mLabelWidthDirty = true; + mSuffixNeedsRefresh = false; +} + +void LLFolderViewItem::refreshSuffix() +{ + LLFolderViewModelItem const* vmi = getViewModelItem(); + + // icons are slightly expensive to get, can be optimized + // see LLInventoryIcon::getIcon() + mIcon = vmi->getIcon(); + mIconOpen = vmi->getIconOpen(); + mIconOverlay = vmi->getIconOverlay(); if (mRoot->useLabelSuffix()) { - mLabelStyle = vmi.getLabelStyle(); - mLabelSuffix = vmi.getLabelSuffix(); + // Very Expensive! + // Can do a number of expensive checks, like checking active motions, wearables or friend list + mLabelStyle = vmi->getLabelStyle(); + mLabelSuffix = vmi->getLabelSuffix(); } - mLabelWidthDirty = true; - // Dirty the filter flag of the model from the view (CHUI-849) - vmi.dirtyFilter(); + mLabelWidthDirty = true; + mSuffixNeedsRefresh = false; } // Utility function for LLFolderView @@ -348,6 +390,12 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) : 0; if (mLabelWidthDirty) { + if (mSuffixNeedsRefresh) + { + // Expensive. But despite refreshing label, + // it is purely visual, so it is fine to do at our laisure + refreshSuffix(); + } mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 61c39e0175..da09d139e9 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -95,6 +95,7 @@ protected: LLPointer mViewModelItem; LLFontGL::StyleFlags mLabelStyle; std::string mLabelSuffix; + bool mSuffixNeedsRefresh; //suffix and icons LLUIImagePtr mIcon, mIconOpen, mIconOverlay; @@ -266,8 +267,13 @@ public: virtual BOOL passedFilter(S32 filter_generation = -1); virtual BOOL isPotentiallyVisible(S32 filter_generation = -1); - // refresh information from the object being viewed. - virtual void refresh(); + // refresh information from the object being viewed. + // refreshes label, suffixes and sets icons. Expensive! + // Causes filter update + virtual void refresh(); + // refreshes suffixes and sets icons. Expensive! + // Does not need filter update + virtual void refreshSuffix(); // LLView functionality virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 3b45fb53a2..ea106b5fae 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -48,7 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText() void LLFolderViewModelCommon::filter() { - getFilter().resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100)); + static LLCachedControl filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10); + getFilter().resetTime(llclamp(filter_visible(), 1, 100)); mFolderView->getViewModelItem()->filter(getFilter()); } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index f71a88c56e..84a1539094 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -285,17 +285,7 @@ public: typedef std::list child_list_t; virtual void addChild(LLFolderViewModelItem* child) - { - // Avoid duplicates: bail out if that child is already present in the list - // Note: this happens when models are created before views - child_list_t::const_iterator iter; - for (iter = mChildren.begin(); iter != mChildren.end(); iter++) - { - if (child == *iter) - { - return; - } - } + { mChildren.push_back(child); child->setParent(this); dirtyFilter(); diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp index 296ea09079..ebd8ca0923 100644 --- a/indra/llui/llspellcheck.cpp +++ b/indra/llui/llspellcheck.cpp @@ -49,8 +49,6 @@ LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal; LLSpellChecker::LLSpellChecker() : mHunspell(NULL) { - // Load initial dictionary information - refreshDictionaryMap(); } LLSpellChecker::~LLSpellChecker() @@ -58,6 +56,12 @@ LLSpellChecker::~LLSpellChecker() delete mHunspell; } +void LLSpellChecker::initSingleton() +{ + // Load initial dictionary information + refreshDictionaryMap(); +} + bool LLSpellChecker::checkSpelling(const std::string& word) const { if ( (!mHunspell) || (word.length() < 3) || (0 != mHunspell->spell(word.c_str())) ) diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index f1964cc091..3da5e30955 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -47,6 +47,7 @@ public: protected: void addToDictFile(const std::string& dict_path, const std::string& word); void initHunspell(const std::string& dict_language); + void initSingleton(); public: typedef std::list dict_list_t; diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 333d03f208..e6835f73fb 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -454,13 +454,17 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const } // -// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link +// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ *secondlifegrid.net/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link // LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL() { mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)" "|" - "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))" + "(http://([-\\w\\.]*\\.)?secondlifegrid\\.net)" + "|" + "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)" + "|" + "(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))" "\\/\\S*", boost::regex::perl|boost::regex::icase); @@ -495,12 +499,14 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const } // -// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link +// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com *secondlifegrid.net and *tilia-inc.com urls to substitute icon 'hand.png' before link // LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL() { - mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)", - boost::regex::perl|boost::regex::icase); + mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)" + "|" + "https?://([-\\w\\.]*\\.)?secondlifegrid\\.net(?!\\S)", + boost::regex::perl|boost::regex::icase); mIcon = "Hand"; mMenuName = "menu_url_http.xml"; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 7783505c27..bef0ae76a8 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -784,9 +784,6 @@ void LLWindowWin32::close() resetDisplayResolution(); } - // Don't process events in our mainWindowProc any longer. - SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, NULL); - // Make sure cursor is visible and we haven't mangled the clipping state. showCursor(); setMouseClipping(FALSE); @@ -832,16 +829,24 @@ void LLWindowWin32::close() LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; - // Make sure we don't leave a blank toolbar button. - ShowWindow(mWindowHandle, SW_HIDE); + if (IsWindow(mWindowHandle)) + { + // Make sure we don't leave a blank toolbar button. + ShowWindow(mWindowHandle, SW_HIDE); - // This causes WM_DESTROY to be sent *immediately* - if (!destroy_window_handler(mWindowHandle)) - { - OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), - mCallbacks->translateString("MBShutdownErr"), - OSMB_OK); - } + // This causes WM_DESTROY to be sent *immediately* + if (!destroy_window_handler(mWindowHandle)) + { + OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), + mCallbacks->translateString("MBShutdownErr"), + OSMB_OK); + } + } + else + { + // Something killed the window while we were busy destroying gl or handle somehow got broken + LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL; + } mWindowHandle = NULL; } @@ -1133,7 +1138,10 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO << " Height: " << (window_rect.bottom - window_rect.top) << " Fullscreen: " << mFullscreen << LL_ENDL; - DestroyWindow(mWindowHandle); + if (!destroy_window_handler(mWindowHandle)) + { + LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL; + } mWindowHandle = CreateWindowEx(dw_ex_style, mWindowClassName, mWindowTitle, @@ -1453,8 +1461,12 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO ReleaseDC (mWindowHandle, mhDC); // Release The Device Context mhDC = 0; // Zero The Device Context } - DestroyWindow (mWindowHandle); // Destroy The Window - + + // Destroy The Window + if (!destroy_window_handler(mWindowHandle)) + { + LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL; + } mWindowHandle = CreateWindowEx(dw_ex_style, mWindowClassName, @@ -3397,7 +3409,10 @@ void LLSplashScreenWin32::hideImpl() { if (mWindow) { - DestroyWindow(mWindow); + if (!destroy_window_handler(mWindow)) + { + LL_WARNS("Window") << "Failed to properly close splash screen window!" << LL_ENDL; + } mWindow = NULL; } } diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index bc967c9bca..0bb62d79ff 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -98,7 +98,9 @@ private: bool mCanCut; bool mCanCopy; bool mCanPaste; + std::string mRootCachePath; std::string mCachePath; + std::string mContextCachePath; std::string mCefLogFile; bool mCefLogVerbose; std::vector mPickedFiles; @@ -458,7 +460,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "cleanup") { - mVolumeCatcher.setVolume(0); // Hack: masks CEF exit issues mCEFLib->requestExit(); } else if (message_name == "force_exit") @@ -527,7 +528,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.accept_language_list = mHostLanguage; settings.background_color = 0xffffffff; settings.cache_enabled = true; + settings.root_cache_path = mRootCachePath; settings.cache_path = mCachePath; + settings.context_cache_path = mContextCachePath; settings.cookies_enabled = mCookiesEnabled; settings.disable_gpu = mDisableGPU; #if LL_DARWIN @@ -583,9 +586,25 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (message_name == "set_user_data_path") { std::string user_data_path_cache = message_in.getValue("cache_path"); - std::string user_data_path_cookies = message_in.getValue("cookies_path"); + std::string subfolder = message_in.getValue("username"); - mCachePath = user_data_path_cache + "cef_cache"; + mRootCachePath = user_data_path_cache + "cef_cache"; + if (!subfolder.empty()) + { + std::string delim; +#if LL_WINDOWS + // media plugin doesn't have access to gDirUtilp + delim = "\\"; +#else + delim = "/"; +#endif + mCachePath = mRootCachePath + delim + subfolder; + } + else + { + mCachePath = mRootCachePath; + } + mContextCachePath = ""; // disabled by "" mCefLogFile = message_in.getValue("cef_log_file"); mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log"); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 70799f761c..1520c0ee69 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2149,7 +2149,7 @@ if (DARWIN) set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}") - set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2019") + set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2020") set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication") diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index e5a66bad38..d613169e88 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.4.11 +6.4.12 diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index 55e1d19f05..d133c6437b 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -30,12 +30,6 @@ #include "llhandle.h" #include "llaccountingcost.h" -#include "httpcommon.h" -#include "llcoros.h" -#include "lleventcoro.h" -#include "httprequest.h" -#include "httpheaders.h" -#include "httpoptions.h" //=============================================================================== // An interface class for panels which display the parcel accounting information. diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 166c2d67c8..e7e9404ded 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -137,6 +137,10 @@ public: EStatus getStatus() const {return mStatus;}; void setStatus(EStatus pStatus) {mStatus = pStatus;}; + static std::map sTeleportStatusName; + static const std::string& statusName(EStatus status); + virtual void toOstream(std::ostream& os) const; + virtual bool canRestartTeleport(); virtual void startTeleport() = 0; @@ -148,12 +152,19 @@ private: EStatus mStatus; }; +std::map LLTeleportRequest::sTeleportStatusName = { { kPending, "kPending" }, + { kStarted, "kStarted" }, + { kFailed, "kFailed" }, + { kRestartPending, "kRestartPending"} }; + class LLTeleportRequestViaLandmark : public LLTeleportRequest { public: LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId); virtual ~LLTeleportRequestViaLandmark(); + virtual void toOstream(std::ostream& os) const; + virtual bool canRestartTeleport(); virtual void startTeleport(); @@ -172,6 +183,8 @@ public: LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike); virtual ~LLTeleportRequestViaLure(); + virtual void toOstream(std::ostream& os) const; + virtual bool canRestartTeleport(); virtual void startTeleport(); @@ -189,6 +202,8 @@ public: LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal); virtual ~LLTeleportRequestViaLocation(); + virtual void toOstream(std::ostream& os) const; + virtual bool canRestartTeleport(); virtual void startTeleport(); @@ -208,6 +223,8 @@ public: LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal); virtual ~LLTeleportRequestViaLocationLookAt(); + virtual void toOstream(std::ostream& os) const; + virtual bool canRestartTeleport(); virtual void startTeleport(); @@ -492,6 +509,8 @@ void LLAgent::init() void LLAgent::cleanup() { mRegionp = NULL; + mTeleportRequest = NULL; + mTeleportCanceled = NULL; if (mTeleportFinishedSlot.connected()) { mTeleportFinishedSlot.disconnect(); @@ -867,7 +886,12 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (mRegionp != regionp) { - LL_INFOS("AgentLocation") << "Moving agent into region: " << regionp->getName() << LL_ENDL; + LL_INFOS("AgentLocation","Teleport") << "Moving agent into region: handle " << regionp->getHandle() + << " id " << regionp->getRegionID() + << " name " << regionp->getName() + << " previous region " + << (mRegionp ? mRegionp->getRegionID() : LLUUID::null) + << LL_ENDL; if (mRegionp) { // We've changed regions, we're now going to change our agent coordinate frame. @@ -2629,6 +2653,7 @@ void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity) else { mMaturityPreferenceNumRetries = 0; + LL_WARNS() << "Too many retries for maturity preference" << LL_ENDL; reportPreferredMaturityError(); } } @@ -2680,6 +2705,7 @@ void LLAgent::reportPreferredMaturityError() mIsMaturityRatingChangingDuringTeleport = false; if (hasPendingTeleportRequest()) { + LL_WARNS("Teleport") << "Teleport failing due to preferred maturity error" << LL_ENDL; setTeleportState(LLAgent::TELEPORT_NONE); } @@ -3775,7 +3801,7 @@ void LLAgent::clearVisualParams(void *data) // protected bool LLAgent::teleportCore(bool is_local) { - LL_INFOS("Teleport") << "In teleport core!" << LL_ENDL; + LL_DEBUGS("Teleport") << "In teleport core" << LL_ENDL; if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING)) { LL_WARNS() << "Attempt to teleport when already teleporting." << LL_ENDL; @@ -3841,11 +3867,13 @@ bool LLAgent::teleportCore(bool is_local) add(LLStatViewer::TELEPORT, 1); if (is_local) { + LL_INFOS("Teleport") << "Setting teleport state to TELEPORT_LOCAL" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_LOCAL ); } else { gTeleportDisplay = TRUE; + LL_INFOS("Teleport") << "Non-local, setting teleport state to TELEPORT_START" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_START ); //release geometry from old location @@ -3912,6 +3940,7 @@ void LLAgent::startTeleportRequest() if (!isMaturityPreferenceSyncedWithServer()) { gTeleportDisplay = TRUE; + LL_INFOS("Teleport") << "Maturity preference not synced yet, setting teleport state to TELEPORT_PENDING" << LL_ENDL; setTeleportState(TELEPORT_PENDING); } else @@ -3955,10 +3984,19 @@ void LLAgent::handleTeleportFinished() { if (mRegionp->capabilitiesReceived()) { + LL_DEBUGS("Teleport") << "capabilities have been received for region handle " + << mRegionp->getHandle() + << " id " << mRegionp->getRegionID() + << ", calling onCapabilitiesReceivedAfterTeleport()" + << LL_ENDL; onCapabilitiesReceivedAfterTeleport(); } else { + LL_DEBUGS("Teleport") << "Capabilities not yet received for region handle " + << mRegionp->getHandle() + << " id " << mRegionp->getRegionID() + << LL_ENDL; mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport)); } } @@ -3996,6 +4034,18 @@ void LLAgent::handleTeleportFailed() /*static*/ void LLAgent::onCapabilitiesReceivedAfterTeleport() { + if (gAgent.getRegion()) + { + LL_DEBUGS("Teleport") << "running after capabilities received callback has been triggered, agent region " + << gAgent.getRegion()->getHandle() + << " id " << gAgent.getRegion()->getRegionID() + << " name " << gAgent.getRegion()->getName() + << LL_ENDL; + } + else + { + LL_WARNS("Teleport") << "called when agent region is null!" << LL_ENDL; + } check_merchant_status(); } @@ -4009,8 +4059,8 @@ void LLAgent::teleportRequest( LLViewerRegion* regionp = getRegion(); if (regionp && teleportCore(region_handle == regionp->getHandle())) { - LL_INFOS("") << "TeleportLocationRequest: '" << region_handle << "':" - << pos_local << LL_ENDL; + LL_INFOS("Teleport") << "Sending TeleportLocationRequest: '" << region_handle << "':" + << pos_local << LL_ENDL; LLMessageSystem* msg = gMessageSystem; msg->newMessage("TeleportLocationRequest"); msg->nextBlockFast(_PREHASH_AgentData); @@ -4041,6 +4091,11 @@ void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id) LLViewerRegion *regionp = getRegion(); if(regionp && teleportCore()) { + LL_INFOS("Teleport") << "Sending TeleportLandmarkRequest. Current region handle " << regionp->getHandle() + << " region id " << regionp->getRegionID() + << " requested landmark id " << landmark_asset_id + << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_TeleportLandmarkRequest); msg->nextBlockFast(_PREHASH_Info); @@ -4073,6 +4128,11 @@ void LLAgent::doTeleportViaLure(const LLUUID& lure_id, BOOL godlike) teleport_flags |= TELEPORT_FLAGS_VIA_LURE; } + LL_INFOS("Teleport") << "Sending TeleportLureRequest." + << " Current region handle " << regionp->getHandle() + << " region id " << regionp->getRegionID() + << " lure id " << lure_id + << LL_ENDL; // send the message LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_TeleportLureRequest); @@ -4095,6 +4155,8 @@ void LLAgent::teleportCancel() LLViewerRegion* regionp = getRegion(); if(regionp) { + LL_INFOS("Teleport") << "Sending TeleportCancel" << LL_ENDL; + // send the message LLMessageSystem* msg = gMessageSystem; msg->newMessage("TeleportCancel"); @@ -4107,13 +4169,14 @@ void LLAgent::teleportCancel() } clearTeleportRequest(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); - gPipeline.resetVertexBuffers(); + gPipeline.resetVertexBuffers(); } void LLAgent::restoreCanceledTeleportRequest() { if (mTeleportCanceled != NULL) { + LL_INFOS() << "Restoring canceled teleport request, setting state to TELEPORT_REQUESTED" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); mTeleportRequest = mTeleportCanceled; mTeleportCanceled.reset(); @@ -4151,7 +4214,6 @@ void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global) else if(regionp && teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY]))) { - LL_WARNS() << "Using deprecated teleportlocationrequest." << LL_ENDL; // send the message LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_TeleportLocationRequest); @@ -4171,6 +4233,14 @@ void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global) msg->addVector3Fast(_PREHASH_Position, pos); pos.mV[VX] += 1; msg->addVector3Fast(_PREHASH_LookAt, pos); + + LL_WARNS("Teleport") << "Sending deprecated(?) TeleportLocationRequest." + << " pos_global " << pos_global + << " region_x " << region_x + << " region_y " << region_y + << " region_handle " << region_handle + << LL_ENDL; + sendReliableMessage(); } } @@ -4212,7 +4282,11 @@ void LLAgent::setTeleportState(ETeleportState state) " for previously failed teleport. Ignore!" << LL_ENDL; return; } - LL_DEBUGS("Teleport") << "Setting teleport state to " << state << " Previous state: " << mTeleportState << LL_ENDL; + LL_DEBUGS("Teleport") << "Setting teleport state to " + << LLAgent::teleportStateName(state) << "(" << state << ")" + << " Previous state: " + << teleportStateName(mTeleportState) << "(" << mTeleportState << ")" + << LL_ENDL; mTeleportState = state; if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime")) { @@ -4549,6 +4623,34 @@ void LLAgent::observeFriends() } } +std::map LLAgent::sTeleportStateName = { { TELEPORT_NONE, "TELEPORT_NONE" }, + { TELEPORT_START, "TELEPORT_START" }, + { TELEPORT_REQUESTED, "TELEPORT_REQUESTED" }, + { TELEPORT_MOVING, "TELEPORT_MOVING" }, + { TELEPORT_START_ARRIVAL, "TELEPORT_START_ARRIVAL" }, + { TELEPORT_ARRIVING, "TELEPORT_ARRIVING" }, + { TELEPORT_LOCAL, "TELEPORT_LOCAL" }, + { TELEPORT_PENDING, "TELEPORT_PENDING" } }; + +const std::string& LLAgent::teleportStateName(S32 state) +{ + static std::string invalid_state_str("INVALID"); + auto iter = LLAgent::sTeleportStateName.find(state); + if (iter != LLAgent::sTeleportStateName.end()) + { + return iter->second; + } + else + { + return invalid_state_str; + } +} + +const std::string& LLAgent::getTeleportStateName() const +{ + return teleportStateName(getTeleportState()); +} + void LLAgent::parseTeleportMessages(const std::string& xml_filename) { LLXMLNodePtr root; @@ -4672,40 +4774,70 @@ void LLTeleportRequest::restartTeleport() llassert(0); } +// TODO this enum -> name idiom should be in a common class rather than repeated various places. +const std::string& LLTeleportRequest::statusName(EStatus status) +{ + static std::string invalid_status_str("INVALID"); + auto iter = LLTeleportRequest::sTeleportStatusName.find(status); + if (iter != LLTeleportRequest::sTeleportStatusName.end()) + { + return iter->second; + } + else + { + return invalid_status_str; + } +} + +std::ostream& operator<<(std::ostream& os, const LLTeleportRequest& req) +{ + req.toOstream(os); + return os; +} + +void LLTeleportRequest::toOstream(std::ostream& os) const +{ + os << "status " << statusName(mStatus) << "(" << mStatus << ")"; +} + //----------------------------------------------------------------------------- // LLTeleportRequestViaLandmark //----------------------------------------------------------------------------- - LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId) : LLTeleportRequest(), mLandmarkId(pLandmarkId) { - LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark created." << LL_ENDL; + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark created, " << *this << LL_ENDL; } LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark() { - LL_INFOS("Teleport") << "~LLTeleportRequestViaLandmark" << LL_ENDL; + LL_INFOS("Teleport") << "~LLTeleportRequestViaLandmark, " << *this << LL_ENDL; +} + +void LLTeleportRequestViaLandmark::toOstream(std::ostream& os) const +{ + os << "landmark " << mLandmarkId << " "; + LLTeleportRequest::toOstream(os); } bool LLTeleportRequestViaLandmark::canRestartTeleport() { - LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::canRestartTeleport? -> true" << LL_ENDL; + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::canRestartTeleport? -> true, " << *this << LL_ENDL; return true; } void LLTeleportRequestViaLandmark::startTeleport() { - LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::startTeleport" << LL_ENDL; + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::startTeleport, " << *this << LL_ENDL; gAgent.doTeleportViaLandmark(getLandmarkId()); } void LLTeleportRequestViaLandmark::restartTeleport() { - LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::restartTeleport" << LL_ENDL; + LL_INFOS("Teleport") << "LLTeleportRequestViaLandmark::restartTeleport, " << *this << LL_ENDL; gAgent.doTeleportViaLandmark(getLandmarkId()); } - //----------------------------------------------------------------------------- // LLTeleportRequestViaLure //----------------------------------------------------------------------------- @@ -4722,6 +4854,12 @@ LLTeleportRequestViaLure::~LLTeleportRequestViaLure() LL_INFOS("Teleport") << "~LLTeleportRequestViaLure" << LL_ENDL; } +void LLTeleportRequestViaLure::toOstream(std::ostream& os) const +{ + os << "mIsLureGodLike " << (S32) mIsLureGodLike << " "; + LLTeleportRequestViaLandmark::toOstream(os); +} + bool LLTeleportRequestViaLure::canRestartTeleport() { // stinson 05/17/2012 : cannot restart a teleport via lure because of server-side restrictions @@ -4762,6 +4900,12 @@ LLTeleportRequestViaLocation::~LLTeleportRequestViaLocation() LL_INFOS("Teleport") << "~LLTeleportRequestViaLocation" << LL_ENDL; } +void LLTeleportRequestViaLocation::toOstream(std::ostream& os) const +{ + os << "mPosGlobal " << mPosGlobal << " "; + LLTeleportRequest::toOstream(os); +} + bool LLTeleportRequestViaLocation::canRestartTeleport() { LL_INFOS("Teleport") << "LLTeleportRequestViaLocation::canRestartTeleport -> true" << LL_ENDL; @@ -4795,6 +4939,11 @@ LLTeleportRequestViaLocationLookAt::~LLTeleportRequestViaLocationLookAt() LL_INFOS("Teleport") << "~LLTeleportRequestViaLocationLookAt" << LL_ENDL; } +void LLTeleportRequestViaLocationLookAt::toOstream(std::ostream& os) const +{ + LLTeleportRequestViaLocation::toOstream(os); +} + bool LLTeleportRequestViaLocationLookAt::canRestartTeleport() { LL_INFOS("Teleport") << "LLTeleportRequestViaLocationLookAt::canRestartTeleport -> true" << LL_ENDL; diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 88cce0b911..f72378f654 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -47,20 +47,15 @@ extern const BOOL ANIMATE; extern const U8 AGENT_STATE_TYPING; // Typing indication extern const U8 AGENT_STATE_EDITING; // Set when agent has objects selected -class LLChat; class LLViewerRegion; class LLMotion; -class LLToolset; class LLMessageSystem; class LLPermissions; class LLHost; class LLFriendObserver; -class LLPickInfo; -class LLViewerObject; class LLAgentDropGroupViewerNode; class LLAgentAccess; class LLSLURL; -class LLPauseRequestHandle; class LLUIColor; class LLTeleportRequest; @@ -91,8 +86,6 @@ struct LLGroupData class LLAgentListener; -class LLAgentImpl; - //------------------------------------------------------------------------ // LLAgent //------------------------------------------------------------------------ @@ -619,6 +612,10 @@ public: TELEPORT_PENDING = 7 }; + static std::map sTeleportStateName; + static const std::string& teleportStateName(S32); + const std::string& getTeleportStateName() const; + public: static void parseTeleportMessages(const std::string& xml_filename); const void getTeleportSourceSLURL(LLSLURL& slurl) const; diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 2411f0f86d..7f18ea6fe2 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -881,13 +881,6 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer AISAPI::sPostponedQuery; + +const S32 MAX_SIMULTANEOUS_COROUTINES = 2048; + //------------------------------------------------------------------------- /*static*/ bool AISAPI::isAvailable() @@ -366,9 +370,51 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t /*static*/ void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc) { + LLCoprocedureManager &inst = LLCoprocedureManager::instance(); + S32 pending_in_pool = inst.countPending("AIS"); std::string procFullName = "AIS(" + procName + ")"; - LLCoprocedureManager::instance().enqueueCoprocedure("AIS", procFullName, proc); + if (pending_in_pool < MAX_SIMULTANEOUS_COROUTINES) + { + inst.enqueueCoprocedure("AIS", procFullName, proc); + } + else + { + // As I understand it, coroutines have built-in 'pending' pool + // but unfortunately it has limited size which inventory often goes over + // so this is a workaround to not overfill it. + if (sPostponedQuery.empty()) + { + sPostponedQuery.push_back(ais_query_item_t(procFullName, proc)); + gIdleCallbacks.addFunction(onIdle, NULL); + } + else + { + sPostponedQuery.push_back(ais_query_item_t(procFullName, proc)); + } + } +} +/*static*/ +void AISAPI::onIdle(void *userdata) +{ + if (!sPostponedQuery.empty()) + { + LLCoprocedureManager &inst = LLCoprocedureManager::instance(); + S32 pending_in_pool = inst.countPending("AIS"); + while (pending_in_pool < MAX_SIMULTANEOUS_COROUTINES && !sPostponedQuery.empty()) + { + ais_query_item_t &item = sPostponedQuery.front(); + inst.enqueueCoprocedure("AIS", item.first, item.second); + sPostponedQuery.pop_front(); + pending_in_pool++; + } + } + + if (sPostponedQuery.empty()) + { + // Nothing to do anymore + gIdleCallbacks.deleteFunction(onIdle, NULL); + } } /*static*/ diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index e97059014b..856f3fc180 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -31,7 +31,6 @@ #include #include #include -#include "llhttpretrypolicy.h" #include "llviewerinventory.h" #include "llcorehttputil.h" #include "llcoproceduremanager.h" @@ -72,6 +71,7 @@ private: const std::string, LLSD, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t) > invokationFn_t; static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc); + static void onIdle(void *userdata); // launches postponed AIS commands static std::string getInvCap(); static std::string getLibCap(); @@ -80,6 +80,8 @@ private: invokationFn_t invoke, std::string url, LLUUID targetId, LLSD body, completion_t callback, COMMAND_TYPE type); + typedef std::pair ais_query_item_t; + static std::list sPostponedQuery; }; class AISUpdate diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 168b8eb47a..e5c505501e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3278,6 +3278,50 @@ void update_base_outfit_after_ordering() bool copy_folder_links = false; app_mgr.slamCategoryLinks(app_mgr.getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater); + if (base_outfit_id.notNull()) + { + LLIsValidItemLink collector; + + LLInventoryModel::cat_array_t cof_cats; + LLInventoryModel::item_array_t cof_item_array; + gInventory.collectDescendentsIf(app_mgr.getCOF(), cof_cats, cof_item_array, + LLInventoryModel::EXCLUDE_TRASH, collector); + + for (U32 i = 0; i < outfit_item_array.size(); ++i) + { + LLViewerInventoryItem* linked_item = outfit_item_array.at(i)->getLinkedItem(); + if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE) + { + outfit_item_array.erase(outfit_item_array.begin() + i); + break; + } + } + + if (outfit_item_array.size() != cof_item_array.size()) + { + return; + } + + std::sort(cof_item_array.begin(), cof_item_array.end(), sort_by_linked_uuid); + std::sort(outfit_item_array.begin(), outfit_item_array.end(), sort_by_linked_uuid); + + for (U32 i = 0; i < cof_item_array.size(); ++i) + { + LLViewerInventoryItem *cof_it = cof_item_array.at(i); + LLViewerInventoryItem *base_it = outfit_item_array.at(i); + + if (cof_it->getActualDescription() != base_it->getActualDescription()) + { + if (cof_it->getLinkedUUID() == base_it->getLinkedUUID()) + { + base_it->setDescription(cof_it->getActualDescription()); + gInventory.updateItem(base_it); + } + } + } + LLAppearanceMgr::getInstance()->updateIsDirty(); + } + } // Save COF changes - update the contents of the current base outfit diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 70b41a0a5f..515d6ffc14 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -527,7 +527,8 @@ bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base) LLIconCtrl* icon; - if(gAgent.isInGroup(match_id, TRUE)) + if( match->getMenuName() == "menu_url_group.xml" // See LLUrlEntryGroup constructor + || gAgent.isInGroup(match_id, TRUE)) //This check seems unfiting, urls are either /agent or /group { LLGroupIconCtrl::Params icon_params; icon_params.group_id = match_id; @@ -605,8 +606,9 @@ static void settings_to_globals() static void settings_modify() { LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred"); + LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred"); + LLPipeline::sRenderDeferred = LLPipeline::sRenderTransparentWater && LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred"); LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor"); LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; @@ -781,7 +783,7 @@ bool LLAppViewer::init() // initialize the LLSettingsType translation bridge. LLTranslationBridge::ptr_t trans = std::make_shared(); - LLSettingsType::initClass(trans); + LLSettingsType::initParamSingleton(trans); // initialize SSE options LLVector4a::initClass(); @@ -1024,13 +1026,27 @@ bool LLAppViewer::init() { // can't use an alert here since we're exiting and // all hell breaks lose. + LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"); OSMessageBox( - LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"), + details.getString(), LLStringUtil::null, OSMB_OK); return 0; } + // If we don't have the right shader requirements. + if (!gGLManager.mHasShaderObjects + || !gGLManager.mHasVertexShader + || !gGLManager.mHasFragmentShader) + { + LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedShaderRequirements"); + OSMessageBox( + details.getString(), + LLStringUtil::null, + OSMB_OK); + return 0; + } + // Without SSE2 support we will crash almost immediately, warn here. if (!gSysCPU.hasSSE2()) { @@ -1501,8 +1517,10 @@ bool LLAppViewer::doFrame() } // yield cooperatively when not running as foreground window - if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) - || !gFocusMgr.getAppHasFocus()) + // and when not quiting (causes trouble at mac's cleanup stage) + if (!LLApp::isExiting() + && ((gViewerWindow && !gViewerWindow->getWindow()->getVisible()) + || !gFocusMgr.getAppHasFocus())) { // Sleep if we're not rendering, or the window is minimized. static LLCachedControl s_bacground_yeild_time(gSavedSettings, "BackgroundYieldTime", 40); @@ -2100,8 +2118,6 @@ bool LLAppViewer::cleanup() LLError::LLCallStacks::cleanup(); - removeMarkerFiles(); - // It's not at first obvious where, in this long sequence, a generic cleanup // call OUGHT to go. So let's say this: as we migrate cleanup from // explicit hand-placed calls into the generic mechanism, eventually @@ -2109,14 +2125,12 @@ bool LLAppViewer::cleanup() // still see above are calls that MUST happen before the generic cleanup // kicks in. - // The logging subsystem depends on an LLSingleton. Any logging after - // LLSingletonBase::deleteAll() won't be recorded. - LL_INFOS() << "Goodbye!" << LL_ENDL; - // This calls every remaining LLSingleton's cleanupSingleton() and // deleteSingleton() methods. LLSingletonBase::deleteAll(); + LL_INFOS() << "Goodbye!" << LL_ENDL; + removeDumpDir(); // return 0; diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index a4ef762e8b..90aeff3032 100644 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -30,8 +30,6 @@ #include "llsingleton.h" -class LLViewerInventoryItem; - //-------------------------------------------------------------------------------- // LLAttachmentsMgr // diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index a1dacd1a27..c510e86958 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -31,7 +31,6 @@ #include "lliconctrl.h" #include "llavatarpropertiesprocessor.h" -#include "llviewermenu.h" class LLAvatarName; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 36d18114aa..b95cd68526 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -30,7 +30,6 @@ #include #include "llpanel.h" -#include "lloutputmonitorctrl.h" #include "llbutton.h" #include "lltextbox.h" #include "llstyle.h" @@ -38,6 +37,7 @@ #include "llcallingcard.h" // for LLFriendObserver class LLAvatarIconCtrl; +class LLOutputMonitorCtrl; class LLAvatarName; class LLIconCtrl; diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 54c6c985d6..3ab5c669c4 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -57,7 +57,6 @@ #include "llinventorymodel.h" #include "llmultigesture.h" #include "llui.h" -#include "llviewermenu.h" #include "lluictrlfactory.h" // diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 431a8c60be..2ba2c6d8b5 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -64,6 +64,7 @@ #include "llstring.h" #include "llurlaction.h" #include "llviewercontrol.h" +#include "llviewermenu.h" #include "llviewerobjectlist.h" static LLDefaultChildRegistry::Register r("chat_history"); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 4f42868f1a..1c22e055bb 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llchatitemscontainerctrl.h" +#include "llchatmsgbox.h" #include "lltextbox.h" #include "llavataractions.h" diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index f66670ec8c..ebff9ca298 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -28,12 +28,13 @@ #define LL_LLCHATITEMSCONTAINERCTRL_H_ #include "llchat.h" -#include "llchatmsgbox.h" #include "llpanel.h" #include "llscrollbar.h" #include "llviewerchat.h" #include "lltoastpanel.h" +class LLChatMsgBox; + typedef enum e_show_item_header { CHATITEMHEADER_SHOW_ONLY_NAME = 0, diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 8d89455cd4..0f187b0ecf 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -36,6 +36,7 @@ #include "llsingleton.h" #include "llsyswellwindow.h" #include "llfloaternotificationstabbed.h" +#include "llviewermenu.h" static LLDefaultChildRegistry::Register t1("chiclet_panel"); static LLDefaultChildRegistry::Register t2("chiclet_notification"); diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 1caefd58ab..b31981b235 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -140,10 +140,31 @@ protected: { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Attachment.Touch", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs)); + registrar.add("Attachment.Edit", boost::bind(handleMultiple, handle_item_edit, mUUIDs)); registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + enable_registrar.add("Attachment.OnEnable", boost::bind(&CofAttachmentContextMenu::onEnable, this, _2)); + return createFromFile("menu_cof_attachment.xml"); } + + bool onEnable(const LLSD& userdata) + { + const std::string event_name = userdata.asString(); + + if ("touch" == event_name) + { + return (1 == mUUIDs.size()) && (enable_attachment_touch(mUUIDs.front())); + } + else if ("edit" == event_name) + { + return (1 == mUUIDs.size()) && (get_is_item_editable(mUUIDs.front())); + } + + return true; + } }; ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h index 380fdccfa3..a17cab486a 100644 --- a/indra/newview/llcolorswatch.h +++ b/indra/newview/llcolorswatch.h @@ -36,7 +36,6 @@ // Classes // class LLColor4; -class LLFloaterColorPicker; class LLColorSwatchCtrl : public LLUICtrl diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index fe14bc081f..06d959ba3c 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -402,23 +402,30 @@ bool LLCommandLineParser::parseCommandLineString(const std::string& str) } } - // Split the string content into tokens - const char* escape_chars = "\\"; - const char* separator_chars = "\r\n "; - const char* quote_chars = "\"'"; - boost::escaped_list_separator sep(escape_chars, separator_chars, quote_chars); - boost::tokenizer< boost::escaped_list_separator > tok(cmd_line_string, sep); std::vector tokens; - // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); - for(boost::tokenizer< boost::escaped_list_separator >::iterator i = tok.begin(); - i != tok.end(); - ++i) + try { - if(0 != i->size()) + // Split the string content into tokens + const char* escape_chars = "\\"; + const char* separator_chars = "\r\n "; + const char* quote_chars = "\"'"; + boost::escaped_list_separator sep(escape_chars, separator_chars, quote_chars); + boost::tokenizer< boost::escaped_list_separator > tok(cmd_line_string, sep); + // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); + for (boost::tokenizer< boost::escaped_list_separator >::iterator i = tok.begin(); + i != tok.end(); + ++i) { - tokens.push_back(*i); + if (0 != i->size()) + { + tokens.push_back(*i); + } } } + catch (...) + { + CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("Unexpected crash while parsing: " << str)); + } po::command_line_parser clp(tokens); return parseAndStoreResults(clp); diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h index 1b3d8f83a0..adb854875a 100644 --- a/indra/newview/llcompilequeue.h +++ b/indra/newview/llcompilequeue.h @@ -29,14 +29,11 @@ #include "llinventory.h" #include "llviewerobject.h" -#include "llvoinventorylistener.h" #include "lluuid.h" #include "llfloater.h" #include "llscrolllistctrl.h" -#include "llviewerinventory.h" - #include "llevents.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index c258136889..4aa74a550c 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -92,6 +92,23 @@ LLConversationItem::~LLConversationItem() } } +//virtual +void LLConversationItem::addChild(LLFolderViewModelItem* child) +{ + // Avoid duplicates: bail out if that child is already present in the list + // Note: this happens when models are created and 'parented' before views + // This is performance unfriendly, but conversation can addToFolder multiple times + child_list_t::const_iterator iter; + for (iter = mChildren.begin(); iter != mChildren.end(); iter++) + { + if (child == *iter) + { + return; + } + } + LLFolderViewModelItemCommon::addChild(child); +} + void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant) { LLUUID session_id = (session ? session->getUUID() : LLUUID()); diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 80385fad5f..30c7481864 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -96,6 +96,7 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { } virtual BOOL isUpToDate() const { return TRUE; } virtual bool hasChildren() const { return FALSE; } + virtual void addChild(LLFolderViewModelItem* child); virtual bool potentiallyVisible() { return true; } virtual bool filter( LLFolderViewFilter& filter) { return false; } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 60a5204547..093e772abe 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -430,7 +430,7 @@ void LLConversationViewSession::refresh() // Refresh the session view from its model data LLConversationItem* vmi = dynamic_cast(getViewModelItem()); vmi->resetRefresh(); - + if (mSessionTitle) { mSessionTitle->setText(vmi->getDisplayName()); @@ -545,7 +545,9 @@ BOOL LLConversationViewParticipant::postBuild() } updateChildren(); - return LLFolderViewItem::postBuild(); + LLFolderViewItem::postBuild(); + refresh(); + return TRUE; } void LLConversationViewParticipant::draw() @@ -619,7 +621,7 @@ void LLConversationViewParticipant::refresh() // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted()); - + // Do the regular upstream refresh LLFolderViewItem::refresh(); } diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 420c250dfe..c5930c8a29 100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -34,6 +34,7 @@ #include "lloutputmonitorctrl.h" class LLTextBox; +class LLFloater; class LLFloaterIMContainer; class LLConversationViewSession; class LLConversationViewParticipant; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 6fc39f213e..87772d9eb6 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -38,7 +38,6 @@ #include "lldrawable.h" #include "lldrawpoolbump.h" #include "llface.h" -#include "llvolume.h" #include "llmeshrepository.h" #include "llsky.h" #include "llviewercamera.h" diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 7249f22555..aa426cd785 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -163,7 +163,7 @@ void LLDrawPoolWater::render(S32 pass) std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); // See if we are rendering water as opaque or not - if (!gSavedSettings.getBOOL("RenderTransparentWater")) + if (!LLPipeline::sRenderTransparentWater) { // render water for low end hardware renderOpaqueLegacyWater(); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 342ee3ccf5..e56ed92d9e 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -806,6 +806,25 @@ const F32 LLEnvironment::SUN_DELTA_YAW(F_PI); // 180deg const U32 LLEnvironment::DayInstance::NO_ANIMATE_SKY(0x01); const U32 LLEnvironment::DayInstance::NO_ANIMATE_WATER(0x02); +std::string env_selection_to_string(LLEnvironment::EnvSelection_t sel) +{ +#define RTNENUM(E) case LLEnvironment::E: return #E + switch (sel){ + RTNENUM(ENV_EDIT); + RTNENUM(ENV_LOCAL); + RTNENUM(ENV_PUSH); + RTNENUM(ENV_PARCEL); + RTNENUM(ENV_REGION); + RTNENUM(ENV_DEFAULT); + RTNENUM(ENV_END); + RTNENUM(ENV_CURRENT); + RTNENUM(ENV_NONE); + default: + return llformat("Unknown(%d)", sel); + } +#undef RTNENUM +} + //------------------------------------------------------------------------- LLEnvironment::LLEnvironment(): @@ -981,7 +1000,7 @@ bool LLEnvironment::canAgentUpdateRegionEnvironment() const if (gAgent.isGodlike()) return true; - return gAgent.getRegion()->canManageEstate(); + return gAgent.canManageEstate(); } bool LLEnvironment::isExtendedEnvironmentEnabled() const @@ -1037,7 +1056,8 @@ F32 LLEnvironment::getCamHeight() const F32 LLEnvironment::getWaterHeight() const { - return gAgent.getRegion()->getWaterHeight(); + LLViewerRegion* cur_region = gAgent.getRegion(); + return cur_region ? cur_region->getWaterHeight() : DEFAULT_WATER_HEIGHT; } bool LLEnvironment::getIsSunUp() const @@ -1059,6 +1079,7 @@ void LLEnvironment::setSelectedEnvironment(LLEnvironment::EnvSelection_t env, LL { mSelectedEnvironment = env; updateEnvironment(transition, forced); + LL_DEBUGS("ENVIRONMENT") << "Setting environment " << env_selection_to_string(env) << " with transition: " << transition << LL_ENDL; } bool LLEnvironment::hasEnvironment(LLEnvironment::EnvSelection_t env) @@ -1095,11 +1116,13 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getEnvironmentInstance(LLEnviro void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version) { if ((env < ENV_EDIT) || (env >= ENV_DEFAULT)) - { - LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL; + { + LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL; return; } + logEnvironment(env, pday, env_version); + DayInstance::ptr_t environment = getEnvironmentInstance(env, true); environment->clear(); @@ -1116,7 +1139,7 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm { if ((env < ENV_EDIT) || (env >= ENV_DEFAULT)) { - LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL; + LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL; return; } @@ -1125,30 +1148,32 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm if (fixed.first) { + logEnvironment(env, fixed.first, env_version); environment->setSky(fixed.first); environment->setFlags(DayInstance::NO_ANIMATE_SKY); } else if (!environment->getSky()) { + LL_DEBUGS("ENVIRONMENT") << "Blank sky for " << env_selection_to_string(env) << ". Reusing environment for sky." << LL_ENDL; environment->setSky(mCurrentEnvironment->getSky()); environment->setFlags(DayInstance::NO_ANIMATE_SKY); } if (fixed.second) { + logEnvironment(env, fixed.second, env_version); environment->setWater(fixed.second); environment->setFlags(DayInstance::NO_ANIMATE_WATER); } else if (!environment->getWater()) { + LL_DEBUGS("ENVIRONMENT") << "Blank water for " << env_selection_to_string(env) << ". Reusing environment for water." << LL_ENDL; environment->setWater(mCurrentEnvironment->getWater()); environment->setFlags(DayInstance::NO_ANIMATE_WATER); } if (!mSignalEnvChanged.empty()) mSignalEnvChanged(env, env_version); - - /*TODO: readjust environment*/ } void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version) @@ -1221,10 +1246,12 @@ void LLEnvironment::onSetEnvAssetLoaded(EnvSelection_t env, if (!settings || status) { LLSD args; - args["DESC"] = asset_id.asString(); + args["NAME"] = asset_id.asString(); LLNotificationsUtil::add("FailedToFindSettings", args); + LL_DEBUGS("ENVIRONMENT") << "Failed to find settings for " << env_selection_to_string(env) << ", asset_id: " << asset_id << LL_ENDL; return; } + LL_DEBUGS("ENVIRONMENT") << "Loaded asset: " << asset_id << LL_ENDL; setEnvironment(env, settings); updateEnvironment(transition); @@ -1238,19 +1265,48 @@ void LLEnvironment::clearEnvironment(LLEnvironment::EnvSelection_t env) return; } + LL_DEBUGS("ENVIRONMENT") << "Cleaning environment " << env_selection_to_string(env) << LL_ENDL; + mEnvironments[env].reset(); if (!mSignalEnvChanged.empty()) mSignalEnvChanged(env, VERSION_CLEANUP); +} - /*TODO: readjust environment*/ +void LLEnvironment::logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version) +{ + LL_DEBUGS("ENVIRONMENT") << "Setting Day environment " << env_selection_to_string(env) << " with version(update type): " << env_version << LL_NEWLINE; + // code between LL_DEBUGS and LL_ENDL won't execute unless log is enabled + if (settings) + { + LLUUID asset_id = settings->getAssetId(); + if (asset_id.notNull()) + { + LL_CONT << "Asset id: " << asset_id << LL_NEWLINE; + } + + LLUUID id = settings->getId(); // Not in use? + if (id.notNull()) + { + LL_CONT << "Settings id: " << id << LL_NEWLINE; + } + + LL_CONT << "Name: " << settings->getName() << LL_NEWLINE + << "Type: " << settings->getSettingsType() << LL_NEWLINE + << "Flags: " << settings->getFlags(); // Not in use? + } + else + { + LL_CONT << "Empty settings!"; + } + LL_CONT << LL_ENDL; } LLSettingsDay::ptr_t LLEnvironment::getEnvironmentDay(LLEnvironment::EnvSelection_t env) { if ((env < ENV_EDIT) || (env > ENV_DEFAULT)) { - LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL; + LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL; return LLSettingsDay::ptr_t(); } @@ -1266,7 +1322,7 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayLength(EnvSelection_t env { if ((env < ENV_EDIT) || (env > ENV_DEFAULT)) { - LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL; + LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL; return LLSettingsDay::Seconds(0); } @@ -1282,7 +1338,7 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayOffset(EnvSelection_t env { if ((env < ENV_EDIT) || (env > ENV_DEFAULT)) { - LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL; + LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL; return LLSettingsDay::Seconds(0); } @@ -1325,7 +1381,7 @@ LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironme if ((env < ENV_EDIT) || (env > ENV_DEFAULT)) { - LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL; + LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL; return fixedEnvironment_t(); } @@ -2361,7 +2417,7 @@ void LLEnvironment::onSetExperienceEnvAssetLoaded(LLUUID experience_id, LLSettin if (!settings || status) { LLSD args; - args["DESC"] = experience_id.asString(); + args["NAME"] = experience_id.asString(); LLNotificationsUtil::add("FailedToFindSettings", args); return; } @@ -3332,7 +3388,7 @@ namespace return; } - LL_WARNS("PUSHENV") << "Underlying environment has changed (" << env << ")! Base env is type " << base_env << LL_ENDL; + LL_WARNS("PUSHENV", "ENVIRONMENT") << "Underlying environment has changed (" << env << ")! Base env is type " << base_env << LL_ENDL; LLEnvironment::DayInstance::ptr_t trans = std::make_shared(std::static_pointer_cast(shared_from_this()), mBaseDayInstance->getSky(), mBaseDayInstance->getWater(), nextbase, LLEnvironment::TRANSITION_DEFAULT); diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index 91c4b85135..6ab0db7501 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -148,8 +148,11 @@ public: void setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version = NO_VERSION); void setSharedEnvironment(); - void clearEnvironment(EnvSelection_t env); + + static void logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version = NO_VERSION); + + LLSettingsDay::ptr_t getEnvironmentDay(EnvSelection_t env); LLSettingsDay::Seconds getEnvironmentDayLength(EnvSelection_t env); LLSettingsDay::Seconds getEnvironmentDayOffset(EnvSelection_t env); diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index dd2baacb7e..580a3f2610 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -84,7 +84,10 @@ BOOL LLFloaterConversationPreview::postBuild() file = "chat"; } mChatHistoryFileName = file; - + if (mIsGroup && !LLStringUtil::endsWith(mChatHistoryFileName, GROUP_CHAT_SUFFIX)) + { + mChatHistoryFileName += GROUP_CHAT_SUFFIX; + } LLStringUtil::format_map_t args; args["[NAME]"] = name; std::string title = getString("Title", args); diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index ea22043de8..a7c2cbbeaa 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -1498,7 +1498,7 @@ void LLFloaterEditExtDayCycle::onAssetLoaded(LLUUID asset_id, LLSettingsBase::pt if (!settings || status) { LLSD args; - args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : "Unknown"; + args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString(); LLNotificationsUtil::add("FailedToFindSettings", args); closeFloater(); return; diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp index 37e162b249..cd8e0a48e7 100644 --- a/indra/newview/llfloaterfixedenvironment.cpp +++ b/indra/newview/llfloaterfixedenvironment.cpp @@ -346,7 +346,7 @@ void LLFloaterFixedEnvironment::onAssetLoaded(LLUUID asset_id, LLSettingsBase::p if (!settings || status) { LLSD args; - args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : "Unknown"; + args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString(); LLNotificationsUtil::add("FailedToFindSettings", args); closeFloater(); return; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 82ce97f311..2a05f82f94 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -54,6 +54,7 @@ #include "llcallbacklist.h" #include "llworld.h" #include "llsdserialize.h" +#include "llviewermenu.h" // is_agent_mappable #include "llviewerobjectlist.h" #include "boost/foreach.hpp" diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 96094dcf14..1cd8841bb4 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1322,9 +1322,11 @@ void LLFloaterPreference::refreshEnabledState() //Deferred/SSAO/Shadows BOOL bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump"); + BOOL transparent_water = LLFeatureManager::getInstance()->isFeatureAvailable("RenderTransparentWater") && gSavedSettings.getBOOL("RenderTransparentWater"); BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && bumpshiny && + transparent_water && shaders && gGLManager.mHasFramebufferObject && gSavedSettings.getBOOL("RenderAvatarVP") && @@ -1347,7 +1349,10 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps; ctrl_reflections->setEnabled(reflections); reflections_text->setEnabled(reflections); - + + // Transparent Water + LLCheckBoxCtrl* transparent_water_ctrl = getChild("TransparentWater"); + // Bump & Shiny LLCheckBoxCtrl* bumpshiny_ctrl = getChild("BumpShiny"); bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); @@ -1398,6 +1403,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState() BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) && + ((transparent_water_ctrl && transparent_water_ctrl->get()) ? TRUE : FALSE) && gGLManager.mHasFramebufferObject && gSavedSettings.getBOOL("RenderAvatarVP") && (ctrl_wind_light->get()) ? TRUE : FALSE; diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index bcba14d63d..8221b0a637 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -34,6 +34,7 @@ class LLSpinCtrl; class LLSnapshotLivePreview; +class LLToolset; class LLFloaterSnapshotBase : public LLFloater { diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index fce945df6c..97e99297cf 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -33,7 +33,6 @@ #define LL_LLFLOATERWORLDMAP_H #include "llfloater.h" -#include "llhudtext.h" #include "llmapimagetype.h" #include "lltracker.h" #include "llslurl.h" diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 2f7a98c86c..ce128519ea 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -102,7 +102,7 @@ protected: static void sortObjects(); LLHUDObject(const U8 type); - ~LLHUDObject(); + virtual ~LLHUDObject(); virtual void render() = 0; virtual void renderForTimer() {}; diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 82824861a9..72d28a3d44 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -565,7 +565,10 @@ S32 LLHUDText::getMaxLines() void LLHUDText::markDead() { - sTextObjects.erase(LLPointer(this)); + // make sure we have at least one pointer + // till the end of the function + LLPointer ptr(this); + sTextObjects.erase(ptr); LLHUDObject::markDead(); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 67d65547b6..ae96963b2a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -6420,6 +6420,14 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) { LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. } + else if ("touch" == action) + { + handle_attachment_touch(mUUID); + } + else if ("edit" == action) + { + handle_attachment_edit(mUUID); + } else if (isRemoveAction(action)) { LLAppearanceMgr::instance().removeItemFromAvatar(mUUID); @@ -6570,6 +6578,19 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if( get_is_item_worn( mUUID ) ) { items.push_back(std::string("Wearable And Object Separator")); + + items.push_back(std::string("Attachment Touch")); + if ( ((flags & FIRST_SELECTED_ITEM) == 0) || !enable_attachment_touch(mUUID) ) + { + disabled_items.push_back(std::string("Attachment Touch")); + } + + items.push_back(std::string("Wearable Edit")); + if ( ((flags & FIRST_SELECTED_ITEM) == 0) || !get_is_item_editable(mUUID) ) + { + disabled_items.push_back(std::string("Wearable Edit")); + } + items.push_back(std::string("Detach From Yourself")); } else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder()) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 9eb84ed259..628363a47e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -78,6 +78,7 @@ #include "lltooldraganddrop.h" #include "lltrans.h" #include "lluictrlfactory.h" +#include "llviewermenu.h" #include "llviewermessage.h" #include "llviewerfoldertype.h" #include "llviewerobjectlist.h" @@ -655,6 +656,50 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id) return TRUE; } +bool get_is_item_editable(const LLUUID& inv_item_id) +{ + if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id)) + { + switch (inv_item->getType()) + { + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_CLOTHING: + return gAgentWearables.isWearableModifiable(inv_item_id); + case LLAssetType::AT_OBJECT: + return true; + default: + return false;; + } + } + return gAgentAvatarp->getWornAttachment(inv_item_id) != nullptr; +} + +void handle_item_edit(const LLUUID& inv_item_id) +{ + if (get_is_item_editable(inv_item_id)) + { + if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id)) + { + switch (inv_item->getType()) + { + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_CLOTHING: + LLAgentWearables::editWearable(inv_item_id); + break; + case LLAssetType::AT_OBJECT: + handle_attachment_edit(inv_item_id); + break; + default: + break; + } + } + else + { + handle_attachment_edit(inv_item_id); + } + } +} + BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id) { // NOTE: This function doesn't check the folder's children. diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index fd106bc2d8..04eb962372 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -53,6 +53,10 @@ BOOL get_can_item_be_worn(const LLUUID& id); BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id); +// Performs the appropiate edit action (if one exists) for this item +bool get_is_item_editable(const LLUUID& inv_item_id); +void handle_item_edit(const LLUUID& inv_item_id); + BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id); BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a44a54632c..48187c6179 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -56,6 +56,7 @@ #include "llcallbacklist.h" #include "llvoavatarself.h" #include "llgesturemgr.h" +#include "llsdserialize.h" #include "llsdutil.h" #include "bufferarray.h" #include "bufferstream.h" @@ -76,8 +77,8 @@ BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; ///---------------------------------------------------------------------------- //BOOL decompress_file(const char* src_filename, const char* dst_filename); -static const char PRODUCTION_CACHE_FORMAT_STRING[] = "%s.inv"; -static const char GRID_CACHE_FORMAT_STRING[] = "%s.%s.inv"; +static const char PRODUCTION_CACHE_FORMAT_STRING[] = "%s.inv.llsd"; +static const char GRID_CACHE_FORMAT_STRING[] = "%s.%s.inv.llsd"; static const char * const LOG_INV("Inventory"); struct InventoryIDPtrLess @@ -683,17 +684,59 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv LLUUID categoryId = result["folder_id"].asUUID(); - // Add the category to the internal representation - LLPointer cat = new LLViewerInventoryCategory(categoryId, - result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), - result["name"].asString(), gAgent.getID()); + LLViewerInventoryCategory* folderp = gInventory.getCategory(categoryId); + if (!folderp) + { + // Add the category to the internal representation + LLPointer cat = new LLViewerInventoryCategory(categoryId, + result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), + result["name"].asString(), gAgent.getID()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 - cat->setDescendentCount(0); - LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); - - accountForUpdate(update); - updateCategory(cat); + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + accountForUpdate(update); + + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 + cat->setDescendentCount(0); + updateCategory(cat); + } + else + { + // bulk processing was faster than coroutine (coro request->processBulkUpdateInventory->coro response) + // category already exists, but needs an update + if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_INITIAL + || folderp->getDescendentCount() != LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) + { + LL_WARNS() << "Inventory desync on folder creation. Newly created folder already has descendants or got a version.\n" + << "Name: " << folderp->getName() + << " Id: " << folderp->getUUID() + << " Version: " << folderp->getVersion() + << " Descendants: " << folderp->getDescendentCount() + << LL_ENDL; + } + // Recreate category with correct values + // Creating it anew just simplifies figuring out needed change-masks + // and making all needed updates, see updateCategory + LLPointer cat = new LLViewerInventoryCategory(categoryId, + result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), + result["name"].asString(), gAgent.getID()); + + if (folderp->getParentUUID() != cat->getParentUUID()) + { + LL_WARNS() << "Inventory desync on folder creation. Newly created folder has wrong parent.\n" + << "Name: " << folderp->getName() + << " Id: " << folderp->getUUID() + << " Expected parent: " << cat->getParentUUID() + << " Actual parent: " << folderp->getParentUUID() + << LL_ENDL; + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + accountForUpdate(update); + } + // else: Do not update parent, parent is already aware of the change. See processBulkUpdateInventory + + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 + cat->setDescendentCount(0); + updateCategory(cat); + } if (callback) { @@ -908,16 +951,29 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) LLUUID new_parent_id = item->getParentUUID(); bool update_parent_on_server = false; - if (new_parent_id.isNull()) + if (new_parent_id.isNull() && !LLApp::isExiting()) { - // item with null parent will end in random location and then in Lost&Found, - // either move to default folder as if it is new item or don't move at all - LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID() - << " to null folder. Moving to Lost&Found. Old item name: " << old_item->getName() - << ". New name: " << item->getName() - << "." << LL_ENDL; - new_parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - update_parent_on_server = true; + if (old_parent_id.isNull()) + { + // Item with null parent will end in random location and then in Lost&Found, + // either move to default folder as if it is new item or don't move at all + LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID() + << " to null folder. Moving to Lost&Found. Old item name: " << old_item->getName() + << ". New name: " << item->getName() + << "." << LL_ENDL; + new_parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + update_parent_on_server = true; + } + else + { + // Probably not the best way to handle this, we might encounter real case of 'lost&found' at some point + LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID() + << " to null folder. Old parent not null. Moving to old parent. Old item name: " << old_item->getName() + << ". New name: " << item->getName() + << "." << LL_ENDL; + new_parent_id = old_parent_id; + update_parent_on_server = true; + } } if(old_parent_id != new_parent_id) @@ -2653,29 +2709,37 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, { if(filename.empty()) { - LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL; + LL_ERRS(LOG_INV) << "filename is Null!" << LL_ENDL; return false; } - LL_INFOS(LOG_INV) << "LLInventoryModel::loadFromFile(" << filename << ")" << LL_ENDL; - LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ - if(!file) + LL_INFOS(LOG_INV) << "loading inventory from: (" << filename << ")" << LL_ENDL; + + llifstream file(filename.c_str()); + + if (!file.is_open()) { LL_INFOS(LOG_INV) << "unable to load inventory from: " << filename << LL_ENDL; return false; } - // *NOTE: This buffer size is hard coded into scanf() below. - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - char keyword[MAX_STRING]; /*Flawfinder: ignore*/ - char value[MAX_STRING]; /*Flawfinder: ignore*/ - is_cache_obsolete = true; // Obsolete until proven current - while(!feof(file) && fgets(buffer, MAX_STRING, file)) + + is_cache_obsolete = true; // Obsolete until proven current + + std::string line; + LLPointer parser = new LLSDNotationParser(); + while (std::getline(file, line)) { - sscanf(buffer, " %126s %126s", keyword, value); /* Flawfinder: ignore */ - if(0 == strcmp("inv_cache_version", keyword)) + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) { - S32 version; - int succ = sscanf(value,"%d",&version); - if ((1 == succ) && (version == sCurrentInvCacheVersion)) + LL_WARNS(LOG_INV)<< "Parsing inventory cache failed" << LL_ENDL; + break; + } + + if (s_item.has("inv_cache_version")) + { + S32 version = s_item["inv_cache_version"].asInteger(); + if (version == sCurrentInvCacheVersion) { // Cache is up to date is_cache_obsolete = false; @@ -2683,43 +2747,33 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, } else { - // Cache is out of date + LL_WARNS(LOG_INV)<< "Inventory cache is out of date" << LL_ENDL; break; } } - else if(0 == strcmp("inv_category", keyword)) + else if (s_item.has("cat_id")) { if (is_cache_obsolete) break; - + LLPointer inv_cat = new LLViewerInventoryCategory(LLUUID::null); - if(inv_cat->importFileLocal(file)) + if(inv_cat->importLLSD(s_item)) { categories.push_back(inv_cat); } - else - { - LL_WARNS(LOG_INV) << "loadInventoryFromFile(). Ignoring invalid inventory category: " << inv_cat->getName() << LL_ENDL; - //delete inv_cat; // automatic when inv_cat is reassigned or destroyed - } } - else if(0 == strcmp("inv_item", keyword)) + else if (s_item.has("item_id")) { if (is_cache_obsolete) break; LLPointer inv_item = new LLViewerInventoryItem; - if( inv_item->importFileLocal(file) ) + if( inv_item->fromLLSD(s_item) ) { - // *FIX: Need a better solution, this prevents the - // application from freezing, but breaks inventory - // caching. if(inv_item->getUUID().isNull()) { - //delete inv_item; // automatic when inv_cat is reassigned or destroyed LL_WARNS(LOG_INV) << "Ignoring inventory with null item id: " - << inv_item->getName() << LL_ENDL; - + << inv_item->getName() << LL_ENDL; } else { @@ -2732,62 +2786,63 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, items.push_back(inv_item); } } - } - else - { - LL_WARNS(LOG_INV) << "loadInventoryFromFile(). Ignoring invalid inventory item: " << inv_item->getName() << LL_ENDL; - //delete inv_item; // automatic when inv_cat is reassigned or destroyed - } - } - else - { - LL_WARNS(LOG_INV) << "Unknown token in inventory file '" << keyword << "'" - << LL_ENDL; + } } } - fclose(file); - if (is_cache_obsolete) - return false; - return true; + + file.close(); + + return !is_cache_obsolete; } // static bool LLInventoryModel::saveToFile(const std::string& filename, - const cat_array_t& categories, - const item_array_t& items) + const cat_array_t& categories, + const item_array_t& items) { - if(filename.empty()) + if (filename.empty()) { LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL; return false; } - LL_INFOS(LOG_INV) << "LLInventoryModel::saveToFile(" << filename << ")" << LL_ENDL; - LLFILE* file = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ - if(!file) + + LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL; + + llofstream fileXML(filename.c_str()); + if (!fileXML.is_open()) { LL_WARNS(LOG_INV) << "unable to save inventory to: " << filename << LL_ENDL; return false; } - fprintf(file, "\tinv_cache_version\t%d\n",sCurrentInvCacheVersion); + LLSD cache_ver; + cache_ver["inv_cache_version"] = sCurrentInvCacheVersion; + + fileXML << LLSDOStreamer(cache_ver) << std::endl; + S32 count = categories.size(); + S32 cat_count = 0; S32 i; for(i = 0; i < count; ++i) { LLViewerInventoryCategory* cat = categories[i]; if(cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) { - cat->exportFileLocal(file); + fileXML << LLSDOStreamer(cat->exportLLSD()) << std::endl; + cat_count++; } } - count = items.size(); - for(i = 0; i < count; ++i) + S32 it_count = items.size(); + for(i = 0; i < it_count; ++i) { - items[i]->exportFile(file); + fileXML << LLSDOStreamer(items[i]->asLLSD()) << std::endl; } - fclose(file); + fileXML.close(); + + LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL; + return true; } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 740c27ae8b..0246878ab6 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -146,7 +146,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mCompletionObserver(NULL), mScroller(NULL), mSortOrderSetting(p.sort_order_setting), - mInventory(p.inventory), + mInventory(p.inventory), //inventory("", &gInventory) mAcceptsDragAndDrop(p.accepts_drag_and_drop), mAllowMultiSelect(p.allow_multi_select), mAllowDrag(p.allow_drag), @@ -514,7 +514,18 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve view_item->destroyView(); removeItemID(idp); } - view_item = buildNewViews(item_id); + + LLInventoryObject const* objectp = mInventory->getObject(item_id); + if (objectp) + { + // providing NULL directly avoids unnessesary getItemByID calls + view_item = buildNewViews(item_id, objectp, NULL); + } + else + { + view_item = NULL; + } + viewmodel_item = static_cast(view_item ? view_item->getViewModelItem() : NULL); view_folder = dynamic_cast(view_item); @@ -557,7 +568,13 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve if (model_item && !view_item) { // Add the UI element for this item. - buildNewViews(item_id); + LLInventoryObject const* objectp = mInventory->getObject(item_id); + if (objectp) + { + // providing NULL directly avoids unnessesary getItemByID calls + buildNewViews(item_id, objectp, NULL); + } + // Select any newly created object that has the auto rename at top of folder root set. if(mFolderRoot.get()->getRoot()->needsAutoRename()) { @@ -854,7 +871,7 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { - LLInventoryObject const* objectp = gInventory.getObject(id); + LLInventoryObject const* objectp = mInventory->getObject(id); return buildNewViews(id, objectp); } @@ -864,11 +881,43 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO { return NULL; } - LLFolderViewItem* folder_view_item = getItemByID(id); + if (!typedViewsFilter(id, objectp)) + { + // if certain types are not allowed permanently, no reason to create views + return NULL; + } const LLUUID &parent_id = objectp->getParentUUID(); - LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); - + LLFolderViewItem* folder_view_item = getItemByID(id); + LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); + + return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder); +} + +LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryObject const* objectp, LLFolderViewItem *folder_view_item) +{ + if (!objectp) + { + return NULL; + } + if (!typedViewsFilter(id, objectp)) + { + // if certain types are not allowed permanently, no reason to create views + return NULL; + } + + const LLUUID &parent_id = objectp->getParentUUID(); + LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id); + + return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder); +} + +LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id, + const LLUUID& parent_id, + LLInventoryObject const* objectp, + LLFolderViewItem *folder_view_item, + LLFolderViewFolder *parent_folder) +{ // Force the creation of an extra root level folder item if required by the inventory panel (default is "false") bool allow_drop = true; bool create_root = false; @@ -889,7 +938,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO { if (objectp->getType() <= LLAssetType::AT_NONE) { - LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " + LL_WARNS() << "LLInventoryPanel::buildViewsTree called with invalid objectp->mType : " << ((S32)objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() << LL_ENDL; return NULL; @@ -898,7 +947,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO if (objectp->getType() >= LLAssetType::AT_COUNT) { // Example: Happens when we add assets of new, not yet supported type to library - LL_DEBUGS() << "LLInventoryPanel::buildNewViews called with unknown objectp->mType : " + LL_DEBUGS() << "LLInventoryPanel::buildViewsTree called with unknown objectp->mType : " << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() << LL_ENDL; @@ -975,26 +1024,52 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO LLViewerInventoryCategory::cat_array_t* categories; LLViewerInventoryItem::item_array_t* items; mInventory->lockDirectDescendentArrays(id, categories, items); - + + LLFolderViewFolder *parentp = dynamic_cast(folder_view_item); + if(categories) - { + { + bool has_folders = parentp->getFoldersCount() > 0; for (LLViewerInventoryCategory::cat_array_t::const_iterator cat_iter = categories->begin(); cat_iter != categories->end(); ++cat_iter) { const LLViewerInventoryCategory* cat = (*cat_iter); - buildNewViews(cat->getUUID()); + if (typedViewsFilter(cat->getUUID(), cat)) + { + if (has_folders) + { + // This can be optimized: we don't need to call getItemByID() + // each time, especially since content is growing, we can just + // iter over copy of mItemMap in some way + LLFolderViewItem* view_itemp = getItemByID(cat->getUUID()); + buildViewsTree(cat->getUUID(), id, cat, view_itemp, parentp); + } + else + { + buildViewsTree(cat->getUUID(), id, cat, NULL, parentp); + } + } } } if(items) - { + { for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin(); item_iter != items->end(); ++item_iter) { const LLViewerInventoryItem* item = (*item_iter); - buildNewViews(item->getUUID()); + if (typedViewsFilter(item->getUUID(), item)) + { + + // This can be optimized: we don't need to call getItemByID() + // each time, especially since content is growing, we can just + // iter over copy of mItemMap in some way + LLFolderViewItem* view_itemp = getItemByID(item->getUUID()); + buildViewsTree(item->getUUID(), id, item, view_itemp, parentp); + } + } } mInventory->unlockDirectDescendentArrays(id); @@ -1911,21 +1986,20 @@ BOOL LLAssetFilteredInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, B return result; } -LLFolderViewItem* LLAssetFilteredInventoryPanel::buildNewViews(const LLUUID& id) +/*virtual*/ +bool LLAssetFilteredInventoryPanel::typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) { - LLInventoryObject const* objectp = gInventory.getObject(id); - if (!objectp) { - return NULL; + return false; } if (objectp->getType() != mAssetType && objectp->getType() != LLAssetType::AT_CATEGORY) { - return NULL; + return false; } - return LLInventoryPanel::buildNewViews(id, objectp); + return true; } void LLAssetFilteredInventoryPanel::itemChanged(const LLUUID& id, U32 mask, const LLInventoryObject* model_item) diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index e51281b4b3..e13c68812e 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -329,8 +329,15 @@ protected: static LLUIColor sLibraryColor; static LLUIColor sLinkColor; - virtual LLFolderViewItem* buildNewViews(const LLUUID& id); - LLFolderViewItem* buildNewViews(const LLUUID& id, LLInventoryObject const* objectp); + LLFolderViewItem* buildNewViews(const LLUUID& id); + LLFolderViewItem* buildNewViews(const LLUUID& id, + LLInventoryObject const* objectp); + LLFolderViewItem* buildNewViews(const LLUUID& id, + LLInventoryObject const* objectp, + LLFolderViewItem *target_view); + // if certain types are not allowed, no reason to create views + virtual bool typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) { return true; } + virtual void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item); BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const; @@ -338,10 +345,39 @@ protected: virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop); virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge); private: + // buildViewsTree does not include some checks and is meant + // for recursive use, use buildNewViews() for first call + LLFolderViewItem* buildViewsTree(const LLUUID& id, + const LLUUID& parent_id, + LLInventoryObject const* objectp, + LLFolderViewItem *target_view, + LLFolderViewFolder *parent_folder_view); + bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild() bool mViewsInitialized; // 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 */ @@ -373,7 +409,7 @@ public: std::string& tooltip_msg) override; protected: - /*virtual*/ LLFolderViewItem* buildNewViews(const LLUUID& id) override; + /*virtual*/ bool typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) override; /*virtual*/ void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override; private: diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 1fc70cd6d6..b4236c406b 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -40,8 +40,8 @@ LLLandmarkList gLandmarkList; // number is mostly arbitrary, but it should be below DEFAULT_QUEUE_SIZE pool size, -// which is 4096, to not overfill the pool if user has more than 4K of landmarks, -// and low number helps with not flooding server with requests +// which is 4096, to not overfill the pool if user has more than 4K of landmarks +// and it should leave some space for other potential simultaneous asset request const S32 MAX_SIMULTANEOUS_REQUESTS = 512; @@ -98,7 +98,11 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t if (mRequestedList.size() > MAX_SIMULTANEOUS_REQUESTS) { - // Postpone download till queu is emptier + // Workarounds for corutines pending list size limit: + // Postpone download till queue is emptier. + // Coroutines have own built in 'pending' list, but unfortunately + // it is too small compared to potential amount of landmarks + // or assets. mWaitList.insert(asset_uuid); return NULL; } @@ -176,17 +180,27 @@ void LLLandmarkList::processGetAssetReply( // todo: this should clean mLoadedCallbackMap! } - if (!gLandmarkList.mWaitList.empty()) + // getAssetData can fire callback immediately, causing + // a recursion which is suboptimal for very large wait list. + // 'scheduling' indicates that we are inside request and + // shouldn't be launching more requests. + static bool scheduling = false; + if (!scheduling && !gLandmarkList.mWaitList.empty()) { - // start new download from wait list - landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin(); - LLUUID asset_uuid = *iter; - gLandmarkList.mWaitList.erase(iter); - gAssetStorage->getAssetData(asset_uuid, - LLAssetType::AT_LANDMARK, - LLLandmarkList::processGetAssetReply, - NULL); - gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds; + scheduling = true; + while (!gLandmarkList.mWaitList.empty() && gLandmarkList.mRequestedList.size() < MAX_SIMULTANEOUS_REQUESTS) + { + // start new download from wait list + landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin(); + LLUUID asset_uuid = *iter; + gLandmarkList.mWaitList.erase(iter); + gAssetStorage->getAssetData(asset_uuid, + LLAssetType::AT_LANDMARK, + LLLandmarkList::processGetAssetReply, + NULL); + gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds; + } + scheduling = false; } } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 354f5a453b..415781bc27 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -133,6 +133,16 @@ void append_to_last_message(std::list& messages, const std::string& line) messages.back()[LL_IM_TEXT] = im_text; } +std::string remove_utf8_bom(const char* buf) +{ + std::string res(buf); + if (res[0] == (char)0xEF && res[1] == (char)0xBB && res[2] == (char)0xBF) + { + res.erase(0, 3); + } + return res; +} + class LLLogChatTimeScanner: public LLSingleton { LLSINGLETON(LLLogChatTimeScanner); @@ -417,7 +427,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list& m continue; } - std::string line(buffer); + std::string line(remove_utf8_bom(buffer)); //updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message if (' ' == line[0]) @@ -805,7 +815,7 @@ bool LLLogChat::isTranscriptFileFound(std::string fullname) { //matching a timestamp boost::match_results matches; - if (boost::regex_match(std::string(buffer), matches, TIMESTAMP)) + if (boost::regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP)) { result = true; } @@ -1126,7 +1136,7 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::listunlock(); break; } - LoadedMesh mesh = mLoadedQ.front(); + LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point mLoadedQ.pop(); mMutex->unlock(); update_metrics = true; - if (mesh.mVolume && mesh.mVolume->getNumVolumeFaces() > 0) + if (mesh.mVolume->getNumVolumeFaces() > 0) { gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); } @@ -3213,7 +3219,6 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; header = iter->second; } - gMeshRepo.mThread->mHeaderMutex->unlock(); if (header_bytes > 0 && !header.has("404") @@ -3234,7 +3239,10 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); - S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; + // Do not unlock mutex untill we are done with LLSD. + // LLSD is smart and can work like smart pointer, is not thread safe. + gMeshRepo.mThread->mHeaderMutex->unlock(); + S32 bytes = lod_bytes + header_bytes; @@ -3270,6 +3278,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b { LL_WARNS(LOG_MESH) << "Trying to cache nonexistent mesh, mesh id: " << mesh_id << LL_ENDL; + gMeshRepo.mThread->mHeaderMutex->unlock(); + // headerReceived() parsed header, but header's data is invalid so none of the LODs will be available LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) @@ -4139,42 +4149,42 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail) bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) { - LLSD mesh = mThread->getMeshHeader(mesh_id); - if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) - { - return true; - } + if (mesh_id.isNull()) + { + return false; + } - LLModel::Decomposition* decomp = getDecomposition(mesh_id); - if (decomp && !decomp->mHull.empty()) - { - return true; - } + if (mThread->hasPhysicsShapeInHeader(mesh_id)) + { + return true; + } - return false; + LLModel::Decomposition* decomp = getDecomposition(mesh_id); + if (decomp && !decomp->mHull.empty()) + { + return true; + } + + return false; } -LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id) +bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id) { - LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); + LLMutexLock lock(mHeaderMutex); + if (mMeshHeaderSize[mesh_id] > 0) + { + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end()) + { + LLSD &mesh = iter->second; + if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) + { + return true; + } + } + } - return mThread->getMeshHeader(mesh_id); -} - -LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) -{ - static LLSD dummy_ret; - if (mesh_id.notNull()) - { - LLMutexLock lock(mHeaderMutex); - mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0) - { - return iter->second; - } - } - - return dummy_ret; + return false; } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 9a627dabcb..81e49cb1d8 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -343,7 +343,7 @@ public: bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); - LLSD& getMeshHeader(const LLUUID& mesh_id); + bool hasPhysicsShapeInHeader(const LLUUID& mesh_id); void notifyLoadedMeshes(); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -595,9 +595,6 @@ public: bool meshUploadEnabled(); bool meshRezEnabled(); - - - LLSD& getMeshHeader(const LLUUID& mesh_id); void uploadModel(std::vector& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position, diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index d60d1d748e..a9e80ab5da 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -245,6 +245,12 @@ LLModelPreview::~LLModelPreview() { mModelLoader->shutdown(); } + + if (mPreviewAvatar) + { + mPreviewAvatar->markDead(); + mPreviewAvatar = NULL; + } } U32 LLModelPreview::calcResourceCost() diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 5d1b582d1f..37ed4bc74c 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -44,6 +44,7 @@ #include "llavatariconctrl.h" #include "llfloaterreg.h" #include "llnotificationsutil.h" +#include "llviewermenu.h" // is_agent_mappable #include "llvoiceclient.h" #include "lltextbox.h" #include "lltrans.h" diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 06bb886ae8..6751c25fb9 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -39,6 +39,7 @@ #include "llagent.h" #include "llagentui.h" #include "lllandmarkactions.h" +#include "llparcel.h" #include "llslurl.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" @@ -77,7 +78,7 @@ BOOL LLPanelLandmarkInfo::postBuild() mCreator = getChild("creator"); mCreated = getChild("created"); - mLandmarkTitle = getChild("title_value"); + mLandmarkTitle = getChild("title_value"); mLandmarkTitleEditor = getChild("title_editor"); mNotesEditor = getChild("notes_editor"); mFolderCombo = getChild("folder_combo"); @@ -113,6 +114,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) landmark_info_panel->setVisible(type == LANDMARK); getChild("folder_label")->setVisible(is_info_type_create_landmark); + getChild("edit_btn")->setVisible(!is_info_type_create_landmark); mFolderCombo->setVisible(is_info_type_create_landmark); switch(type) @@ -126,13 +128,10 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) mNotesEditor->setEnabled(TRUE); LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); - std::string name = parcel_mgr->getAgentParcelName(); + LLParcel* parcel = parcel_mgr->getAgentParcel(); + std::string name = parcel->getName(); LLVector3 agent_pos = gAgent.getPositionAgent(); - std::string desc; - LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, agent_pos); - mNotesEditor->setText(desc); - if (name.empty()) { S32 region_x = ll_round(agent_pos.mV[VX]); @@ -147,6 +146,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) } else { + std::string desc; LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos); region_name = desc; } @@ -159,6 +159,25 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) mLandmarkTitleEditor->setText(name); } + LLUUID owner_id = parcel->getOwnerID(); + if (owner_id.notNull()) + { + if (parcel->getIsGroupOwned()) + { + std::string owner_name = LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString(); + mParcelOwner->setText(owner_name); + } + else + { + std::string owner_name = LLSLURL("agent", owner_id, "inspect").getSLURLString(); + mParcelOwner->setText(owner_name); + } + } + else + { + mParcelOwner->setText(getString("public")); + } + // Moved landmark creation here from LLPanelLandmarkInfo::processParcelInfo() // because we use only agent's current coordinates instead of waiting for // remote parcel request to complete. @@ -210,6 +229,24 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); } + if (parcel_data.owner_id.notNull()) + { + if (parcel_data.flags & 0x4) // depends onto DRTSIM-453 + { + std::string owner_name = LLSLURL("group", parcel_data.owner_id, "inspect").getSLURLString(); + mParcelOwner->setText(owner_name); + } + else + { + std::string owner_name = LLSLURL("agent", parcel_data.owner_id, "inspect").getSLURLString(); + mParcelOwner->setText(owner_name); + } + } + else + { + mParcelOwner->setText(getString("public")); + } + LLSD info; info["update_verbs"] = true; info["global_x"] = parcel_data.global_x; @@ -264,7 +301,8 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem) } else { - mOwner->setText(getString("public")); + std::string public_str = getString("public"); + mOwner->setText(public_str); } ////////////////// @@ -311,6 +349,7 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled) mNotesEditor->setReadOnly(!enabled); mFolderCombo->setVisible(enabled); getChild("folder_label")->setVisible(enabled); + getChild("edit_btn")->setVisible(!enabled); // HACK: To change the text color in a text editor // when it was enabled/disabled we set the text once again. @@ -357,7 +396,7 @@ void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id) // If no parcel exists use the region name instead. if (name.empty()) { - name = mRegionName->getText(); + name = mRegionTitle; } } diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index 01a6fd6b3d..9712736182 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -71,7 +71,7 @@ private: LLTextBox* mOwner; LLTextBox* mCreator; LLTextBox* mCreated; - LLTextBox* mLandmarkTitle; + LLLineEditor* mLandmarkTitle; LLLineEditor* mLandmarkTitleEditor; LLTextEditor* mNotesEditor; LLComboBox* mFolderCombo; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index cd1dc0f070..ccd8497484 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -227,6 +227,12 @@ BOOL LLLandmarksPanel::postBuild() initMyInventoryPanel(); initLibraryInventoryPanel(); + LLAccordionCtrl* accordion = getChild("landmarks_accordion"); + if (accordion) + { + accordion->setSkipScrollToChild(true); + } + return TRUE; } diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index da21d5e69a..a19182b01e 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -563,7 +563,7 @@ void LLPanelLogin::populateFields(LLPointer credential, bool remem { sInstance->getChild("remember_name")->setValue(remember_user); LLUICtrl* remember_password = sInstance->getChild("remember_password"); - remember_password->setValue(remember_psswrd); + remember_password->setValue(remember_user && remember_psswrd); remember_password->setEnabled(remember_user); sInstance->populateUserList(credential); } @@ -687,7 +687,6 @@ void LLPanelLogin::getFields(LLPointer& credential, if (LLPanelLogin::sInstance->mPasswordModified) { - authenticator = LLSD::emptyMap(); // password is plaintext authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR; authenticator["secret"] = password; @@ -698,6 +697,15 @@ void LLPanelLogin::getFields(LLPointer& credential, if (credential.notNull()) { authenticator = credential->getAuthenticator(); + if (authenticator.emptyMap()) + { + // Likely caused by user trying to log in to non-system grid + // with unsupported name format, just retry + LL_WARNS() << "Authenticator failed to load for: " << username << LL_ENDL; + // password is plaintext + authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR; + authenticator["secret"] = password; + } } } } @@ -1137,7 +1145,11 @@ void LLPanelLogin::onRememberUserCheck(void*) remember_name->setValue(true); LLNotificationsUtil::add("LoginCantRemoveUsername"); } - remember_psswrd->setEnabled(remember); + if (!remember) + { + remember_psswrd->setValue(false); + } + remember_psswrd->setEnabled(remember); } } diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 0c70aa87c2..9157df789f 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -43,6 +43,7 @@ #include "llagent.h" #include "llexpandabletextbox.h" #include "llpanelpick.h" +#include "llslurl.h" #include "lltexturectrl.h" #include "llviewerregion.h" #include "llhttpconstants.h" @@ -78,6 +79,7 @@ BOOL LLPanelPlaceInfo::postBuild() mSnapshotCtrl = getChild("logo"); mRegionName = getChild("region_title"); mParcelName = getChild("parcel_title"); + mParcelOwner = getChild("parcel_owner"); mDescEditor = getChild("description"); mMaturityRatingIcon = getChild("maturity_icon"); @@ -98,11 +100,13 @@ void LLPanelPlaceInfo::resetLocation() mParcelID.setNull(); mRequestedID.setNull(); mPosRegion.clearVec(); + mRegionTitle.clear(); std::string loading = LLTrans::getString("LoadingData"); mMaturityRatingText->setValue(loading); - mRegionName->setText(loading); + mRegionName->setTextArg("[REGIONAMEPOS]", loading); mParcelName->setText(loading); + mParcelOwner->setText(loading); mDescEditor->setText(loading); mMaturityRatingIcon->setValue(LLUUID::null); @@ -182,9 +186,11 @@ void LLPanelPlaceInfo::setErrorStatus(S32 status, const std::string& reason) std::string not_available = getString("not_available"); mMaturityRatingText->setValue(not_available); - mRegionName->setText(not_available); + mRegionName->setTextArg("[REGIONAMEPOS]", not_available); mParcelName->setText(not_available); + mParcelOwner->setText(not_available); mMaturityRatingIcon->setValue(LLUUID::null); + mRegionTitle.clear(); // Enable "Back" button that was disabled when parcel request was sent. getChild("back_btn")->setEnabled(TRUE); @@ -198,12 +204,34 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id); } - if(!parcel_data.sim_name.empty()) - { - mRegionName->setText(parcel_data.sim_name); + S32 region_x; + S32 region_y; + S32 region_z; + + // If the region position is zero, grab position from the global + if (mPosRegion.isExactlyZero()) + { + region_x = ll_round(parcel_data.global_x) % REGION_WIDTH_UNITS; + region_y = ll_round(parcel_data.global_y) % REGION_WIDTH_UNITS; + region_z = ll_round(parcel_data.global_z); + } + else + { + region_x = ll_round(mPosRegion.mV[VX]); + region_y = ll_round(mPosRegion.mV[VY]); + region_z = ll_round(mPosRegion.mV[VZ]); + } + + if (!parcel_data.sim_name.empty()) + { + mRegionTitle = parcel_data.sim_name; + std::string name_and_pos = llformat("%s (%d, %d, %d)", + mRegionTitle.c_str(), region_x, region_y, region_z); + mRegionName->setTextArg("[REGIONAMEPOS]", name_and_pos); } else { + mRegionTitle.clear(); mRegionName->setText(LLStringUtil::null); } @@ -216,30 +244,11 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) mDescEditor->setText(getString("not_available")); } - S32 region_x; - S32 region_y; - S32 region_z; - - // If the region position is zero, grab position from the global - if(mPosRegion.isExactlyZero()) - { - region_x = ll_round(parcel_data.global_x) % REGION_WIDTH_UNITS; - region_y = ll_round(parcel_data.global_y) % REGION_WIDTH_UNITS; - region_z = ll_round(parcel_data.global_z); - } - else - { - region_x = ll_round(mPosRegion.mV[VX]); - region_y = ll_round(mPosRegion.mV[VY]); - region_z = ll_round(mPosRegion.mV[VZ]); - } - if (!parcel_data.name.empty()) { mParcelTitle = parcel_data.name; - mParcelName->setText(llformat("%s (%d, %d, %d)", - mParcelTitle.c_str(), region_x, region_y, region_z)); + mParcelName->setText(mParcelTitle); } else { @@ -280,12 +289,10 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent) void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel) { - std::string region_name = mRegionName->getText(); - LLPickData data; data.pos_global = pos_global; - data.name = mParcelTitle.empty() ? region_name : mParcelTitle; - data.sim_name = region_name; + data.name = mParcelTitle.empty() ? mRegionTitle : mParcelTitle; + data.sim_name = mRegionTitle; data.desc = mDescEditor->getText(); data.snapshot_id = mSnapshotCtrl->getImageAssetID(); data.parcel_id = mParcelID; diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 30327378ef..8bf67cfe7d 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -109,6 +109,7 @@ protected: LLUUID mRequestedID; LLVector3 mPosRegion; std::string mParcelTitle; // used for pick title without coordinates + std::string mRegionTitle; std::string mCurrentTitle; S32 mScrollingPanelMinHeight; S32 mScrollingPanelWidth; @@ -120,6 +121,7 @@ protected: LLTextureCtrl* mSnapshotCtrl; LLTextBox* mRegionName; LLTextBox* mParcelName; + LLTextBox* mParcelOwner; LLExpandableTextBox* mDescEditor; LLIconCtrl* mMaturityRatingIcon; LLTextBox* mMaturityRatingText; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 104316e253..9283dfa218 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -104,8 +104,6 @@ BOOL LLPanelPlaceProfile::postBuild() mForSalePanel->getChild("icon_for_sale")-> setMouseDownCallback(boost::bind(&LLPanelPlaceProfile::onForSaleBannerClick, this)); - mParcelOwner = getChild("owner_value"); - mParcelRatingIcon = getChild("rating_icon"); mParcelRatingText = getChild("rating_value"); mVoiceIcon = getChild("voice_icon"); @@ -183,7 +181,6 @@ void LLPanelPlaceProfile::resetLocation() mYouAreHerePanel->setVisible(FALSE); std::string loading = LLTrans::getString("LoadingData"); - mParcelOwner->setValue(loading); mParcelRatingIcon->setValue(loading); mParcelRatingText->setText(loading); @@ -248,14 +245,14 @@ void LLPanelPlaceProfile::setInfoType(EInfoType type) const S32 SEARCH_DESC_HEIGHT = 150; // Remember original geometry (once). - static const S32 sOrigDescVPad = getChildView("parcel_title")->getRect().mBottom - mDescEditor->getRect().mTop; + static const S32 sOrigDescVPad = getChildView("owner_label")->getRect().mBottom - mDescEditor->getRect().mTop; static const S32 sOrigDescHeight = mDescEditor->getRect().getHeight(); static const S32 sOrigMRIconVPad = mDescEditor->getRect().mBottom - mMaturityRatingIcon->getRect().mTop; static const S32 sOrigMRTextVPad = mDescEditor->getRect().mBottom - mMaturityRatingText->getRect().mTop; // Resize the description. const S32 desc_height = is_info_type_agent ? sOrigDescHeight : SEARCH_DESC_HEIGHT; - const S32 desc_top = getChildView("parcel_title")->getRect().mBottom - sOrigDescVPad; + const S32 desc_top = getChildView("owner_label")->getRect().mBottom - sOrigDescVPad; LLRect desc_rect = mDescEditor->getRect(); desc_rect.setOriginAndSize(desc_rect.mLeft, desc_top - desc_height, desc_rect.getWidth(), desc_height); mDescEditor->reshape(desc_rect.getWidth(), desc_rect.getHeight()); @@ -401,6 +398,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, parcel_data.global_x = pos_global.mdV[VX]; parcel_data.global_y = pos_global.mdV[VY]; parcel_data.global_z = pos_global.mdV[VZ]; + parcel_data.owner_id = parcel->getOwnerID(); std::string on = getString("on"); std::string off = getString("off"); diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index 3d2654fc12..16478bc179 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -76,8 +76,6 @@ private: LLPanel* mForSalePanel; LLPanel* mYouAreHerePanel; - LLTextBox* mParcelOwner; - LLIconCtrl* mParcelRatingIcon; LLTextBox* mParcelRatingText; LLIconCtrl* mVoiceIcon; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 2ef82d0cf9..53870fb5c7 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -59,6 +59,7 @@ #include "llinventorymodel.h" #include "lllandmarkactions.h" #include "lllandmarklist.h" +#include "lllayoutstack.h" #include "llpanellandmarkinfo.h" #include "llpanellandmarks.h" #include "llpanelpick.h" @@ -280,9 +281,6 @@ BOOL LLPanelPlaces::postBuild() mShowOnMapBtn = getChild("map_btn"); mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this)); - mEditBtn = getChild("edit_btn"); - mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this)); - mSaveBtn = getChild("save_btn"); mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this)); @@ -355,6 +353,9 @@ BOOL LLPanelPlaces::postBuild() LLComboBox* folder_combo = mLandmarkInfo->getChild("folder_combo"); folder_combo->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this)); + LLButton* edit_btn = mLandmarkInfo->getChild("edit_btn"); + edit_btn->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this)); + createTabs(); updateVerbs(); @@ -532,7 +533,6 @@ void LLPanelPlaces::setItem(LLInventoryItem* item) BOOL is_landmark_editable = gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) && mItem->getPermissions().allowModifyBy(gAgent.getID()); - mEditBtn->setEnabled(is_landmark_editable); mSaveBtn->setEnabled(is_landmark_editable); if (is_landmark_editable) @@ -1216,13 +1216,16 @@ void LLPanelPlaces::updateVerbs() mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible); - mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn); - mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn); 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) diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 27f991c202..978b030b2e 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -121,7 +121,6 @@ private: LLButton* mPlaceProfileBackBtn; LLButton* mTeleportBtn; LLButton* mShowOnMapBtn; - LLButton* mEditBtn; LLButton* mSaveBtn; LLButton* mCancelBtn; LLButton* mCloseBtn; diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 89cb495db9..3347c40687 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -64,7 +64,9 @@ public: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - registrar.add("Gear.Edit", boost::bind(&edit_outfit)); + registrar.add("Gear.TouchAttach", boost::bind(&LLWearingGearMenu::handleMultiple, this, handle_attachment_touch)); + registrar.add("Gear.EditItem", boost::bind(&LLWearingGearMenu::handleMultiple, this, handle_item_edit)); + registrar.add("Gear.EditOutfit", boost::bind(&edit_outfit)); registrar.add("Gear.TakeOff", boost::bind(&LLPanelWearing::onRemoveItem, mPanelWearing)); registrar.add("Gear.Copy", boost::bind(&LLPanelWearing::copyToClipboard, mPanelWearing)); @@ -78,6 +80,16 @@ public: LLToggleableMenu* getMenu() { return mMenu; } private: + void handleMultiple(std::function functor) + { + uuid_vec_t selected_item_ids; + mPanelWearing->getSelectedItemsUUIDs(selected_item_ids); + + for (const LLUUID& item_id : selected_item_ids) + { + functor(item_id); + } + } LLToggleableMenu* mMenu; LLPanelWearing* mPanelWearing; @@ -92,7 +104,9 @@ protected: { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - registrar.add("Wearing.Edit", boost::bind(&edit_outfit)); + registrar.add("Wearing.TouchAttach", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs)); + registrar.add("Wearing.EditItem", boost::bind(handleMultiple, handle_item_edit, mUUIDs)); + registrar.add("Wearing.EditOutfit", boost::bind(&edit_outfit)); registrar.add("Wearing.ShowOriginal", boost::bind(show_item_original, mUUIDs.front())); registrar.add("Wearing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); @@ -138,14 +152,19 @@ protected: } // Enable/disable some menu items depending on the selection. + bool show_touch = !bp_selected && !clothes_selected && attachments_selected; + bool show_edit = bp_selected || clothes_selected || attachments_selected; bool allow_detach = !bp_selected && !clothes_selected && attachments_selected; bool allow_take_off = !bp_selected && clothes_selected && !attachments_selected; + menu->setItemVisible("touch_attach", show_touch); + menu->setItemEnabled("touch_attach", 1 == mUUIDs.size() && enable_attachment_touch(mUUIDs.front())); + menu->setItemVisible("edit_item", show_edit); + menu->setItemEnabled("edit_item", 1 == mUUIDs.size() && get_is_item_editable(mUUIDs.front())); menu->setItemVisible("take_off", allow_take_off); menu->setItemVisible("detach", allow_detach); - menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach); + menu->setItemVisible("edit_outfit_separator", show_touch | show_edit | allow_take_off || allow_detach); menu->setItemVisible("show_original", mUUIDs.size() == 1); - menu->setItemVisible("edit_item", FALSE); } }; @@ -173,12 +192,15 @@ protected: void updateMenuItemsVisibility(LLContextMenu* menu) { + menu->setItemVisible("touch_attach", TRUE); + menu->setItemEnabled("touch_attach", 1 == mUUIDs.size()); + menu->setItemVisible("edit_item", TRUE); + menu->setItemEnabled("edit_item", 1 == mUUIDs.size()); menu->setItemVisible("take_off", FALSE); menu->setItemVisible("detach", TRUE); - menu->setItemVisible("edit_outfit_separator", TRUE); + menu->setItemVisible("edit_outfit_separator", FALSE); menu->setItemVisible("show_original", FALSE); - menu->setItemVisible("edit_item", TRUE); - menu->setItemVisible("edit", FALSE); + menu->setItemVisible("edit_outfit", FALSE); } LLPanelWearing* mPanelWearing; @@ -350,6 +372,18 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata) } } + uuid_vec_t selected_uuids; + getSelectedItemsUUIDs(selected_uuids); + + if (command_name == "touch_attach") + { + return (1 == selected_uuids.size()) && (enable_attachment_touch(selected_uuids.front())); + } + else if (command_name == "edit_item") + { + return (1 == selected_uuids.size()) && (get_is_item_editable(selected_uuids.front())); + } + return false; } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 7ef0ef0e8b..1b60610668 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -307,6 +307,7 @@ void LLPreviewNotecard::loadAsset() { editor->setEnabled(FALSE); getChildView("lock")->setVisible( TRUE); + getChildView("Edit")->setEnabled(FALSE); } if((allow_modify || is_owner) && !source_library) diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index 5b0d189137..70c117be44 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -45,7 +45,7 @@ struct LLParcelData std::string desc; S32 actual_area; S32 billable_area; - U8 flags; + U8 flags; // group owned, maturity F32 global_x; F32 global_y; F32 global_z; diff --git a/indra/newview/llsearchableui.cpp b/indra/newview/llsearchableui.cpp index 93143eb33f..1119e80005 100644 --- a/indra/newview/llsearchableui.cpp +++ b/indra/newview/llsearchableui.cpp @@ -68,7 +68,10 @@ ll::prefs::PanelData::~PanelData() bool ll::prefs::PanelData::hightlightAndHide( LLWString const &aFilter ) { for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr ) - (*itr)->setNotHighlighted( ); + (*itr)->setNotHighlighted(); + + for (tPanelDataList::iterator itr = mChildPanel.begin(); itr != mChildPanel.end(); ++itr) + (*itr)->setNotHighlighted(); if (aFilter.empty()) { @@ -85,6 +88,15 @@ bool ll::prefs::PanelData::hightlightAndHide( LLWString const &aFilter ) return bVisible; } +void ll::prefs::PanelData::setNotHighlighted() +{ + for (tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr) + (*itr)->setNotHighlighted(); + + for (tPanelDataList::iterator itr = mChildPanel.begin(); itr != mChildPanel.end(); ++itr) + (*itr)->setNotHighlighted(); +} + bool ll::prefs::TabContainerData::hightlightAndHide( LLWString const &aFilter ) { for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr ) diff --git a/indra/newview/llsearchableui.h b/indra/newview/llsearchableui.h index 9741557e49..e033cae3ab 100644 --- a/indra/newview/llsearchableui.h +++ b/indra/newview/llsearchableui.h @@ -73,6 +73,7 @@ namespace ll virtual ~PanelData(); + void setNotHighlighted(); virtual bool hightlightAndHide( LLWString const &aFilter ); }; diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 26a2df8270..b9259cb18d 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -117,7 +117,7 @@ LLSD LLCredential::getLoginParams() else if (mIdentifier["type"].asString() == "account") { result["username"] = mIdentifier["account_name"]; - result["passwd"] = mAuthenticator["secret"]; + result["passwd"] = mAuthenticator["secret"].asString(); username = result["username"].asString(); } } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index f3439daee9..8369def968 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -155,7 +155,7 @@ F32 LLSnapshotLivePreview::getImageAspect() void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) { - LL_DEBUGS() << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL; + LL_DEBUGS("Snapshot") << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL; // Update snapshot if requested. if (new_snapshot) @@ -343,7 +343,7 @@ void LLSnapshotLivePreview::draw() } else if (mShineAnimTimer.getStarted()) { - LL_DEBUGS() << "Drawing shining animation" << LL_ENDL; + LL_DEBUGS("Snapshot") << "Drawing shining animation" << LL_ENDL; F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME); // draw "shine" effect @@ -391,7 +391,7 @@ void LLSnapshotLivePreview::draw() S32 old_image_index = (mCurImageIndex + 1) % 2; if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME) { - LL_DEBUGS() << "Drawing fall animation" << LL_ENDL; + LL_DEBUGS("Snapshot") << "Drawing fall animation" << LL_ENDL; F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME; F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f); LLColor4 image_color(1.f, 1.f, 1.f, alpha); @@ -435,7 +435,7 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare LLView::reshape(width, height, called_from_parent); if (old_rect.getWidth() != width || old_rect.getHeight() != height) { - LL_DEBUGS() << "window reshaped, updating thumbnail" << LL_ENDL; + LL_DEBUGS("Window", "Snapshot") << "window reshaped, updating thumbnail" << LL_ENDL; if (mViewContainer && mViewContainer->isInVisibleChain()) { // We usually resize only on window reshape, so give it a chance to redraw, assign delay @@ -580,7 +580,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) } else { - LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; + LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } // Scale to a power of 2 so it can be mapped to a texture @@ -628,7 +628,7 @@ LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage() } else { - LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; + LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } // Scale to a power of 2 so it can be mapped to a texture @@ -648,7 +648,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; if (previewp->getWidth() == 0 || previewp->getHeight() == 0) { - LL_WARNS() << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << LL_ENDL; + LL_WARNS("Snapshot") << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << LL_ENDL; return FALSE; } @@ -679,7 +679,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->mCameraRot = new_camera_rot; // request a new snapshot whenever the camera moves, with a time delay BOOL new_snapshot = gSavedSettings.getBOOL("AutoSnapshot") || previewp->mForceUpdateSnapshot; - LL_DEBUGS() << "camera moved, updating thumbnail" << LL_ENDL; + LL_DEBUGS("Snapshot") << "camera moved, updating thumbnail" << LL_ENDL; previewp->updateSnapshot( new_snapshot, // whether a new snapshot is needed or merely invalidate the existing one FALSE, // or if 1st arg is false, whether to produce a new thumbnail image. @@ -695,7 +695,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // time to produce a snapshot if(!previewp->getSnapshotUpToDate()) { - LL_DEBUGS() << "producing snapshot" << LL_ENDL; + LL_DEBUGS("Snapshot") << "producing snapshot" << LL_ENDL; if (!previewp->mPreviewImage) { previewp->mPreviewImage = new LLImageRaw; @@ -745,7 +745,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) previewp->getWindow()->decBusyCount(); previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode previewp->mSnapshotActive = FALSE; - LL_DEBUGS() << "done creating snapshot" << LL_ENDL; + LL_DEBUGS("Snapshot") << "done creating snapshot" << LL_ENDL; } if (!previewp->getThumbnailUpToDate()) @@ -836,7 +836,7 @@ LLPointer LLSnapshotLivePreview::getEncodedImage() if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE) { // We don't store the intermediate formatted image in mFormattedImage in the J2C case - LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL; + LL_DEBUGS("Snapshot") << "Encoding new image of format J2C" << LL_ENDL; LLPointer formatted = new LLImageJ2C; // Copy the preview LLPointer scaled = new LLImageRaw( @@ -921,13 +921,13 @@ LLPointer LLSnapshotLivePreview::getFormattedImage() } else { - LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; + LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } // Create the new formatted image of the appropriate format. LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat(); - LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL; + LL_DEBUGS("Snapshot") << "Encoding new image of format " << format << LL_ENDL; switch (format) { @@ -952,7 +952,7 @@ LLPointer LLSnapshotLivePreview::getFormattedImage() void LLSnapshotLivePreview::setSize(S32 w, S32 h) { - LL_DEBUGS() << "setSize(" << w << ", " << h << ")" << LL_ENDL; + LL_DEBUGS("Snapshot") << "setSize(" << w << ", " << h << ")" << LL_ENDL; setWidth(w); setHeight(h); } @@ -974,7 +974,7 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) { - LL_DEBUGS() << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL; + LL_DEBUGS("Snapshot") << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL; // gen a new uuid for this asset LLTransactionID tid; tid.generate(); @@ -997,12 +997,12 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) } else { - LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; + LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL; } } scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE); - LL_DEBUGS() << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << LL_ENDL; + LL_DEBUGS("Snapshot") << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << LL_ENDL; if (formatted->encode(scaled, 0.0f)) { @@ -1030,7 +1030,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) else { LLNotificationsUtil::add("ErrorEncodingSnapshot"); - LL_WARNS() << "Error encoding snapshot" << LL_ENDL; + LL_WARNS("Snapshot") << "Error encoding snapshot" << LL_ENDL; } add(LLStatViewer::SNAPSHOT, 1); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index afb25778aa..8fc2405f0a 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3125,13 +3125,13 @@ void renderRaycast(LLDrawable* drawablep) LLGLEnable blend(GL_BLEND); gGL.diffuseColor4f(0,1,1,0.5f); - if (drawablep->getVOVolume()) + LLVOVolume* vobj = drawablep->getVOVolume(); + if (vobj && !vobj->isDead()) { //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - LLVOVolume* vobj = drawablep->getVOVolume(); LLVolume* volume = vobj->getVolume(); bool transform = true; @@ -3360,7 +3360,7 @@ public: for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) + if(!drawable || drawable->isDead()) { continue; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f307daa198..3c250b3bb3 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1232,7 +1232,6 @@ bool idle_startup() display_startup(); gAgentCamera.init(); display_startup(); - set_underclothes_menu_options(); display_startup(); // Since we connected, save off the settings so the user doesn't have to diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 2e52414d71..6211d0ce3b 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -616,6 +616,9 @@ bool LLTextureCacheRemoteWorker::doWrite() if(idx >= 0) { // write to the fast cache. + // mRawImage is not entirely safe here since it is a pointer to one owned by cache worker, + // it could have been retrieved via getRequestFinished() and then modified. + // If writeToFastCache crashes, something is wrong around fetch worker. if(!mCache->writeToFastCache(mID, idx, mRawImage, mRawDiscardLevel)) { LL_WARNS() << "writeToFastCache failed" << LL_ENDL; @@ -2155,8 +2158,8 @@ bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer>= i; if(w * h *c > 0) //valid { - //make a duplicate to keep the original raw image untouched. - + // Make a duplicate to keep the original raw image untouched. + // Might be good idea to do a copy during writeToCache() call instead of here try { #if LL_WINDOWS diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index fe058024f6..f64db7beb5 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1977,6 +1977,11 @@ bool LLTextureFetchWorker::doWork(S32 param) setState(WAIT_ON_WRITE); ++mCacheWriteCount; CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID); + // This call might be under work mutex, but mRawImage is not nessesary safe here. + // If something retrieves it via getRequestFinished() and modifies, image won't + // be protected by work mutex and won't be safe to use here nor in cache worker. + // So make sure users of getRequestFinished() does not attempt to modify image while + // fetcher is working mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority, mFormattedImage->getData(), datasize, mFileSize, mRawImage, mDecodedDiscard, responder); diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index cdf8868597..2aa194e141 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -92,6 +92,7 @@ public: void deleteAllRequests(); // Threads: T* + // keep in mind that if fetcher isn't done, it still might need original raw image bool getRequestFinished(const LLUUID& id, S32& discard_level, LLPointer& raw, LLPointer& aux, LLCore::HttpStatus& last_http_get_status); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index c65431d6f6..8aa5b07561 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -187,6 +187,16 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue) bool handleRenderTransparentWaterChanged(const LLSD& newvalue) { + LLRenderTarget::sUseFBO = newvalue.asBoolean(); + if (gPipeline.isInit()) + { + gPipeline.updateRenderTransparentWater(); + gPipeline.updateRenderDeferred(); + gPipeline.releaseGLBuffers(); + gPipeline.createGLBuffers(); + gPipeline.resetVertexBuffers(); + LLViewerShaderMgr::instance()->setShaders(); + } LLWorld::getInstance()->updateWaterObjects(); return true; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index caf79edfe4..d314b1477a 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -423,6 +423,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) { // Give up. Don't keep the UI locked forever. + LL_WARNS("Teleport") << "Giving up on teleport. elapsed time " << teleport_elapsed << " exceeds max time " << teleport_save_time << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); gAgent.setTeleportMessage(std::string()); } @@ -444,6 +445,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gTeleportDisplayTimer.reset(); gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + LL_INFOS("Teleport") << "A teleport request has been sent, setting state to TELEPORT_REQUESTED" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); @@ -468,6 +470,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gTeleportArrivalTimer.reset(); gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); gViewerWindow->setProgressPercent(75.f); + LL_INFOS("Teleport") << "Changing state to TELEPORT_ARRIVING" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["arriving"]); @@ -484,6 +487,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { arrival_fraction = 1.f; //LLFirstUse::useTeleport(); + LL_INFOS("Teleport") << "arrival_fraction is " << arrival_fraction << " changing state to TELEPORT_NONE" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); @@ -499,6 +503,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if( gTeleportDisplayTimer.getElapsedTimeF32() > teleport_local_delay() ) { //LLFirstUse::useTeleport(); + LL_INFOS("Teleport") << "State is local and gTeleportDisplayTimer " << gTeleportDisplayTimer.getElapsedTimeF32() + << " exceeds teleport_local_delete " << teleport_local_delay + << "; setting state to TELEPORT_NONE" + << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d0cbd1181b..bbed741a33 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -81,6 +81,9 @@ static const char * const LOG_INV("Inventory"); static const char * const LOG_LOCAL("InventoryLocalize"); static const char * const LOG_NOTECARD("copy_inventory_from_notecard"); +static const std::string INV_OWNER_ID("owner_id"); +static const std::string INV_VERSION("version"); + #if 1 // *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model. // temp code in transition @@ -518,14 +521,6 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const msg->addU32Fast(_PREHASH_CRC, crc); } -// virtual -BOOL LLViewerInventoryItem::importFile(LLFILE* fp) -{ - BOOL rv = LLInventoryItem::importFile(fp); - mIsComplete = TRUE; - return rv; -} - // virtual BOOL LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) { @@ -534,32 +529,6 @@ BOOL LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) return rv; } -bool LLViewerInventoryItem::importFileLocal(LLFILE* fp) -{ - // TODO: convert all functions that return BOOL to return bool - bool rv = (LLInventoryItem::importFile(fp) ? true : false); - mIsComplete = false; - return rv; -} - -bool LLViewerInventoryItem::exportFileLocal(LLFILE* fp) const -{ - std::string uuid_str; - fprintf(fp, "\tinv_item\t0\n\t{\n"); - mUUID.toString(uuid_str); - fprintf(fp, "\t\titem_id\t%s\n", uuid_str.c_str()); - mParentUUID.toString(uuid_str); - fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); - mPermissions.exportFile(fp); - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); - if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str()); - fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); - fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate); - fprintf(fp,"\t}\n"); - return true; -} - void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const { LLMessageSystem* msg = gMessageSystem; @@ -720,90 +689,26 @@ S32 LLViewerInventoryCategory::getViewerDescendentCount() const return descendents_actual; } -bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp) +LLSD LLViewerInventoryCategory::exportLLSD() const { - // *NOTE: This buffer size is hard coded into scanf() below. - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - char valuestr[MAX_STRING]; /* Flawfinder: ignore */ + LLSD cat_data = LLInventoryCategory::exportLLSD(); + cat_data[INV_OWNER_ID] = mOwnerID; + cat_data[INV_VERSION] = mVersion; - keyword[0] = '\0'; - valuestr[0] = '\0'; - while(!feof(fp)) - { - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, " %254s %254s", keyword, valuestr); - if(0 == strcmp("{",keyword)) - { - continue; - } - if(0 == strcmp("}", keyword)) - { - break; - } - else if(0 == strcmp("cat_id", keyword)) - { - mUUID.set(valuestr); - } - else if(0 == strcmp("parent_id", keyword)) - { - mParentUUID.set(valuestr); - } - else if(0 == strcmp("type", keyword)) - { - mType = LLAssetType::lookup(valuestr); - } - else if(0 == strcmp("pref_type", keyword)) - { - mPreferredType = LLFolderType::lookup(valuestr); - } - else if(0 == strcmp("name", keyword)) - { - //strcpy(valuestr, buffer + strlen(keyword) + 3); - // *NOTE: Not ANSI C, but widely supported. - sscanf( /* Flawfinder: ignore */ - buffer, " %254s %254[^|]", keyword, valuestr); - mName.assign(valuestr); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - } - else if(0 == strcmp("owner_id", keyword)) - { - mOwnerID.set(valuestr); - } - else if(0 == strcmp("version", keyword)) - { - sscanf(valuestr, "%d", &mVersion); - } - else - { - LL_WARNS(LOG_INV) << "unknown keyword '" << keyword - << "' in inventory import category " << mUUID << LL_ENDL; - } - } - return true; + return cat_data; } -bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const +bool LLViewerInventoryCategory::importLLSD(const LLSD& cat_data) { - std::string uuid_str; - fprintf(fp, "\tinv_category\t0\n\t{\n"); - mUUID.toString(uuid_str); - fprintf(fp, "\t\tcat_id\t%s\n", uuid_str.c_str()); - mParentUUID.toString(uuid_str); - fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str()); - fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); - mOwnerID.toString(uuid_str); - fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str()); - fprintf(fp, "\t\tversion\t%d\n", mVersion); - fprintf(fp,"\t}\n"); + LLInventoryCategory::importLLSD(cat_data); + if (cat_data.has(INV_OWNER_ID)) + { + mOwnerID = cat_data[INV_OWNER_ID].asUUID(); + } + if (cat_data.has(INV_VERSION)) + { + setVersion(cat_data[INV_VERSION].asInteger()); + } return true; } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index d537b28682..24b632632b 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -131,14 +131,8 @@ public: virtual void packMessage(LLMessageSystem* msg) const; virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); virtual BOOL unpackMessage(const LLSD& item); - virtual BOOL importFile(LLFILE* fp); virtual BOOL importLegacyStream(std::istream& input_stream); - // file handling on the viewer. These are not meant for anything - // other than cacheing. - bool exportFileLocal(LLFILE* fp) const; - bool importFileLocal(LLFILE* fp); - // new methods BOOL isFinished() const { return mIsComplete; } void setComplete(BOOL complete) { mIsComplete = complete; } @@ -226,10 +220,9 @@ public: // How many descendents do we currently have information for in the InventoryModel? S32 getViewerDescendentCount() const; - // file handling on the viewer. These are not meant for anything - // other than caching. - bool exportFileLocal(LLFILE* fp) const; - bool importFileLocal(LLFILE* fp); + LLSD exportLLSD() const; + bool importLLSD(const LLSD& cat_data); + void determineFolderType(); void changeType(LLFolderType::EType new_folder_type); virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index c36d877a59..534a67195e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1719,23 +1719,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string user_data_path_cache = gDirUtilp->getCacheDir(false); user_data_path_cache += gDirUtilp->getDirDelimiter(); - std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir(); - user_data_path_cookies += gDirUtilp->getDirDelimiter(); - std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt"); - // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) - // If the linden username returned is blank, that can only mean we are - // at the login page displaying login Web page or Web browser test via Develop menu. - // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this - // is what we always used before this change) - std::string linden_user_dir = gDirUtilp->getLindenUserDir(); - if ( ! linden_user_dir.empty() ) - { - user_data_path_cookies = linden_user_dir; - user_data_path_cookies += gDirUtilp->getDirDelimiter(); - }; - // See if the plugin executable exists llstat s; if(LLFile::stat(launcher_name, &s)) @@ -1752,7 +1737,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ { media_source = new LLPluginClassMedia(owner); media_source->setSize(default_width, default_height); - media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_cef_log); + media_source->setUserDataPath(user_data_path_cache, gDirUtilp->getUserName(), user_data_path_cef_log); media_source->setLanguageCode(LLUI::getLanguage()); media_source->setZoomFactor(zoom_factor); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3f0b744d94..4605bccb13 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -376,20 +376,6 @@ void initialize_menus(); // Break up groups of more than 6 items with separators //----------------------------------------------------------------------------- -void set_underclothes_menu_options() -{ - if (gMenuHolder && gAgent.isTeen()) - { - gMenuHolder->getChild("Self Underpants")->setVisible(FALSE); - gMenuHolder->getChild("Self Undershirt")->setVisible(FALSE); - } - if (gMenuBarView && gAgent.isTeen()) - { - gMenuBarView->getChild("Menu Underpants")->setVisible(FALSE); - gMenuBarView->getChild("Menu Undershirt")->setVisible(FALSE); - } -} - void set_merchant_SLM_menu() { // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool @@ -2782,7 +2768,6 @@ class LLObjectBuild : public view_listener_t } }; - void handle_object_edit() { LLViewerParcelMgr::getInstance()->deselectLand(); @@ -2827,6 +2812,57 @@ void handle_object_edit() return; } +void handle_attachment_edit(const LLUUID& inv_item_id) +{ + if (isAgentAvatarValid()) + { + if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id)) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj); + + handle_object_edit(); + } + } +} + +void handle_attachment_touch(const LLUUID& inv_item_id) +{ + if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) ) + { + if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id))) + { + LLSelectMgr::getInstance()->deselectAll(); + + LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj); + if (!LLToolMgr::getInstance()->inBuildMode()) + { + struct SetTransient : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + node->setTransient(TRUE); + return true; + } + } f; + sel->applyToNodes(&f); + } + + handle_object_touch(); + } + } +} + +bool enable_attachment_touch(const LLUUID& inv_item_id) +{ + if (isAgentAvatarValid()) + { + const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)); + return (attach_obj) && (attach_obj->flagHandleTouch()); + } + return false; +} + void handle_object_inspect() { LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 6882405407..0f63c8cf58 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -82,7 +82,6 @@ void handle_detach(void*); BOOL enable_god_full(void* user_data); BOOL enable_god_liaison(void* user_data); BOOL enable_god_basic(void* user_data); -void set_underclothes_menu_options(); void check_merchant_status(bool force = false); void exchange_callingcard(const LLUUID& dest_id); @@ -110,6 +109,10 @@ void handle_object_return(); void handle_object_delete(); void handle_object_edit(); +void handle_attachment_edit(const LLUUID& inv_item_id); +void handle_attachment_touch(const LLUUID& inv_item_id); +bool enable_attachment_touch(const LLUUID& inv_item_id); + void handle_buy_land(); // Takes avatar UUID, or if no UUID passed, uses last selected object diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 7d8c6e68ea..99aeee72b8 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -406,6 +406,7 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_ void send_complete_agent_movement(const LLHost& sim_host) { + LL_DEBUGS("Teleport", "Messaging") << "Sending CompleteAgentMovement to sim_host " << sim_host << LL_ENDL; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_CompleteAgentMovement); msg->nextBlockFast(_PREHASH_AgentData); @@ -2876,12 +2877,12 @@ BOOL LLPostTeleportNotifiers::tick() // We're going to pretend to be a new agent void process_teleport_finish(LLMessageSystem* msg, void**) { - LL_DEBUGS("Messaging") << "Got teleport location message" << LL_ENDL; + LL_DEBUGS("Teleport","Messaging") << "Received TeleportFinish message" << LL_ENDL; LLUUID agent_id; msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id); if (agent_id != gAgent.getID()) { - LL_WARNS("Messaging") << "Got teleport notification for wrong agent!" << LL_ENDL; + LL_WARNS("Teleport","Messaging") << "Got teleport notification for wrong agent " << agent_id << " expected " << gAgent.getID() << ", ignoring!" << LL_ENDL; return; } @@ -2891,12 +2892,13 @@ void process_teleport_finish(LLMessageSystem* msg, void**) { // Server either ignored teleport cancel message or did not receive it in time. // This message can't be ignored since teleport is complete at server side + LL_INFOS("Teleport") << "Restoring canceled teleport request" << LL_ENDL; gAgent.restoreCanceledTeleportRequest(); } else { // Race condition? Make sure all variables are set correctly for teleport to work - LL_WARNS("Messaging") << "Teleport 'finish' message without 'start'" << LL_ENDL; + LL_WARNS("Teleport","Messaging") << "Teleport 'finish' message without 'start'. Setting state to TELEPORT_REQUESTED" << LL_ENDL; gTeleportDisplay = TRUE; LLViewerMessage::getInstance()->mTeleportStartedSignal(); gAgent.setTeleportState(LLAgent::TELEPORT_REQUESTED); @@ -2905,7 +2907,7 @@ void process_teleport_finish(LLMessageSystem* msg, void**) } else if (gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING) { - LL_WARNS("Messaging") << "Teleport message in the middle of other teleport" << LL_ENDL; + LL_WARNS("Teleport","Messaging") << "Teleport message in the middle of other teleport" << LL_ENDL; } // Teleport is finished; it can't be cancelled now. @@ -2933,11 +2935,18 @@ void process_teleport_finish(LLMessageSystem* msg, void**) msg->getU64Fast(_PREHASH_Info, _PREHASH_RegionHandle, region_handle); U32 teleport_flags; msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); - - + std::string seedCap; msg->getStringFast(_PREHASH_Info, _PREHASH_SeedCapability, seedCap); + LL_DEBUGS("Teleport") << "TeleportFinish message params are:" + << " sim_ip " << sim_ip + << " sim_port " << sim_port + << " region_handle " << region_handle + << " teleport_flags " << teleport_flags + << " seedCap " << seedCap + << LL_ENDL; + // update home location if we are teleporting out of prelude - specific to teleporting to welcome area if((teleport_flags & TELEPORT_FLAGS_SET_HOME_TO_TARGET) && (!gAgent.isGodlike())) @@ -2979,7 +2988,7 @@ void process_teleport_finish(LLMessageSystem* msg, void**) gAgent.standUp(); // now, use the circuit info to tell simulator about us! - LL_INFOS("Messaging") << "process_teleport_finish() Enabling " + LL_INFOS("Teleport","Messaging") << "process_teleport_finish() sending UseCircuitCode to enable sim_host " << sim_host << " with code " << msg->mOurCircuitCode << LL_ENDL; msg->newMessageFast(_PREHASH_UseCircuitCode); msg->nextBlockFast(_PREHASH_CircuitCode); @@ -2988,11 +2997,12 @@ void process_teleport_finish(LLMessageSystem* msg, void**) msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); msg->sendReliable(sim_host); + LL_INFOS("Teleport") << "Calling send_complete_agent_movement() and setting state to TELEPORT_MOVING" << LL_ENDL; send_complete_agent_movement(sim_host); gAgent.setTeleportState( LLAgent::TELEPORT_MOVING ); gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["contacting"]); - LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from process_teleport_finish(). Seed cap == " + LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability(). Seed cap == " << seedCap << LL_ENDL; regionp->setSeedCapability(seedCap); @@ -3025,6 +3035,8 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**) void process_agent_movement_complete(LLMessageSystem* msg, void**) { + LL_INFOS("Teleport","Messaging") << "Received ProcessAgentMovementComplete" << LL_ENDL; + gShiftFrame = true; gAgentMovementCompleted = true; @@ -3034,13 +3046,13 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); if((gAgent.getID() != agent_id) || (gAgent.getSessionID() != session_id)) { - LL_WARNS("Messaging") << "Incorrect id in process_agent_movement_complete()" - << LL_ENDL; + LL_WARNS("Teleport", "Messaging") << "Incorrect agent or session id in process_agent_movement_complete()" + << " agent " << agent_id << " expected " << gAgent.getID() + << " session " << session_id << " expected " << gAgent.getSessionID() + << ", ignoring" << LL_ENDL; return; } - LL_DEBUGS("Messaging") << "process_agent_movement_complete()" << LL_ENDL; - // *TODO: check timestamp to make sure the movement compleation // makes sense. LLVector3 agent_pos; @@ -3057,7 +3069,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) { // Could happen if you were immediately god-teleported away on login, // maybe other cases. Continue, but warn. - LL_WARNS("Messaging") << "agent_movement_complete() with NULL avatarp." << LL_ENDL; + LL_WARNS("Teleport", "Messaging") << "agent_movement_complete() with NULL avatarp." << LL_ENDL; } F32 x, y; @@ -3067,19 +3079,21 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) { if (gAgent.getRegion()) { - LL_WARNS("Messaging") << "current region " << gAgent.getRegion()->getOriginGlobal() << LL_ENDL; + LL_WARNS("Teleport", "Messaging") << "current region origin " + << gAgent.getRegion()->getOriginGlobal() << " id " << gAgent.getRegion()->getRegionID() << LL_ENDL; } - LL_WARNS("Messaging") << "Agent being sent to invalid home region: " - << x << ":" << y - << " current pos " << gAgent.getPositionGlobal() - << LL_ENDL; + LL_WARNS("Teleport", "Messaging") << "Agent being sent to invalid home region: " + << x << ":" << y + << " current pos " << gAgent.getPositionGlobal() + << ", calling forceDisconnect()" + << LL_ENDL; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("SentToInvalidRegion")); return; } - LL_INFOS("Messaging") << "Changing home region to " << x << ":" << y << LL_ENDL; + LL_INFOS("Teleport","Messaging") << "Changing home region to region id " << regionp->getRegionID() << " handle " << region_handle << " == x,y " << x << "," << y << LL_ENDL; // set our upstream host the new simulator and shuffle things as // appropriate. @@ -3107,6 +3121,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) gAgentCamera.slamLookAt(look_at); gAgentCamera.updateCamera(); + LL_INFOS("Teleport") << "Agent movement complete, setting state to TELEPORT_START_ARRIVAL" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_START_ARRIVAL ); if (isAgentAvatarValid()) @@ -3120,6 +3135,8 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) else { // This is initial log-in or a region crossing + LL_INFOS("Teleport") << "State is not TELEPORT_MOVING, so this is initial log-in or region crossing. " + << "Setting state to TELEPORT_NONE" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); if(LLStartUp::getStartupState() < STATE_STARTED) @@ -5963,6 +5980,8 @@ std::string formatted_time(const time_t& the_time) void process_teleport_failed(LLMessageSystem *msg, void**) { + LL_WARNS("Teleport","Messaging") << "Received TeleportFailed message" << LL_ENDL; + std::string message_id; // Tag from server, like "RegionEntryAccessBlocked" std::string big_reason; // Actual message to display LLSD args; @@ -5981,6 +6000,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) // Nothing found in the map - use what the server returned in the original message block msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, big_reason); } + LL_WARNS("Teleport") << "AlertInfo message_id " << message_id << " reason: " << big_reason << LL_ENDL; LLSD llsd_block; std::string llsd_raw; @@ -5990,10 +6010,11 @@ void process_teleport_failed(LLMessageSystem *msg, void**) std::istringstream llsd_data(llsd_raw); if (!LLSDSerialize::deserialize(llsd_block, llsd_data, llsd_raw.length())) { - LL_WARNS() << "process_teleport_failed: Attempted to read alert parameter data into LLSD but failed:" << llsd_raw << LL_ENDL; + LL_WARNS("Teleport") << "process_teleport_failed: Attempted to read alert parameter data into LLSD but failed:" << llsd_raw << LL_ENDL; } else { + LL_WARNS("Teleport") << "AlertInfo llsd block received: " << llsd_block << LL_ENDL; if(llsd_block.has("REGION_NAME")) { std::string region_name = llsd_block["REGION_NAME"].asString(); @@ -6009,6 +6030,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) { if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { + LL_WARNS("Teleport") << "called handle_teleport_access_blocked, setting state to TELEPORT_NONE" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } return; @@ -6031,22 +6053,27 @@ void process_teleport_failed(LLMessageSystem *msg, void**) args["REASON"] = message_id; } } + LL_WARNS("Teleport") << "Displaying CouldNotTeleportReason string, REASON= " << args["REASON"] << LL_ENDL; LLNotificationsUtil::add("CouldNotTeleportReason", args); if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { + LL_WARNS("Teleport") << "End of process_teleport_failed(). Reason message arg is " << args["REASON"] + << ". Setting state to TELEPORT_NONE" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } } void process_teleport_local(LLMessageSystem *msg,void**) { + LL_INFOS("Teleport","Messaging") << "Received TeleportLocal message" << LL_ENDL; + LLUUID agent_id; msg->getUUIDFast(_PREHASH_Info, _PREHASH_AgentID, agent_id); if (agent_id != gAgent.getID()) { - LL_WARNS("Messaging") << "Got teleport notification for wrong agent!" << LL_ENDL; + LL_WARNS("Teleport", "Messaging") << "Got teleport notification for wrong agent " << agent_id << " expected " << gAgent.getID() << ", ignoring!" << LL_ENDL; return; } @@ -6058,6 +6085,7 @@ void process_teleport_local(LLMessageSystem *msg,void**) msg->getVector3Fast(_PREHASH_Info, _PREHASH_LookAt, look_at); msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); + LL_INFOS("Teleport") << "Message params are location_id " << location_id << " teleport_flags " << teleport_flags << LL_ENDL; if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { if( gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL ) @@ -6070,6 +6098,8 @@ void process_teleport_local(LLMessageSystem *msg,void**) } else { + LL_WARNS("Teleport") << "State is not TELEPORT_LOCAL: " << gAgent.getTeleportStateName() + << ", setting state to TELEPORT_NONE" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index aa775b2bab..b88baf6aa7 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4800,9 +4800,7 @@ LLViewerTexture* LLViewerObject::getBakedTextureForMagicId(const LLUUID& id) } LLVOAvatar* avatar = getAvatar(); - if (avatar && !isHUDAttachment() - && isMesh() - && getVolume() && getVolume()->getParams().getSculptID().notNull()) // checking for the rigged mesh by params instead of using isRiggedMesh() to avoid false negatives when skin info isn't ready + if (avatar && !isHUDAttachment()) { LLAvatarAppearanceDefines::EBakedTextureIndex texIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(id); LLViewerTexture* bakedTexture = avatar->getBakedTexture(texIndex); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 12a9b47307..250c4ac328 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -114,7 +114,7 @@ class LLViewerObject public LLTrace::MemTrackable { protected: - ~LLViewerObject(); // use unref() + virtual ~LLViewerObject(); // use unref() // TomY: Provide for a list of extra parameter structures, mapped by structure name struct ExtraParameter diff --git a/indra/newview/llviewerparcelaskplay.cpp b/indra/newview/llviewerparcelaskplay.cpp index 74586dadc3..afbe2c94de 100644 --- a/indra/newview/llviewerparcelaskplay.cpp +++ b/indra/newview/llviewerparcelaskplay.cpp @@ -59,7 +59,10 @@ void LLViewerParcelAskPlay::initSingleton() } void LLViewerParcelAskPlay::cleanupSingleton() { - cancelNotification(); + if (LLNotifications::instanceExists()) + { + cancelNotification(); + } } void LLViewerParcelAskPlay::askToPlay(const LLUUID ®ion_id, const S32 &parcel_id, const std::string &url, ask_callback cb) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a30c5156fa..5c99e693d2 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -291,6 +291,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url << " region name " << regionp->getName() + << " handle " << regionp->getHandle() << " (attempt #" << mSeedCapAttempts + 1 << ")" << LL_ENDL; LL_DEBUGS("AppInit", "Capabilities") << "Capabilities requested: " << capabilityNames << LL_ENDL; @@ -350,9 +351,9 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) log_capabilities(mCapabilities); #endif + LL_DEBUGS("AppInit", "Capabilities", "Teleport") << "received caps for handle " << regionHandle + << " region name " << regionp->getName() << LL_ENDL; regionp->setCapabilitiesReceived(true); - LL_DEBUGS("AppInit", "Capabilities") << "received caps for handle " << regionHandle - << " region name " << regionp->getName() << LL_ENDL; if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) { diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index f108d96320..be5c22e7c3 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -400,6 +400,15 @@ void LLViewerShaderMgr::setShaders() return; } + if (!gGLManager.mHasShaderObjects + || !gGLManager.mHasVertexShader + || !gGLManager.mHasFragmentShader) + { + // Viewer will show 'hardware requirements' warning later + LL_INFOS("ShaderLoading") << "Shaders not supported" << LL_ENDL; + return; + } + static LLCachedControl max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) max_texture_index), 1); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a2cec9a613..bd83a61e5b 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1238,6 +1238,8 @@ void LLViewerFetchedTexture::loadFromFastCache() { if (mBoostLevel == LLGLTexture::BOOST_ICON) { + // Shouldn't do anything usefull since texures in fast cache are 16x16, + // it is here in case fast cache changes. S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) @@ -1485,7 +1487,8 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) mOrigWidth = mRawImage->getWidth(); mOrigHeight = mRawImage->getHeight(); - + // This is only safe because it's a local image and fetcher doesn't use raw data + // from local images, but this might become unsafe in case of changes to fetcher if (mBoostLevel == BOOST_PREVIEW) { mRawImage->biasedScaleToPowerOfTwo(1024); @@ -1989,6 +1992,7 @@ bool LLViewerFetchedTexture::updateFetch() if (mRawImage.notNull()) sRawCount--; if (mAuxRawImage.notNull()) sAuxCount--; + // keep in mind that fetcher still might need raw image, don't modify original bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage, mLastHttpGetStatus); if (mRawImage.notNull()) sRawCount++; @@ -2048,7 +2052,8 @@ bool LLViewerFetchedTexture::updateFetch() if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl - mRawImage->scale(expected_width, expected_height); + // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy + mRawImage = mRawImage->scaled(expected_width, expected_height); } } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5b83cf7163..bea4f2e4a5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -346,6 +346,12 @@ public: void update() { + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + clearText(); + return; + } + static LLCachedControl log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; std::string wind_vel_text; @@ -2317,7 +2323,7 @@ void LLViewerWindow::shutdownGL() LLViewerWindow::~LLViewerWindow() { LL_INFOS() << "Destroying Window" << LL_ENDL; - gDebugWindowProc = TRUE; // event catching, at this point it shouldn't output at all + gDebugWindowProc = TRUE; // event catching, disable once we figure out cause for exit crashes destroyWindow(); delete mDebugText; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index cc590fc947..377f3174f3 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -981,7 +981,12 @@ LLSpeakerVolumeStorage::LLSpeakerVolumeStorage() LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage() { - save(); +} + +//virtual +void LLSpeakerVolumeStorage::cleanupSingleton() +{ + save(); } void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, F32 volume) diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 3d04e1f0db..1a4d253208 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -499,9 +499,13 @@ protected: **/ class LLSpeakerVolumeStorage : public LLSingleton { - LLSINGLETON(LLSpeakerVolumeStorage); + LLSINGLETON_C11(LLSpeakerVolumeStorage); ~LLSpeakerVolumeStorage(); LOG_CLASS(LLSpeakerVolumeStorage); + +protected: + virtual void cleanupSingleton() override; + public: /** diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 976ef61d8e..a8d668420e 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -1744,6 +1744,12 @@ bool LLVivoxVoiceClient::waitForChannel() return false; } + if (sShuttingDown) + { + logoutOfVivox(true); + return false; + } + if (LLVoiceClient::instance().getVoiceEffectEnabled()) { retrieveVoiceFonts(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index ef39faa814..492d37edba 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -235,7 +235,8 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mLastFetchedMediaVersion = -1; memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); mMDCImplCount = 0; - mLastRiggingInfoLOD = -1; + mLastRiggingInfoLOD = -1; + mResetDebugText = false; } LLVOVolume::~LLVOVolume() @@ -1391,6 +1392,15 @@ BOOL LLVOVolume::calcLOD() { std::string debug_object_text = get_debug_object_lod_text(this); setDebugText(debug_object_text); + mResetDebugText = true; + } + } + else + { + if (mResetDebugText) + { + restoreHudText(); + mResetDebugText = false; } } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index de00ef494e..ce400a3498 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -424,6 +424,8 @@ private: S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; S32 mMDCImplCount; + bool mResetDebugText; + LLPointer mRiggedVolume; // statics diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index ccda92810e..12def24a0d 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -145,7 +145,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) static const unsigned int vertices_per_quad = 4; static const unsigned int indices_per_quad = 6; - const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") && LLGLSLShader::sNoFixedFunction ? 16 : 1; + const S32 size = LLPipeline::sRenderTransparentWater && LLGLSLShader::sNoFixedFunction ? 16 : 1; const S32 num_quads = size * size; face->setSize(vertices_per_quad * num_quads, diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index e7bbee5efd..e7f62e77b4 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -38,6 +38,7 @@ #include "llgesturemgr.h" #include "lltransutil.h" #include "llviewerattachmenu.h" +#include "llviewermenu.h" #include "llvoavatarself.h" class LLFindOutfitItems : public LLInventoryCollectFunctor @@ -794,7 +795,7 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() // Register handlers common for all wearable types. registrar.add("Wearable.Wear", boost::bind(wear_multiple, ids, true)); registrar.add("Wearable.Add", boost::bind(wear_multiple, ids, false)); - registrar.add("Wearable.Edit", boost::bind(handleMultiple, LLAgentWearables::editWearable, ids)); + registrar.add("Wearable.Edit", boost::bind(handle_item_edit, selected_id)); registrar.add("Wearable.CreateNew", boost::bind(createNewWearable, selected_id)); registrar.add("Wearable.ShowOriginal", boost::bind(show_item_original, selected_id)); registrar.add("Wearable.TakeOffDetach", @@ -809,6 +810,7 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() // Register handlers for attachments. registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); + registrar.add("Attachment.Touch", boost::bind(handle_attachment_touch, selected_id)); registrar.add("Attachment.Profile", boost::bind(show_item_profile, selected_id)); registrar.add("Object.Attach", boost::bind(LLViewerAttachMenu::attachObjects, ids, _2)); @@ -838,6 +840,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu U32 n_already_worn = 0; // number of items worn of same type as selected items U32 n_links = 0; // number of links among the selected items U32 n_editable = 0; // number of editable items among the selected ones + U32 n_touchable = 0; // number of touchable items among the selected ones bool can_be_worn = true; @@ -858,12 +861,17 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu const LLWearableType::EType wearable_type = item->getWearableType(); const bool is_link = item->getIsLinkType(); const bool is_worn = get_is_item_worn(id); - const bool is_editable = gAgentWearables.isWearableModifiable(id); + const bool is_editable = get_is_item_editable(id); + const bool is_touchable = enable_attachment_touch(id); const bool is_already_worn = gAgentWearables.selfHasWearable(wearable_type); if (is_worn) { ++n_worn; } + if (is_touchable) + { + ++n_touchable; + } if (is_editable) { ++n_editable; @@ -893,8 +901,10 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu setMenuItemEnabled(menu, "wear_add", LLAppearanceMgr::instance().canAddWearables(ids)); setMenuItemVisible(menu, "wear_replace", n_worn == 0 && n_already_worn != 0 && can_be_worn); //visible only when one item selected and this item is worn - setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1); - setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1); + setMenuItemVisible(menu, "touch", !standalone && mask == MASK_ATTACHMENT && n_worn == n_items); + setMenuItemEnabled(menu, "touch", n_touchable && n_worn == 1 && n_items == 1); + setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART|MASK_ATTACHMENT) && n_worn == n_items); + setMenuItemEnabled(menu, "edit", n_editable && n_worn == 1 && n_items == 1); setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); setMenuItemEnabled(menu, "create_new", LLAppearanceMgr::instance().canAddWearables(ids)); setMenuItemVisible(menu, "show_original", !standalone); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 604c5f770d..644934d1d8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -329,6 +329,7 @@ bool LLPipeline::sDelayVBUpdate = true; bool LLPipeline::sAutoMaskAlphaDeferred = true; bool LLPipeline::sAutoMaskAlphaNonDeferred = false; bool LLPipeline::sDisableShaders = false; +bool LLPipeline::sRenderTransparentWater = true; bool LLPipeline::sRenderBump = true; bool LLPipeline::sBakeSunlight = false; bool LLPipeline::sNoAlpha = false; @@ -1043,6 +1044,12 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) return true; } +//static +void LLPipeline::updateRenderTransparentWater() +{ + sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); +} + //static void LLPipeline::updateRenderBump() { @@ -1056,6 +1063,7 @@ void LLPipeline::updateRenderDeferred() RenderDeferred && LLRenderTarget::sUseFBO && LLPipeline::sRenderBump && + LLPipeline::sRenderTransparentWater && RenderAvatarVP && WindLightUseAtmosShaders && (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); @@ -6053,25 +6061,18 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_ { return max_dist; } - F32 radius = light->getLightRadius(); bool selected = light->isSelected(); - LLVector3 dpos = light->getRenderPosition() - cam_pos; - F32 dist2 = dpos.lengthSquared(); - if (!selected && dist2 > (max_dist + radius)*(max_dist + radius)) - { - return max_dist; - } - F32 dist = (F32) sqrt(dist2); - dist *= 1.f / inten; - dist -= radius; if (selected) { - dist -= 10000.f; // selected lights get highest priority + return 0.f; // selected lights get highest priority } + F32 radius = light->getLightRadius(); + F32 dist = dist_vec(light->getRenderPosition(), cam_pos); + dist = llmax(dist - radius, 0.f); if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) { // moving lights get a little higher priority (too much causes artifacts) - dist -= light->getLightRadius()*0.25f; + dist = llmax(dist - light->getLightRadius()*0.25f, 0.f); } return dist; } @@ -6090,13 +6091,18 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) // mNearbyLight (and all light_set_t's) are sorted such that // begin() == the closest light and rbegin() == the farthest light const S32 MAX_LOCAL_LIGHTS = 6; -// LLVector3 cam_pos = gAgent.getCameraPositionAgent(); - LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ? - camera.getOrigin() : - gAgent.getPositionAgent(); - - F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad + LLVector3 cam_pos = camera.getOrigin(); + F32 max_dist; + if (LLPipeline::sRenderDeferred) + { + max_dist = RenderFarClip; + } + else + { + max_dist = llmin(RenderFarClip, LIGHT_MAX_RADIUS * 4.f); + } + // UPDATE THE EXISTING NEARBY LIGHTS light_set_t cur_nearby_lights; for (light_set_t::iterator iter = mNearbyLights.begin(); @@ -6130,8 +6136,38 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) continue; } - F32 dist = calc_light_dist(volight, cam_pos, max_dist); - cur_nearby_lights.insert(Light(drawable, dist, light->fade)); + F32 dist = calc_light_dist(volight, cam_pos, max_dist); + F32 fade = light->fade; + // actual fade gets decreased/increased by setupHWLights + // light->fade value is 'time'. + // >=0 and light will become visible as value increases + // <0 and light will fade out + if (dist < max_dist) + { + if (fade < 0) + { + // mark light to fade in + // if fade was -LIGHT_FADE_TIME - it was fully invisible + // if fade -0 - it was fully visible + // visibility goes up from 0 to LIGHT_FADE_TIME. + fade += LIGHT_FADE_TIME; + } + } + else + { + // mark light to fade out + // visibility goes down from -0 to -LIGHT_FADE_TIME. + if (fade >= LIGHT_FADE_TIME) + { + fade = -0.0001f; // was fully visible + } + else if (fade >= 0) + { + // 0.75 visible light should stay 0.75 visible, but should reverse direction + fade -= LIGHT_FADE_TIME; + } + } + cur_nearby_lights.insert(Light(drawable, dist, fade)); } mNearbyLights = cur_nearby_lights; @@ -6150,17 +6186,23 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) { continue; // no lighting from HUD objects } - F32 dist = calc_light_dist(light, cam_pos, max_dist); - if (dist >= max_dist) + if (!sRenderAttachedLights && light && light->isAttachment()) { continue; } - if (!sRenderAttachedLights && light && light->isAttachment()) + LLVOAvatar * av = light->getAvatar(); + if (av && (av->isTooComplex() || av->isInMuteList())) + { + // avatars that are already in the list will be removed by removeMutedAVsLights + continue; + } + F32 dist = calc_light_dist(light, cam_pos, max_dist); + if (dist >= max_dist) { continue; } new_nearby_lights.insert(Light(drawable, dist, 0.f)); - if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) + if (!LLPipeline::sRenderDeferred && new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) { new_nearby_lights.erase(--new_nearby_lights.end()); const Light& last = *new_nearby_lights.rbegin(); @@ -6173,7 +6215,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) iter != new_nearby_lights.end(); iter++) { const Light* light = &(*iter); - if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS) + if (LLPipeline::sRenderDeferred || mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS) { mNearbyLights.insert(*light); ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT); @@ -6186,10 +6228,22 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) Light* farthest_light = (const_cast(&(*(mNearbyLights.rbegin())))); if (light->dist < farthest_light->dist) { - if (farthest_light->fade >= 0.f) - { - farthest_light->fade = -(gFrameIntervalSeconds.value()); - } + // mark light to fade out + // visibility goes down from -0 to -LIGHT_FADE_TIME. + // + // This is a mess, but for now it needs to be in sync + // with fade code above. Ex: code above detects distance < max, + // sets fade time to positive, this code then detects closer + // lights and sets fade time negative, fully compensating + // for the code above + if (farthest_light->fade >= LIGHT_FADE_TIME) + { + farthest_light->fade = -0.0001f; // was fully visible + } + else if (farthest_light->fade >= 0) + { + farthest_light->fade -= LIGHT_FADE_TIME; + } } else { @@ -6309,12 +6363,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) } } - const LLViewerObject *vobj = drawable->getVObj(); - if(vobj && vobj->getAvatar() && vobj->getAvatar()->isInMuteList()) - { - continue; - } - if (drawable->isState(LLDrawable::ACTIVE)) { mLightMovingMask |= (1<setBuffer(LLVertexBuffer::MAP_VERTEX); LLGLDepthTest depth(GL_TRUE, GL_FALSE); - for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + // mNearbyLights already includes distance calculation and excludes muted avatars. + // It is calculated from mLights + // mNearbyLights also provides fade value to gracefully fade-out out of range lights + for (light_set_t::iterator iter = mNearbyLights.begin(); iter != mNearbyLights.end(); ++iter) { - LLDrawable *drawablep = *iter; - - LLVOVolume *volume = drawablep->getVOVolume(); + LLDrawable * drawablep = iter->drawable; + LLVOVolume * volume = drawablep->getVOVolume(); if (!volume) { continue; @@ -8704,24 +8754,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target) } } - const LLViewerObject *vobj = drawablep->getVObj(); - if (vobj) - { - LLVOAvatar *av = vobj->getAvatar(); - if (av && (av->isTooComplex() || av->isInMuteList())) - { - continue; - } - } - - const LLVector3 position = drawablep->getPositionAgent(); - if (dist_vec(position, LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip + volume->getLightRadius()) - { - continue; - } - LLVector4a center; - center.load3(position.mV); + center.load3(drawablep->getPositionAgent().mV); const F32 *c = center.getF32ptr(); F32 s = volume->getLightRadius() * 1.5f; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 600bdd9d06..52fd51cd80 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -409,6 +409,7 @@ public: static bool getRenderHighlights(); static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay + static void updateRenderTransparentWater(); static void updateRenderBump(); static void updateRenderDeferred(); static void refreshCachedSettings(); @@ -578,6 +579,7 @@ public: static bool sAutoMaskAlphaDeferred; static bool sAutoMaskAlphaNonDeferred; static bool sDisableShaders; // if true, rendering will be done without shaders + static bool sRenderTransparentWater; static bool sRenderBump; static bool sBakeSunlight; static bool sNoAlpha; diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 8587243791..ff2d8b4943 100755 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -155,7 +155,7 @@ BEGIN VALUE "FileDescription", "Second Life" VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" VALUE "InternalName", "Second Life" - VALUE "LegalCopyright", "Copyright � 2001, Linden Research, Inc." + VALUE "LegalCopyright", "Copyright (c) 2020, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}" diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 57325739e4..034576d30c 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -41,6 +41,9 @@ + diff --git a/indra/newview/skins/default/xui/da/menu_cof_attachment.xml b/indra/newview/skins/default/xui/da/menu_cof_attachment.xml index 9d7fc0f223..37e9351ab5 100644 --- a/indra/newview/skins/default/xui/da/menu_cof_attachment.xml +++ b/indra/newview/skins/default/xui/da/menu_cof_attachment.xml @@ -1,4 +1,6 @@ + + diff --git a/indra/newview/skins/default/xui/da/menu_inventory.xml b/indra/newview/skins/default/xui/da/menu_inventory.xml index f9bdf36f1f..ba96d6dca1 100644 --- a/indra/newview/skins/default/xui/da/menu_inventory.xml +++ b/indra/newview/skins/default/xui/da/menu_inventory.xml @@ -78,6 +78,7 @@ + diff --git a/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml index 63f4b0b388..67adf74bcd 100644 --- a/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml @@ -3,6 +3,7 @@ + diff --git a/indra/newview/skins/default/xui/da/menu_wearing_gear.xml b/indra/newview/skins/default/xui/da/menu_wearing_gear.xml index 515a15b287..ff58cd68b2 100644 --- a/indra/newview/skins/default/xui/da/menu_wearing_gear.xml +++ b/indra/newview/skins/default/xui/da/menu_wearing_gear.xml @@ -1,5 +1,7 @@ - + + + diff --git a/indra/newview/skins/default/xui/da/menu_wearing_tab.xml b/indra/newview/skins/default/xui/da/menu_wearing_tab.xml index c0db7b6842..adaac35f68 100644 --- a/indra/newview/skins/default/xui/da/menu_wearing_tab.xml +++ b/indra/newview/skins/default/xui/da/menu_wearing_tab.xml @@ -1,6 +1,8 @@ + + - + diff --git a/indra/newview/skins/default/xui/de/menu_cof_attachment.xml b/indra/newview/skins/default/xui/de/menu_cof_attachment.xml index 05d3dfca9d..7c7da58866 100644 --- a/indra/newview/skins/default/xui/de/menu_cof_attachment.xml +++ b/indra/newview/skins/default/xui/de/menu_cof_attachment.xml @@ -1,4 +1,6 @@ + + diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml index 84cded77ce..743b8b2073 100644 --- a/indra/newview/skins/default/xui/de/menu_inventory.xml +++ b/indra/newview/skins/default/xui/de/menu_inventory.xml @@ -105,6 +105,7 @@ + diff --git a/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml index 283e454a06..e4c2c88f11 100644 --- a/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml @@ -3,6 +3,7 @@ + diff --git a/indra/newview/skins/default/xui/de/menu_wearing_gear.xml b/indra/newview/skins/default/xui/de/menu_wearing_gear.xml index dacf898b6a..6cb0d095e7 100644 --- a/indra/newview/skins/default/xui/de/menu_wearing_gear.xml +++ b/indra/newview/skins/default/xui/de/menu_wearing_gear.xml @@ -1,6 +1,8 @@ - + + + diff --git a/indra/newview/skins/default/xui/de/menu_wearing_tab.xml b/indra/newview/skins/default/xui/de/menu_wearing_tab.xml index 61002b3dad..c729ef6b00 100644 --- a/indra/newview/skins/default/xui/de/menu_wearing_tab.xml +++ b/indra/newview/skins/default/xui/de/menu_wearing_tab.xml @@ -1,8 +1,9 @@ + - + diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index d16815c0f4..359a835630 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -266,6 +266,10 @@ Möchten Sie den ausgewählten Einwohnern Änderungsrechte gewähren? Möchten Sie den ausgewählten Einwohnern die Änderungsrechte entziehen? + + Ein Gruppenname muss zwischen [MIN_LEN] und [MAX_LEN] Zeichen lang sein. + + Gruppe konnte nicht erstellt werden. [MESSAGE] @@ -366,7 +370,7 @@ Fortfahren? Sie haben nicht genug L$, um dieser Gruppe beizutreten. - Die Gründung dieser Gruppe kostet 100 L$. + Die Erstellung dieser Gruppe kostet L$[COST]. Gruppen müssen mehr als ein Mitglied haben oder sie werden gelöscht. Bitte laden Sie innerhalb von 48 Stunden Mitglieder in Ihre Gruppe ein. @@ -508,6 +512,9 @@ Um Medien nur auf einer Fläche einzufügen, wählen Sie „Oberfläche auswähl Fehler beim Erstellen des Fotos! + + Du brauchst L$[COST], um diesen Artikel hochzuladen. + Es kostet L$[COST], um ein Foto in Ihrem Inventar zu speichern. Sie können entweder L$ kaufen oder das Foto auf Ihrem Computer speichern. @@ -1753,11 +1760,14 @@ Diese Gruppe verlassen? - Die Gruppenbegrenzung für Basiskonten ist [MAX_BASIC]; für -[https://secondlife.com/premium/ Premium-]Konten ist sie [MAX_PREMIUM]. -Wenn Sie ein Downgrade Ihres Kontos durchgeführt haben, müssen Sie das Gruppenlimit unter [MAX_BASIC] bringen, bevor sich weitere Personen registrieren können. - -[https://secondlife.com/my/account/membership.php Noch heute upgraden!] + Einwohner mit Basic-Mitgliedschaft können bis zu [MAX_BASIC] Gruppen beitreten. +Premium-Mitgliedschaften erlauben bis zu [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Mehr Informationen oder Upgrade] + + + + Einwohner mit Basic-Mitgliedschaft können bis zu [MAX_BASIC] Gruppen beitreten. +Premium-Mitgliedschaften erlauben bis zu [MAX_PREMIUM]. Premium-Plus-Mitgliedschaften +erlauben bis zu [MAX_PREMIUM_PLUS]. [https://secondlife.com/my/account/membership.php? Mehr Informationen oder Upgrade] @@ -3320,6 +3330,22 @@ Diese werden für ein paar Sekunden sicherheitshalber gesperrt. Sie wurden vom Moderator stummgeschaltet. + + Leider konnten wir für diese Sitzung keine Informationen zu den Leistungen erhalten. Dies sollte in einer normalen Produktionsumgebung nicht passieren. Kontaktiere bitte den Support. Diese Sitzung wird nicht normal laufen, und wir empfehlen, die Sitzung neu zu starten. + + + + Dadurch werden [COUNT] Artikel zu einem Gesamtpreis von L$[COST] hochgeladen. Möchtest du mit dem Hochladen fortfahren? + + + + Ausgewählte Dateien können nicht per Bulk-Upload hochgeladen werden. + + + + Einige der ausgewählten Dateien können nicht per Bulk-Upload hochgeladen werden. + + Das Hochladen kostet [PRICE] L$. Möchten Sie fortfahren? diff --git a/indra/newview/skins/default/xui/de/panel_people.xml b/indra/newview/skins/default/xui/de/panel_people.xml index 1eb3d4d1b9..81de679429 100644 --- a/indra/newview/skins/default/xui/de/panel_people.xml +++ b/indra/newview/skins/default/xui/de/panel_people.xml @@ -18,7 +18,7 @@ Sie suchen nach Leuten? Verwenden Sie die [secondlife:///app/worldmap Karte]. - + @@ -51,7 +51,7 @@ Sie suchen nach Leuten? Verwenden Sie die [secondlife:///app/worldmap Karte]. - Sie gehören [COUNT] Gruppen an und können [REMAINING] weiteren beitreten. + Du gehörst zu [COUNT] Gruppen, und kannst [REMAINING] weiteren beitreten. diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 7db76ec552..43327c132d 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -1645,11 +1645,14 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich unter http://suppo Aktualisierung läuft... + + Die Gebühr richtet sich nach deiner Abonnementstufe. Bei höheren Stufen werden niedrigere Gebühren erhoben. [https://secondlife.com/my/account/membership.php? Mehr erfahren] + - Landmarken öffnen + Wegweiser öffnen - Variabel + Unbegrenzt @@ -5096,6 +5099,15 @@ Bitte überprüfen Sie http://status.secondlifegrid.net, um herauszufinden, ob e Chat + + Basis + + + Premium + + + Premium Plus + Ausgewählte Objekte löschen? diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index e93568a87e..e282f1b179 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -596,7 +596,10 @@ left="420" name="TransparentWater" top_delta="16" - width="300" /> + width="300"> + + + + + + + + + + - - - + value="SampleParcel, Name Long" /> + Region: [REGIONAMEPOS] + + + + value="TempOwner" + width="215" /> + + + This landmark: + - +