diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..5766126411 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "monthly" diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c7a758bd0f..7b6187f3bb 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -73,7 +73,7 @@ jobs: uses: actions/checkout@v4 with: repository: secondlife/build-variables - ref: viewer + ref: master path: .build-variables - name: Checkout master-message-template @@ -224,7 +224,7 @@ jobs: - name: Upload executable if: matrix.configuration != 'ReleaseOS' && steps.build.outputs.viewer_app - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "${{ steps.build.outputs.artifact }}-app" path: | @@ -234,7 +234,7 @@ jobs: # artifact for that too. - name: Upload symbol file if: matrix.configuration != 'ReleaseOS' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "${{ steps.build.outputs.artifact }}-symbols" path: | @@ -242,7 +242,7 @@ jobs: - name: Upload metadata if: matrix.configuration != 'ReleaseOS' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "${{ steps.build.outputs.artifact }}-metadata" # emitted by build.sh, possibly multiple lines @@ -250,7 +250,7 @@ jobs: ${{ steps.build.outputs.metadata }} - name: Upload physics package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 # should only be set for viewer-private if: matrix.configuration != 'ReleaseOS' && steps.build.outputs.physicstpv with: diff --git a/.github/workflows/label.yaml b/.github/workflows/label.yaml index 6e41d8aa2d..a34c575680 100644 --- a/.github/workflows/label.yaml +++ b/.github/workflows/label.yaml @@ -9,7 +9,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v4 + - uses: actions/labeler@v5 with: configuration-path: .github/labeler.yaml repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index d626eef38d..dcb64a3b29 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: 3.x - - uses: pre-commit/action@v3.0.0 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index e44e223589..6d0eaacca5 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -12,7 +12,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6 + - uses: actions/stale@v9 id: stale with: stale-pr-message: This pull request is stale because it has been open 30 days with no activity. Remove stale label or comment or it will be closed in 7 days diff --git a/autobuild.xml b/autobuild.xml index 76ef04f697..20a4f5fb7a 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -142,9 +142,11 @@ archive hash - 81fe1e927e4fe3c5e5f15ce6219ca883 + 691fef2ddd57d7b6c26e87fc82d9ace3f54e078c + hash_algorithm + sha1 url - https://3p.firestormviewer.org/fltk-1.3.5.202282121-linux64-202282121.tar.bz2 + https://github.com/secondlife/3p-fltk/releases/download/v1.3.9-r1/fltk-1.3.9.8556992788-linux64-8556992788.tar.zst name linux @@ -1177,34 +1179,6 @@ description a library for writing and using C++ mock classes - gstreamer - - platforms - - linux64 - - archive - - hash - 86a358f1b5a2c2baf68444b2bfc5bb32 - url - https://3p.firestormviewer.org/gstreamer-0.10.6.180841551-linux64-180841551.tar.bz2 - - name - linux64 - - - license - LGPL - license_file - LICENSES/gstreamer.txt - copyright - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - version - 0.10.6.314267 - name - gstreamer - havok-source platforms @@ -1302,11 +1276,11 @@ archive hash - f5e5be3af96f1eb0842219a94765c04aa9c561c5 + bdd74e2a02c7b78fded9222140d197da4af9904e hash_algorithm sha1 url - https://3p.firestormviewer.org/icu4c-4.8.1-linux64-240621048.tar.zst + https://github.com/secondlife/3p-icu4c/releases/download/v4.8.1-8bff176/icu4c-4.8.1-linux64-8512575562.tar.zst name linux64 @@ -1856,11 +1830,11 @@ archive hash - e50ea94bbaa4ff41bf53b84b7192df1a694c5337 + 3a3e14563cd5fc019c3f139b82aa46ec79847709 hash_algorithm sha1 url - https://github.com/secondlife/llca/releases/download/v202310121525.0-d22bd98/llca-202310121530.0-common-d22bd98.tar.zst + https://github.com/secondlife/llca/releases/download/v202312051403.17-0f5d9c3/llca-202312051404.0-common-0f5d9c3.tar.zst name common @@ -1874,7 +1848,7 @@ Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project. version - 202310121530.0 + 202312051404.0 name llca diff --git a/build.sh b/build.sh index dea8fb4f2e..c55179f423 100755 --- a/build.sh +++ b/build.sh @@ -112,7 +112,8 @@ installer_CYGWIN() fi } -[[ -n "$GITHUB_OUTPUT" ]] || fatal "Need to export GITHUB_OUTPUT" +# if someone wants to run build.sh outside the GitHub environment +[[ -n "$GITHUB_OUTPUT" ]] || export GITHUB_OUTPUT='/dev/null' # The following is based on the Warning for GitHub multiline output strings: # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) diff --git a/doc/contributions.txt b/doc/contributions.txt index 123189f5be..0e53e2ecbd 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -297,6 +297,7 @@ Beq Janus SL-18637 SL-19317 SL-19660 + SL-20610 Beth Walcher Bezilon Kasei Biancaluce Robbiani diff --git a/indra/llcommon/classic_callback.h b/indra/llcommon/classic_callback.h index 1ad6dbc58f..009c25d67c 100644 --- a/indra/llcommon/classic_callback.h +++ b/indra/llcommon/classic_callback.h @@ -119,11 +119,11 @@ public: * ClassicCallback must not itself be copied or moved! Once you've passed * get_userdata() to some API, this object MUST remain at that address. */ - // However, we can't yet count on C++17 Class Template Argument Deduction, - // which means makeClassicCallback() is still useful, which means we MUST - // be able to return one to construct into caller's instance (move ctor). - // Possible defense: bool 'referenced' data member set by get_userdata(), - // with an llassert_always(! referenced) check in the move constructor. + // However, makeClassicCallback() is useful for deducing the CALLABLE + // type, which means we MUST be able to return one to construct into + // caller's instance (move ctor). Possible defense: bool 'referenced' data + // member set by get_userdata(), with an llassert_always(! referenced) + // check in the move constructor. ClassicCallback(ClassicCallback const&) = delete; ClassicCallback(ClassicCallback&&) = default; // delete; ClassicCallback& operator=(ClassicCallback const&) = delete; diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index e3bb661c63..d1457a4e0e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -104,7 +104,6 @@ BOOL LLApp::sLogInSignal = FALSE; // Keeps track of application status LLScalarCond LLApp::sStatus{LLApp::APP_STATUS_STOPPED}; LLAppErrorHandler LLApp::sErrorHandler = NULL; -BOOL LLApp::sErrorThreadRunning = FALSE; LLApp::LLApp() @@ -793,13 +792,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) return; } - // Flag status to ERROR, so thread_error does its work. + // Flag status to ERROR LLApp::setError(); - // Block in the signal handler until somebody says that we're done. - while (LLApp::sErrorThreadRunning && !LLApp::isStopped()) - { - ms_sleep(10); - } if (LLApp::sLogInSignal) { diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index c832c8b142..a892bfeb1e 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -291,7 +291,6 @@ protected: static void setStatus(EAppStatus status); // Use this to change the application status. static LLScalarCond sStatus; // Reflects current application status - static BOOL sErrorThreadRunning; // Set while the error thread is running static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp index bb85fe32a3..433b54f6f8 100644 --- a/indra/llcommon/llbase64.cpp +++ b/indra/llcommon/llbase64.cpp @@ -42,7 +42,7 @@ std::string LLBase64::encode(const U8* input, size_t input_size) && input_size > 0) { // Yes, it returns int. - int b64_buffer_length = apr_base64_encode_len(narrow(input_size)); + int b64_buffer_length = apr_base64_encode_len(narrow(input_size)); char* b64_buffer = new char[b64_buffer_length]; // This is faster than apr_base64_encode() if you know @@ -52,7 +52,7 @@ std::string LLBase64::encode(const U8* input, size_t input_size) b64_buffer_length = apr_base64_encode_binary( b64_buffer, input, - narrow(input_size)); + narrow(input_size)); output.assign(b64_buffer); delete[] b64_buffer; } diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 1d383f174d..c13900f74a 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -123,7 +123,7 @@ LLCoros::LLCoros(): // Previously we used // boost::context::guarded_stack_allocator::default_stacksize(); // empirically this is insufficient. - mStackSize(768*1024), + mStackSize(900*1024), // mCurrent does NOT own the current CoroData instance -- it simply // points to it. So initialize it with a no-op deleter. mCurrent{ [](CoroData*){} } diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h index 5800ec5e5d..18664e340e 100644 --- a/indra/llcommon/lldictionary.h +++ b/indra/llcommon/lldictionary.h @@ -87,11 +87,10 @@ protected: } void addEntry(Index index, Entry *entry) { - if (lookup(index)) + if (!this->emplace(index, entry).second) { LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL; } - (*this)[index] = entry; } }; diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index f9de0c7929..64aceddf32 100644 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -46,33 +46,32 @@ template class LLPointer { public: - - LLPointer() : + LLPointer() : mPointer(NULL) { } - LLPointer(Type* ptr) : + LLPointer(Type* ptr) : mPointer(ptr) { ref(); } - LLPointer(const LLPointer& ptr) : + LLPointer(const LLPointer& ptr) : mPointer(ptr.mPointer) { ref(); } - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + // Support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template - LLPointer(const LLPointer& ptr) : + LLPointer(const LLPointer& ptr) : mPointer(ptr.get()) { ref(); } - ~LLPointer() + ~LLPointer() { unref(); } @@ -83,39 +82,39 @@ public: const Type& operator*() const { return *mPointer; } Type& operator*() { return *mPointer; } - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } + operator BOOL() const { return (mPointer != NULL); } + operator bool() const { return (mPointer != NULL); } bool operator!() const { return (mPointer == NULL); } bool isNull() const { return (mPointer == NULL); } bool notNull() const { return (mPointer != NULL); } - operator Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } + operator Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } - LLPointer& operator =(Type* ptr) - { + LLPointer& operator =(Type* ptr) + { assign(ptr); - return *this; + return *this; } - LLPointer& operator =(const LLPointer& ptr) - { + LLPointer& operator =(const LLPointer& ptr) + { assign(ptr); - return *this; + return *this; } // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template - LLPointer& operator =(const LLPointer& ptr) - { + LLPointer& operator =(const LLPointer& ptr) + { assign(ptr.get()); - return *this; + return *this; } - + // Just exchange the pointers, which will not change the reference counts. static void swap(LLPointer& a, LLPointer& b) { @@ -129,16 +128,6 @@ protected: void ref(); void unref(); #else - - void assign(const LLPointer& ptr) - { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - } void ref() { if (mPointer) @@ -161,7 +150,18 @@ protected: } } } -#endif +#endif // LL_LIBRARY_INCLUDE + + void assign(const LLPointer& ptr) + { + if (mPointer != ptr.mPointer) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + } + protected: Type* mPointer; }; @@ -169,18 +169,18 @@ protected: template class LLConstPointer { public: - LLConstPointer() : + LLConstPointer() : mPointer(NULL) { } - LLConstPointer(const Type* ptr) : + LLConstPointer(const Type* ptr) : mPointer(ptr) { ref(); } - LLConstPointer(const LLConstPointer& ptr) : + LLConstPointer(const LLConstPointer& ptr) : mPointer(ptr.mPointer) { ref(); @@ -188,7 +188,7 @@ public: // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template - LLConstPointer(const LLConstPointer& ptr) : + LLConstPointer(const LLConstPointer& ptr) : mPointer(ptr.get()) { ref(); @@ -203,55 +203,55 @@ public: const Type* operator->() const { return mPointer; } const Type& operator*() const { return *mPointer; } - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } + operator BOOL() const { return (mPointer != NULL); } + operator bool() const { return (mPointer != NULL); } bool operator!() const { return (mPointer == NULL); } bool isNull() const { return (mPointer == NULL); } bool notNull() const { return (mPointer != NULL); } - operator const Type*() const { return mPointer; } - bool operator !=(const Type* ptr) const { return (mPointer != ptr); } - bool operator ==(const Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLConstPointer& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLConstPointer& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLConstPointer& ptr) const { return (mPointer > ptr.mPointer); } + operator const Type*() const { return mPointer; } + bool operator !=(const Type* ptr) const { return (mPointer != ptr); } + bool operator ==(const Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLConstPointer& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLConstPointer& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLConstPointer& ptr) const { return (mPointer > ptr.mPointer); } - LLConstPointer& operator =(const Type* ptr) + LLConstPointer& operator =(const Type* ptr) { if( mPointer != ptr ) { - unref(); - mPointer = ptr; + unref(); + mPointer = ptr; ref(); } - return *this; + return *this; } - LLConstPointer& operator =(const LLConstPointer& ptr) - { + LLConstPointer& operator =(const LLConstPointer& ptr) + { if( mPointer != ptr.mPointer ) { - unref(); + unref(); mPointer = ptr.mPointer; ref(); } - return *this; + return *this; } // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template - LLConstPointer& operator =(const LLConstPointer& ptr) - { + LLConstPointer& operator =(const LLConstPointer& ptr) + { if( mPointer != ptr.get() ) { - unref(); + unref(); mPointer = ptr.get(); ref(); } - return *this; + return *this; } - + // Just exchange the pointers, which will not change the reference counts. static void swap(LLConstPointer& a, LLConstPointer& b) { @@ -262,11 +262,11 @@ public: protected: #ifdef LL_LIBRARY_INCLUDE - void ref(); + void ref(); void unref(); -#else - void ref() - { +#else // LL_LIBRARY_INCLUDE + void ref() + { if (mPointer) { mPointer->ref(); @@ -277,9 +277,9 @@ protected: { if (mPointer) { - const Type *tempp = mPointer; + const Type *temp = mPointer; mPointer = NULL; - tempp->unref(); + temp->unref(); if (mPointer != NULL) { LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; @@ -287,7 +287,8 @@ protected: } } } -#endif +#endif // LL_LIBRARY_INCLUDE + protected: const Type* mPointer; }; @@ -297,13 +298,13 @@ class LLCopyOnWritePointer : public LLPointer { public: typedef LLCopyOnWritePointer self_t; - typedef LLPointer pointer_t; - - LLCopyOnWritePointer() + typedef LLPointer pointer_t; + + LLCopyOnWritePointer() : mStayUnique(false) {} - LLCopyOnWritePointer(Type* ptr) + LLCopyOnWritePointer(Type* ptr) : LLPointer(ptr), mStayUnique(false) {} diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp index 33afc50cf7..0192111574 100644 --- a/indra/llcommon/llrand.cpp +++ b/indra/llcommon/llrand.cpp @@ -58,7 +58,9 @@ * to restore uniform distribution. */ -static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); +// gRandomGenerator is a stateful static object, which is therefore not +// inherently thread-safe. +static thread_local LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed()); // no default implementation, only specific F64 and F32 specializations template @@ -71,7 +73,7 @@ inline F64 ll_internal_random() // CPUs (or at least multi-threaded processes) seem to // occasionally give an obviously incorrect random number -- like // 5^15 or something. Sooooo, clamp it as described above. - F64 rv = gRandomGenerator(); + F64 rv{ gRandomGenerator() }; if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0); return rv; } @@ -79,7 +81,13 @@ inline F64 ll_internal_random() template <> inline F32 ll_internal_random() { - return F32(ll_internal_random()); + // *HACK: clamp the result as described above. + // Per Monty, it's important to clamp using the correct fmodf() rather + // than expanding to F64 for fmod() and then truncating back to F32. Prior + // to this change, we were getting sporadic ll_frand() == 1.0 results. + F32 rv{ narrow(gRandomGenerator()) }; + if(!((rv >= 0.0f) && (rv < 1.0f))) return fmodf(rv, 1.0f); + return rv; } /*------------------------------ F64 aliases -------------------------------*/ diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 6852b5536a..3da94e7a8d 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -30,7 +30,7 @@ #include "llerror.h" // maximum reference count before sounding memory leak alarm -const S32 gMaxRefCount = S32_MAX; +const S32 gMaxRefCount = LL_REFCOUNT_FREE; LLRefCount::LLRefCount(const LLRefCount& other) : mRef(0) @@ -49,7 +49,7 @@ LLRefCount::LLRefCount() : } LLRefCount::~LLRefCount() -{ +{ if (mRef != LL_REFCOUNT_FREE && mRef != 0) { LL_ERRS() << "deleting non-zero reference" << LL_ENDL; diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 2080da1565..15e7175fc8 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -51,24 +51,20 @@ protected: public: LLRefCount(); - inline void validateRefCount() const - { - llassert(mRef > 0); // ref count below 0, likely corrupted - llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak - } - inline void ref() const - { - mRef++; - validateRefCount(); - } + { + llassert(mRef != LL_REFCOUNT_FREE); // object is deleted + mRef++; + llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak + } inline S32 unref() const { - validateRefCount(); + llassert(mRef != LL_REFCOUNT_FREE); // object is deleted + llassert(mRef > 0); // ref count below 1, likely corrupted if (0 == --mRef) { - mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging + mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging delete this; return 0; } @@ -82,8 +78,8 @@ public: return mRef; } -private: - mutable S32 mRef; +private: + mutable S32 mRef; }; @@ -106,7 +102,7 @@ protected: public: LLThreadSafeRefCount(); LLThreadSafeRefCount(const LLThreadSafeRefCount&); - LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) + LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) { mRef = 0; return *this; @@ -114,8 +110,8 @@ public: void ref() { - mRef++; - } + mRef++; + } void unref() { @@ -136,36 +132,36 @@ public: return currentVal; } -private: - LLAtomicS32 mRef; +private: + LLAtomicS32 mRef; }; /** * intrusive pointer support for LLThreadSafeRefCount * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type */ -inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) +inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) { p->ref(); } -inline void intrusive_ptr_release(LLThreadSafeRefCount* p) +inline void intrusive_ptr_release(LLThreadSafeRefCount* p) { - p->unref(); + p->unref(); } /** * intrusive pointer support * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type */ -inline void intrusive_ptr_add_ref(LLRefCount* p) +inline void intrusive_ptr_add_ref(LLRefCount* p) { p->ref(); } -inline void intrusive_ptr_release(LLRefCount* p) +inline void intrusive_ptr_release(LLRefCount* p) { - p->unref(); + p->unref(); } #endif diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index cdb9a7ed8a..8ed254919c 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -197,12 +197,12 @@ public: typename std::enable_if::value && ! std::is_same::value, bool>::type = true> - LLSD(VALUE v): LLSD(Integer(narrow(v))) {} + LLSD(VALUE v): LLSD(Integer(narrow(v))) {} // support construction from F32 et al. template ::value, bool>::type = true> - LLSD(VALUE v): LLSD(Real(narrow(v))) {} + LLSD(VALUE v): LLSD(Real(narrow(v))) {} //@} /** @name Scalar Assignment */ diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 2460af381b..5a90abf38b 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -2174,7 +2174,7 @@ std::string zip_llsd(LLSD& data) U8 out[CHUNK]; - strm.avail_in = narrow(source.size()); + strm.avail_in = narrow(source.size()); strm.next_in = (U8*) source.data(); U8* output = NULL; diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 727aad3b96..584bbd07fa 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -197,12 +197,12 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, // *FIX: memory inefficient. // *TODO: convert to use LLBase64 ostr << pre << ""; - int b64_buffer_length = apr_base64_encode_len(narrow(buffer.size())); + int b64_buffer_length = apr_base64_encode_len(narrow(buffer.size())); char* b64_buffer = new char[b64_buffer_length]; b64_buffer_length = apr_base64_encode_binary( b64_buffer, &buffer[0], - narrow(buffer.size())); + narrow(buffer.size())); ostr.write(b64_buffer, b64_buffer_length - 1); delete[] b64_buffer; ostr << "" << post; @@ -415,11 +415,18 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) if (buffer) { ((char*) buffer)[count ? count - 1 : 0] = '\0'; + if (mEmitErrors) + { + LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*)buffer << LL_ENDL; + } } - if (mEmitErrors) - { - LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << LL_ENDL; - } + else + { + if (mEmitErrors) + { + LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR, null buffer" << LL_ENDL; + } + } data = LLSD(); return LLSDParser::PARSE_FAILURE; } diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 2511ca00b3..ec792ad240 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1533,9 +1533,17 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, } else { +#if 0 + // EXT-1565 : Zai Lynch, James Linden : 15/Oct/09 + // [BSI] Feedback: Viewer clock mentions SLT, but would prefer it to show PST/PDT // "slt" = Second Life Time, which is deprecated. // If not utc or user local time, fallback to Pacific time replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST"; +#else + // SL-20370 : Steeltoe Linden : 29/Sep/23 + // Change "PDT" to "SLT" on menu bar + replacement = "SLT"; +#endif } return true; } diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 72825067a8..c5787b9704 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -929,7 +929,7 @@ void LLMemoryInfo::stream(std::ostream& s) const // Now stream stats BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap)) { - s << pfx << std::setw(narrow(key_width+1)) << (pair.first + ':') << ' '; + s << pfx << std::setw(narrow(key_width+1)) << (pair.first + ':') << ' '; LLSD value(pair.second); if (value.isInteger()) s << std::setw(12) << value.asInteger(); diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index fcf46c79e7..dd279614f6 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -113,15 +113,16 @@ LL_COMMON_API bool on_main_thread() return (LLThread::currentID() == main_thread()); } -LL_COMMON_API void assert_main_thread() +LL_COMMON_API bool assert_main_thread() { auto curr = LLThread::currentID(); auto main = main_thread(); - if (curr != main) - { - LL_WARNS() << "Illegal execution from thread id " << curr - << " outside main thread " << main << LL_ENDL; - } + if (curr == main) + return true; + + LL_WARNS() << "Illegal execution from thread id " << curr + << " outside main thread " << main << LL_ENDL; + return false; } // this function has become moot diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 613431ee6a..34ccbbcfe6 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -152,7 +152,7 @@ public: //============================================================================ -extern LL_COMMON_API void assert_main_thread(); +extern LL_COMMON_API bool assert_main_thread(); extern LL_COMMON_API bool on_main_thread(); #endif // LL_LLTHREAD_H diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 082337cf3e..2a702c8d04 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -342,13 +342,7 @@ bool LLThreadSafeQueue::pushIfOpen(T&& element) return true; // Storage Full. Wait for signal. - // [FIRE-32453][BUG-232971] Improve shutdown behaviour. Time bound the sleep - // mCapacityCond.wait(lock1); - // When the queue is full and the consuming thread has exited we would never wake up. - // For safety, we now wait max half a second then recheck close. - const auto timeout = std::chrono::milliseconds(500); - mCapacityCond.wait_for(lock1, timeout); - // + mCapacityCond.wait(lock1); } } diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index ff671a8370..87457ad907 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -33,8 +33,6 @@ namespace LLTrace { -MemStatHandle gTraceMemStat("LLTrace"); - StatBase::StatBase( const char* name, const char* description ) : mName(name), mDescription(description ? description : "") @@ -65,7 +63,7 @@ void TimeBlockTreeNode::setParent( BlockTimerStatHandle* parent ) llassert_always(parent != mBlock); llassert_always(parent != NULL); - TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(narrow(parent->getIndex())); + TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(narrow(parent->getIndex())); if (!parent_tree_node) return; if (mParent) diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index d129eae0eb..7ecb984db8 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -211,61 +211,6 @@ void add(CountStatHandle& count, VALUE_T value) #endif } -template<> -class StatType -: public StatType -{ -public: - - StatType(const char* name, const char* description = "") - : StatType(name, description) - {} -}; - -template<> -class StatType -: public StatType -{ -public: - - StatType(const char* name, const char* description = "") - : StatType(name, description) - {} -}; - -class MemStatHandle : public StatType -{ -public: - typedef StatType stat_t; - MemStatHandle(const char* name, const char* description = "") - : stat_t(name, description) - { - mName = name; - } - - void setName(const char* name) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - mName = name; - setKey(name); - } - - /*virtual*/ const char* getUnitLabel() const { return "KB"; } - - StatType& allocations() - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return static_cast&>(*(StatType*)this); - } - - StatType& deallocations() - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return static_cast&>(*(StatType*)this); - } -}; - - // measures effective memory footprint of specified type // specialize to cover different types template @@ -352,33 +297,6 @@ struct MeasureMem, IS_MEM_TRACKABLE, IS_BYTES> } }; - -template -inline void claim_alloc(MemStatHandle& measurement, const T& value) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; -#if LL_TRACE_ENABLED - auto size = MeasureMem::measureFootprint(value); - if(size == 0) return; - MemAccumulator& accumulator = measurement.getCurrentAccumulator(); - accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size); - accumulator.mAllocations.record(size); -#endif -} - -template -inline void disclaim_alloc(MemStatHandle& measurement, const T& value) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; -#if LL_TRACE_ENABLED - auto size = MeasureMem::measureFootprint(value); - if(size == 0) return; - MemAccumulator& accumulator = measurement.getCurrentAccumulator(); - accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size); - accumulator.mDeallocations.add(size); -#endif -} - } #endif // LL_LLTRACE_H diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp index 6bd886ae98..b5b32cba38 100644 --- a/indra/llcommon/lltraceaccumulators.cpp +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -1,24 +1,24 @@ -/** +/** * @file lltracesampler.cpp * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,73 +32,52 @@ namespace LLTrace { -extern MemStatHandle gTraceMemStat; - - /////////////////////////////////////////////////////////////////////// // AccumulatorBufferGroup /////////////////////////////////////////////////////////////////////// -AccumulatorBufferGroup::AccumulatorBufferGroup() +AccumulatorBufferGroup::AccumulatorBufferGroup() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator)); - claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator)); - claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); - claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator)); - claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator)); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; } AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other) : mCounts(other.mCounts), mSamples(other.mSamples), mEvents(other.mEvents), - mStackTimers(other.mStackTimers), - mMemStats(other.mMemStats) + mStackTimers(other.mStackTimers) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator)); - claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator)); - claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); - claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator)); - claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator)); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; } AccumulatorBufferGroup::~AccumulatorBufferGroup() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator)); - disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator)); - disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); - disclaim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator)); - disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator)); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; } void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; other.mCounts.reset(&mCounts); other.mSamples.reset(&mSamples); other.mEvents.reset(&mEvents); other.mStackTimers.reset(&mStackTimers); - other.mMemStats.reset(&mMemStats); } void AccumulatorBufferGroup::makeCurrent() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mCounts.makeCurrent(); mSamples.makeCurrent(); mEvents.makeCurrent(); mStackTimers.makeCurrent(); - mMemStats.makeCurrent(); ThreadRecorder* thread_recorder = get_thread_recorder(); AccumulatorBuffer& timer_accumulator_buffer = mStackTimers; // update stacktimer parent pointers for (size_t i = 0, end_i = mStackTimers.size(); i < end_i; i++) { - TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(narrow(i)); + TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(narrow(i)); if (tree_node) { timer_accumulator_buffer[i].mParent = tree_node->mParent; @@ -109,12 +88,11 @@ void AccumulatorBufferGroup::makeCurrent() //static void AccumulatorBufferGroup::clearCurrent() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - AccumulatorBuffer::clearCurrent(); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + AccumulatorBuffer::clearCurrent(); AccumulatorBuffer::clearCurrent(); AccumulatorBuffer::clearCurrent(); AccumulatorBuffer::clearCurrent(); - AccumulatorBuffer::clearCurrent(); } bool AccumulatorBufferGroup::isCurrent() const @@ -124,44 +102,39 @@ bool AccumulatorBufferGroup::isCurrent() const void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mCounts.addSamples(other.mCounts, SEQUENTIAL); mSamples.addSamples(other.mSamples, SEQUENTIAL); mEvents.addSamples(other.mEvents, SEQUENTIAL); - mMemStats.addSamples(other.mMemStats, SEQUENTIAL); mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL); } void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mCounts.addSamples(other.mCounts, NON_SEQUENTIAL); mSamples.addSamples(other.mSamples, NON_SEQUENTIAL); mEvents.addSamples(other.mEvents, NON_SEQUENTIAL); - mMemStats.addSamples(other.mMemStats, NON_SEQUENTIAL); // for now, hold out timers from merge, need to be displayed per thread //mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL); } void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mCounts.reset(other ? &other->mCounts : NULL); mSamples.reset(other ? &other->mSamples : NULL); mEvents.reset(other ? &other->mEvents : NULL); mStackTimers.reset(other ? &other->mStackTimers : NULL); - mMemStats.reset(other ? &other->mMemStats : NULL); } void AccumulatorBufferGroup::sync() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; if (isCurrent()) { F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); - mSamples.sync(time_stamp); - mMemStats.sync(time_stamp); } } @@ -197,10 +170,9 @@ F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const Samp return a.getSumOfSquares(); } - void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type ) { - if (append_type == NON_SEQUENTIAL) + if (append_type == NON_SEQUENTIAL) { return; } @@ -299,7 +271,7 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT void EventAccumulator::reset( const EventAccumulator* other ) { - mNumSamples = 0; + mNumSamples = 0; mSum = 0; mMin = F32(NaN); mMax = F32(NaN); @@ -308,5 +280,4 @@ void EventAccumulator::reset( const EventAccumulator* other ) mLastValue = other ? other->mLastValue : NaN; } - } diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index 7267a44300..b9d577be9e 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -1,26 +1,26 @@ -/** +/** * @file lltraceaccumulators.h * @brief Storage for accumulating statistics * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -28,7 +28,6 @@ #ifndef LL_LLTRACEACCUMULATORS_H #define LL_LLTRACEACCUMULATORS_H - #include "stdtypes.h" #include "llpreprocessor.h" #include "llunits.h" @@ -66,7 +65,7 @@ namespace LLTrace : mStorageSize(0), mStorage(NULL) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; const AccumulatorBuffer& other = *getDefaultBuffer(); resize(sNextStorageSlot); for (S32 i = 0; i < sNextStorageSlot; i++) @@ -77,7 +76,7 @@ namespace LLTrace ~AccumulatorBuffer() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; if (isCurrent()) { LLThreadLocalSingletonPointer::setInstance(NULL); @@ -85,14 +84,14 @@ namespace LLTrace delete[] mStorage; } - LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) - { - return mStorage[index]; + LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) + { + return mStorage[index]; } LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const - { - return mStorage[index]; + { + return mStorage[index]; } @@ -100,7 +99,7 @@ namespace LLTrace : mStorageSize(0), mStorage(NULL) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; resize(sNextStorageSlot); for (S32 i = 0; i < sNextStorageSlot; i++) { @@ -110,7 +109,7 @@ namespace LLTrace void addSamples(const AccumulatorBuffer& other, EBufferAppendType append_type) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -120,7 +119,7 @@ namespace LLTrace void copyFrom(const AccumulatorBuffer& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -130,7 +129,7 @@ namespace LLTrace void reset(const AccumulatorBuffer* other = NULL) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -140,7 +139,7 @@ namespace LLTrace void sync(F64SecondsImplicit time_stamp) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { @@ -160,13 +159,13 @@ namespace LLTrace static void clearCurrent() { - LLThreadLocalSingletonPointer::setInstance(NULL); + LLThreadLocalSingletonPointer::setInstance(NULL); } // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned size_t reserveSlot() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; size_t next_slot = sNextStorageSlot++; if (next_slot >= mStorageSize) { @@ -180,7 +179,7 @@ namespace LLTrace void resize(size_t new_size) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; if (new_size <= mStorageSize) return; ACCUMULATOR* old_storage = mStorage; @@ -214,14 +213,14 @@ namespace LLTrace return mStorageSize; } - static size_t getNumIndices() + static size_t getNumIndices() { return sNextStorageSlot; } static self_t* getDefaultBuffer() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; static bool sInitialized = false; if (!sInitialized) { @@ -336,7 +335,7 @@ namespace LLTrace void sample(F64 value) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); // store effect of last value @@ -399,7 +398,7 @@ namespace LLTrace F64 mMean, mSumOfSquares; - F64SecondsImplicit + F64SecondsImplicit mLastSampleTimeStamp, mTotalSamplingTime; @@ -409,7 +408,7 @@ namespace LLTrace S32 mNumSamples; // distinct from mNumSamples, since we might have inherited a last value from // a previous sampling period - bool mHasValue; + bool mHasValue; }; class CountAccumulator @@ -457,14 +456,14 @@ namespace LLTrace class alignas(32) TimeBlockAccumulator { - public: + public: typedef F64Seconds value_t; static F64Seconds getDefaultValue() { return F64Seconds(0); } typedef TimeBlockAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic - struct CallCountFacet + struct CallCountFacet { typedef S32 value_t; }; @@ -515,12 +514,12 @@ namespace LLTrace BlockTimerStatHandle* getParent() { return mParent; } BlockTimerStatHandle* mBlock; - BlockTimerStatHandle* mParent; + BlockTimerStatHandle* mParent; std::vector mChildren; bool mCollapsed; bool mNeedsSorting; }; - + struct BlockTimerStackRecord { class BlockTimer* mActiveTimer; @@ -528,65 +527,6 @@ namespace LLTrace U64 mChildTime; }; - struct MemAccumulator - { - typedef F64Bytes value_t; - static F64Bytes getDefaultValue() { return F64Bytes(0); } - - typedef MemAccumulator self_t; - - // fake classes that allows us to view different facets of underlying statistic - struct AllocationFacet - { - typedef F64Bytes value_t; - static F64Bytes getDefaultValue() { return F64Bytes(0); } - }; - - struct DeallocationFacet - { - typedef F64Bytes value_t; - static F64Bytes getDefaultValue() { return F64Bytes(0); } - }; - - void addSamples(const MemAccumulator& other, EBufferAppendType append_type) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - mAllocations.addSamples(other.mAllocations, append_type); - mDeallocations.addSamples(other.mDeallocations, append_type); - - if (append_type == SEQUENTIAL) - { - mSize.addSamples(other.mSize, SEQUENTIAL); - } - else - { - F64 allocation_delta(other.mAllocations.getSum() - other.mDeallocations.getSum()); - mSize.sample(mSize.hasValue() - ? mSize.getLastValue() + allocation_delta - : allocation_delta); - } - } - - void reset(const MemAccumulator* other) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - mSize.reset(other ? &other->mSize : NULL); - mAllocations.reset(other ? &other->mAllocations : NULL); - mDeallocations.reset(other ? &other->mDeallocations : NULL); - } - - void sync(F64SecondsImplicit time_stamp) - { - mSize.sync(time_stamp); - } - - bool hasValue() const { return mSize.hasValue(); } - - SampleAccumulator mSize; - EventAccumulator mAllocations; - CountAccumulator mDeallocations; - }; - struct AccumulatorBufferGroup : public LLRefCount { AccumulatorBufferGroup(); @@ -607,9 +547,7 @@ namespace LLTrace AccumulatorBuffer mSamples; AccumulatorBuffer mEvents; AccumulatorBuffer mStackTimers; - AccumulatorBuffer mMemStats; }; } #endif // LL_LLTRACEACCUMULATORS_H - diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index bb3d667a42..075e7c1d28 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -1,24 +1,24 @@ -/** +/** * @file lltracesampler.cpp * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -32,7 +32,7 @@ #include "lltracethreadrecorder.h" #include "llthread.h" -inline F64 lerp(F64 a, F64 b, F64 u) +inline F64 lerp(F64 a, F64 b, F64 u) { return a + ((b - a) * u); } @@ -40,34 +40,29 @@ inline F64 lerp(F64 a, F64 b, F64 u) namespace LLTrace { -extern MemStatHandle gTraceMemStat; - /////////////////////////////////////////////////////////////////////// // Recording /////////////////////////////////////////////////////////////////////// -Recording::Recording(EPlayState state) +Recording::Recording(EPlayState state) : mElapsedSeconds(0), mActiveBuffers(NULL) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - claim_alloc(gTraceMemStat, this); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mBuffers = new AccumulatorBufferGroup(); - claim_alloc(gTraceMemStat, mBuffers); setPlayState(state); } Recording::Recording( const Recording& other ) : mActiveBuffers(NULL) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - claim_alloc(gTraceMemStat, this); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; *this = other; } Recording& Recording::operator = (const Recording& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; // this will allow us to seamlessly start without affecting any data we've acquired from other setPlayState(PAUSED); @@ -85,14 +80,11 @@ Recording& Recording::operator = (const Recording& other) return *this; } - Recording::~Recording() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - disclaim_alloc(gTraceMemStat, this); - disclaim_alloc(gTraceMemStat, mBuffers); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - // allow recording destruction without thread recorder running, + // allow recording destruction without thread recorder running, // otherwise thread shutdown could crash if a recording outlives the thread recorder // besides, recording construction and destruction is fine without a recorder...just don't attempt to start one if (isStarted() && LLTrace::get_thread_recorder() != NULL) @@ -107,14 +99,14 @@ void Recording::update() #if LL_TRACE_ENABLED if (isStarted()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); - // must have - llassert(mActiveBuffers != NULL + // must have + llassert(mActiveBuffers != NULL && LLTrace::get_thread_recorder() != NULL); - if(!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL) + if (!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL) { AccumulatorBufferGroup* buffers = mBuffers.write(); LLTrace::get_thread_recorder()->deactivate(buffers); @@ -128,7 +120,7 @@ void Recording::update() void Recording::handleReset() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; #if LL_TRACE_ENABLED mBuffers.write()->reset(); @@ -139,7 +131,7 @@ void Recording::handleReset() void Recording::handleStart() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; #if LL_TRACE_ENABLED mSamplingTimer.reset(); mBuffers.setStayUnique(true); @@ -151,7 +143,7 @@ void Recording::handleStart() void Recording::handleStop() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; #if LL_TRACE_ENABLED mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); // must have thread recorder running on this thread @@ -204,7 +196,6 @@ F64Seconds Recording::getSum(const StatType return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond()); } - S32 Recording::getSum(const StatType& stat) { update(); @@ -219,7 +210,7 @@ F64Seconds Recording::getPerSec(const StatType& stat) const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL; - return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0)) + return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0)) / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value())); } @@ -241,144 +232,9 @@ F32 Recording::getPerSec(const StatType& s return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value(); } -bool Recording::hasValue(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return accumulator.mSize.hasValue() || (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.hasValue() : false); -} - -F64Kilobytes Recording::getMin(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes(llmin(accumulator.mSize.getMin(), (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMin() : F32_MAX))); -} - -F64Kilobytes Recording::getMean(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - - if (active_accumulator && active_accumulator->mSize.hasValue()) - { - F32 t = 0.0f; - S32 div = accumulator.mSize.getSampleCount() + active_accumulator->mSize.getSampleCount(); - if (div > 0) - { - t = active_accumulator->mSize.getSampleCount() / div; - } - return F64Bytes(lerp(accumulator.mSize.getMean(), active_accumulator->mSize.getMean(), t)); - } - else - { - return F64Bytes(accumulator.mSize.getMean()); - } -} - -F64Kilobytes Recording::getMax(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes(llmax(accumulator.mSize.getMax(), active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMax() : F32_MIN)); -} - -F64Kilobytes Recording::getStandardDeviation(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - if (active_accumulator && active_accumulator->hasValue()) - { - F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator.mSize, active_accumulator->mSize); - return F64Bytes(sqrtf(sum_of_squares / (accumulator.mSize.getSamplingTime().value() + active_accumulator->mSize.getSamplingTime().value()))); - } - else - { - return F64Bytes(accumulator.mSize.getStandardDeviation()); - } -} - -F64Kilobytes Recording::getLastValue(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes(active_accumulator ? active_accumulator->mSize.getLastValue() : accumulator.mSize.getLastValue()); -} - -bool Recording::hasValue(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return accumulator.mAllocations.hasValue() || (active_accumulator ? active_accumulator->mAllocations.hasValue() : false); -} - -F64Kilobytes Recording::getSum(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes(accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)); -} - -F64Kilobytes Recording::getPerSec(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes((accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)) / mElapsedSeconds.value()); -} - -S32 Recording::getSampleCount(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return accumulator.mAllocations.getSampleCount() + (active_accumulator ? active_accumulator->mAllocations.getSampleCount() : 0); -} - -bool Recording::hasValue(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return accumulator.mDeallocations.hasValue() || (active_accumulator ? active_accumulator->mDeallocations.hasValue() : false); -} - - -F64Kilobytes Recording::getSum(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes(accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)); -} - -F64Kilobytes Recording::getPerSec(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return F64Bytes((accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)) / mElapsedSeconds.value()); -} - -S32 Recording::getSampleCount(const StatType& stat) -{ - update(); - const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()]; - const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL; - return accumulator.mDeallocations.getSampleCount() + (active_accumulator ? active_accumulator->mDeallocations.getSampleCount() : 0); -} - bool Recording::hasValue(const StatType& stat) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false); @@ -386,7 +242,7 @@ bool Recording::hasValue(const StatType& stat) F64 Recording::getSum(const StatType& stat) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0); @@ -394,7 +250,7 @@ F64 Recording::getSum(const StatType& stat) F64 Recording::getPerSec( const StatType& stat ) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0); @@ -403,7 +259,7 @@ F64 Recording::getPerSec( const StatType& stat ) S32 Recording::getSampleCount( const StatType& stat ) { - update(); + update(); const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0); @@ -411,7 +267,7 @@ S32 Recording::getSampleCount( const StatType& stat ) bool Recording::hasValue(const StatType& stat) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue()); @@ -419,7 +275,7 @@ bool Recording::hasValue(const StatType& stat) F64 Recording::getMin( const StatType& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX); @@ -427,7 +283,7 @@ F64 Recording::getMin( const StatType& stat ) F64 Recording::getMax( const StatType& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN); @@ -435,17 +291,17 @@ F64 Recording::getMax( const StatType& stat ) F64 Recording::getMean( const StatType& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) { - F32 t = 0.0f; - S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); - if (div > 0) - { - t = active_accumulator->getSampleCount() / div; - } + F32 t = 0.0f; + S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); + if (div > 0) + { + t = active_accumulator->getSampleCount() / div; + } return lerp(accumulator.getMean(), active_accumulator->getMean(), t); } else @@ -456,7 +312,7 @@ F64 Recording::getMean( const StatType& stat ) F64 Recording::getStandardDeviation( const StatType& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; @@ -473,7 +329,7 @@ F64 Recording::getStandardDeviation( const StatType& stat ) F64 Recording::getLastValue( const StatType& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue()); @@ -481,7 +337,7 @@ F64 Recording::getLastValue( const StatType& stat ) S32 Recording::getSampleCount( const StatType& stat ) { - update(); + update(); const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0); @@ -489,7 +345,7 @@ S32 Recording::getSampleCount( const StatType& stat ) bool Recording::hasValue(const StatType& stat) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue()); @@ -497,7 +353,7 @@ bool Recording::hasValue(const StatType& stat) F64 Recording::getSum( const StatType& stat) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0)); @@ -505,7 +361,7 @@ F64 Recording::getSum( const StatType& stat) F64 Recording::getMin( const StatType& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX); @@ -513,7 +369,7 @@ F64 Recording::getMin( const StatType& stat ) F64 Recording::getMax( const StatType& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN); @@ -521,17 +377,17 @@ F64 Recording::getMax( const StatType& stat ) F64 Recording::getMean( const StatType& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) { F32 t = 0.0f; - S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); - if (div > 0) - { - t = active_accumulator->getSampleCount() / div; - } + S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); + if (div > 0) + { + t = active_accumulator->getSampleCount() / div; + } return lerp(accumulator.getMean(), active_accumulator->getMean(), t); } else @@ -542,7 +398,7 @@ F64 Recording::getMean( const StatType& stat ) F64 Recording::getStandardDeviation( const StatType& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; @@ -559,7 +415,7 @@ F64 Recording::getStandardDeviation( const StatType& stat ) F64 Recording::getLastValue( const StatType& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue(); @@ -567,7 +423,7 @@ F64 Recording::getLastValue( const StatType& stat ) S32 Recording::getSampleCount( const StatType& stat ) { - update(); + update(); const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0); @@ -577,7 +433,7 @@ S32 Recording::getSampleCount( const StatType& stat ) // PeriodicRecording /////////////////////////////////////////////////////////////////////// -PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state) +PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state) : mAutoResize(num_periods == 0), mCurPeriod(0), mNumRecordedPeriods(0), @@ -585,15 +441,13 @@ PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state) // code in several methods. mRecordingPeriods(num_periods ? num_periods : 1) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; setPlayState(state); - claim_alloc(gTraceMemStat, this); } PeriodicRecording::~PeriodicRecording() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - disclaim_alloc(gTraceMemStat, this); + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; } void PeriodicRecording::nextPeriod() @@ -615,12 +469,11 @@ void PeriodicRecording::nextPeriod() void PeriodicRecording::appendRecording(Recording& recording) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; getCurRecording().appendRecording(recording); nextPeriod(); } - void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; @@ -693,16 +546,14 @@ F64Seconds PeriodicRecording::getDuration() const return duration; } - LLTrace::Recording PeriodicRecording::snapshotCurRecording() const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; Recording recording_copy(getCurRecording()); recording_copy.stop(); return recording_copy; } - Recording& PeriodicRecording::getLastRecording() { return getPrevRecording(1); @@ -737,19 +588,19 @@ const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const void PeriodicRecording::handleStart() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; getCurRecording().start(); } void PeriodicRecording::handleStop() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; getCurRecording().pause(); } void PeriodicRecording::handleReset() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; getCurRecording().stop(); if (mAutoResize) @@ -771,13 +622,13 @@ void PeriodicRecording::handleReset() void PeriodicRecording::handleSplitTo(PeriodicRecording& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; getCurRecording().splitTo(other.getCurRecording()); } F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -792,14 +643,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType& stat, siz } } - return has_value - ? min_val + return has_value + ? min_val : NaN; } F64 PeriodicRecording::getPeriodMax( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -814,15 +665,15 @@ F64 PeriodicRecording::getPeriodMax( const StatType& stat, siz } } - return has_value - ? max_val + return has_value + ? max_val : NaN; } // calculates means using aggregates per period F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 mean = 0; @@ -838,14 +689,14 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, si } } - return valid_period_count + return valid_period_count ? mean / (F64)valid_period_count : NaN; } F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 period_mean = getPeriodMean(stat, num_periods); @@ -870,7 +721,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -885,14 +736,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType& stat, si } } - return has_value - ? min_val + return has_value + ? min_val : NaN; } F64 PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -907,15 +758,15 @@ F64 PeriodicRecording::getPeriodMax(const StatType& stat, siz } } - return has_value - ? max_val + return has_value + ? max_val : NaN; } F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); S32 valid_period_count = 0; @@ -938,7 +789,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, s F64 PeriodicRecording::getPeriodMedian( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); std::vector buf; @@ -964,7 +815,7 @@ F64 PeriodicRecording::getPeriodMedian( const StatType& stat, F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 period_mean = getPeriodMean(stat, num_periods); @@ -987,105 +838,13 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - F64Kilobytes min_val(std::numeric_limits::max()); - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - min_val = llmin(min_val, recording.getMin(stat)); - } - - return min_val; -} - -F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods) -{ - return getPeriodMin(static_cast&>(stat), num_periods); -} - -F64Kilobytes PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - F64Kilobytes max_val(0.0); - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - max_val = llmax(max_val, recording.getMax(stat)); - } - - return max_val; -} - -F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods) -{ - return getPeriodMax(static_cast&>(stat), num_periods); -} - -F64Kilobytes PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - F64Kilobytes mean(0); - - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - mean += recording.getMean(stat); - } - - return mean / F64(num_periods); -} - -F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods) -{ - return getPeriodMean(static_cast&>(stat), num_periods); -} - -F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - F64Kilobytes period_mean = getPeriodMean(stat, num_periods); - S32 valid_period_count = 0; - F64 sum_of_squares = 0; - - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.hasValue(stat)) - { - F64Kilobytes delta = recording.getMean(stat) - period_mean; - sum_of_squares += delta.value() * delta.value(); - valid_period_count++; - } - } - - return F64Kilobytes(valid_period_count - ? sqrt(sum_of_squares / (F64)valid_period_count) - : NaN); -} - -F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods) -{ - return getPeriodStandardDeviation(static_cast&>(stat), num_periods); -} - /////////////////////////////////////////////////////////////////////// // ExtendableRecording /////////////////////////////////////////////////////////////////////// void ExtendableRecording::extend() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; // push the data back to accepted recording mAcceptedRecording.appendRecording(mPotentialRecording); // flush data, so we can start from scratch @@ -1094,76 +853,72 @@ void ExtendableRecording::extend() void ExtendableRecording::handleStart() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mPotentialRecording.start(); } void ExtendableRecording::handleStop() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mPotentialRecording.pause(); } void ExtendableRecording::handleReset() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mAcceptedRecording.reset(); mPotentialRecording.reset(); } void ExtendableRecording::handleSplitTo(ExtendableRecording& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mPotentialRecording.splitTo(other.mPotentialRecording); } - /////////////////////////////////////////////////////////////////////// // ExtendablePeriodicRecording /////////////////////////////////////////////////////////////////////// - -ExtendablePeriodicRecording::ExtendablePeriodicRecording() -: mAcceptedRecording(0), +ExtendablePeriodicRecording::ExtendablePeriodicRecording() +: mAcceptedRecording(0), mPotentialRecording(0) {} void ExtendablePeriodicRecording::extend() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; // push the data back to accepted recording mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); // flush data, so we can start from scratch mPotentialRecording.reset(); } - void ExtendablePeriodicRecording::handleStart() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mPotentialRecording.start(); } void ExtendablePeriodicRecording::handleStop() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mPotentialRecording.pause(); } void ExtendablePeriodicRecording::handleReset() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mAcceptedRecording.reset(); mPotentialRecording.reset(); } void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mPotentialRecording.splitTo(other.mPotentialRecording); } - PeriodicRecording& get_frame_recording() { static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED); @@ -1174,7 +929,7 @@ PeriodicRecording& get_frame_recording() void LLStopWatchControlsMixinCommon::start() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch (mPlayState) { case STOPPED: @@ -1196,7 +951,7 @@ void LLStopWatchControlsMixinCommon::start() void LLStopWatchControlsMixinCommon::stop() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch (mPlayState) { case STOPPED: @@ -1216,7 +971,7 @@ void LLStopWatchControlsMixinCommon::stop() void LLStopWatchControlsMixinCommon::pause() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch (mPlayState) { case STOPPED: @@ -1236,7 +991,7 @@ void LLStopWatchControlsMixinCommon::pause() void LLStopWatchControlsMixinCommon::unpause() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch (mPlayState) { case STOPPED: @@ -1256,7 +1011,7 @@ void LLStopWatchControlsMixinCommon::unpause() void LLStopWatchControlsMixinCommon::resume() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch (mPlayState) { case STOPPED: @@ -1277,7 +1032,7 @@ void LLStopWatchControlsMixinCommon::resume() void LLStopWatchControlsMixinCommon::restart() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch (mPlayState) { case STOPPED: @@ -1301,13 +1056,13 @@ void LLStopWatchControlsMixinCommon::restart() void LLStopWatchControlsMixinCommon::reset() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; handleReset(); } void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; switch(state) { case STOPPED: diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index a6b1a67d02..61b9096ae2 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -1,25 +1,25 @@ -/** +/** * @file lltracerecording.h * @brief Sampling object for collecting runtime statistics originating from lltrace. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -112,7 +112,6 @@ private: // atomically stop this object while starting the other // no data can be missed in between stop and start virtual void handleSplitTo(DERIVED& other) {}; - }; namespace LLTrace @@ -129,8 +128,6 @@ namespace LLTrace template class EventStatHandle; - class MemStatHandle; - template struct RelatedTypes { @@ -152,7 +149,7 @@ namespace LLTrace typedef S32 sum_t; }; - class Recording + class Recording : public LLStopWatchControlsMixin { public: @@ -182,24 +179,6 @@ namespace LLTrace F64Seconds getPerSec(const StatType& stat); F32 getPerSec(const StatType& stat); - // Memory accessors - bool hasValue(const StatType& stat); - F64Kilobytes getMin(const StatType& stat); - F64Kilobytes getMean(const StatType& stat); - F64Kilobytes getMax(const StatType& stat); - F64Kilobytes getStandardDeviation(const StatType& stat); - F64Kilobytes getLastValue(const StatType& stat); - - bool hasValue(const StatType& stat); - F64Kilobytes getSum(const StatType& stat); - F64Kilobytes getPerSec(const StatType& stat); - S32 getSampleCount(const StatType& stat); - - bool hasValue(const StatType& stat); - F64Kilobytes getSum(const StatType& stat); - F64Kilobytes getPerSec(const StatType& stat); - S32 getSampleCount(const StatType& stat); - // CountStatHandle accessors bool hasValue(const StatType& stat); F64 getSum(const StatType& stat); @@ -318,7 +297,7 @@ namespace LLTrace /*virtual*/ void handleSplitTo(Recording& other); // returns data for current thread - class ThreadRecorder* getThreadRecorder(); + class ThreadRecorder* getThreadRecorder(); LLTimer mSamplingTimer; F64Seconds mElapsedSeconds; @@ -335,10 +314,10 @@ namespace LLTrace ~PeriodicRecording(); void nextPeriod(); - auto getNumRecordedPeriods() - { + auto getNumRecordedPeriods() + { // current period counts if not active - return mNumRecordedPeriods + (isStarted() ? 0 : 1); + return mNumRecordedPeriods + (isStarted() ? 0 : 1); } F64Seconds getDuration() const; @@ -367,7 +346,7 @@ namespace LLTrace } return num_samples; } - + // // PERIODIC MIN // @@ -376,7 +355,7 @@ namespace LLTrace template typename T::value_t getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -391,15 +370,15 @@ namespace LLTrace } } - return has_value - ? min_val + return has_value + ? min_val : T::getDefaultValue(); } template T getPeriodMin(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMin(static_cast&>(stat), num_periods)); } @@ -407,7 +386,7 @@ namespace LLTrace template T getPeriodMin(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMin(static_cast&>(stat), num_periods)); } @@ -415,17 +394,14 @@ namespace LLTrace template T getPeriodMin(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMin(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max()); - F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); - template typename RelatedTypes::fractional_t getPeriodMinPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes::fractional_t min_val(std::numeric_limits::max()); @@ -440,7 +416,7 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodMinPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMinPerSec(static_cast&>(stat), num_periods)); } @@ -452,7 +428,7 @@ namespace LLTrace template typename T::value_t getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; @@ -467,15 +443,15 @@ namespace LLTrace } } - return has_value - ? max_val + return has_value + ? max_val : T::getDefaultValue(); } template T getPeriodMax(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMax(static_cast&>(stat), num_periods)); } @@ -483,7 +459,7 @@ namespace LLTrace template T getPeriodMax(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMax(static_cast&>(stat), num_periods)); } @@ -491,17 +467,14 @@ namespace LLTrace template T getPeriodMax(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMax(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max()); - F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); - template typename RelatedTypes::fractional_t getPeriodMaxPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 max_val = std::numeric_limits::min(); @@ -516,7 +489,7 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodMaxPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMaxPerSec(static_cast&>(stat), num_periods)); } @@ -528,7 +501,7 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes::fractional_t mean(0); @@ -549,14 +522,14 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodMean(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods)); } F64 getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()); - template + template typename RelatedTypes::fractional_t getPeriodMean(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods)); } @@ -564,17 +537,14 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodMean(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()); - F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); - template typename RelatedTypes::fractional_t getPeriodMeanPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes::fractional_t mean = 0; @@ -596,7 +566,7 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodMeanPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMeanPerSec(static_cast&>(stat), num_periods)); } @@ -635,10 +605,10 @@ namespace LLTrace F64 getPeriodStandardDeviation(const StatType& stat, size_t num_periods = std::numeric_limits::max()); - template + template typename RelatedTypes::fractional_t getPeriodStandardDeviation(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodStandardDeviation(static_cast&>(stat), num_periods)); } @@ -646,13 +616,10 @@ namespace LLTrace template typename RelatedTypes::fractional_t getPeriodStandardDeviation(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodStandardDeviation(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodStandardDeviation(const StatType& stat, size_t num_periods = std::numeric_limits::max()); - F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); - private: // implementation for LLStopWatchControlsMixin /*virtual*/ void handleStart(); @@ -731,7 +698,7 @@ namespace LLTrace PeriodicRecording& getResults() { return mAcceptedRecording; } const PeriodicRecording& getResults() const {return mAcceptedRecording;} - + void nextPeriod() { mPotentialRecording.nextPeriod(); } private: diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 282c454a2a..914bfb55dc 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -32,7 +32,7 @@ namespace LLTrace { -extern MemStatHandle gTraceMemStat; +//extern MemStatHandle gTraceMemStat; static ThreadRecorder* sMasterThreadRecorder = NULL; @@ -81,9 +81,9 @@ void ThreadRecorder::init() BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1; - claim_alloc(gTraceMemStat, this); - claim_alloc(gTraceMemStat, mRootTimer); - claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); + //claim_alloc(gTraceMemStat, this); + //claim_alloc(gTraceMemStat, mRootTimer); + //claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); #endif } @@ -101,9 +101,9 @@ ThreadRecorder::~ThreadRecorder() #if LL_TRACE_ENABLED LLThreadLocalSingletonPointer::setInstance(NULL); - disclaim_alloc(gTraceMemStat, this); - disclaim_alloc(gTraceMemStat, sizeof(BlockTimer)); - disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); + //disclaim_alloc(gTraceMemStat, this); + //disclaim_alloc(gTraceMemStat, sizeof(BlockTimer)); + //disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); deactivate(&mThreadRecordingBuffers); diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp index e4f229dd16..f79a98a56d 100644 --- a/indra/llcommon/lluriparser.cpp +++ b/indra/llcommon/lluriparser.cpp @@ -164,8 +164,10 @@ void LLUriParser::extractParts() #if LL_DARWIN typedef void(*sighandler_t)(int); jmp_buf return_to_normalize; +static int sLastSignal = 0; void uri_signal_handler(int signal) { + sLastSignal = signal; // Apparently signal handler throwing an exception doesn't work. // This is ugly and unsafe due to not unwinding content of uriparser library, // but unless we have a way to catch this as NSexception, jump appears to be the only option. @@ -179,8 +181,10 @@ S32 LLUriParser::normalize() if (!mRes) { #if LL_DARWIN - sighandler_t last_handler; - last_handler = signal(SIGILL, &uri_signal_handler); // illegal instruction + sighandler_t last_sigill_handler, last_sigbus_handler; + last_sigill_handler = signal(SIGILL, &uri_signal_handler); // illegal instruction + last_sigbus_handler = signal(SIGBUS, &uri_signal_handler); + if (setjmp(return_to_normalize)) { // Issue: external library crashed via signal @@ -194,8 +198,9 @@ S32 LLUriParser::normalize() // if this can be handled by NSexception, it needs to be remade llassert(0); - LL_WARNS() << "Uriparser crashed with SIGILL, while processing: " << mNormalizedUri << LL_ENDL; - signal(SIGILL, last_handler); + LL_WARNS() << "Uriparser crashed with " << sLastSignal << " , while processing: " << mNormalizedUri << LL_ENDL; + signal(SIGILL, last_sigill_handler); + signal(SIGBUS, last_sigbus_handler); return 1; } #endif @@ -203,7 +208,8 @@ S32 LLUriParser::normalize() mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST); #if LL_DARWIN - signal(SIGILL, last_handler); + signal(SIGILL, last_sigill_handler); + signal(SIGBUS, last_sigbus_handler); #endif if (!mRes) @@ -226,7 +232,7 @@ S32 LLUriParser::normalize() } } - if(mTmpScheme) + if(mTmpScheme && mNormalizedUri.size() > 7) { mNormalizedUri = mNormalizedUri.substr(7); mTmpScheme = false; diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index 0b43d7ad4b..3aba9dda00 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -156,18 +156,15 @@ typedef int intptr_t; * type. */ // narrow_holder is a struct that accepts the passed value as its original -// type and provides templated conversion functions to other types. Once we're -// building with compilers that support Class Template Argument Deduction, we -// can rename this class template 'narrow' and eliminate the narrow() factory -// function below. +// type and provides templated conversion functions to other types. template -class narrow_holder +class narrow { private: FROM mValue; public: - narrow_holder(FROM value): mValue(value) {} + narrow(FROM value): mValue(value) {} /*---------------------- Narrowing unsigned to signed ----------------------*/ template (), which can be -/// implicitly converted to the target type. -template -inline -narrow_holder narrow(FROM value) -{ - return { value }; -} - #endif diff --git a/indra/llcommon/tests/threadsafeschedule_test.cpp b/indra/llcommon/tests/threadsafeschedule_test.cpp index c421cc7b1c..8851590189 100644 --- a/indra/llcommon/tests/threadsafeschedule_test.cpp +++ b/indra/llcommon/tests/threadsafeschedule_test.cpp @@ -46,11 +46,12 @@ namespace tut // the real time required for each push() call. Explicitly increment // the timestamp for each one -- but since we're passing explicit // timestamps, make the queue reorder them. - queue.push(Queue::TimeTuple(Queue::Clock::now() + 200ms, "ghi")); + auto now{ Queue::Clock::now() }; + queue.push(Queue::TimeTuple(now + 200ms, "ghi")); // Given the various push() overloads, you have to match the type // exactly: conversions are ambiguous. queue.push("abc"s); - queue.push(Queue::Clock::now() + 100ms, "def"); + queue.push(now + 100ms, "def"); queue.close(); auto entry = queue.pop(); ensure_equals("failed to pop first", std::get<0>(entry), "abc"s); diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index ec5a69a7df..63020a9b6a 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -60,12 +60,15 @@ struct sleepy_robin: public boost::fibers::algo::round_robin /***************************************************************************** * ThreadPoolBase *****************************************************************************/ -LL::ThreadPoolBase::ThreadPoolBase(const std::string& name, size_t threads, - WorkQueueBase* queue): +LL::ThreadPoolBase::ThreadPoolBase(const std::string& name, + size_t threads, + WorkQueueBase* queue, + bool auto_shutdown): super(name), mName("ThreadPool:" + name), mThreadCount(getConfiguredWidth(name, threads)), - mQueue(queue) + mQueue(queue), + mAutomaticShutdown(auto_shutdown) {} void LL::ThreadPoolBase::start() @@ -80,6 +83,14 @@ void LL::ThreadPoolBase::start() run(tname); }); } + + if (!mAutomaticShutdown) + { + // Some threads, like main window's might need to run a bit longer + // to wait for a proper shutdown message + return; + } + // Listen on "LLApp", and when the app is shutting down, close the queue // and join the workers. LLEventPumps::instance().obtain("LLApp").listen( @@ -110,8 +121,11 @@ void LL::ThreadPoolBase::close() mQueue->close(); for (auto& pair: mThreads) { - LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL; - pair.second.join(); + if (pair.second.joinable()) + { + LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL; + pair.second.join(); + } } LL_DEBUGS("ThreadPool") << mName << " shutdown complete" << LL_ENDL; } diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index 61a7bef5be..74056aea17 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -40,7 +40,7 @@ namespace LL * overrides this parameter. */ ThreadPoolBase(const std::string& name, size_t threads, - WorkQueueBase* queue); + WorkQueueBase* queue, bool auto_shutdown = true); virtual ~ThreadPoolBase(); /** @@ -55,10 +55,7 @@ namespace LL * ThreadPool listens for application shutdown messages on the "LLApp" * LLEventPump. Call close() to shut down this ThreadPool early. */ - // [FIRE-32453][BUG-232971] Improve shutdown behaviour. - // void close(); virtual void close(); - // std::string getName() const { return mName; } size_t getWidth() const { return mThreads.size(); } @@ -90,14 +87,14 @@ namespace LL protected: std::unique_ptr mQueue; + std::vector> mThreads; + bool mAutomaticShutdown; private: void run(const std::string& name); - - protected: // [FIRE-32453][BUG-232971] Improve shutdown behaviour. + std::string mName; size_t mThreadCount; - std::vector> mThreads; }; /** @@ -121,8 +118,11 @@ namespace LL * Constraining the queue can cause a submitter to block. Do not * constrain any ThreadPool accepting work from the main thread. */ - ThreadPoolUsing(const std::string& name, size_t threads=1, size_t capacity=1024*1024): - ThreadPoolBase(name, threads, new queue_t(name, capacity)) + ThreadPoolUsing(const std::string& name, + size_t threads=1, + size_t capacity=1024*1024, + bool auto_shutdown = true): + ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown) {} ~ThreadPoolUsing() override {} diff --git a/indra/llcorehttp/bufferarray.cpp b/indra/llcorehttp/bufferarray.cpp index 8d2e7c6a63..c780c06b4e 100644 --- a/indra/llcorehttp/bufferarray.cpp +++ b/indra/llcorehttp/bufferarray.cpp @@ -288,7 +288,7 @@ int BufferArray::findBlock(size_t pos, size_t * ret_offset) if (pos >= mLen) return -1; // Doesn't exist - const int block_limit(narrow(mBlocks.size())); + const int block_limit(narrow(mBlocks.size())); for (int i(0); i < block_limit; ++i) { if (pos < mBlocks[i]->mUsed) diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index c8fb9666d9..96e217df0c 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -50,6 +50,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec) if (file_size == 0) { + mWarning = "texture_load_empty_file"; setLastError("File is empty",src_filename); return false; } @@ -90,6 +91,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp() if (signature[0] != 'B' || signature[1] != 'M') { LL_WARNS() << "Not a BMP" << LL_ENDL; + mWarning = "texture_load_format_error"; return false; } @@ -140,6 +142,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng() if (memcmp(signature, png_magic, PNG_MAGIC_SIZE) != 0) { LL_WARNS() << "Not a PNG" << LL_ENDL; + mWarning = "texture_load_format_error"; return false; } @@ -184,6 +187,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0) { LL_WARNS() << "Not a JPEG" << LL_ENDL; + mWarning = "texture_load_format_error"; fclose(fp); // Don't leak the file handle return false; } diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h index 8f716c5d02..ade283bb85 100644 --- a/indra/llimage/llimagedimensionsinfo.h +++ b/indra/llimage/llimagedimensionsinfo.h @@ -55,6 +55,12 @@ public: { return mLastError; } + + const std::string& getWarningName() + { + return mWarning; + } + protected: void clean() @@ -129,6 +135,7 @@ protected: std::string mSrcFilename; std::string mLastError; + std::string mWarning; U8* mData; diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 8bd5bd9584..8d54417e9c 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -35,8 +35,10 @@ class ImageRequest { public: ImageRequest(const LLPointer& image, - S32 discard, BOOL needs_aux, - const LLPointer& responder); + S32 discard, + BOOL needs_aux, + const LLPointer& responder, + U32 request_id); virtual ~ImageRequest(); /*virtual*/ bool processRequest(); @@ -48,6 +50,7 @@ private: // input LLPointer mFormattedImage; S32 mDiscardLevel; + U32 mRequestId; BOOL mNeedsAux; // output LLPointer mDecodedImageRaw; @@ -62,6 +65,7 @@ private: // MAIN THREAD LLImageDecodeThread::LLImageDecodeThread(bool /*threaded*/) + : mDecodeCount(0) { mThreadPool.reset(new LL::ThreadPool("ImageDecode", 8)); mThreadPool->start(); @@ -92,9 +96,10 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + U32 decode_id = ++mDecodeCount; // Instantiate the ImageRequest right in the lambda, why not? bool posted = mThreadPool->getQueue().post( - [req = ImageRequest(image, discard, needs_aux, responder)] + [req = ImageRequest(image, discard, needs_aux, responder, decode_id)] () mutable { auto done = req.processRequest(); @@ -103,13 +108,10 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage( if (! posted) { LL_DEBUGS() << "Tried to start decoding on shutdown" << LL_ENDL; - // should this return 0? + return 0; } - // It's important to our consumer (LLTextureFetchWorker) that we return a - // nonzero handle. It is NOT important that the nonzero handle be unique: - // nothing is ever done with it except to compare it to zero, or zero it. - return 17; + return decode_id; } void LLImageDecodeThread::shutdown() @@ -123,15 +125,18 @@ LLImageDecodeThread::Responder::~Responder() //---------------------------------------------------------------------------- -ImageRequest::ImageRequest(const LLPointer& image, - S32 discard, BOOL needs_aux, - const LLPointer& responder) +ImageRequest::ImageRequest(const LLPointer& image, + S32 discard, + BOOL needs_aux, + const LLPointer& responder, + U32 request_id) : mFormattedImage(image), mDiscardLevel(discard), mNeedsAux(needs_aux), mDecodedRaw(FALSE), mDecodedAux(FALSE), - mResponder(responder) + mResponder(responder), + mRequestId(request_id) { } @@ -211,7 +216,7 @@ void ImageRequest::finishRequest(bool completed) if (mResponder.notNull()) { bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); - mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux); + mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux, mRequestId); } // Will automatically be deleted } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index ca4c0d93d0..b4ab9432e6 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -39,7 +39,7 @@ public: protected: virtual ~Responder(); public: - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0; }; public: @@ -53,6 +53,7 @@ public: const LLPointer& responder); size_t getPending(); size_t update(F32 max_time_ms); + S32 getTotalDecodeCount() { return mDecodeCount; } void shutdown(); private: @@ -60,6 +61,7 @@ private: // LLQueuedThread - instead this is the API by which we submit work to the // "ImageDecode" ThreadPool. std::unique_ptr mThreadPool; + LLAtomicU32 mDecodeCount; }; #endif diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index a4ab5e8ded..b26ab18a90 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5630,9 +5630,9 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) U32 stream_count = data.w.empty() ? 4 : 5; - U32 vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count); + size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count); - if (vert_count < 65535) + if (vert_count < 65535 && vert_count != 0) { std::vector indices; indices.resize(mNumIndices); @@ -5651,6 +5651,13 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) { U32 src_idx = i; U32 dst_idx = remap[i]; + if (dst_idx >= mNumVertices) + { + dst_idx = mNumVertices - 1; + // Shouldn't happen, figure out what gets returned in remap and why. + llassert(false); + LL_DEBUGS_ONCE("LLVOLUME") << "Invalid destination index, substituting" << LL_ENDL; + } mIndices[i] = dst_idx; mPositions[dst_idx].load3(data.p[src_idx].mV); @@ -5684,6 +5691,10 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) } else { + if (vert_count == 0) + { + LL_WARNS_ONCE("LLVOLUME") << "meshopt_generateVertexRemapMulti failed to process a model or model was invalid" << LL_ENDL; + } // blew past the max vertex size limit, use legacy tangent generation which never adds verts createTangents(); } diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp index 93d5cfc131..212d0619d1 100644 --- a/indra/llmessage/llxfer.cpp +++ b/indra/llmessage/llxfer.cpp @@ -386,12 +386,3 @@ std::ostream& operator<< (std::ostream& os, LLXfer &hh) os << hh.getFileName() ; return os; } - - - - - - - - - diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index c6777e9133..eae19a8f62 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1056,7 +1056,12 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) weight_map::iterator iterPos = mSkinWeights.begin(); weight_map::iterator iterEnd = mSkinWeights.end(); - llassert(!mSkinWeights.empty()); + if (mSkinWeights.empty()) + { + // function calls iter->second on all return paths + // everything that calls this function should precheck that there is data. + LL_ERRS() << "called getJointInfluences with empty weights list" << LL_ENDL; + } for ( ; iterPos!=iterEnd; ++iterPos ) { @@ -1083,11 +1088,16 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) const F32 epsilon = 1e-5f; weight_map::iterator iter_up = mSkinWeights.lower_bound(pos); weight_map::iterator iter_down = iter_up; - if (iter_up != mSkinWeights.end()) - { - iter_down = ++iter_up; - } - weight_map::iterator best = iter_up; + weight_map::iterator best = iter_up; + if (iter_up != mSkinWeights.end()) + { + iter_down = ++iter_up; + } + else + { + // Assumes that there is at least one element + --best; + } // FIRE-9251; There is no way iter can be valid here, otherwise we had hit the if branch and not the else branch. // F32 min_dist = (iter->first - pos).magVec(); diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 113d12a65a..b2ca583611 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -101,6 +101,17 @@ void APIENTRY gl_debug_callback(GLenum source, return; }*/ + if (gGLManager.mIsDisabled && + severity == GL_DEBUG_SEVERITY_HIGH_ARB && + source == GL_DEBUG_SOURCE_API_ARB && + type == GL_DEBUG_TYPE_ERROR_ARB && + id == GL_INVALID_VALUE) + { + // Suppress messages about deleting already deleted objects called from LLViewerWindow::stopGL() + // "GL_INVALID_VALUE error generated. Handle does not refer to an object generated by OpenGL." + return; + } + // list of messages to suppress const char* suppress[] = { @@ -155,8 +166,9 @@ void APIENTRY gl_debug_callback(GLenum source, glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &ubo_size); glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &ubo_immutable); } - - if (severity == GL_DEBUG_SEVERITY_HIGH) + + // No needs to halt when is called from LLViewerWindow::stopGL() + if (severity == GL_DEBUG_SEVERITY_HIGH && !gGLManager.mIsDisabled) { LL_ERRS() << "Halting on GL Error" << LL_ENDL; } diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 896a34cac4..496c34c38b 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -126,12 +126,12 @@ public: void setSelected(bool is_selected); - bool getCollapsible() {return mCollapsible;}; + bool getCollapsible() { return mCollapsible; }; - void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; + void setCollapsible(bool collapsible) { mCollapsible = collapsible; }; void changeOpenClose(bool is_open); - void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; + void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; }; bool canOpenClose() const { return mCanOpenClose; }; virtual BOOL postBuild(); @@ -142,8 +142,8 @@ public: void draw(); - void storeOpenCloseState (); - void restoreOpenCloseState (); + void storeOpenCloseState(); + void restoreOpenCloseState(); protected: LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index 4b057fa62c..b34496c1d3 100644 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -296,7 +296,7 @@ void LLContainerView::setLabel(const std::string& label) mLabel = label; } -void LLContainerView::setDisplayChildren(const BOOL displayChildren) +void LLContainerView::setDisplayChildren(BOOL displayChildren) { mDisplayChildren = displayChildren; for (child_list_const_iter_t child_iter = getChildList()->begin(); diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index 48ec36a861..7f69670230 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -86,7 +86,7 @@ public: void setLabel(const std::string& label); void showLabel(BOOL show) { mShowLabel = show; } - void setDisplayChildren(const BOOL displayChildren); + void setDisplayChildren(BOOL displayChildren); BOOL getDisplayChildren() { return mDisplayChildren; } void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 4363d2c475..c5fb9bb459 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1373,26 +1373,28 @@ void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) mForceShowingUnmatchedItems = show; } -void LLFlatListViewEx::setFilterSubString(const std::string& filter_str) +void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) { if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) { mFilterSubString = filter_str; updateNoItemsMessage(mFilterSubString); - filterItems(); + filterItems(false, notify_parent); } } -void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) +bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) { - if (!item) return; + if (!item) + return false; + + BOOL visible = TRUE; // 0 signifies that filter is matched, // i.e. we don't hide items that don't support 'match_filter' action, separators etc. if (0 == item->notify(action)) { mHasMatchedItems = true; - item->setVisible(true); } else { @@ -1400,34 +1402,45 @@ void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) if (!mForceShowingUnmatchedItems) { selectItem(item, false); + visible = FALSE; } - item->setVisible(mForceShowingUnmatchedItems); } + + if (item->getVisible() != visible) + { + item->setVisible(visible); + return true; + } + + return false; } -void LLFlatListViewEx::filterItems() +void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent) { - typedef std::vector item_panel_list_t; - std::string cur_filter = mFilterSubString; LLStringUtil::toUpper(cur_filter); LLSD action; action.with("match_filter", cur_filter); - item_panel_list_t items; - getItems(items); - mHasMatchedItems = false; - item_panel_list_t::iterator iter = items.begin(), iter_end = items.end(); - while (iter < iter_end) + bool visibility_changed = false; + pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end(); + while (iter != iter_end) { - LLPanel* pItem = *(iter++); - updateItemVisibility(pItem, action); + LLPanel* pItem = (*(iter++))->first; + visibility_changed |= updateItemVisibility(pItem, action); } - sort(); - notifyParentItemsRectChanged(); + if (re_sort) + { + sort(); + } + + if (visibility_changed && notify_parent) + { + notifyParentItemsRectChanged(); + } } bool LLFlatListViewEx::hasMatchedItems() diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 7fe5d90876..054dab44d5 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -308,6 +308,7 @@ public: virtual S32 notify(const LLSD& info) ; virtual ~LLFlatListView(); + protected: /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ @@ -383,7 +384,9 @@ protected: LLRect getLastSelectedItemRect(); - void ensureSelectedVisible(); + void ensureSelectedVisible(); + + const pairs_list_t& getItemPairs() { return mItemPairs; } private: @@ -496,14 +499,14 @@ public: /** * Sets up new filter string and filters the list. */ - void setFilterSubString(const std::string& filter_str); + void setFilterSubString(const std::string& filter_str, bool notify_parent); std::string getFilterSubString() { return mFilterSubString; } /** * Filters the list, rearranges and notifies parent about shape changes. * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration. */ - void filterItems(); + void filterItems(bool re_sort, bool notify_parent); /** * Returns true if last call of filterItems() found at least one matching item @@ -527,7 +530,7 @@ protected: * @param item - item we are changing * @param item - action - parameters to determin visibility from */ - void updateItemVisibility(LLPanel* item, const LLSD &action); + bool updateItemVisibility(LLPanel* item, const LLSD &action); private: std::string mNoFilteredItemsMsg; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index dbd59e3393..ed5a256764 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -541,7 +541,6 @@ void LLFloater::enableResizeCtrls(bool enable, bool width, bool height) void LLFloater::destroy() { - gFloaterView->onDestroyFloater(this); // LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before // it was deleted via LLMortician::updateClass(). See EXT-8458. LLFloaterReg::removeInstance(mInstanceName, mKey); @@ -2631,8 +2630,7 @@ LLFloaterView::LLFloaterView (const Params& p) mSnapOffsetBottom(0), mSnapOffsetChatBar(0), mSnapOffsetLeft(0), - mSnapOffsetRight(0), - mFrontChild(NULL) + mSnapOffsetRight(0) { mSnapView = getHandle(); } @@ -2788,7 +2786,8 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore if (!child) return; - if (mFrontChild == child) + LLFloater* front_child = mFrontChildHandle.get(); + if (front_child == child) { if (give_focus && child->canFocusStealFrontmost() && !gFocusMgr.childHasKeyboardFocus(child)) { @@ -2797,12 +2796,12 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore return; } - if (mFrontChild && !mFrontChild->isDead()) + if (front_child && !front_child->isDead() && front_child->getVisible()) { - mFrontChild->goneFromFront(); + front_child->goneFromFront(); } - mFrontChild = child; + mFrontChildHandle = child->getHandle(); // *TODO: make this respect floater's mAutoFocus value, instead of // using parameter @@ -3389,7 +3388,8 @@ LLFloater *LLFloaterView::getBackmost() const void LLFloaterView::syncFloaterTabOrder() { - if (mFrontChild && !mFrontChild->isDead() && mFrontChild->getIsChrome()) + LLFloater* front_child = mFrontChildHandle.get(); + if (front_child && front_child->getIsChrome()) return; // look for a visible modal dialog, starting from first @@ -3427,11 +3427,12 @@ void LLFloaterView::syncFloaterTabOrder() LLFloater* floaterp = dynamic_cast(*child_it); if (gFocusMgr.childHasKeyboardFocus(floaterp)) { - if (mFrontChild != floaterp) + LLFloater* front_child = mFrontChildHandle.get(); + if (front_child != floaterp) { // Grab a list of the top floaters that want to stay on top of the focused floater std::list listTop; - if (mFrontChild && !mFrontChild->canFocusStealFrontmost()) + if (front_child && !front_child->canFocusStealFrontmost()) { for (LLView* childp : *getChildList()) { @@ -3451,7 +3452,7 @@ void LLFloaterView::syncFloaterTabOrder() { sendChildToFront(childp); } - mFrontChild = listTop.back(); + mFrontChildHandle = listTop.back()->getHandle(); } } @@ -3547,14 +3548,6 @@ void LLFloaterView::setToolbarRect(LLToolBarEnums::EToolBarLocation tb, const LL } } -void LLFloaterView::onDestroyFloater(LLFloater* floater) -{ - if (mFrontChild == floater) - { - mFrontChild = nullptr; - } -} - // Prevent floaters being dragged under main chat bar void LLFloaterView::setMainChatbarRect(LLLayoutPanel* panel, const LLRect& chatbar_rect) { diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 21b132f239..71c46b1300 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -645,7 +645,6 @@ public: // Fix for bad edge snapping void setToolbarRect(LLToolBarEnums::EToolBarLocation tb, const LLRect& toolbar_rect); - void onDestroyFloater(LLFloater* floater); // Prevent floaters being dragged under main chat bar void setMainChatbarRect(LLLayoutPanel* panel, const LLRect& chatbar_rect); @@ -670,7 +669,7 @@ private: S32 mMinimizePositionVOffset; typedef std::vector, boost::signals2::connection> > hidden_floaters_t; hidden_floaters_t mHiddenFloaters; - LLFloater * mFrontChild; + LLHandle mFrontChildHandle; // Prevent floaters being dragged under main chat bar LLRect mMainChatbarRect; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 9606d6e7ca..b31c4e8c1c 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -206,14 +206,18 @@ LLFolderViewItem::~LLFolderViewItem() BOOL LLFolderViewItem::postBuild() { - 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()); + LLFolderViewModelItem* vmi = getViewModelItem(); + llassert(vmi); // not supposed to happen, if happens, find out why and fix + if (vmi) + { + // 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(); + // 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. diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 4cf7bc4256..46166ca3f7 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -502,7 +502,7 @@ LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring"); // Walk through a string, applying the rules specified by the keyword token list and // create a list of color segments. -void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, const LLColor4 &defaultColor, LLTextEditor& editor) +void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, LLTextEditor& editor, LLStyleConstSP style) { LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING); seg_list->clear(); @@ -515,10 +515,10 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW S32 text_len = wtext.size() + 1; // Script editor ignoring font selection - //seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) ); - LLStyleSP style = getDefaultStyle(editor); - style->setColor(defaultColor); - seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) ); + //seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) ); + LLStyleSP actual_style = getDefaultStyle(editor); + actual_style->setColor(style->getColor()); + seg_list->push_back( new LLNormalTextSegment( actual_style, 0, text_len, editor ) ); // const llwchar* base = wtext.c_str(); @@ -530,11 +530,11 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW if( *cur == '\n' ) { // Script editor ignoring font selection - //LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(cur-base); + //LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, cur-base); LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(getDefaultStyle(editor), cur-base); // text_segment->setToken( 0 ); - insertSegment( *seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( *seg_list, text_segment, text_len, style, editor); cur++; if( !*cur || *cur == '\n' ) { @@ -572,7 +572,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW S32 seg_end = cur - base; //create segments from seg_start to seg_end - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); line_done = TRUE; // to break out of second loop. break; } @@ -679,7 +679,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); } - insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, style, editor); /* // Script editor ignoring font selection //LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); @@ -723,7 +723,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW // LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL; - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); } cur += seg_len; continue; @@ -738,9 +738,12 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLW } } -void LLKeywords::insertSegments(const LLWString& wtext, std::vector& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor ) +void LLKeywords::insertSegments(const LLWString& wtext, std::vector& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, LLStyleConstSP style, LLTextEditor& editor ) { std::string::size_type pos = wtext.find('\n',seg_start); + + // Script editor ignoring font selection + //LLStyleConstSP cur_token_style = new LLStyle(LLStyle::Params().font(style->getFont()).color(cur_token->getColor())); while (pos!=-1 && pos < (std::string::size_type)seg_end) { @@ -753,28 +756,28 @@ void LLKeywords::insertSegments(const LLWString& wtext, std::vector text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( seg_list, text_segment, text_len, style, editor); } // Script editor ignoring font selection - //LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(pos); + //LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, pos); LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(getDefaultStyle(editor), pos); // text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( seg_list, text_segment, text_len, style, editor); seg_start = pos+1; pos = wtext.find('\n',seg_start); } // Script editor ignoring font selection - //LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); - LLStyleSP style = getDefaultStyle(editor); - style->setColor(cur_token->getColor()); - LLTextSegmentPtr text_segment = new LLNormalTextSegment( style, seg_start, seg_end, editor ); + //LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, seg_end, editor); + LLStyleSP actual_style = getDefaultStyle(editor); + actual_style->setColor(cur_token->getColor()); + LLTextSegmentPtr text_segment = new LLNormalTextSegment(actual_style, seg_start, seg_end, editor); // text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( seg_list, text_segment, text_len, style, editor); } void LLKeywords::insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) @@ -803,6 +806,32 @@ void LLKeywords::insertSegment(std::vector& seg_list, LLTextSe } } +void LLKeywords::insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor ) +{ + LLTextSegmentPtr last = seg_list.back(); + S32 new_seg_end = new_segment->getEnd(); + + if( new_segment->getStart() == last->getStart() ) + { + seg_list.pop_back(); + } + else + { + last->setEnd( new_segment->getStart() ); + } + seg_list.push_back( new_segment ); + + if( new_seg_end < text_len ) + { + // Script editor ignoring font selection + //seg_list.push_back( new LLNormalTextSegment( style, new_seg_end, text_len, editor ) ); + LLStyleSP actual_style = getDefaultStyle(editor); + actual_style->setColor(style->getColor()); + seg_list.push_back(new LLNormalTextSegment(actual_style, new_seg_end, text_len, editor)); + // + } +} + // Re-add support for Cinder's legacy file format bool LLKeywords::loadFromLegacyFile(const std::string& filename) { diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 0ee4f70692..9314d08c82 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -29,6 +29,7 @@ #include "lldir.h" +#include "llstyle.h" #include "llstring.h" #include "v3color.h" #include "v4color.h" @@ -121,8 +122,8 @@ public: void findSegments(std::vector *seg_list, const LLWString& text, - const LLColor4 &defaultColor, - class LLTextEditor& editor); + class LLTextEditor& editor, + LLStyleConstSP style); void initialize(LLSD SyntaxXML); void processTokens(); @@ -187,9 +188,11 @@ protected: S32 text_len, S32 seg_start, S32 seg_end, - const LLColor4 &defaultColor, + LLStyleConstSP style, LLTextEditor& editor); + void insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor ); + bool mLoaded; LLSD mSyntax; word_token_map_t mWordTokenMap; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 286d4602c4..7aa9c11be4 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1811,7 +1811,8 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p) mNeedsArrange(FALSE), mAlwaysShowMenu(FALSE), mResetScrollPositionOnShow(true), - mShortcutPad(p.shortcut_pad) + mShortcutPad(p.shortcut_pad), + mFont(p.font) { typedef boost::tokenizer > tokenizer; boost::char_separator sep("_"); @@ -3682,6 +3683,7 @@ BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu ) p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + p.font = menu->getFont(); LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create(p); success &= branch->addToAcceleratorList(&mAccelerators); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index f3bc724644..a35c0fcf7d 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -563,6 +563,8 @@ public: // add a context menu branch BOOL appendContextSubMenu(LLMenuGL *menu); + const LLFontGL *getFont() const { return mFont; } + // Items-accessor typedef std::list< LLMenuItemGL* > item_list_t; item_list_t* getItems() { return &mItems; } @@ -599,6 +601,9 @@ protected: BOOL mKeepFixedSize; BOOL mNeedsArrange; + // Font for top menu items only + const LLFontGL* mFont; + private: diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index d8f0bda543..fb82f594aa 100644 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -184,7 +184,7 @@ LLStatBar::LLStatBar(const Params& p) mTargetMinBar(llmin(p.bar_min, p.bar_max)), mTargetMaxBar(llmax(p.bar_max, p.bar_min)), mCurMaxBar(p.bar_max), - mCurMinBar(0), + mCurMinBar(0), mDecimalDigits(p.decimal_digits), mNumHistoryFrames(p.num_frames), mNumShortHistoryFrames(p.num_frames_short), @@ -279,9 +279,6 @@ BOOL LLStatBar::handleHover(S32 x, S32 y, MASK mask) case STAT_SAMPLE: LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.sampleStatp->getDescription()).sticky_rect(calcScreenRect())); break; - case STAT_MEM: - LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.memStatp->getDescription()).sticky_rect(calcScreenRect())); - break; default: break; } @@ -430,18 +427,6 @@ void LLStatBar::draw() } } break; - case STAT_MEM: - { - const LLTrace::StatType& mem_stat = *mStat.memStatp; - - unit_label = mUnitLabel.empty() ? mem_stat.getUnitLabel() : mUnitLabel; - current = last_frame_recording.getLastValue(mem_stat).value(); - min = frame_recording.getPeriodMin(mem_stat, num_frames).value(); - max = frame_recording.getPeriodMax(mem_stat, num_frames).value(); - mean = frame_recording.getPeriodMean(mem_stat, num_frames).value(); - display_value = current; - } - break; default: break; } @@ -560,11 +545,6 @@ void LLStatBar::draw() max_value = recording.getMax(*mStat.sampleStatp); num_samples = recording.getSampleCount(*mStat.sampleStatp); break; - case STAT_MEM: - min_value = recording.getMin(*mStat.memStatp).value(); - max_value = recording.getMax(*mStat.memStatp).value(); - num_samples = 1; - break; default: break; } @@ -661,14 +641,8 @@ void LLStatBar::setStat(const std::string& stat_name) mStat.sampleStatp = sample_stat.get(); mStatType = STAT_SAMPLE; } - else if (auto mem_stat = StatType::getInstance(stat_name)) - { - mStat.memStatp = mem_stat.get(); - mStatType = STAT_MEM; - } } - void LLStatBar::setRange(F32 bar_min, F32 bar_max) { mTargetMinBar = llmin(bar_min, bar_max); diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index 6c84fb8e38..49622485be 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -100,17 +100,15 @@ private: STAT_NONE, STAT_COUNT, STAT_EVENT, - STAT_SAMPLE, - STAT_MEM + STAT_SAMPLE } mStatType; union { - void* valid; + void* valid; const LLTrace::StatType* countStatp; const LLTrace::StatType* eventStatp; - const LLTrace::StatType* sampleStatp; - const LLTrace::StatType* memStatp; + const LLTrace::StatType* sampleStatp; } mStat; LLUIString mLabel; diff --git a/indra/llui/llstatview.cpp b/indra/llui/llstatview.cpp index bb4969c81f..03f2fb7cc0 100644 --- a/indra/llui/llstatview.cpp +++ b/indra/llui/llstatview.cpp @@ -58,10 +58,7 @@ LLStatView::~LLStatView() } } - static StatViewRegistry::Register r1("stat_bar"); static StatViewRegistry::Register r2("stat_view"); // stat_view can be a child of panels/etc. static LLDefaultChildRegistry::Register r3("stat_view"); - - diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index af4db7d7ea..044f0a8679 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -63,7 +63,7 @@ protected: friend class LLUICtrlFactory; protected: - std::string mSetting; - + const std::string mSetting; }; + #endif // LL_STATVIEW_ diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 124b0d073b..3928cb5655 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1657,25 +1657,23 @@ BOOL LLTabContainer::selectTab(S32 which) LLTabTuple* selected_tuple = getTab(which); if (!selected_tuple) - { return FALSE; - } - + LLSD cbdata; if (selected_tuple->mTabPanel) cbdata = selected_tuple->mTabPanel->getName(); - BOOL res = FALSE; - if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) ) + BOOL result = FALSE; + if (!mValidateSignal || (*mValidateSignal)(this, cbdata)) { - res = setTab(which); - if (res && mCommitSignal) + result = setTab(which); + if (result && mCommitSignal) { (*mCommitSignal)(this, cbdata); } } - - return res; + + return result; } // private diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 978e7cf25e..69aedb647b 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -3829,7 +3829,7 @@ BOOL LLNormalTextSegment::handleToolTip(S32 x, S32 y, MASK mask) if (mToken && !mToken->getToolTip().empty()) { const LLWString& wmsg = mToken->getToolTip(); - LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg)); + LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg), (mToken->getType() == LLKeywordToken::TT_FUNCTION)); return TRUE; } // or do we have an explicitly set tooltip (e.g., for Urls) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 1f1d525fac..e938fa3c8f 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2048,7 +2048,8 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) } if (mEnableTooltipPaste && - LLToolTipMgr::instance().toolTipVisible() && + LLToolTipMgr::instance().toolTipVisible() && + LLToolTipMgr::instance().isTooltipPastable() && KEY_TAB == key) { // Paste the first line of a tooltip into the editor std::string message; diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index b286912f17..62371a9208 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -154,7 +154,8 @@ LLToolTip::Params::Params() text_color("text_color"), time_based_media("time_based_media", false), web_based_media("web_based_media", false), - media_playing("media_playing", false) + media_playing("media_playing", false), + allow_paste_tooltip("allow_paste_tooltip", false) { changeDefault(chrome, true); } @@ -167,7 +168,8 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) mTextBox(NULL), mInfoButton(NULL), mPlayMediaButton(NULL), - mHomePageButton(NULL) + mHomePageButton(NULL), + mIsTooltipPastable(p.allow_paste_tooltip) { LLTextBox::Params params; params.name = params.initial_value().asString(); @@ -289,6 +291,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) mTextBox->setText(p.message()); } + mIsTooltipPastable = p.allow_paste_tooltip; + updateTextBox(); snapToChildren(); } @@ -483,9 +487,9 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) } -void LLToolTipMgr::show(const std::string& msg) +void LLToolTipMgr::show(const std::string& msg, bool allow_paste_tooltip) { - show(LLToolTip::Params().message(msg)); + show(LLToolTip::Params().message(msg).allow_paste_tooltip(allow_paste_tooltip)); } void LLToolTipMgr::show(const LLToolTip::Params& params) @@ -625,5 +629,13 @@ void LLToolTipMgr::getToolTipMessage(std::string & message) } } +bool LLToolTipMgr::isTooltipPastable() +{ + if (toolTipVisible()) + { + return mToolTip->isTooltipPastable(); + } + return false; + } // EOF diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 86943625ff..fef5e7c75f 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -94,6 +94,8 @@ public: padding; Optional wrap; + Optional allow_paste_tooltip; + Params(); }; /*virtual*/ void draw(); @@ -109,6 +111,7 @@ public: virtual void initFromParams(const LLToolTip::Params& params); void getToolTipMessage(std::string & message); + bool isTooltipPastable() { return mIsTooltipPastable; } protected: void updateTextBox(); @@ -125,6 +128,8 @@ protected: bool mHasClickCallback; S32 mPadding; // pixels S32 mMaxWidth; + + bool mIsTooltipPastable; }; // used for the inspector tooltips which need different background images etc. @@ -142,7 +147,7 @@ class LLToolTipMgr : public LLSingleton public: void show(const LLToolTip::Params& params); - void show(const std::string& message); + void show(const std::string& message, bool allow_paste_tooltip = false); void unblockToolTips(); void blockToolTips(); @@ -154,6 +159,7 @@ public: void updateToolTipVisibility(); void getToolTipMessage(std::string & message); + bool isTooltipPastable(); private: void createToolTip(const LLToolTip::Params& params); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index c1d6696b69..3c94858c0b 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -237,14 +237,20 @@ bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const { + if (url.empty()) + { + return url; + } LLUriParser up(escapeUrl(url)); - up.normalize(); + if (up.normalize() == 0) + { + std::string label; + up.extractParts(); + up.glueFirst(label); - std::string label; - up.extractParts(); - up.glueFirst(label); - - return unescapeUrl(label); + return unescapeUrl(label); + } + return std::string(); } std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp index dcc2197982..b949320b27 100644 --- a/indra/llui/llurlregistry.cpp +++ b/indra/llui/llurlregistry.cpp @@ -293,16 +293,18 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL //if (match_entry == mUrlEntryTrusted) //{ // LLUriParser up(url); - // up.normalize(); - // url = up.normalizedUri(); + // if (up.normalize() == 0) + // { + // url = up.normalizedUri(); + // } //} if (match_entry != mUrlEntryNoLink && match_entry == mUrlEntryTrustedUrl) { LLUriParser up(url); - if (!up.normalize()) - { - url = up.normalizedUri(); - } + if (up.normalize() == 0) + { + url = up.normalizedUri(); + } } // diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 16e3c99608..a9be33bfe9 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -37,7 +37,6 @@ #include "llwindowcallbacks.h" // Linden library includes -#include "llapp.h" // [FIRE-32453][BUG-232971] Improve shutdown behaviour. #include "llerror.h" #include "llexception.h" #include "llfasttimer.h" @@ -94,7 +93,6 @@ const UINT WM_DUMMY_(WM_USER + 0x0017); const UINT WM_POST_FUNCTION_(WM_USER + 0x0018); extern BOOL gDebugWindowProc; -extern BOOL gDisconnected; // [FIRE-32453][BUG-232971] Improve shutdown behaviour. static std::thread::id sWindowThreadId; static std::thread::id sMainThreadId; @@ -353,7 +351,10 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool LLWindowWin32Thread(); void run() override; - void close() override; // [FIRE-32453][BUG-232971] Improve shutdown behaviour. + void close() override; + + // closes queue, wakes thread, waits until thread closes + void wakeAndDestroy(); void glReady() { @@ -366,6 +367,9 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool // initialize D3D (if DXGI cannot be used) void initD3D(); + //clean up DXGI/D3D resources + void cleanupDX(); + // call periodically to update available VRAM void updateVRAMUsage(); @@ -415,8 +419,8 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool using FuncType = std::function; // call GetMessage() and pull enqueue messages for later processing void gatherInput(); - HWND mWindowHandle = NULL; - HDC mhDC = 0; + HWND mWindowHandleThrd = NULL; + HDC mhDCThrd = 0; // *HACK: Attempt to prevent startup crashes by deferring memory accounting // until after some graphics setup. See SL-20177. -Cosmic,2023-09-18 @@ -992,53 +996,10 @@ void LLWindowWin32::close() LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; - mWindowThread->post([=]() - { - if (IsWindow(mWindowHandle)) - { - if (mhDC) - { - if (!ReleaseDC(mWindowHandle, mhDC)) - { - LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL; - } - } - - // 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)) - { - // Can't use a message box here because we're about to stop servicing the events. - // OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"), - // mCallbacks->translateString("MBShutdownErr"), - // OSMB_OK); - LL_INFOS("Window") << "Destroying Window failed" << LL_ENDL; - // - } - } - 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; - } - - }); - // Window thread might be waiting for a getMessage(), give it - // a push to enshure it will process destroy_window_handler - kickWindowThread(); - - // Even though the above lambda might not yet have run, we've already - // bound mWindowHandle into it by value, which should suffice for the - // operations we're asking. That's the last time WE should touch it. mhDC = NULL; mWindowHandle = NULL; - // [FIRE-32453][BUG-232971] close the related queues first to prevent spinning. - mFunctionQueue.close(); - mMouseQueue.close(); - // - mWindowThread->close(); + + mWindowThread->wakeAndDestroy(); } BOOL LLWindowWin32::isValid() @@ -1791,8 +1752,8 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw () { LL_DEBUGS("Window") << "recreateWindow(): window_work entry" << LL_ENDL; - self->mWindowHandle = 0; - self->mhDC = 0; + self->mWindowHandleThrd = 0; + self->mhDCThrd = 0; if (oldWindowHandle) { @@ -1826,20 +1787,20 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw { // Failed to create window: clear the variables. This // assignment is valid because we're running on mWindowThread. - self->mWindowHandle = NULL; - self->mhDC = 0; + self->mWindowHandleThrd = NULL; + self->mhDCThrd = 0; } else { // Update mWindowThread's own mWindowHandle and mhDC. - self->mWindowHandle = handle; - self->mhDC = GetDC(handle); + self->mWindowHandleThrd = handle; + self->mhDCThrd = GetDC(handle); } updateWindowRect(); // It's important to wake up the future either way. - promise.set_value(std::make_pair(self->mWindowHandle, self->mhDC)); + promise.set_value(std::make_pair(self->mWindowHandleThrd, self->mhDCThrd)); LL_DEBUGS("Window") << "recreateWindow(): window_work done" << LL_ENDL; }; // But how we pass window_work to the window thread depends on whether we @@ -3723,6 +3684,7 @@ void LLWindowWin32::swapBuffers() } } + // // LLSplashScreenImp // @@ -3745,6 +3707,9 @@ void LLSplashScreenWin32::showImpl() NULL, // no parent (DLGPROC) LLSplashScreenWin32::windowProc); ShowWindow(mWindow, SW_SHOW); + + // Should set taskbar text without creating a header for the window (caption) + SetWindowTextA(mWindow, APP_NAME.c_str()); } @@ -4708,11 +4673,25 @@ void LLWindowWin32::getWindowChrome( U32 &aChromeW, U32 &aChromeH ) #endif // LL_WINDOWS inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() - : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) + : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, true /*should be false, temporary workaround for SL-18721*/) { LL::ThreadPool::start(); } +void LLWindowWin32::LLWindowWin32Thread::close() +{ + if (!mQueue->isClosed()) + { + LL_WARNS() << "Closing window thread without using destroy_window_handler" << LL_ENDL; + LL::ThreadPool::close(); + + // Workaround for SL-18721 in case window closes too early and abruptly + LLSplashScreen::show(); + LLSplashScreen::update("..."); // will be updated later + } +} + + /** * LogChange is to log changes in status while trying to avoid spamming the * log with repeated messages, especially in a tight loop. It refuses to log @@ -4864,7 +4843,7 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D() { if (!mGLReady) { return; } - if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandle != 0) + if (mDXGIAdapter == NULL && mD3DDevice == NULL && mWindowHandleThrd != 0) { mD3D = Direct3DCreate9(D3D_SDK_VERSION); @@ -4874,7 +4853,7 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D() d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice); + HRESULT res = mD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mWindowHandleThrd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &mD3DDevice); if (FAILED(res)) { @@ -4887,6 +4866,28 @@ void LLWindowWin32::LLWindowWin32Thread::initD3D() } } +void LLWindowWin32::LLWindowWin32Thread::cleanupDX() +{ + //clean up DXGI/D3D resources + if (mDXGIAdapter) + { + mDXGIAdapter->Release(); + mDXGIAdapter = nullptr; + } + + if (mD3DDevice) + { + mD3DDevice->Release(); + mD3DDevice = nullptr; + } + + if (mD3D) + { + mD3D->Release(); + mD3D = nullptr; + } +} + void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() { LL_PROFILE_ZONE_SCOPED; @@ -4960,45 +4961,10 @@ void LLWindowWin32::LLWindowWin32Thread::updateVRAMUsage() } } -// [FIRE-32453][BUG-232971] Improve shutdown behaviour. -// Provide a close() override that ignores the initial close triggered by the threadpool detecting "quit" -// but waits for the viewer to be disconected and the second close call triggered by the app window destructor -void LLWindowWin32::LLWindowWin32Thread::close() -{ - assert_main_thread(); - if (!mQueue->isClosed() && gDisconnected) - { - LL_DEBUGS("ThreadPool") << mName << " closing queue and joining threads" << LL_ENDL; - mQueue->close(); - for (auto& pair: mThreads) - { - LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL; - // As we cannot seem to rely on the clean and timely exit of the windows thread in ALL situations we apply a timeout. - std::future f = std::async(std::launch::async, [&] { pair.second.join(); }); - if (f.wait_until(std::chrono::steady_clock::now() + std::chrono::seconds(5)) == std::future_status::ready) { - LL_DEBUGS("ThreadPool") << mName << " joined normally." << LL_ENDL; - } else { - LL_WARNS("ThreadPool") << mName << " join timed out." << LL_ENDL; - // the specified time point was reached before the thread finished execution and could be joined - } - } - LL_DEBUGS("ThreadPool") << mName << " shutdown complete" << LL_ENDL; - } - else - { - LL_DEBUGS("ThreadPool") << mName << " shutdown request ignored - not yet disconneced." << LL_ENDL; - } -} -// - void LLWindowWin32::LLWindowWin32Thread::run() { sWindowThreadId = std::this_thread::get_id(); LogChange logger("Window"); - // [FIRE-32453][BUG-232971] Improve shutdown behaviour. - try - { - // //as good a place as any to up the MM timer resolution (see ms_sleep) //attempt to set timer resolution to 1ms TIMECAPS tc; @@ -5014,7 +4980,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() // lazily call initD3D inside this loop to catch when mGLReady has been set to true initDX(); - if (mWindowHandle != 0) + if (mWindowHandleThrd != 0) { // lazily call initD3D inside this loop to catch when mWindowHandle has been set, and mGLReady has been set to true // *TODO: Shutdown if this fails when mWindowHandle exists @@ -5022,16 +4988,16 @@ void LLWindowWin32::LLWindowWin32Thread::run() MSG msg; BOOL status; - if (mhDC == 0) + if (mhDCThrd == 0) { LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - PeekMessage"); - logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")"); - status = PeekMessage(&msg, mWindowHandle, 0, 0, PM_REMOVE); + logger.onChange("PeekMessage(", std::hex, mWindowHandleThrd, ")"); + status = PeekMessage(&msg, mWindowHandleThrd, 0, 0, PM_REMOVE); } else { LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - GetMessage"); - logger.always("GetMessage(", std::hex, mWindowHandle, ")"); + logger.always("GetMessage(", std::hex, mWindowHandleThrd, ")"); status = GetMessage(&msg, NULL, 0, 0); } if (status > 0) @@ -5040,21 +5006,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() ", ", msg.wParam, ")"); TranslateMessage(&msg); DispatchMessage(&msg); - // [FIRE-32453][BUG-232971] Improve shutdown behaviour. - // mMessageQueue.pushFront(msg); - try - { - // Nobody is reading this queue once we are quitting. Writing to it causes a hang. - if(!LLApp::isQuitting()) - mMessageQueue.pushFront(msg); - } - catch (const LLThreadSafeQueueInterrupt&) - { - // Shutdown timing is tricky. The main thread can end up trying - // to post a cursor position after having closed the WorkQueue. - logger.always("Message procesing tried to push() to closed MessageQueue - caught"); - } - // + mMessageQueue.pushFront(msg); } } @@ -5080,38 +5032,111 @@ void LLWindowWin32::LLWindowWin32Thread::run() } #endif } - // [FIRE-32453][BUG-232971] Improve shutdown behaviour. - } - catch (const std::exception& e) - { - logger.always("Windows thread exiting - Exception: ", e.what()); - } - catch (...) - { - logger.always("Windows thread exiting - Exception: Unknown"); - } - logger.always("done - queue closed on windows thread."); - // - //clean up DXGI/D3D resources - if (mDXGIAdapter) + cleanupDX(); +} + +void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy() +{ + if (mQueue->isClosed()) { - mDXGIAdapter->Release(); - mDXGIAdapter = nullptr; + LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL; + return; } - if (mD3DDevice) + // Make sure we don't leave a blank toolbar button. + // Also hiding window now prevents user from suspending it + // via some action (like dragging it around) + ShowWindow(mWindowHandleThrd, SW_HIDE); + + // Schedule destruction + HWND old_handle = mWindowHandleThrd; + post([this]() + { + if (IsWindow(mWindowHandleThrd)) + { + if (mhDCThrd) + { + if (!ReleaseDC(mWindowHandleThrd, mhDCThrd)) + { + LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL; + } + mhDCThrd = NULL; + } + + // This causes WM_DESTROY to be sent *immediately* + if (!destroy_window_handler(mWindowHandleThrd)) + { + LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL; + } + } + 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; + } + mWindowHandleThrd = NULL; + mhDCThrd = NULL; + mGLReady = false; + }); + + LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL; + mQueue->close(); + + // Post a nonsense user message to wake up the thread in + // case it is waiting for a getMessage() + if (old_handle) { - mD3DDevice->Release(); - mD3DDevice = nullptr; + WPARAM wparam{ 0xB0B0 }; + LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle + << ", " << WM_DUMMY_ + << ", " << wparam << ")" << std::dec << LL_ENDL; + PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337); } - if (mD3D) + // There are cases where window will refuse to close, + // can't wait forever on join, check state instead + LLTimer timeout; + timeout.setTimerExpirySec(2.0); + while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd) { - mD3D->Release(); - mD3D = nullptr; + ms_sleep(100); } + if (getQueue().done() || mWindowHandleThrd == NULL) + { + // Window is closed, started closing or is cleaning up + // now wait for our single thread to die. + if (mWindowHandleThrd) + { + LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL; + } + else + { + LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL; + } + for (auto& pair : mThreads) + { + pair.second.join(); + } + } + else + { + // Something suspended window thread, can't afford to wait forever + // so kill thread instead + // Ex: This can happen if user starts dragging window arround (if it + // was visible) or a modal notification pops up + LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL; + + for (auto& pair : mThreads) + { + // very unsafe + TerminateThread(pair.second.native_handle(), 0); + pair.second.detach(); + cleanupDX(); + } + } + LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL; } void LLWindowWin32::post(const std::function& func) diff --git a/indra/media_plugins/cef/linux_volume_catcher.cpp b/indra/media_plugins/cef/linux_volume_catcher.cpp index 43773bb952..6e7691ff57 100755 --- a/indra/media_plugins/cef/linux_volume_catcher.cpp +++ b/indra/media_plugins/cef/linux_volume_catcher.cpp @@ -286,7 +286,11 @@ void VolumeCatcherImpl::setVolume(F32 volume) void VolumeCatcherImpl::pump() { - return; + // PR#17 makidoll: Fix Linux volume catcher + if (mGotSyms && mMainloop) { + llpa_mainloop_iterate(mMainloop, 0, NULL); + } + // } void VolumeCatcherImpl::connected_okay() diff --git a/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc b/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc index 2c9f760fba..4e65221003 100755 --- a/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc +++ b/indra/media_plugins/cef/linux_volume_catcher_pa_syms.inc @@ -21,5 +21,6 @@ LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v); LL_PA_SYM(true, pa_mainloop_free, void, pa_mainloop* m); LL_PA_SYM(true, pa_mainloop_get_api, pa_mainloop_api*, pa_mainloop* m); LL_PA_SYM(true, pa_mainloop_new, pa_mainloop*, void); +LL_PA_SYM(true, pa_mainloop_iterate, int, pa_mainloop*, int, int*); // optional symbols to grab diff --git a/indra/newview/Info-Firestorm.plist b/indra/newview/Info-Firestorm.plist index 2b0e24e92e..6b2e73a5a2 100644 --- a/indra/newview/Info-Firestorm.plist +++ b/indra/newview/Info-Firestorm.plist @@ -28,6 +28,8 @@ ${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION} CSResourcesFileMapped + LSApplicationCategoryType + public.app-category.games LSRequiresCarbon NSAppSleepDisabled diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 69adf3456f..14627a7c8c 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.1.5 +7.1.6 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 31bb4589ab..38611ea3e0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5152,171 +5152,6 @@ Value -1 - DebugStatModeMemTrace - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemUI - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemFonts - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemInventory - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemObjects - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemOctreeGroupData - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemOctreeData - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemObjectCache - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemDrawable - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemFaceData - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemDrawInfo - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemTextureData - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemImageData - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemGLImageData - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - - DebugStatModeMemVertexBuffer - - Comment - Mode of stat in Statistics floater - Persist - 1 - Type - S32 - Value - -1 - DebugStatModeMaterials Comment @@ -7732,6 +7567,17 @@ Backup 0 + LSLFontSizeName + + Comment + UNUSED - Text font size in LSL editor + Persist + 1 + Type + String + Value + Monospace + GridStatusRSS Comment @@ -10342,21 +10188,10 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 - OpenDebugStatAdvanced - - Comment - Expand advanced performance stats display - Persist - 1 - Type - Boolean - Value - 1 - OpenDebugStatBasic Comment - Expand basic performance stats display + Expand Basic performance stats display Persist 1 Type @@ -10364,10 +10199,10 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 - OpenDebugStatNet + OpenDebugStatAdvanced Comment - Expand network stats display + Expand Advanced performance stats display Persist 1 Type @@ -10378,18 +10213,7 @@ Change of this parameter will affect the layout of buttons in notification toast OpenDebugStatRender Comment - Expand render stats display - Persist - 1 - Type - Boolean - Value - 1 - - OpenDebugStatSim - - Comment - Expand simulator performance stats display + Expand Render performance stats display Persist 1 Type @@ -10408,10 +10232,32 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 - OpenDebugStatSimPathfinding + OpenDebugStatNet Comment - Expand Pathfinding performance stats display + Expand Network performance stats display + Persist + 1 + Type + Boolean + Value + 1 + + OpenDebugStatSim + + Comment + Expand Simulator performance stats display + Persist + 1 + Type + Boolean + Value + 1 + + OpenDebugStatPhysicsDetails + + Comment + Expand Physics Details performance stats display Persist 1 Type @@ -10419,10 +10265,10 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 - OpenDebugStatPhysicsDetails + OpenDebugStatPathfinding Comment - Expand Physics Details performance stats display + Expand Pathfinding performance stats display Persist 1 Type @@ -10452,17 +10298,6 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 - OpenDebugStatMemory - - Comment - Expand Memory performance stats display - Persist - 1 - Type - Boolean - Value - 1 - OutBandwidth Comment @@ -21989,17 +21824,6 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 - FSDisplaySavedOutfitsCap - - Comment - Display only so many saved outfits in edit appearance. 0 to disable. - Persist - 1 - Type - U32 - Value - 0 - FSAdvancedWorldmapRegionInfo Comment @@ -25198,17 +25022,6 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 - VoiceMultiInstance - - Comment - Enables using voice in multiple simultaneous viewer instances - Persist - 1 - Type - Boolean - Value - 1 - FSSoundCacheLocation Comment diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index ed9a8240e4..243b17cf73 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -2023,7 +2023,7 @@ value_min="-1" value_max="1"> - + - - - @@ -2044,7 +2043,7 @@ name="mFaceEyeAltRight" scale="0 0 0" offset="-.005 0 0" /> - + - @@ -2064,17 +2063,17 @@ name="mFaceEyeLidUpperLeft" scale="0 0.3 0.7" offset=" 0 0 0" /> - + - + - + diff --git a/indra/newview/fsfloaterwearablefavorites.cpp b/indra/newview/fsfloaterwearablefavorites.cpp index cd632b70d2..f95c238ec0 100644 --- a/indra/newview/fsfloaterwearablefavorites.cpp +++ b/indra/newview/fsfloaterwearablefavorites.cpp @@ -311,7 +311,7 @@ void FSFloaterWearableFavorites::handleRemove() void FSFloaterWearableFavorites::onFilterEdit(const std::string& search_string) { - mItemsList->setFilterSubString(search_string); + mItemsList->setFilterSubString(search_string, true); mItemsList->setNoItemsCommentText(getString("empty_list")); } diff --git a/indra/newview/fsslurl.cpp b/indra/newview/fsslurl.cpp index 86e7b9794e..31f061cc67 100644 --- a/indra/newview/fsslurl.cpp +++ b/indra/newview/fsslurl.cpp @@ -66,14 +66,14 @@ LLSLURL::LLSLURL(const std::string& slurl) // by default we go to agni. mType = INVALID; LL_DEBUGS("AppInit", "SLURL") << "SLURL: " << slurl << LL_ENDL; - if(slurl == SIM_LOCATION_HOME) - { - mType = HOME_LOCATION; - } - else if(slurl.empty() || (slurl == SIM_LOCATION_LAST)) + if (slurl.empty() || (slurl == SIM_LOCATION_LAST)) { mType = LAST_LOCATION; } + else if (slurl == SIM_LOCATION_HOME) + { + mType = HOME_LOCATION; + } else { LLURI slurl_uri; @@ -154,6 +154,15 @@ LLSLURL::LLSLURL(const std::string& slurl) if(slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) { LL_DEBUGS("SLURL") << "secondlife scheme" << LL_ENDL; + if (path_array.size() == 0 + && slurl_uri.authority().empty() + && slurl_uri.escapedQuery().empty()) + { + mType = EMPTY; + // um, we need a path... + return; + } + // parse a maingrid style slurl. We know the grid is maingrid // so grab it. // A location slurl for maingrid (with the special schemes) can be in the form @@ -676,28 +685,24 @@ std::string LLSLURL::asString() const // std::string LLSLURL::getTypeHumanReadable(SLURL_TYPE type) { - std::string ret; switch(type) { case INVALID: - ret = "INVALID"; - break; + return "INVALID"; case LOCATION: - ret = "LOCATION"; - break; + return "LOCATION"; case HOME_LOCATION: - ret = "HOME_LOCATION"; - break; + return "HOME_LOCATION"; case LAST_LOCATION: - ret = "LAST_LOCATION"; - break; + return "LAST_LOCATION"; case APP: - ret = "APP"; - break; + return "APP"; case HELP: - ret = "HELP"; + return "HELP"; + case EMPTY: + return "EMPTY"; + default: + return{}; } - - return ret; } // diff --git a/indra/newview/fsslurl.h b/indra/newview/fsslurl.h index a3bd8e495b..03eb95853a 100644 --- a/indra/newview/fsslurl.h +++ b/indra/newview/fsslurl.h @@ -60,7 +60,8 @@ public: HOME_LOCATION, LAST_LOCATION, APP, - HELP + HELP, + EMPTY }; LLSLURL(): mType(INVALID) { } diff --git a/indra/newview/installers/darwin/apple-notarize.sh b/indra/newview/installers/darwin/apple-notarize.sh index b7006bf5cd..cd3f9eb803 100755 --- a/indra/newview/installers/darwin/apple-notarize.sh +++ b/indra/newview/installers/darwin/apple-notarize.sh @@ -18,22 +18,23 @@ if [[ -f "$CONFIG_FILE" ]]; then res=$(xcrun notarytool submit "$zip_file" \ --apple-id $USERNAME \ --password $PASSWORD \ - --verbose \ + --team-id $ASC_PROVIDER \ --wait 2>&1) echo "Notarytool submit:" echo $res [[ "$res" =~ 'id: '([^[:space:]]+) ]] match=$? + echo "Notarized with id: [$match]" - if [[ ! $match -eq 0 ]]; then - echo "Running Stapler" - xcrun stapler staple "$app_file" - exit 0 - else - echo "Notarization error" - exit 1 - fi + # if [[ ! $match -eq 0 ]]; then + echo "Running Stapler" + xcrun stapler staple "$app_file" + exit 0 + # else + # echo "Notarization error" + # exit 1 + # fi else echo "Notarization error: ditto failed" exit 1 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ac96b70c4f..83f5ee1376 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2214,6 +2214,9 @@ bool LLAppViewer::cleanup() LL_INFOS() << "ViewerWindow deleted" << LL_ENDL; } + LLSplashScreen::show(); + LLSplashScreen::update(LLTrans::getString("ShuttingDown")); + LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL; // viewer UI relies on keyboard so keep it aound until viewer UI isa gone @@ -2530,6 +2533,8 @@ bool LLAppViewer::cleanup() // deleteSingleton() methods. LLSingletonBase::deleteAll(); + LLSplashScreen::hide(); + LL_INFOS() << "Goodbye!" << LL_ENDL; removeDumpDir(); @@ -3478,20 +3483,19 @@ bool LLAppViewer::initConfiguration() return false; } - if (mSecondInstance) - { - // This is the second instance of SL. Turn off voice support, - // but make sure the setting is *not* persisted. - LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); - // Voice in multiple instances; by Latif Khalifa - //if(disable_voice) - if(disable_voice && !gSavedSettings.getBOOL("VoiceMultiInstance")) - // - { - const BOOL DO_NOT_PERSIST = FALSE; - disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); - } - } + // Voice in multiple instances + //if (mSecondInstance) + //{ + // // This is the second instance of SL. Mute voice, + // // but make sure the setting is *not* persisted. + // LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat"); + // if(enable_voice) + // { + // const BOOL DO_NOT_PERSIST = FALSE; + // enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST); + // } + //} + // gLastRunVersion = gSavedSettings.getString("LastRunVersion"); @@ -5932,6 +5936,9 @@ void LLAppViewer::idleShutdown() && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME && !logoutRequestSent()) { + gViewerWindow->setShowProgress(TRUE, !gSavedSettings.getBOOL("FSDisableLogoutScreens")); + gViewerWindow->setProgressPercent(100.f); + gViewerWindow->setProgressString(LLTrans::getString("LoggingOut")); return; } @@ -6336,9 +6343,18 @@ void LLAppViewer::forceErrorBadMemoryAccess() void LLAppViewer::forceErrorInfiniteLoop() { LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL; + // Loop is intentionally complicated to fool basic loop detection + LLTimer timer_total; + LLTimer timer_expiry; + const S32 report_frequency = 10; + timer_expiry.setTimerExpirySec(report_frequency); while(true) { - ; + if (timer_expiry.hasExpired()) + { + LL_INFOS() << "Infinite loop time : " << timer_total.getElapsedSeconds() << LL_ENDL; + timer_expiry.setTimerExpirySec(report_frequency); + } } return; } @@ -6349,6 +6365,13 @@ void LLAppViewer::forceErrorSoftwareException() LLTHROW(LLException("User selected Force Software Exception")); } +void LLAppViewer::forceErrorOSSpecificException() +{ + // Virtual, MacOS only + const std::string exception_text = "User selected Force OS Exception, Not implemented on this OS"; + throw std::runtime_error(exception_text); +} + void LLAppViewer::forceErrorDriverCrash() { LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL; diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 63530c113a..95a443131d 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -154,6 +154,7 @@ public: virtual void forceErrorBadMemoryAccess(); virtual void forceErrorInfiniteLoop(); virtual void forceErrorSoftwareException(); + virtual void forceErrorOSSpecificException(); virtual void forceErrorDriverCrash(); // Wrongly merged back in by LL //virtual void forceErrorCoroutineCrash(); diff --git a/indra/newview/llappviewermacosx-objc.h b/indra/newview/llappviewermacosx-objc.h index c6dcec8e34..3721151aba 100644 --- a/indra/newview/llappviewermacosx-objc.h +++ b/indra/newview/llappviewermacosx-objc.h @@ -33,4 +33,6 @@ //Why? Because BOOL void launchApplication(const std::string* app_name, const std::vector* args); +void force_ns_sxeption(); + #endif // LL_LLAPPVIEWERMACOSX_OBJC_H diff --git a/indra/newview/llappviewermacosx-objc.mm b/indra/newview/llappviewermacosx-objc.mm index 17301847e8..5d9ca24db2 100644 --- a/indra/newview/llappviewermacosx-objc.mm +++ b/indra/newview/llappviewermacosx-objc.mm @@ -71,3 +71,9 @@ void launchApplication(const std::string* app_name, const std::vectormLODRadius; + F32 lod_radius = mRootVolp ? mRootVolp->mLODRadius : 0.f; for (std::vector::iterator it = volumes.begin(); it != volumes.end(); ++it) diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index f6e32ce260..b053094a5a 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -92,6 +92,8 @@ LLConversationItem::~LLConversationItem() { mAvatarNameCacheConnection.disconnect(); } + + clearChildren(); } //virtual @@ -256,6 +258,11 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde mConvType = CONV_SESSION_UNKNOWN; } +LLConversationItemSession::~LLConversationItemSession() +{ + clearAndDeparentModels(); +} + bool LLConversationItemSession::hasChildren() const { return getChildrenCount() > 0; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 4d93f6b7ef..f3e790e9a4 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -160,6 +160,7 @@ class LLConversationItemSession : public LLConversationItem public: LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); + ~LLConversationItemSession(); /*virtual*/ bool hasChildren() const; LLPointer getIcon() const { return NULL; } diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index d710eafb68..71d910d9be 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -971,7 +971,7 @@ void LLFastTimerView::printLineStats() { std::string legend_stat; bool first = true; - for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); + for(LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); it != LLTrace::end_block_timer_tree_df(); ++it) { @@ -993,7 +993,7 @@ void LLFastTimerView::printLineStats() std::string timer_stat; first = true; - for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); + for(LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); it != LLTrace::end_block_timer_tree_df(); ++it) { @@ -1070,7 +1070,7 @@ void LLFastTimerView::drawLineGraph() F32Seconds cur_max(0); U32 cur_max_calls = 0; - for(block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); + for(LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); it != LLTrace::end_block_timer_tree_df(); ++it) { @@ -1229,8 +1229,8 @@ void LLFastTimerView::drawLegend() #pragma GCC diagnostic ignored "-Wnonnull" #endif // - for (block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); - it != block_timer_tree_df_iterator_t(); + for (LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); + it != LLTrace::end_block_timer_tree_df(); ++it) // GCC12 warning: nonnull - probably bogus #if defined(__GNUC__) && (__GNUC__ >= 12) @@ -1355,8 +1355,8 @@ void LLFastTimerView::generateUniqueColors() #pragma GCC diagnostic ignored "-Wnonnull" #endif // - for (block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); - it != block_timer_tree_df_iterator_t(); + for (LLTrace::block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME); + it != LLTrace::end_block_timer_tree_df(); ++it) // GCC12 warning: nonnull - probably bogus #if defined(__GNUC__) && (__GNUC__ >= 12) diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index ceb7a188bd..178b8f81ab 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -446,6 +446,7 @@ public: if (item) { + LLFavoritesBarCtrl::sWaitingForCallabck = 0.f; LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); item->setComplete(TRUE); @@ -491,6 +492,9 @@ struct LLFavoritesSort } }; + +F64 LLFavoritesBarCtrl::sWaitingForCallabck = 0.f; + LLFavoritesBarCtrl::Params::Params() : image_drag_indication("image_drag_indication"), more_button("more_button"), @@ -510,7 +514,7 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) mShowDragMarker(FALSE), mLandingTab(NULL), mLastTab(NULL), - mTabsHighlightEnabled(TRUE), + mItemsListDirty(false), mUpdateDropDownItems(true), mRestoreOverflowMenu(false), mGetPrevItems(true), @@ -765,6 +769,9 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con int sortField = 0; LLPointer cb; + const F64 CALLBACK_WAIT_TIME = 30.f; + sWaitingForCallabck = LLTimer::getTotalSeconds() + CALLBACK_WAIT_TIME; + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) { @@ -838,16 +845,22 @@ void LLFavoritesBarCtrl::changed(U32 mask) LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID()); } - updateButtons(); - if (!mItemsChangedTimer.getStarted()) - { - mItemsChangedTimer.start(); - } - else - { - mItemsChangedTimer.reset(); - } - + if (sWaitingForCallabck < LLTimer::getTotalSeconds()) + { + updateButtons(); + if (!mItemsChangedTimer.getStarted()) + { + mItemsChangedTimer.start(); + } + else + { + mItemsChangedTimer.reset(); + } + } + else + { + mItemsListDirty = true; + } } } @@ -901,6 +914,18 @@ void LLFavoritesBarCtrl::draw() mItemsChangedTimer.start(); } + if (mItemsListDirty && sWaitingForCallabck < LLTimer::getTotalSeconds()) + { + updateButtons(); + if (!mItemsChangedTimer.getStarted()) + { + mItemsChangedTimer.start(); + } + else + { + mItemsChangedTimer.reset(); + } + } } const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() @@ -929,6 +954,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update) return; } + mItemsListDirty = false; mItems.clear(); if (!collectFavoriteItems(mItems)) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index a7cd5ba0a2..78e6246b84 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -56,6 +56,7 @@ public: protected: LLFavoritesBarCtrl(const Params&); friend class LLUICtrlFactory; + friend class LLItemCopiedCallback; public: virtual ~LLFavoritesBarCtrl(); @@ -87,7 +88,6 @@ protected: void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask); void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); - void onOverflowMenuItemMouseDown(LLUUID id, LLUICtrl* item, S32 x, S32 y, MASK mask); void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); void onEndDrag(); @@ -171,7 +171,8 @@ private: BOOL mStartDrag; LLInventoryModel::item_array_t mItems; - BOOL mTabsHighlightEnabled; + static F64 sWaitingForCallabck; + bool mItemsListDirty; S32 mMouseX; S32 mMouseY; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a070645bdf..9ac7c74746 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1782,6 +1782,7 @@ void LLFloaterIMContainer::setTimeNow(const LLUUID& session_id, const LLUUID& pa LLConversationItemSession* item = dynamic_cast(getSessionModel(session_id)); if (item) { + item->setTimeNow(participant_id); mConversationViewModel.requestSortAll(); mConversationsRoot->arrangeAll(); } diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 2031fc6a4e..2f3d75d123 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -619,6 +619,8 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, static LLCachedControl FSllOwnerSayToScriptDebugWindow(gSavedPerAccountSettings, "FSllOwnerSayToScriptDebugWindow"); if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG || (chat_msg.mChatType == CHAT_TYPE_OWNER && FSllOwnerSayToScriptDebugWindow)) { + if (LLFloater::isQuitRequested()) return; + // [FSllOwnerSayToScriptDebugWindow] Show llOwnerSays in the script debug window instead of local chat // if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE && chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ed1080eda9..bddec16b09 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -126,6 +126,7 @@ #include "llpresetsmanager.h" #include "llviewercontrol.h" #include "llpresetsmanager.h" +#include "llinventoryfunctions.h" #include "llsearchableui.h" #include "llperfstats.h" @@ -2839,25 +2840,6 @@ void LLFloaterPreference::onChangeMaturity() getChild("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT); } -std::string get_category_path(LLUUID cat_id) -{ - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - std::string localized_cat_name; - if (!LLTrans::findString(localized_cat_name, "InvFolder " + cat->getName())) - { - localized_cat_name = cat->getName(); - } - - if (cat->getParentUUID().notNull()) - { - return get_category_path(cat->getParentUUID()) + " > " + localized_cat_name; - } - else - { - return localized_cat_name; - } -} - std::string get_category_path(LLFolderType::EType cat_type) { LLUUID cat_id = gInventory.findUserDefinedCategoryUUIDForType(cat_type); diff --git a/indra/newview/llfloaterprofiletexture.cpp b/indra/newview/llfloaterprofiletexture.cpp index 94340eb36f..5fc0ea55ea 100644 --- a/indra/newview/llfloaterprofiletexture.cpp +++ b/indra/newview/llfloaterprofiletexture.cpp @@ -60,6 +60,8 @@ LLFloaterProfileTexture::~LLFloaterProfileTexture() mImage->forceActive(); // Make sure it can get discarded mImage = NULL; } + + LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList); } // virtual diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 0bdb7e3907..315f7e0c84 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -150,7 +150,7 @@ public: const LLUUID& invoice, const sparam_t& strings); - LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); + static LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); }; @@ -2987,11 +2987,12 @@ bool LLDispatchSetEstateAccess::operator()( return true; } +// static LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ) { LLSD idList = LLSD::emptyArray(); LLUUID id; - while(count--> 0) + while (count-- > 0 && it < end) { memcpy(id.mData, (*(it++)).data(), UUID_BYTES); idList.append(id); @@ -3005,7 +3006,7 @@ LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_ // strings[2] = str(num blocked) // strings[3] = str(num trusted) // strings[4] = str(num allowed) -// strings[8] = bin(uuid) ... +// strings[5] = bin(uuid) ... // ... bool LLDispatchSetEstateExperience::operator()( const LLDispatcher* dispatcher, @@ -3014,23 +3015,30 @@ bool LLDispatchSetEstateExperience::operator()( const sparam_t& strings) { LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); - if (!panel) return true; + if (!panel) + return true; + const sparam_t::size_type MIN_SIZE = 5; + if (strings.size() < MIN_SIZE) + return true; + + // Skip 2 parameters sparam_t::const_iterator it = strings.begin(); ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10); ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10); + // Read 3 parameters LLUUID id; S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10); S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10); S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10); LLSD ids = LLSD::emptyMap() - .with("blocked", getIDs(it, strings.end(), num_blocked)) - .with("trusted", getIDs(it + (num_blocked), strings.end(), num_trusted)) - .with("allowed", getIDs(it + (num_blocked+num_trusted), strings.end(), num_allowed)); + .with("blocked", getIDs(it, strings.end(), num_blocked)) + .with("trusted", getIDs(it + num_blocked, strings.end(), num_trusted)) + .with("allowed", getIDs(it + num_blocked + num_trusted, strings.end(), num_allowed)); - panel->processResponse(ids); + panel->processResponse(ids); return true; } diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index e744eba5ea..38477be80c 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -71,14 +71,14 @@ void LLFloaterSidePanelContainer::closeFloater(bool app_quitting) if (parent == this ) { LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); - if ( panel_appearance ) + if (panel_appearance) { LLPanelEditWearable *edit_wearable_ptr = panel_appearance->getWearable(); if (edit_wearable_ptr) { edit_wearable_ptr->onClose(); } - if(!app_quitting) + if (!app_quitting) { panel_appearance->showOutfitsInventoryPanel(); } @@ -133,11 +133,16 @@ LLFloater* LLFloaterSidePanelContainer::getTopmostInventoryFloater() LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) { LLView* view = findChildView(panel_name, true); - if (!view) return NULL; + if (!view) + return NULL; if (!getVisible()) { - openFloater(); + openFloater(); + } + else if (!hasFocus()) + { + setFocus(TRUE); } LLPanel* panel = NULL; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index f07ea7ee4f..dcee050953 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -243,8 +243,13 @@ void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::s } } } - - region->cacheFullUpdateGLTFOverride(cache); + // FIRE-33808 - Material Override Cache causes long delays + if(cache.mSides.size() > 0) + { + region->cacheFullUpdateGLTFOverride(cache); + LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL; + } + // } } diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index a5e701b831..fc648d38ba 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -907,6 +907,15 @@ void LLHUDNameTag::shift(const LLVector3& offset) mPositionAgent += offset; } +F32 LLHUDNameTag::getWorldHeight() const +{ + const LLViewerCamera* camera = LLViewerCamera::getInstance(); + F32 height_meters = mLastDistance * (F32)tan(camera->getView() / 2.f); + F32 height_pixels = camera->getViewHeightInPixels() / 2.f; + F32 meters_per_pixel = height_meters / height_pixels; + return mHeight * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY]; +} + //static void LLHUDNameTag::addPickable(std::set &pick_list) { diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 361e4d4f4b..592ab5518f 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -127,11 +127,12 @@ public: /*virtual*/ void markDead(); friend class LLHUDObject; /*virtual*/ F32 getDistance() const { return mLastDistance; } - S32 getLOD() { return mLOD; } - BOOL getVisible() { return mVisible; } + S32 getLOD() const { return mLOD; } + BOOL getVisible() const { return mVisible; } BOOL getHidden() const { return mHidden; } void setHidden( BOOL hide ) { mHidden = hide; } void shift(const LLVector3& offset); + F32 getWorldHeight() const; BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a& intersection, BOOL debug_render = FALSE); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e94aadfb85..ec523d7aff 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1929,7 +1929,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) } else if ("show_in_main_panel" == action) { - LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE); + LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true); return; } else if ("cut" == action) @@ -3719,7 +3719,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) // else if ("show_in_main_panel" == action) { - LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE); + LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true); return; } else if ("cut" == action) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 7b2164c99c..8ca337d4bf 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2282,6 +2282,24 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func); } +std::string get_category_path(LLUUID cat_id) +{ + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + std::string localized_cat_name; + if (!LLTrans::findString(localized_cat_name, "InvFolder " + cat->getName())) + { + localized_cat_name = cat->getName(); + } + + if (cat->getParentUUID().notNull()) + { + return get_category_path(cat->getParentUUID()) + " > " + localized_cat_name; + } + else + { + return localized_cat_name; + } +} // Returns true if the item can be moved to Current Outfit or any outfit folder. bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) { diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index ac3ab5eac2..6d77c8a48d 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -113,6 +113,7 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids); bool is_only_cats_selected(const uuid_vec_t& selected_uuids); bool is_only_items_selected(const uuid_vec_t& selected_uuids); +std::string get_category_path(LLUUID cat_id); bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); bool can_move_to_landmarks(LLInventoryItem* inv_item); diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 23129f7d44..cac859387c 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -240,7 +240,7 @@ void LLInventoryItemsList::refresh() case REFRESH_LIST_SORT: { // Filter, sort, rearrange and notify parent about shape changes - filterItems(); + filterItems(true, true); if (mAddedItems.size() == 0) { diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index ce41105f98..5b83298bb9 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -51,20 +51,20 @@ public: /** * Let list know items need to be refreshed in next doIdle() */ - void setNeedsRefresh(bool needs_refresh){ mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; } + void setNeedsRefresh(bool needs_refresh) { mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; } - U32 getNeedsRefresh(){ return mRefreshState; } + U32 getNeedsRefresh() { return mRefreshState; } /** * Sets the flag indicating that the list needs to be refreshed even if it is * not currently visible. */ - void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; } + void setForceRefresh(bool force_refresh) { mForceRefresh = force_refresh; } /** * If refreshes when invisible. */ - bool getForceRefresh(){ return mForceRefresh; } + bool getForceRefresh() { return mForceRefresh; } virtual bool selectItemByValue(const LLSD& value, bool select = true); diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index de30b31076..0893c9c04e 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -603,8 +603,12 @@ void LLInventoryAddItemByAssetObserver::changed(U32 mask) for (uuid_set_t::iterator it = added.begin(); it != added.end(); ++it) { LLInventoryItem *item = gInventory.getItem(*it); + if (!item) + { + continue; + } const LLUUID& asset_uuid = item->getAssetUUID(); - if (item && item->getUUID().notNull() && asset_uuid.notNull()) + if (item->getUUID().notNull() && asset_uuid.notNull()) { if (isAssetWatched(asset_uuid)) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index c71eb8573b..2662facf35 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -2154,62 +2154,68 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) } //static -void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id, BOOL use_main_panel, BOOL take_keyboard_focus, BOOL reset_filter) +void LLInventoryPanel::openInventoryPanelAndSetSelection(bool auto_open, const LLUUID& obj_id, + bool use_main_panel, bool take_keyboard_focus, bool reset_filter) { // Use correct inventory floater //LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); //sidepanel_inventory->showInventoryPanel(); // - bool in_inbox = (gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX))); + LLUUID cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); + bool in_inbox = gInventory.isObjectDescendentOf(obj_id, cat_id); bool show_inbox = gSavedSettings.getBOOL("FSShowInboxFolder"); // Optional hiding of Received Items folder aka Inbox - // FIRE-22167: Make "Show in Main View" work properly - //if (!in_inbox && (use_main_panel || !sidepanel_inventory->getMainInventoryPanel()->isRecentItemsPanelSelected())) //if (main_panel && !in_inbox) + //if (!in_inbox && use_main_panel) //{ // sidepanel_inventory->selectAllItemsPanel(); //} // - - LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater(); - if(!auto_open && inventory_floater && inventory_floater->getVisible()) + if (!auto_open) { - LLSidepanelInventory *inventory_panel = inventory_floater->findChild("main_panel"); - LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel(); - if(main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode()) + LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater(); + if (inventory_floater && inventory_floater->getVisible()) { - LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL; - main_panel->setGallerySelection(obj_id); - return; + LLSidepanelInventory *inventory_panel = inventory_floater->findChild("main_panel"); + LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel(); + if (main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode()) + { + LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL; + main_panel->setGallerySelection(obj_id); + return; + } } } - // Use correct inventory floater - //LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); - //if (main_inventory && main_inventory->isSingleFolderMode() - // && use_main_panel) + // Use correct inventory floater + //if (use_main_panel) //{ - // const LLInventoryObject *obj = gInventory.getObject(obj_id); - // if (obj) + // LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + // if (main_inventory && main_inventory->isSingleFolderMode()) // { - // LL_DEBUGS("Inventory") << "Opening main inventory panel for item" << obj_id << LL_ENDL; - // main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false); - // main_inventory->setGallerySelection(obj_id); - // return; + // const LLInventoryObject *obj = gInventory.getObject(obj_id); + // if (obj) + // { + // LL_DEBUGS("Inventory") << "Opening main inventory panel for item" << obj_id << LL_ENDL; + // main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false); + // main_inventory->setGallerySelection(obj_id); + // return; + // } // } //} - if (!inventory_floater) + LLFloater* inv_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater(); + if (!inv_floater) { - inventory_floater = LLFloaterReg::showInstance("inventory"); + inv_floater = LLFloaterReg::showInstance("inventory"); } - if (use_main_panel && inventory_floater) + if (use_main_panel && inv_floater) { - LLSidepanelInventory* inventory_panel = inventory_floater->findChild("main_panel"); + LLSidepanelInventory* inventory_panel = inv_floater->findChild("main_panel"); LLPanelMainInventory* main_inventory = inventory_panel->getMainInventoryPanel(); if (main_inventory && main_inventory->isSingleFolderMode()) { - const LLInventoryObject *obj = gInventory.getObject(obj_id); + const LLInventoryObject* obj = gInventory.getObject(obj_id); if (obj) { main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false); @@ -2221,7 +2227,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L // LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open); - if (active_panel) { LL_DEBUGS("Messaging", "Inventory") << "Highlighting" << obj_id << LL_ENDL; @@ -2237,10 +2242,8 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L // { LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); // Use correct inventory floater - LLInventoryPanel * inventory_panel = NULL; sidepanel_inventory->openInbox(); - inventory_panel = sidepanel_inventory->getInboxPanel(); - + LLInventoryPanel* inventory_panel = sidepanel_inventory->getInboxPanel(); if (inventory_panel) { inventory_panel->setSelection(obj_id, take_keyboard_focus); @@ -2273,7 +2276,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L void LLInventoryPanel::setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id) { - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) { diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 06f08fda5c..aefb8482cb 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -260,12 +260,12 @@ public: // "Auto_open" determines if we open an inventory panel if none are open. static LLInventoryPanel *getActiveInventoryPanel(BOOL auto_open = TRUE); - static void openInventoryPanelAndSetSelection(BOOL auto_open, + static void openInventoryPanelAndSetSelection(bool auto_open, const LLUUID& obj_id, - BOOL use_main_panel = FALSE, - BOOL take_keyboard_focus = TAKE_FOCUS_YES, - BOOL reset_filter = FALSE); - static void setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id); + bool use_main_panel = false, + bool take_keyboard_focus = true, + bool reset_filter = false); + static void setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id); void addItemID(const LLUUID& id, LLFolderViewItem* itemp); void removeItemID(const LLUUID& id); LLFolderViewItem* getItemByID(const LLUUID& id); diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index d1938d62f6..9e22d73845 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -1090,6 +1090,13 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename) LLImageDimensionsInfo image_info; if (!image_info.load(filename,codec)) { + LLSD args; + args["NAME"] = gDirUtilp->getBaseFileName(filename); + if (!image_info.getWarningName().empty()) + { + args["REASON"] = LLTrans::getString(image_info.getWarningName()); + } + LLNotificationsUtil::add("CannotUploadTexture", args); return false; } @@ -1105,6 +1112,7 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename) LLSD notif_args; notif_args["REASON"] = mImageLoadError; + notif_args["NAME"] = gDirUtilp->getBaseFileName(filename); LLNotificationsUtil::add("CannotUploadTexture", notif_args); return false; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a09ff3e984..6494d445fe 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -5754,7 +5754,7 @@ void on_new_single_inventory_upload_complete( } else { - LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, server_response["new_inventory_item"].asUUID(), TRUE, TAKE_FOCUS_NO, TRUE); + LLInventoryPanel::openInventoryPanelAndSetSelection(true, server_response["new_inventory_item"].asUUID(), true, false, true); } // restore keyboard focus diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index fde68b1db5..afa5fcda9d 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -311,7 +311,7 @@ void LLModelPreview::updateDimentionsAndOffsets() { accounted.insert(instance.mModel); - //update instance skin info for each lods pelvisZoffset + // update instance skin info for each lods pelvisZoffset for (int j = 0; jsecond.begin(); model_iter != iter->second.end();) - { //for each instance with said transform applied + { // for each instance with said transform applied LLModelInstance instance = *model_iter++; LLModel* base_model = instance.mModel; @@ -804,7 +805,7 @@ void LLModelPreview::rebuildUploadData() // || getLoadState() == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION) { - // This is only valid for these two error types because they are + // This is only valid for these two error types because they are // only used inside rebuildUploadData() and updateStatusMessages() // updateStatusMessages() is called after rebuildUploadData() setLoadState(LLModelLoader::DONE); @@ -1049,7 +1050,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable // it tends to force the UI into strange checkbox options // which cannot be altered. - //only try to load from slm if viewer is configured to do so and this is the + //only try to load from slm if viewer is configured to do so and this is the //initial model load (not an LoD or physics shape) mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty(); } @@ -1168,12 +1169,13 @@ void LLModelPreview::clearIncompatible(S32 lod) // Check if already started bool subscribe_for_generation = mLodsQuery.empty(); - + // Remove previously scheduled work mLodsQuery.clear(); LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; - if (!fmp) return; + if (!fmp) + return; // Schedule new work for (S32 i = LLModel::LOD_HIGH; i >= 0; --i) @@ -2536,7 +2538,7 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target ll_aligned_free_16(output_indices); ll_aligned_free_16(shadow_indices); - + if (size_new_indices < 3) { // At least one triangle is needed @@ -2745,7 +2747,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS); } - + if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) { // Try sloppy variant if normal one failed to simplify model enough. diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index de988555c5..65ec38a41d 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -433,8 +433,7 @@ bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2) } void LLOutfitGallery::reArrangeRows(S32 row_diff) -{ - +{ std::vector buf_items = mItems; for (std::vector::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) { @@ -446,16 +445,24 @@ void LLOutfitGallery::reArrangeRows(S32 row_diff) } mHiddenItems.clear(); - mItemsInRow+= row_diff; + mItemsInRow += row_diff; updateGalleryWidth(); std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); - + + std::string cur_filter = getFilterSubString(); + LLStringUtil::toUpper(cur_filter); + for (std::vector::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) { - (*it)->setHidden(false); - applyFilter(*it,sFilterSubString); + std::string outfit_name = (*it)->getItemName(); + LLStringUtil::toUpper(outfit_name); + + bool hidden = (std::string::npos == outfit_name.find(cur_filter)); + (*it)->setHidden(hidden); + addToGallery(*it); } + updateMessageVisibility(); } @@ -725,9 +732,9 @@ LLOutfitGallery::~LLOutfitGallery() } } -void LLOutfitGallery::setFilterSubString(const std::string& string) +// virtual +void LLOutfitGallery::onFilterSubStringChanged(const std::string& new_string, const std::string& old_string) { - sFilterSubString = string; reArrangeRows(); } @@ -743,20 +750,6 @@ void LLOutfitGallery::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) } } -void LLOutfitGallery::applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring) -{ - if (!item) return; - - std::string outfit_name = item->getItemName(); - LLStringUtil::toUpper(outfit_name); - - std::string cur_filter = filter_substring; - LLStringUtil::toUpper(cur_filter); - - bool hidden = (std::string::npos == outfit_name.find(cur_filter)); - item->setHidden(hidden); -} - void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) { } @@ -904,11 +897,11 @@ bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id) void LLOutfitGallery::updateMessageVisibility() { - if(mItems.empty()) + if (mItems.empty()) { mMessageTextBox->setVisible(TRUE); mScrollPanel->setVisible(FALSE); - std::string message = sFilterSubString.empty()? getString("no_outfits_msg") : getString("no_matched_outfits_msg"); + std::string message = getString(getFilterSubString().empty() ? "no_outfits_msg" : "no_matched_outfits_msg"); mMessageTextBox->setValue(message); } else @@ -1101,8 +1094,11 @@ bool LLOutfitGalleryItem::openOutfitsContent() { outfit_list->setSelectedOutfitByUUID(mUUID); LLAccordionCtrlTab* tab = accordion->getSelectedTab(); - tab->showAndFocusHeader(); - return true; + if (tab) + { + tab->showAndFocusHeader(); + return true; + } } } } diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 9915752962..f2366e6494 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -90,7 +90,7 @@ public: void wearSelectedOutfit(); - /*virtual*/ void setFilterSubString(const std::string& string); + /*virtual*/ void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string); /*virtual*/ void getCurrentCategories(uuid_vec_t& vcur); /*virtual*/ void updateAddedCategory(LLUUID cat_id); @@ -117,8 +117,6 @@ protected: /*virtual*/ void onExpandAllFolders() {} /*virtual*/ LLOutfitListGearMenuBase* createGearMenu(); - void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring); - private: LLUUID getPhotoAssetId(const LLUUID& outfit_id); LLUUID getDefaultPhoto(); diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 08ed61aab2..b88fa87de2 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -201,7 +201,7 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id) list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1)); // Setting list refresh callback to apply filter on list change. - list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); + list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onRefreshComplete, this, _1)); list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); @@ -212,19 +212,17 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id) // Further list updates will be triggered by the category observer. list->updateList(cat_id); - // If filter is currently applied we store the initial tab state and - // open it to show matched items if any. - if (!sFilterSubString.empty()) + // If filter is currently applied we store the initial tab state. + if (!getFilterSubString().empty()) { tab->notifyChildren(LLSD().with("action", "store_state")); - tab->setDisplayChildren(true); // Setting mForceRefresh flag will make the list refresh its contents // even if it is not currently visible. This is required to apply the // filter to the newly added list. list->setForceRefresh(true); - list->setFilterSubString(sFilterSubString); + list->setFilterSubString(getFilterSubString(), false); } } @@ -383,14 +381,6 @@ void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) } } -// virtual -void LLOutfitsList::setFilterSubString(const std::string& string) -{ - applyFilter(string); - - sFilterSubString = string; -} - // virtual bool LLOutfitListBase::isActionEnabled(const LLSD& userdata) { @@ -564,9 +554,9 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID } } -void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) +void LLOutfitsList::onRefreshComplete(LLUICtrl* ctrl) { - if (!ctrl || sFilterSubString.empty()) + if (!ctrl || getFilterSubString().empty()) return; for (outfits_map_t::iterator @@ -580,57 +570,50 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) LLWearableItemsList* list = dynamic_cast(tab->getAccordionView()); if (list != ctrl) continue; - applyFilterToTab(iter->first, tab, sFilterSubString); + applyFilterToTab(iter->first, tab, getFilterSubString()); } } -void LLOutfitsList::applyFilter(const std::string& new_filter_substring) +// virtual +void LLOutfitsList::onFilterSubStringChanged(const std::string& new_string, const std::string& old_string) { - mAccordion->setFilterSubString(new_filter_substring); + mAccordion->setFilterSubString(new_string); - for (outfits_map_t::iterator - iter = mOutfitsMap.begin(), - iter_end = mOutfitsMap.end(); - iter != iter_end; ++iter) + outfits_map_t::iterator iter = mOutfitsMap.begin(), iter_end = mOutfitsMap.end(); + while (iter != iter_end) { - LLAccordionCtrlTab* tab = iter->second; + const LLUUID& category_id = iter->first; + LLAccordionCtrlTab* tab = iter++->second; if (!tab) continue; - bool more_restrictive = sFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, sFilterSubString.size()).compare(sFilterSubString); - - // Restore tab visibility in case of less restrictive filter - // to compare it with updated string if it was previously hidden. - if (!more_restrictive) - { - tab->setVisible(TRUE); - } - LLWearableItemsList* list = dynamic_cast(tab->getAccordionView()); if (list) { - list->setFilterSubString(new_filter_substring); + list->setFilterSubString(new_string, tab->getDisplayChildren()); } - if(sFilterSubString.empty() && !new_filter_substring.empty()) + if (old_string.empty()) { - //store accordion tab state when filter is not empty - tab->notifyChildren(LLSD().with("action","store_state")); + // Store accordion tab state when filter is not empty + tab->notifyChildren(LLSD().with("action", "store_state")); } - if (!new_filter_substring.empty()) + if (!new_string.empty()) { - applyFilterToTab(iter->first, tab, new_filter_substring); + applyFilterToTab(category_id, tab, new_string); } else { - // restore tab title when filter is empty + tab->setVisible(TRUE); + + // Restore tab title when filter is empty tab->setTitle(tab->getTitle()); - //restore accordion state after all those accodrion tab manipulations - tab->notifyChildren(LLSD().with("action","restore_state")); + // Restore accordion state after all those accodrion tab manipulations + tab->notifyChildren(LLSD().with("action", "restore_state")); // Try restoring the tab selection. - restoreOutfitSelection(tab, iter->first); + restoreOutfitSelection(tab, category_id); } } @@ -656,11 +639,11 @@ void LLOutfitsList::applyFilterToTab( if (std::string::npos == title.find(cur_filter)) { - // hide tab if its title doesn't pass filter - // and it has no visible items + // Hide tab if its title doesn't pass filter + // and it has no matched items tab->setVisible(list->hasMatchedItems()); - // remove title highlighting because it might + // Remove title highlighting because it might // have been previously highlighted by less restrictive filter tab->setTitle(tab->getTitle()); @@ -672,18 +655,6 @@ void LLOutfitsList::applyFilterToTab( // Try restoring the tab selection. restoreOutfitSelection(tab, category_id); } - - if (tab->getVisible()) - { - // Open tab if it has passed the filter. - tab->setDisplayChildren(true); - } - else - { - // Set force refresh flag to refresh not visible list - // when some changes occur in it. - list->setForceRefresh(true); - } } bool LLOutfitsList::canWearSelected() @@ -768,11 +739,10 @@ void LLOutfitsList::onCOFChanged() // These links UUIDs are not the same UUIDs that we have in each wearable items list. // So we collect base items' UUIDs to find them or links that point to them in wearable // items lists and update their worn state there. - for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); - iter != item_array.end(); - ++iter) + LLInventoryModel::item_array_t::const_iterator array_iter = item_array.begin(), array_end = item_array.end(); + while (array_iter < array_end) { - vnew.push_back((*iter)->getLinkedUUID()); + vnew.push_back((*(array_iter++))->getLinkedUUID()); } // We need to update only items that were added or removed from COF. @@ -781,20 +751,20 @@ void LLOutfitsList::onCOFChanged() // Store the ids of items currently linked from COF. mCOFLinkedItems = vnew; - for (outfits_map_t::iterator iter = mOutfitsMap.begin(); - iter != mOutfitsMap.end(); - ++iter) + // Append removed ids to added ids because we should update all of them. + vadded.reserve(vadded.size() + vremoved.size()); + vadded.insert(vadded.end(), vremoved.begin(), vremoved.end()); + vremoved.clear(); + + outfits_map_t::iterator map_iter = mOutfitsMap.begin(), map_end = mOutfitsMap.end(); + while (map_iter != map_end) { - LLAccordionCtrlTab* tab = iter->second; + LLAccordionCtrlTab* tab = (map_iter++)->second; if (!tab) continue; LLWearableItemsList* list = dynamic_cast(tab->getAccordionView()); if (!list) continue; - // Append removed ids to added ids because we should update all of them. - vadded.reserve(vadded.size() + vremoved.size()); - vadded.insert(vadded.end(), vremoved.begin(), vremoved.end()); - // Every list updates the labels of changed items or // the links that point to these items. list->updateChangedItems(vadded); @@ -906,7 +876,6 @@ void LLOutfitListBase::onOpen(const LLSD& info) // arrive. category->fetch(); refreshList(outfits); - highlightBaseOutfit(); mIsInitialized = true; } @@ -914,12 +883,14 @@ void LLOutfitListBase::onOpen(const LLSD& info) void LLOutfitListBase::refreshList(const LLUUID& category_id) { + bool wasNull = mRefreshListState.CategoryUUID.isNull(); + mRefreshListState.CategoryUUID.setNull(); + LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; // Collect all sub-categories of a given category. // FIRE-6958/VWR-2862; Make sure to only collect folders of type FT_OUTFIT - class ndOutfitsCollector: public LLIsType { public: @@ -941,8 +912,8 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) // LLIsType is_category(LLAssetType::AT_CATEGORY); ndOutfitsCollector is_category; - // + gInventory.collectDescendentsIf( category_id, cat_array, @@ -950,22 +921,41 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) LLInventoryModel::EXCLUDE_TRASH, is_category); - uuid_vec_t vadded; - uuid_vec_t vremoved; + // Memorize item names for each UUID + std::map names; + for (const LLPointer& cat : cat_array) + { + names.emplace(std::make_pair(cat->getUUID(), cat->getName())); + } + + // Fill added and removed items vectors. + mRefreshListState.Added.clear(); + mRefreshListState.Removed.clear(); + computeDifference(cat_array, mRefreshListState.Added, mRefreshListState.Removed); + // Sort added items vector by item name. + std::sort(mRefreshListState.Added.begin(), mRefreshListState.Added.end(), + [names](const LLUUID& a, const LLUUID& b) + { + return LLStringUtil::compareDict(names.at(a), names.at(b)) < 0; + }); + // Initialize iterators for added and removed items vectors. + mRefreshListState.AddedIterator = mRefreshListState.Added.begin(); + mRefreshListState.RemovedIterator = mRefreshListState.Removed.begin(); + + LL_INFOS() << "added: " << mRefreshListState.Added.size() << + ", removed: " << mRefreshListState.Removed.size() << + ", changed: " << gInventory.getChangedIDs().size() << + LL_ENDL; + + mRefreshListState.CategoryUUID = category_id; + if (wasNull) + { + gIdleCallbacks.addFunction(onIdle, this); + } - // Create added and removed items vectors. - computeDifference(cat_array, vadded, vremoved); - // FIRE-6958/VWR-2862; Handle large amounts of outfits, write a least a warning into the logs. - if( vadded.size() > 128 ) - LL_WARNS() << "Large amount of outfits found: " << vadded.size() << " this may cause hangs and disconnects" << LL_ENDL; - - U32 nCap = gSavedSettings.getU32( "FSDisplaySavedOutfitsCap" ); - if( nCap && nCap < vadded.size() ) - { - vadded.resize( nCap ); - LL_WARNS() << "Capped outfits to " << nCap << " due to debug setting FSDisplaySavedOutfitsCap" << LL_ENDL; - } + if (mRefreshListState.Added.size() > 128) + LL_WARNS() << "Large amount of outfits found: " << mRefreshListState.Added.size() << " this may cause hangs and disconnects" << LL_ENDL; // // FIRE-12939: Add outfit count to outfits list @@ -976,25 +966,53 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) getChild("OutfitcountText")->setTextArg("COUNT", count_string); } // +} + +// static +void LLOutfitListBase::onIdle(void* userdata) +{ + LLOutfitListBase* self = (LLOutfitListBase*)userdata; + + self->onIdleRefreshList(); +} + +void LLOutfitListBase::onIdleRefreshList() +{ + if (mRefreshListState.CategoryUUID.isNull()) + return; + + const F64 MAX_TIME = 0.05f; + F64 curent_time = LLTimer::getTotalSeconds(); + const F64 end_time = curent_time + MAX_TIME; // Handle added tabs. - for (uuid_vec_t::const_iterator iter = vadded.begin(); - iter != vadded.end(); - ++iter) + while (mRefreshListState.AddedIterator < mRefreshListState.Added.end()) { - const LLUUID cat_id = (*iter); + const LLUUID cat_id = (*mRefreshListState.AddedIterator++); updateAddedCategory(cat_id); + + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; } + mRefreshListState.Added.clear(); + mRefreshListState.AddedIterator = mRefreshListState.Added.end(); // We called mAccordion->addCollapsibleCtrl with false as second paramter and did not let it arrange itself each time. Do this here after all is said and done. arrange(); // Handle removed tabs. - for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + while (mRefreshListState.RemovedIterator < mRefreshListState.Removed.end()) { - const LLUUID cat_id = (*iter); + const LLUUID cat_id = (*mRefreshListState.RemovedIterator++); updateRemovedCategory(cat_id); + + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; } + mRefreshListState.Removed.clear(); + mRefreshListState.RemovedIterator = mRefreshListState.Removed.end(); // Get changed items from inventory model and update outfit tabs // which might have been renamed. @@ -1007,9 +1025,9 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) if (!cat) { LLInventoryObject* obj = gInventory.getObject(*items_iter); - if(!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) + if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) { - return; + break; } cat = (LLViewerInventoryCategory*)obj; } @@ -1019,6 +1037,12 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) } sortOutfits(); + highlightBaseOutfit(); + + gIdleCallbacks.deleteFunction(onIdle, this); + mRefreshListState.CategoryUUID.setNull(); + + LL_INFOS() << "done" << LL_ENDL; } void LLOutfitListBase::computeDifference( @@ -1055,7 +1079,6 @@ void LLOutfitListBase::highlightBaseOutfit() mHighlightedOutfitUUID = base_id; onHighlightBaseOutfit(base_id, prev_id); } - } void LLOutfitListBase::removeSelected() diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index b85ee81c78..53bbfddef7 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -121,8 +121,20 @@ protected: void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0; + static void onIdle(void* userdata); + void onIdleRefreshList(); + + struct + { + LLUUID CategoryUUID; + uuid_vec_t Added; + uuid_vec_t Removed; + uuid_vec_t::const_iterator AddedIterator; + uuid_vec_t::const_iterator RemovedIterator; + } mRefreshListState; + bool mIsInitialized; - LLInventoryCategoriesObserver* mCategoriesObserver; + LLInventoryCategoriesObserver* mCategoriesObserver; LLUUID mSelectedOutfitUUID; // id of currently highlited outfit LLUUID mHighlightedOutfitUUID; @@ -232,7 +244,7 @@ public: //void performAction(std::string action); - /*virtual*/ void setFilterSubString(const std::string& string); + /*virtual*/ void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string); /*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const; @@ -303,12 +315,7 @@ private: * Called upon list refresh event to update tab visibility depending on * the results of applying filter to the title and list items of the tab. */ - void onFilteredWearableItemsListRefresh(LLUICtrl* ctrl); - - /** - * Highlights filtered items and hides tabs which haven't passed filter. - */ - void applyFilter(const std::string& new_filter_substring); + void onRefreshComplete(LLUICtrl* ctrl); /** * Applies filter to the given tab diff --git a/indra/newview/llpanelappearancetab.cpp b/indra/newview/llpanelappearancetab.cpp index fdb331163b..81a6cf082a 100644 --- a/indra/newview/llpanelappearancetab.cpp +++ b/indra/newview/llpanelappearancetab.cpp @@ -28,7 +28,6 @@ #include "llpanelappearancetab.h" - #include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llviewerinventory.h" @@ -37,7 +36,31 @@ #include "rlvhandler.h" // [/RLVa:KB] -//virtual +std::string LLPanelAppearanceTab::sRecentFilterSubString; + +void LLPanelAppearanceTab::setFilterSubString(const std::string& new_string) +{ + if (new_string != mFilterSubString) + { + std::string old_string = mFilterSubString; + mFilterSubString = new_string; + onFilterSubStringChanged(mFilterSubString, old_string); + } + + sRecentFilterSubString = new_string; +} + +void LLPanelAppearanceTab::checkFilterSubString() +{ + if (sRecentFilterSubString != mFilterSubString) + { + std::string old_string = mFilterSubString; + mFilterSubString = sRecentFilterSubString; + onFilterSubStringChanged(mFilterSubString, old_string); + } +} + +// virtual bool LLPanelAppearanceTab::canTakeOffSelected() { uuid_vec_t selected_uuids; diff --git a/indra/newview/llpanelappearancetab.h b/indra/newview/llpanelappearancetab.h index 2ed6b00497..e81394dd3c 100644 --- a/indra/newview/llpanelappearancetab.h +++ b/indra/newview/llpanelappearancetab.h @@ -35,13 +35,17 @@ public: LLPanelAppearanceTab() : LLPanel() {} virtual ~LLPanelAppearanceTab() {} - virtual void setFilterSubString(const std::string& string) = 0; + void setFilterSubString(const std::string& new_string); + + void checkFilterSubString(); + + virtual void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string) = 0; virtual bool isActionEnabled(const LLSD& userdata) = 0; virtual void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const {} - static const std::string& getFilterSubString() { return sFilterSubString; } + const std::string& getFilterSubString() { return mFilterSubString; } protected: @@ -50,7 +54,10 @@ protected: */ bool canTakeOffSelected(); - static std::string sFilterSubString; +private: + std::string mFilterSubString; + + static std::string sRecentFilterSubString; }; #endif //LL_LLPANELAPPEARANCETAB_H diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 05838e8af3..739719a73c 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -102,7 +102,7 @@ enum ESubpart { SUBPART_SKIRT, SUBPART_ALPHA, SUBPART_TATTOO, - SUBPART_UNIVERSAL, + SUBPART_UNIVERSAL, SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, @@ -125,7 +125,7 @@ class LLEditWearableDictionary : public LLSingleton //-------------------------------------------------------------------- LLSINGLETON(LLEditWearableDictionary); virtual ~LLEditWearableDictionary(); - + //-------------------------------------------------------------------- // Wearable Types //-------------------------------------------------------------------- @@ -219,7 +219,6 @@ public: LLEditWearableDictionary::LLEditWearableDictionary() { - } //virtual @@ -232,23 +231,23 @@ LLEditWearableDictionary::Wearables::Wearables() // note the subpart that is listed first is treated as "default", regardless of what order is in enum. // Please match the order presented in XUI. -Nyx // this will affect what camera angle is shown when first editing a wearable - addEntry(LLWearableType::WT_SHAPE, new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS})); - addEntry(LLWearableType::WT_SKIN, new WearableEntry(LLWearableType::WT_SKIN,"edit_skin_title","skin_desc_text", texture_vec_t(), texture_vec_t{TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT}, subpart_vec_t{SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL})); - addEntry(LLWearableType::WT_HAIR, new WearableEntry(LLWearableType::WT_HAIR,"edit_hair_title","hair_desc_text", texture_vec_t(), texture_vec_t{TEX_HAIR}, subpart_vec_t{SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL})); - addEntry(LLWearableType::WT_EYES, new WearableEntry(LLWearableType::WT_EYES,"edit_eyes_title","eyes_desc_text", texture_vec_t(), texture_vec_t{TEX_EYES_IRIS}, subpart_vec_t{SUBPART_EYES})); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry(LLWearableType::WT_SHIRT,"edit_shirt_title","shirt_desc_text", texture_vec_t{TEX_UPPER_SHIRT}, texture_vec_t{TEX_UPPER_SHIRT}, subpart_vec_t{SUBPART_SHIRT})); - addEntry(LLWearableType::WT_PANTS, new WearableEntry(LLWearableType::WT_PANTS,"edit_pants_title","pants_desc_text", texture_vec_t{TEX_LOWER_PANTS}, texture_vec_t{TEX_LOWER_PANTS}, subpart_vec_t{SUBPART_PANTS})); - addEntry(LLWearableType::WT_SHOES, new WearableEntry(LLWearableType::WT_SHOES,"edit_shoes_title","shoes_desc_text", texture_vec_t{TEX_LOWER_SHOES}, texture_vec_t{TEX_LOWER_SHOES}, subpart_vec_t{SUBPART_SHOES})); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry(LLWearableType::WT_SOCKS,"edit_socks_title","socks_desc_text", texture_vec_t{TEX_LOWER_SOCKS}, texture_vec_t{TEX_LOWER_SOCKS}, subpart_vec_t{SUBPART_SOCKS})); + addEntry(LLWearableType::WT_SHAPE, new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS})); + addEntry(LLWearableType::WT_SKIN, new WearableEntry(LLWearableType::WT_SKIN,"edit_skin_title","skin_desc_text", texture_vec_t(), texture_vec_t{TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT}, subpart_vec_t{SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL})); + addEntry(LLWearableType::WT_HAIR, new WearableEntry(LLWearableType::WT_HAIR,"edit_hair_title","hair_desc_text", texture_vec_t(), texture_vec_t{TEX_HAIR}, subpart_vec_t{SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL})); + addEntry(LLWearableType::WT_EYES, new WearableEntry(LLWearableType::WT_EYES,"edit_eyes_title","eyes_desc_text", texture_vec_t(), texture_vec_t{TEX_EYES_IRIS}, subpart_vec_t{SUBPART_EYES})); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry(LLWearableType::WT_SHIRT,"edit_shirt_title","shirt_desc_text", texture_vec_t{TEX_UPPER_SHIRT}, texture_vec_t{TEX_UPPER_SHIRT}, subpart_vec_t{SUBPART_SHIRT})); + addEntry(LLWearableType::WT_PANTS, new WearableEntry(LLWearableType::WT_PANTS,"edit_pants_title","pants_desc_text", texture_vec_t{TEX_LOWER_PANTS}, texture_vec_t{TEX_LOWER_PANTS}, subpart_vec_t{SUBPART_PANTS})); + addEntry(LLWearableType::WT_SHOES, new WearableEntry(LLWearableType::WT_SHOES,"edit_shoes_title","shoes_desc_text", texture_vec_t{TEX_LOWER_SHOES}, texture_vec_t{TEX_LOWER_SHOES}, subpart_vec_t{SUBPART_SHOES})); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry(LLWearableType::WT_SOCKS,"edit_socks_title","socks_desc_text", texture_vec_t{TEX_LOWER_SOCKS}, texture_vec_t{TEX_LOWER_SOCKS}, subpart_vec_t{SUBPART_SOCKS})); addEntry(LLWearableType::WT_JACKET, new WearableEntry(LLWearableType::WT_JACKET,"edit_jacket_title","jacket_desc_text", texture_vec_t{TEX_UPPER_JACKET}, texture_vec_t{TEX_UPPER_JACKET, TEX_LOWER_JACKET}, subpart_vec_t{SUBPART_JACKET})); addEntry(LLWearableType::WT_GLOVES, new WearableEntry(LLWearableType::WT_GLOVES,"edit_gloves_title","gloves_desc_text", texture_vec_t{TEX_UPPER_GLOVES}, texture_vec_t{TEX_UPPER_GLOVES}, subpart_vec_t{SUBPART_GLOVES})); addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(LLWearableType::WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text", texture_vec_t{TEX_UPPER_UNDERSHIRT}, texture_vec_t{TEX_UPPER_UNDERSHIRT}, subpart_vec_t{SUBPART_UNDERSHIRT})); addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(LLWearableType::WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text", texture_vec_t{TEX_LOWER_UNDERPANTS}, texture_vec_t{TEX_LOWER_UNDERPANTS}, subpart_vec_t{SUBPART_UNDERPANTS})); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title","skirt_desc_text", texture_vec_t{TEX_SKIRT}, texture_vec_t{TEX_SKIRT}, subpart_vec_t{SUBPART_SKIRT})); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title","alpha_desc_text", texture_vec_t(), texture_vec_t{TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA}, subpart_vec_t{SUBPART_ALPHA})); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title","skirt_desc_text", texture_vec_t{TEX_SKIRT}, texture_vec_t{TEX_SKIRT}, subpart_vec_t{SUBPART_SKIRT})); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title","alpha_desc_text", texture_vec_t(), texture_vec_t{TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA}, subpart_vec_t{SUBPART_ALPHA})); addEntry(LLWearableType::WT_TATTOO, new WearableEntry(LLWearableType::WT_TATTOO,"edit_tattoo_title","tattoo_desc_text", texture_vec_t{TEX_HEAD_TATTOO}, texture_vec_t{TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO}, subpart_vec_t{SUBPART_TATTOO})); - addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(LLWearableType::WT_UNIVERSAL, "edit_universal_title", "universal_desc_text", texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO }, texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO, TEX_UPPER_UNIVERSAL_TATTOO, TEX_LOWER_UNIVERSAL_TATTOO, TEX_SKIRT_TATTOO, TEX_HAIR_TATTOO, TEX_EYES_TATTOO, TEX_LEFT_ARM_TATTOO, TEX_LEFT_LEG_TATTOO, TEX_AUX1_TATTOO, TEX_AUX2_TATTOO, TEX_AUX3_TATTOO }, subpart_vec_t{ SUBPART_UNIVERSAL })); - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(LLWearableType::WT_PHYSICS,"edit_physics_title","physics_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED})); + addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(LLWearableType::WT_UNIVERSAL, "edit_universal_title", "universal_desc_text", texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO }, texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO, TEX_UPPER_UNIVERSAL_TATTOO, TEX_LOWER_UNIVERSAL_TATTOO, TEX_SKIRT_TATTOO, TEX_HAIR_TATTOO, TEX_EYES_TATTOO, TEX_LEFT_ARM_TATTOO, TEX_LEFT_LEG_TATTOO, TEX_AUX1_TATTOO, TEX_AUX2_TATTOO, TEX_AUX3_TATTOO }, subpart_vec_t{ SUBPART_UNIVERSAL })); + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(LLWearableType::WT_PHYSICS, "edit_physics_title", "physics_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{ SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED })); } LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType type, @@ -264,60 +263,68 @@ LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType typ mSubparts(subparts), mColorSwatchCtrls(color_swatches), mTextureCtrls(texture_pickers) -{} +{ +} LLEditWearableDictionary::Subparts::Subparts() { - addEntry(SUBPART_SHAPE_WHOLE, new SubpartEntry(SUBPART_SHAPE_WHOLE, "mPelvis", "shape_body","shape_body_param_list", "shape_body_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_HEAD, new SubpartEntry(SUBPART_SHAPE_HEAD, "mHead", "shape_head", "shape_head_param_list", "shape_head_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_EYES, new SubpartEntry(SUBPART_SHAPE_EYES, "mHead", "shape_eyes", "shape_eyes_param_list", "shape_eyes_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_EARS, new SubpartEntry(SUBPART_SHAPE_EARS, "mHead", "shape_ears", "shape_ears_param_list", "shape_ears_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_NOSE, new SubpartEntry(SUBPART_SHAPE_NOSE, "mHead", "shape_nose", "shape_nose_param_list", "shape_nose_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_MOUTH, new SubpartEntry(SUBPART_SHAPE_MOUTH, "mHead", "shape_mouth", "shape_mouth_param_list", "shape_mouth_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_CHIN, new SubpartEntry(SUBPART_SHAPE_CHIN, "mHead", "shape_chin", "shape_chin_param_list", "shape_chin_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_TORSO, new SubpartEntry(SUBPART_SHAPE_TORSO, "mTorso", "shape_torso", "shape_torso_param_list", "shape_torso_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); - addEntry(SUBPART_SHAPE_LEGS, new SubpartEntry(SUBPART_SHAPE_LEGS, "mPelvis", "shape_legs", "shape_legs_param_list", "shape_legs_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); + // WT_SHAPE + addEntry(SUBPART_SHAPE_WHOLE, new SubpartEntry(SUBPART_SHAPE_WHOLE, "mPelvis", "shape_body","shape_body_param_list", "shape_body_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_HEAD, new SubpartEntry(SUBPART_SHAPE_HEAD, "mHead", "shape_head", "shape_head_param_list", "shape_head_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_EYES, new SubpartEntry(SUBPART_SHAPE_EYES, "mHead", "shape_eyes", "shape_eyes_param_list", "shape_eyes_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_EARS, new SubpartEntry(SUBPART_SHAPE_EARS, "mHead", "shape_ears", "shape_ears_param_list", "shape_ears_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_NOSE, new SubpartEntry(SUBPART_SHAPE_NOSE, "mHead", "shape_nose", "shape_nose_param_list", "shape_nose_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_MOUTH, new SubpartEntry(SUBPART_SHAPE_MOUTH, "mHead", "shape_mouth", "shape_mouth_param_list", "shape_mouth_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_CHIN, new SubpartEntry(SUBPART_SHAPE_CHIN, "mHead", "shape_chin", "shape_chin_param_list", "shape_chin_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_TORSO, new SubpartEntry(SUBPART_SHAPE_TORSO, "mTorso", "shape_torso", "shape_torso_param_list", "shape_torso_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); + addEntry(SUBPART_SHAPE_LEGS, new SubpartEntry(SUBPART_SHAPE_LEGS, "mPelvis", "shape_legs", "shape_legs_param_list", "shape_legs_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); - addEntry(SUBPART_SKIN_COLOR, new SubpartEntry(SUBPART_SKIN_COLOR, "mHead", "skin_color", "skin_color_param_list", "skin_color_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + // WT_SKIN + addEntry(SUBPART_SKIN_COLOR, new SubpartEntry(SUBPART_SKIN_COLOR, "mHead", "skin_color", "skin_color_param_list", "skin_color_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SKIN_FACEDETAIL, new SubpartEntry(SUBPART_SKIN_FACEDETAIL, "mHead", "skin_facedetail", "skin_face_param_list", "skin_face_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SKIN_MAKEUP, new SubpartEntry(SUBPART_SKIN_MAKEUP, "mHead", "skin_makeup", "skin_makeup_param_list", "skin_makeup_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_SKIN_MAKEUP, new SubpartEntry(SUBPART_SKIN_MAKEUP, "mHead", "skin_makeup", "skin_makeup_param_list", "skin_makeup_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SKIN_BODYDETAIL, new SubpartEntry(SUBPART_SKIN_BODYDETAIL, "mPelvis", "skin_bodydetail", "skin_body_param_list", "skin_body_tab", LLVector3d(0.f, 0.f, -0.2f), LLVector3d(-2.5f, 0.5f, 0.5f),SEX_BOTH)); - addEntry(SUBPART_HAIR_COLOR, new SubpartEntry(SUBPART_HAIR_COLOR, "mHead", "hair_color", "hair_color_param_list", "hair_color_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH)); - addEntry(SUBPART_HAIR_STYLE, new SubpartEntry(SUBPART_HAIR_STYLE, "mHead", "hair_style", "hair_style_param_list", "hair_style_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH)); - addEntry(SUBPART_HAIR_EYEBROWS, new SubpartEntry(SUBPART_HAIR_EYEBROWS, "mHead", "hair_eyebrows", "hair_eyebrows_param_list", "hair_eyebrows_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_HAIR_FACIAL, new SubpartEntry(SUBPART_HAIR_FACIAL, "mHead", "hair_facial", "hair_facial_param_list", "hair_facial_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_MALE)); + // WT_HAIR + addEntry(SUBPART_HAIR_COLOR, new SubpartEntry(SUBPART_HAIR_COLOR, "mHead", "hair_color", "hair_color_param_list", "hair_color_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH)); + addEntry(SUBPART_HAIR_STYLE, new SubpartEntry(SUBPART_HAIR_STYLE, "mHead", "hair_style", "hair_style_param_list", "hair_style_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f), SEX_BOTH)); + addEntry(SUBPART_HAIR_EYEBROWS, new SubpartEntry(SUBPART_HAIR_EYEBROWS, "mHead", "hair_eyebrows", "hair_eyebrows_param_list", "hair_eyebrows_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + addEntry(SUBPART_HAIR_FACIAL, new SubpartEntry(SUBPART_HAIR_FACIAL, "mHead", "hair_facial", "hair_facial_param_list", "hair_facial_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_MALE)); - addEntry(SUBPART_EYES, new SubpartEntry(SUBPART_EYES, "mHead", "eyes", "eyes_main_param_list", "eyes_main_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); + // WT_EYES + addEntry(SUBPART_EYES, new SubpartEntry(SUBPART_EYES, "mHead", "eyes", "eyes_main_param_list", "eyes_main_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); - addEntry(SUBPART_SHIRT, new SubpartEntry(SUBPART_SHIRT, "mTorso", "shirt", "shirt_main_param_list", "shirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); - addEntry(SUBPART_PANTS, new SubpartEntry(SUBPART_PANTS, "mPelvis", "pants", "pants_main_param_list", "pants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); - addEntry(SUBPART_SHOES, new SubpartEntry(SUBPART_SHOES, "mPelvis", "shoes", "shoes_main_param_list", "shoes_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); - addEntry(SUBPART_SOCKS, new SubpartEntry(SUBPART_SOCKS, "mPelvis", "socks", "socks_main_param_list", "socks_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); - addEntry(SUBPART_JACKET, new SubpartEntry(SUBPART_JACKET, "mTorso", "jacket", "jacket_main_param_list", "jacket_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-2.f, 0.1f, 0.3f),SEX_BOTH)); - addEntry(SUBPART_SKIRT, new SubpartEntry(SUBPART_SKIRT, "mPelvis", "skirt", "skirt_main_param_list", "skirt_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); - addEntry(SUBPART_GLOVES, new SubpartEntry(SUBPART_GLOVES, "mTorso", "gloves", "gloves_main_param_list", "gloves_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-1.f, 0.15f, 0.f),SEX_BOTH)); - addEntry(SUBPART_UNDERSHIRT, new SubpartEntry(SUBPART_UNDERSHIRT, "mTorso", "undershirt", "undershirt_main_param_list", "undershirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); - addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); + // WT_SHIRT, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_UNDERPANTS, WT_SKIRT, WT_ALPHA, WT_TATTOO, WT_UNIVERSAL + addEntry(SUBPART_SHIRT, new SubpartEntry(SUBPART_SHIRT, "mTorso", "shirt", "shirt_main_param_list", "shirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); + addEntry(SUBPART_PANTS, new SubpartEntry(SUBPART_PANTS, "mPelvis", "pants", "pants_main_param_list", "pants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); + addEntry(SUBPART_SHOES, new SubpartEntry(SUBPART_SHOES, "mPelvis", "shoes", "shoes_main_param_list", "shoes_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); + addEntry(SUBPART_SOCKS, new SubpartEntry(SUBPART_SOCKS, "mPelvis", "socks", "socks_main_param_list", "socks_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); + addEntry(SUBPART_JACKET, new SubpartEntry(SUBPART_JACKET, "mTorso", "jacket", "jacket_main_param_list", "jacket_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-2.f, 0.1f, 0.3f),SEX_BOTH)); + addEntry(SUBPART_GLOVES, new SubpartEntry(SUBPART_GLOVES, "mTorso", "gloves", "gloves_main_param_list", "gloves_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-1.f, 0.15f, 0.f),SEX_BOTH)); + addEntry(SUBPART_UNDERSHIRT, new SubpartEntry(SUBPART_UNDERSHIRT, "mTorso", "undershirt", "undershirt_main_param_list", "undershirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); + addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); + addEntry(SUBPART_SKIRT, new SubpartEntry(SUBPART_SKIRT, "mPelvis", "skirt", "skirt_main_param_list", "skirt_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); // Alpha, tattoo and universal don't adhere to the usual panel layout and don't have a param list and main tab - //addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); - //addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); - //addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", "universal_main_param_list", "universal_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); - addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "", "", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); - addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "", "", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); - addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", "", "", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); + //addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); + //addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); + //addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", "universal_main_param_list", "universal_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); + addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "", "", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); + addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "", "", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); + addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", "", "", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); // - addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "physics_breasts_updown_param_list", "physics_breasts_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); - addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "physics_breasts_inout_param_list", "physics_breasts_inout_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); + + // WT_PHYSIC + addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "physics_breasts_updown_param_list", "physics_breasts_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); + addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "physics_breasts_inout_param_list", "physics_breasts_inout_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); addEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, "mTorso", "physics_breasts_leftright", "physics_breasts_leftright_param_list", "physics_breasts_leftright_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); // Fix XUI warning - //addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); - //addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); - addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); - addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); + //addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); + //addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); + addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); + addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); // - addEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, "mTorso", "physics_butt_leftright", "physics_butt_leftright_param_list", "physics_butt_leftright_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); - addEntry(SUBPART_PHYSICS_ADVANCED, new SubpartEntry(SUBPART_PHYSICS_ADVANCED, "mTorso", "physics_advanced", "physics_advanced_param_list", "physics_advanced_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); + addEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, "mTorso", "physics_butt_leftright", "physics_butt_leftright_param_list", "physics_butt_leftright_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); + addEntry(SUBPART_PHYSICS_ADVANCED, new SubpartEntry(SUBPART_PHYSICS_ADVANCED, "mTorso", "physics_advanced", "physics_advanced_param_list", "physics_advanced_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); } LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part, @@ -342,55 +349,55 @@ LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part, LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls() { - addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Color/Tint" )); - addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Color/Tint" )); - addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Color/Tint" )); - addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Color/Tint" )); - addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Color/Tint" )); - addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Color/Tint" )); - addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Color/Tint" )); - addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Color/Tint" )); - addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Color/Tint" )); - addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Color/Tint" )); - addEntry (TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint")); + addEntry(TEX_UPPER_SHIRT, new PickerControlEntry(TEX_UPPER_SHIRT, "Color/Tint")); + addEntry(TEX_LOWER_PANTS, new PickerControlEntry(TEX_LOWER_PANTS, "Color/Tint")); + addEntry(TEX_LOWER_SHOES, new PickerControlEntry(TEX_LOWER_SHOES, "Color/Tint")); + addEntry(TEX_LOWER_SOCKS, new PickerControlEntry(TEX_LOWER_SOCKS, "Color/Tint")); + addEntry(TEX_UPPER_JACKET, new PickerControlEntry(TEX_UPPER_JACKET, "Color/Tint")); + addEntry(TEX_SKIRT, new PickerControlEntry(TEX_SKIRT, "Color/Tint")); + addEntry(TEX_UPPER_GLOVES, new PickerControlEntry(TEX_UPPER_GLOVES, "Color/Tint")); + addEntry(TEX_UPPER_UNDERSHIRT, new PickerControlEntry(TEX_UPPER_UNDERSHIRT, "Color/Tint")); + addEntry(TEX_LOWER_UNDERPANTS, new PickerControlEntry(TEX_LOWER_UNDERPANTS, "Color/Tint")); + addEntry(TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Color/Tint")); + addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint")); } LLEditWearableDictionary::TextureCtrls::TextureCtrls() { - addEntry ( TEX_HEAD_BODYPAINT, new PickerControlEntry (TEX_HEAD_BODYPAINT, "Head", LLUUID::null, TRUE )); - addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Body", LLUUID::null, TRUE )); - addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Body", LLUUID::null, TRUE )); - addEntry ( TEX_HAIR, new PickerControlEntry (TEX_HAIR, "Texture", LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ), FALSE )); - addEntry ( TEX_EYES_IRIS, new PickerControlEntry (TEX_EYES_IRIS, "Iris", LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ), FALSE )); - addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ), FALSE )); - addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ), FALSE )); - addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ), FALSE )); - addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ), FALSE )); - addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Upper Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); - addEntry ( TEX_LOWER_JACKET, new PickerControlEntry (TEX_LOWER_JACKET, "Lower Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); - addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ), FALSE )); - addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ), FALSE )); - addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); - addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); - addEntry ( TEX_LOWER_ALPHA, new PickerControlEntry (TEX_LOWER_ALPHA, "Lower Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); - addEntry ( TEX_UPPER_ALPHA, new PickerControlEntry (TEX_UPPER_ALPHA, "Upper Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); - addEntry ( TEX_HEAD_ALPHA, new PickerControlEntry (TEX_HEAD_ALPHA, "Head Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); - addEntry ( TEX_EYES_ALPHA, new PickerControlEntry (TEX_EYES_ALPHA, "Eye Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); - addEntry ( TEX_HAIR_ALPHA, new PickerControlEntry (TEX_HAIR_ALPHA, "Hair Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); - addEntry ( TEX_LOWER_TATTOO, new PickerControlEntry (TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE )); - addEntry ( TEX_UPPER_TATTOO, new PickerControlEntry (TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE )); - addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry (TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE )); - addEntry ( TEX_LOWER_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_LOWER_UNIVERSAL_TATTOO, "Lower Universal Tattoo", LLUUID::null, TRUE)); - addEntry ( TEX_UPPER_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_UPPER_UNIVERSAL_TATTOO, "Upper Universal Tattoo", LLUUID::null, TRUE)); - addEntry ( TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_HEAD_UNIVERSAL_TATTOO, "Head Universal Tattoo", LLUUID::null, TRUE)); - addEntry ( TEX_SKIRT_TATTOO, new PickerControlEntry(TEX_SKIRT_TATTOO, "Skirt Tattoo", LLUUID::null, TRUE)); - addEntry ( TEX_HAIR_TATTOO, new PickerControlEntry(TEX_HAIR_TATTOO, "Hair Tattoo", LLUUID::null, TRUE)); - addEntry ( TEX_EYES_TATTOO, new PickerControlEntry(TEX_EYES_TATTOO, "Eyes Tattoo", LLUUID::null, TRUE)); - addEntry (TEX_LEFT_ARM_TATTOO, new PickerControlEntry(TEX_LEFT_ARM_TATTOO, "Left Arm Tattoo", LLUUID::null, TRUE)); - addEntry (TEX_LEFT_LEG_TATTOO, new PickerControlEntry(TEX_LEFT_LEG_TATTOO, "Left Leg Tattoo", LLUUID::null, TRUE)); - addEntry (TEX_AUX1_TATTOO, new PickerControlEntry(TEX_AUX1_TATTOO, "Aux1 Tattoo", LLUUID::null, TRUE)); - addEntry (TEX_AUX2_TATTOO, new PickerControlEntry(TEX_AUX2_TATTOO, "Aux2 Tattoo", LLUUID::null, TRUE)); - addEntry (TEX_AUX3_TATTOO, new PickerControlEntry(TEX_AUX3_TATTOO, "Aux3 Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_HEAD_BODYPAINT, new PickerControlEntry(TEX_HEAD_BODYPAINT, "Head", LLUUID::null, TRUE)); + addEntry(TEX_UPPER_BODYPAINT, new PickerControlEntry(TEX_UPPER_BODYPAINT, "Upper Body", LLUUID::null, TRUE)); + addEntry(TEX_LOWER_BODYPAINT, new PickerControlEntry(TEX_LOWER_BODYPAINT, "Lower Body", LLUUID::null, TRUE)); + addEntry(TEX_HAIR, new PickerControlEntry(TEX_HAIR, "Texture", LLUUID(gSavedSettings.getString("UIImgDefaultHairUUID")), FALSE)); + addEntry(TEX_EYES_IRIS, new PickerControlEntry(TEX_EYES_IRIS, "Iris", LLUUID(gSavedSettings.getString("UIImgDefaultEyesUUID")), FALSE)); + addEntry(TEX_UPPER_SHIRT, new PickerControlEntry(TEX_UPPER_SHIRT, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultShirtUUID")), FALSE)); + addEntry(TEX_LOWER_PANTS, new PickerControlEntry(TEX_LOWER_PANTS, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultPantsUUID")), FALSE)); + addEntry(TEX_LOWER_SHOES, new PickerControlEntry(TEX_LOWER_SHOES, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultShoesUUID")), FALSE)); + addEntry(TEX_LOWER_SOCKS, new PickerControlEntry(TEX_LOWER_SOCKS, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultSocksUUID")), FALSE)); + addEntry(TEX_UPPER_JACKET, new PickerControlEntry(TEX_UPPER_JACKET, "Upper Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultJacketUUID")), FALSE)); + addEntry(TEX_LOWER_JACKET, new PickerControlEntry(TEX_LOWER_JACKET, "Lower Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultJacketUUID")), FALSE)); + addEntry(TEX_SKIRT, new PickerControlEntry(TEX_SKIRT, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultSkirtUUID")), FALSE)); + addEntry(TEX_UPPER_GLOVES, new PickerControlEntry(TEX_UPPER_GLOVES, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultGlovesUUID")), FALSE)); + addEntry(TEX_UPPER_UNDERSHIRT, new PickerControlEntry(TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultUnderwearUUID")), FALSE)); + addEntry(TEX_LOWER_UNDERPANTS, new PickerControlEntry(TEX_LOWER_UNDERPANTS, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultUnderwearUUID")), FALSE)); + addEntry(TEX_LOWER_ALPHA, new PickerControlEntry(TEX_LOWER_ALPHA, "Lower Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE)); + addEntry(TEX_UPPER_ALPHA, new PickerControlEntry(TEX_UPPER_ALPHA, "Upper Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE)); + addEntry(TEX_HEAD_ALPHA, new PickerControlEntry(TEX_HEAD_ALPHA, "Head Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE)); + addEntry(TEX_EYES_ALPHA, new PickerControlEntry(TEX_EYES_ALPHA, "Eye Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE)); + addEntry(TEX_HAIR_ALPHA, new PickerControlEntry(TEX_HAIR_ALPHA, "Hair Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE)); + addEntry(TEX_LOWER_TATTOO, new PickerControlEntry(TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_UPPER_TATTOO, new PickerControlEntry(TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_LOWER_UNIVERSAL_TATTOO, "Lower Universal Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_UPPER_UNIVERSAL_TATTOO, "Upper Universal Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Head Universal Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_SKIRT_TATTOO, new PickerControlEntry(TEX_SKIRT_TATTOO, "Skirt Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_HAIR_TATTOO, new PickerControlEntry(TEX_HAIR_TATTOO, "Hair Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_EYES_TATTOO, new PickerControlEntry(TEX_EYES_TATTOO, "Eyes Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_LEFT_ARM_TATTOO, new PickerControlEntry(TEX_LEFT_ARM_TATTOO, "Left Arm Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_LEFT_LEG_TATTOO, new PickerControlEntry(TEX_LEFT_LEG_TATTOO, "Left Leg Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_AUX1_TATTOO, new PickerControlEntry(TEX_AUX1_TATTOO, "Aux1 Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_AUX2_TATTOO, new PickerControlEntry(TEX_AUX2_TATTOO, "Aux2 Tattoo", LLUUID::null, TRUE)); + addEntry(TEX_AUX3_TATTOO, new PickerControlEntry(TEX_AUX3_TATTOO, "Aux3 Tattoo", LLUUID::null, TRUE)); } LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index, @@ -503,8 +510,8 @@ template const LLEditWearableDictionary::PickerControlEntry* find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred) { - const LLEditWearableDictionary::WearableEntry *wearable_entry - = LLEditWearableDictionary::getInstance()->getWearable(type); + const LLEditWearableDictionary::WearableEntry *wearable_entry = + LLEditWearableDictionary::getInstance()->getWearable(type); if (!wearable_entry) { LL_WARNS() << "could not get wearable dictionary entry for wearable of type: " << type << LL_ENDL; @@ -533,8 +540,7 @@ find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred) } template -void -for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_t fun) +void for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_t fun) { if (!panel) { @@ -555,14 +561,13 @@ for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_ iter != iter_end; ++iter) { const ETextureIndex te = *iter; - const LLEditWearableDictionary::PickerControlEntry* entry - = get_picker_entry(te); + const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry(te); if (!entry) { LL_WARNS() << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << LL_ENDL; continue; } - fun (panel, entry); + fun(panel, entry); } } @@ -607,7 +612,7 @@ static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const { LLUUID new_id; LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(entry->mTextureIndex); - if( lto && (lto->getID() != IMG_DEFAULT_AVATAR) ) + if (lto && (lto->getID() != IMG_DEFAULT_AVATAR)) { new_id = lto->getID(); } @@ -776,7 +781,7 @@ BOOL LLPanelEditWearable::postBuild() mPanelSkirt = getChild("edit_skirt_panel"); mPanelAlpha = getChild("edit_alpha_panel"); mPanelTattoo = getChild("edit_tattoo_panel"); - mPanelUniversal = getChild("edit_universal_panel"); + mPanelUniversal = getChild("edit_universal_panel"); mPanelPhysics = getChild("edit_physics_panel"); mTxtAvatarHeight = mPanelShape->getChild("avatar_height"); @@ -803,19 +808,19 @@ BOOL LLPanelEditWearable::postBuild() // Appearance panel not updating camera position bool tab_container_cb_set = false; - + for (U8 index = 0; index < num_subparts; ++index) { // dive into data structures to get the panel we need ESubpart subpart_e = wearable_entry->mSubparts[index]; const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e); - + if (!subpart_entry) { LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL; continue; } - + const std::string accordion_tab = subpart_entry->mAccordionTab; // Alpha and tattoo don't adhere to the usual panel layout and don't have a param list and main tab @@ -828,13 +833,13 @@ BOOL LLPanelEditWearable::postBuild() } LLAccordionCtrlTab *tab = findChild(accordion_tab); // - + if (!tab) { LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL; continue; } - + // initialize callback to ensure camera view changes appropriately. tab->setDropDownStateChangedCallback(boost::bind(&LLPanelEditWearable::onTabExpandedCollapsed,this,_2,index)); @@ -881,14 +886,16 @@ BOOL LLPanelEditWearable::isDirty() const BOOL isDirty = FALSE; if (mWearablePtr) { - if (mWearablePtr->isDirty() || - ( mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0 )) - { - isDirty = TRUE; - } + if (mWearablePtr->isDirty() || + (mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0)) + { + isDirty = TRUE; + } } return isDirty; } + + //virtual void LLPanelEditWearable::draw() { @@ -904,8 +911,8 @@ void LLPanelEditWearable::draw() void LLPanelEditWearable::onClose() { - // any unsaved changes should be reverted at this point - revertChanges(); + // any unsaved changes should be reverted at this point + revertChanges(); } void LLPanelEditWearable::setVisible(BOOL visible) @@ -922,7 +929,7 @@ void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_c showWearable(mWearablePtr, FALSE, disable_camera_switch); if (mWearablePtr) mWearablePtr->unregisterObserver(this); - mWearablePtr = wearable; + mWearablePtr = wearable; if( mWearablePtr ) mWearablePtr->registerObserver( this ); showWearable(mWearablePtr, TRUE, disable_camera_switch); @@ -931,11 +938,11 @@ void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_c //static void LLPanelEditWearable::onBackButtonClicked(void* userdata) { - LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata; - if ( panel->isDirty() ) - { - LLAppearanceMgr::instance().setOutfitDirty( true ); - } + LLPanelEditWearable* panel = (LLPanelEditWearable*)userdata; + if (panel->isDirty()) + { + LLAppearanceMgr::instance().setOutfitDirty(true); + } } //static @@ -960,7 +967,7 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r { std::string wearable_name = response["message"].asString(); LLStringUtil::trim(wearable_name); - if( !wearable_name.empty() ) + if (!wearable_name.empty()) { mNameEditor->setText(wearable_name); saveChanges(true); @@ -970,24 +977,27 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r void LLPanelEditWearable::onCommitSexChange() { - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid()) + { + return; + } LLWearableType::EType type = mWearablePtr->getType(); U32 index; - if( !gAgentWearables.getWearableIndex(mWearablePtr, index) || - !gAgentWearables.isWearableModifiable(type, index)) + if (!gAgentWearables.getWearableIndex(mWearablePtr, index) || + !gAgentWearables.isWearableModifiable(type, index)) { - return; + return; } LLViewerVisualParam* param = static_cast(gAgentAvatarp->getVisualParam( "male" )); - if( !param ) + if (!param) { - return; + return; } bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE; - LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index); if (wearable) { // [Legacy Bake] @@ -1027,25 +1037,25 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl) { // Set the new version LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID()); - if( image->getID() == IMG_DEFAULT ) + if (image->getID() == IMG_DEFAULT) { image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); } if (getWearable()) { - U32 index; - if (gAgentWearables.getWearableIndex(getWearable(), index)) - { - gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); - LLVisualParamHint::requestHintUpdates(); - // [Legacy Bake] - //gAgentAvatarp->wearableUpdated(type); - gAgentAvatarp->wearableUpdated(type, FALSE); - } - else - { - LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL; - } + U32 index; + if (gAgentWearables.getWearableIndex(getWearable(), index)) + { + gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); + LLVisualParamHint::requestHintUpdates(); + // [Legacy Bake] + //gAgentAvatarp->wearableUpdated(type); + gAgentAvatarp->wearableUpdated(type, FALSE); + } + else + { + LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL; + } } } else @@ -1061,13 +1071,13 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl) { LLWearableType::EType type = getWearable()->getType(); const PickerControlEntryNamePredicate name_pred(ctrl->getName()); - const LLEditWearableDictionary::PickerControlEntry* entry - = find_picker_ctrl_entry_if(type, name_pred); + const LLEditWearableDictionary::PickerControlEntry* entry = + find_picker_ctrl_entry_if(type, name_pred); if (entry) { const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex); const LLColor4& new_color = LLColor4(ctrl->getValue()); - if( old_color != new_color ) + if (old_color != new_color) { // [Legacy Bake] //getWearable()->setClothesColor(entry->mTextureIndex, new_color); @@ -1089,11 +1099,13 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) { LLPanel* panel = getPanel(type); if (!panel) + { return; + } bool is_modifiable = false; - if(mWearableItem) + if (mWearableItem) { const LLPermissions& perm = mWearableItem->getPermissions(); is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); @@ -1115,7 +1127,6 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) void LLPanelEditWearable::incrementCofVersionLegacy() { - } void LLPanelEditWearable::saveChanges(bool force_save_as) @@ -1127,61 +1138,59 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) } U32 index; - if (!gAgentWearables.getWearableIndex(mWearablePtr, index)) - { - LL_WARNS() << "wearable not found" << LL_ENDL; - return; - } + if (!gAgentWearables.getWearableIndex(mWearablePtr, index)) + { + LL_WARNS() << "wearable not found" << LL_ENDL; + return; + } std::string new_name = mNameEditor->getText(); - // Find an existing link to this wearable's inventory item, if any, and its description field. - LLInventoryItem *link_item = NULL; - std::string description; - LLInventoryModel::item_array_t links = - LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); - if (links.size()>0) - { - link_item = links.at(0).get(); - if (link_item && link_item->getIsLinkType()) - { - description = link_item->getActualDescription(); - } - } + // Find an existing link to this wearable's inventory item, if any, and its description field. + LLInventoryItem* link_item = NULL; + std::string description; + LLInventoryModel::item_array_t links = + LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); + if (links.size() > 0) + { + link_item = links.at(0).get(); + if (link_item && link_item->getIsLinkType()) + { + description = link_item->getActualDescription(); + } + } if (force_save_as) { - // the name of the wearable has changed, re-save wearable with new name - LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),gAgentAvatarp->mEndCustomizeCallback); - gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); - mNameEditor->setText(mWearableItem->getName()); + // the name of the wearable has changed, re-save wearable with new name + LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(), gAgentAvatarp->mEndCustomizeCallback); + gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); + mNameEditor->setText(mWearableItem->getName()); } else { - // Make another copy of this link, with the same - // description. This is needed to bump the COF - // version so texture baking service knows appearance has changed. - if (link_item) - { - // Create new link - LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID() - << " removing old link at " << link_item->getUUID() - << " wearable item id " << mWearablePtr->getItemID() << LL_ENDL; + // Make another copy of this link, with the same + // description. This is needed to bump the COF + // version so texture baking service knows appearance has changed. + if (link_item) + { + // Create new link + LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID() + << " removing old link at " << link_item->getUUID() + << " wearable item id " << mWearablePtr->getItemID() << LL_ENDL; - LLInventoryObject::const_object_list_t obj_array; - obj_array.push_back(LLConstPointer(link_item)); - link_inventory_array(LLAppearanceMgr::instance().getCOF(), - obj_array, - gAgentAvatarp->mEndCustomizeCallback); - // Remove old link - remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback); - } - // [Legacy Bake] - //gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name); - gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); + LLInventoryObject::const_object_list_t obj_array; + obj_array.push_back(LLConstPointer(link_item)); + link_inventory_array(LLAppearanceMgr::instance().getCOF(), + obj_array, + gAgentAvatarp->mEndCustomizeCallback); + // Remove old link + remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback); + } + // [Legacy Bake] + //gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name); + gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } - - } void LLPanelEditWearable::revertChanges() @@ -1233,15 +1242,15 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO targetPanel->setVisible(show); toggleTypeSpecificControls(type); - // Update type controls here - updateTypeSpecificControls(type); + // Update type controls here + updateTypeSpecificControls(type); if (show) { mPanelTitle->setText(title); mPanelTitle->setToolTip(title); mDescTitle->setText(description_title); - + // set name mNameEditor->setText(mWearableItem->getName()); @@ -1249,19 +1258,19 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO // clear and rebuild visual param list U8 num_subparts = (U8)(wearable_entry->mSubparts.size()); - + for (U8 index = 0; index < num_subparts; ++index) { // dive into data structures to get the panel we need ESubpart subpart_e = wearable_entry->mSubparts[index]; const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e); - + if (!subpart_entry) { LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL; continue; } - + const std::string scrolling_panel = subpart_entry->mParamList; const std::string accordion_tab = subpart_entry->mAccordionTab; @@ -1275,51 +1284,52 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO LLScrollingPanelList *panel_list = getChild(scrolling_panel); LLAccordionCtrlTab *tab = getChild(accordion_tab); - + if (!panel_list) { LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL; continue; } - + if (!tab) { LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL; continue; } - // Don't show female subparts if you're not female, etc. - if (!(gAgentAvatarp->getSex() & subpart_entry->mSex)) - { - tab->setVisible(FALSE); - continue; - } - else - { - tab->setVisible(TRUE); - } - + // Don't show female subparts if you're not female, etc. + if (!(gAgentAvatarp->getSex() & subpart_entry->mSex)) + { + tab->setVisible(FALSE); + continue; + } + else + { + tab->setVisible(TRUE); + } + // what edit group do we want to extract params for? const std::string edit_group = subpart_entry->mEditGroup; - + // storage for ordered list of visual params value_map_t sorted_params; getSortedParams(sorted_params, edit_group); -// Query by JointKey rather than just a string, the key can be a U32 index for faster lookup -// LLJoint* jointp = gAgentAvatarp->getJoint( subpart_entry->mTargetJoint ); - LLJoint* jointp = gAgentAvatarp->getJoint( JointKey::construct( subpart_entry->mTargetJoint ) ); - if( !jointp ) + // Query by JointKey rather than just a string, the key can be a U32 index for faster lookup + //LLJoint* jointp = gAgentAvatarp->getJoint( subpart_entry->mTargetJoint ); + LLJoint* jointp = gAgentAvatarp->getJoint( JointKey::construct( subpart_entry->mTargetJoint ) ); + if (!jointp) { -// jointp = gAgentAvatarp->getJoint( "mHead" ); - jointp = gAgentAvatarp->getJoint( JointKey::construct( "mHead" ) ); - } -// + //jointp = gAgentAvatarp->getJoint( "mHead" ); + jointp = gAgentAvatarp->getJoint( JointKey::construct( "mHead" ) ); + } + // buildParamList(panel_list, sorted_params, tab, jointp); - + updateScrollingPanelUI(); } + if (!disable_camera_switch) { showDefaultSubpart(); @@ -1357,55 +1367,55 @@ void LLPanelEditWearable::onTabExpandedCollapsed(const LLSD& param, U8 index) mLastShownSubpartIndex[mWearablePtr->getType()] = index; // Correct camera position for last subpart changeCamera(index); } - } // Appearance panel not updating camera position void LLPanelEditWearable::onTabChanged(LLUICtrl* ctrl, LLWearableType::EType type) { - LLTabContainer* container = dynamic_cast(ctrl); - if (!container) - { - return; - } + LLTabContainer* container = dynamic_cast(ctrl); + if (!container) + { + return; + } - if (!mWearablePtr || !gAgentCamera.cameraCustomizeAvatar()) - { - // we don't have a valid wearable we're editing, or we've left the wearable editor - return; - } + if (!mWearablePtr || !gAgentCamera.cameraCustomizeAvatar()) + { + // we don't have a valid wearable we're editing, or we've left the wearable editor + return; + } - const LLEditWearableDictionary::WearableEntry* wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type); - if (!wearable_entry) - { - return; - } + const LLEditWearableDictionary::WearableEntry* wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type); + if (!wearable_entry) + { + return; + } - llassert_always(wearable_entry->mSubparts.size() <= 0xFF); - U8 num_subparts = static_cast(wearable_entry->mSubparts.size()); - for (U8 index = 0; index < num_subparts; ++index) - { - ESubpart subpart_e = wearable_entry->mSubparts[index]; - const LLEditWearableDictionary::SubpartEntry* subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e); + llassert_always(wearable_entry->mSubparts.size() <= 0xFF); + U8 num_subparts = static_cast(wearable_entry->mSubparts.size()); + for (U8 index = 0; index < num_subparts; ++index) + { + ESubpart subpart_e = wearable_entry->mSubparts[index]; + const LLEditWearableDictionary::SubpartEntry* subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e); - if (subpart_entry && container->getCurrentPanel()->hasChild(subpart_entry->mAccordionTab, TRUE)) - { - mLastShownSubpartIndex[type] = index; // Correct camera position for last subpart - changeCamera(index); - break; - } - } + if (subpart_entry && container->getCurrentPanel()->hasChild(subpart_entry->mAccordionTab, TRUE)) + { + mLastShownSubpartIndex[type] = index; // Correct camera position for last subpart + changeCamera(index); + break; + } + } } // void LLPanelEditWearable::changeCamera(U8 subpart) { - // Don't change the camera if this type doesn't have a camera switch. - // Useful for wearables like physics that don't have an associated physical body part. - if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType())) - { - return; - } + // Don't change the camera if this type doesn't have a camera switch. + // Useful for wearables like physics that don't have an associated physical body part. + if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType())) + { + return; + } + const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(mWearablePtr->getType()); if (!wearable_entry) { @@ -1438,9 +1448,9 @@ void LLPanelEditWearable::changeCamera(U8 subpart) gMorphView->setCameraOffset( subpart_entry->mCameraOffset ); if (gSavedSettings.getBOOL("AppearanceCameraMovement")) { - // Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE - gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating()); - gMorphView->updateCamera(); + // Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE + gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating()); + gMorphView->updateCamera(); } } @@ -1468,10 +1478,9 @@ void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type) if (type == LLWearableType::WT_SHAPE) { // Update avatar height - // The .195 is a fudge factor derived by measuring against - // prims inworld, and carried forward from Phoenix. -- TS - F32 new_size = gAgentAvatarp->mBodySize.mV[VZ] + .195f; - + // The .195 is a fudge factor derived by measuring against + // prims inworld, and carried forward from Phoenix. -- TS + F32 new_size = gAgentAvatarp->mBodySize.mV[VZ] + .195f; if (gSavedSettings.getBOOL("HeightUnits") == FALSE) { // convert meters to feet @@ -1502,14 +1511,18 @@ void LLPanelEditWearable::updateScrollingPanelUI() LLWearableType::EType type = mWearablePtr->getType(); LLPanel *panel = getPanel(type); - if(panel && (mWearablePtr->getItemID().notNull())) + if (panel && (mWearablePtr->getItemID().notNull())) { const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type); llassert(wearable_entry); - if (!wearable_entry) return; - U8 num_subparts = (U8)(wearable_entry->mSubparts.size()); + if (!wearable_entry) + { + return; + } LLScrollingPanelParam::sUpdateDelayFrames = 0; + + U8 num_subparts = (U8)(wearable_entry->mSubparts.size()); for (U8 index = 0; index < num_subparts; ++index) { // dive into data structures to get the panel we need @@ -1519,13 +1532,13 @@ void LLPanelEditWearable::updateScrollingPanelUI() const std::string scrolling_panel = subpart_entry->mParamList; LLScrollingPanelList *panel_list = getChild(scrolling_panel); - + if (!panel_list) { LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL; continue; } - + panel_list->updatePanels(TRUE); } } @@ -1537,76 +1550,58 @@ LLPanel* LLPanelEditWearable::getPanel(LLWearableType::EType type) { case LLWearableType::WT_SHAPE: return mPanelShape; - break; case LLWearableType::WT_SKIN: return mPanelSkin; - break; case LLWearableType::WT_HAIR: return mPanelHair; - break; case LLWearableType::WT_EYES: return mPanelEyes; - break; case LLWearableType::WT_SHIRT: return mPanelShirt; - break; case LLWearableType::WT_PANTS: return mPanelPants; - break; case LLWearableType::WT_SHOES: return mPanelShoes; - break; case LLWearableType::WT_SOCKS: return mPanelSocks; - break; case LLWearableType::WT_JACKET: return mPanelJacket; - break; case LLWearableType::WT_GLOVES: return mPanelGloves; - break; case LLWearableType::WT_UNDERSHIRT: return mPanelUndershirt; - break; case LLWearableType::WT_UNDERPANTS: return mPanelUnderpants; - break; case LLWearableType::WT_SKIRT: return mPanelSkirt; - break; case LLWearableType::WT_ALPHA: return mPanelAlpha; - break; case LLWearableType::WT_TATTOO: return mPanelTattoo; - break; - - case LLWearableType::WT_UNIVERSAL: - return mPanelUniversal; - break; + + case LLWearableType::WT_UNIVERSAL: + return mPanelUniversal; case LLWearableType::WT_PHYSICS: return mPanelPhysics; - break; default: - break; + return NULL; } - return NULL; } void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std::string &edit_group) @@ -1644,11 +1639,11 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value // sorted_params is sorted according to magnitude of effect from // least to greatest. Adding to the front of the child list // reverses that order. - if( panel_list ) + if (panel_list) { panel_list->clearPanels(); value_map_t::iterator end = sorted_params.end(); - for(value_map_t::iterator it = sorted_params.begin(); it != end; ++it) + for (value_map_t::iterator it = sorted_params.begin(); it != end; ++it) { LLPanel::Params p; p.name("LLScrollingPanelParam"); @@ -1674,7 +1669,7 @@ void LLPanelEditWearable::updateVerbs() { bool can_copy = false; - if(mWearableItem) + if (mWearableItem) { can_copy = mWearableItem->getPermissions().allowCopyBy(gAgentID); } @@ -1688,7 +1683,7 @@ void LLPanelEditWearable::updateVerbs() // no modify, but what the hell, check anyways. childSetEnabled("import_btn", mWearableItem->getPermissions().allowModifyBy(gAgentID)); - if(isAgentAvatarValid()) + if (isAgentAvatarValid()) { // Update viewer's radio buttons (of RadioGroup with control_name="AvatarSex") of Avatar's gender // with value from "AvatarSex" setting @@ -1729,17 +1724,20 @@ void LLPanelEditWearable::configureAlphaCheckbox(LLAvatarAppearanceDefines::ETex void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te) { - if (!checkbox_ctrl) return; - if (!getWearable()) return; + if (!checkbox_ctrl || !getWearable()) + { + return; + } LL_INFOS() << "onInvisibilityCommit, self " << this << " checkbox_ctrl " << checkbox_ctrl << LL_ENDL; - U32 index; - if (!gAgentWearables.getWearableIndex(getWearable(),index)) - { - LL_WARNS() << "wearable not found" << LL_ENDL; - return; - } + U32 index; + if (!gAgentWearables.getWearableIndex(getWearable(), index)) + { + LL_WARNS() << "wearable not found" << LL_ENDL; + return; + } + bool new_invis_state = checkbox_ctrl->get(); if (new_invis_state) { @@ -1747,10 +1745,10 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL mPreviousAlphaTexture[te] = lto->getID(); LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE ); - gAgentAvatarp->setLocalTexture(te, image, FALSE, index); - // [Legacy Bake] - //gAgentAvatarp->wearableUpdated(getWearable()->getType()); - gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE); + gAgentAvatarp->setLocalTexture(te, image, FALSE, index); + // [Legacy Bake] + //gAgentAvatarp->wearableUpdated(getWearable()->getType()); + gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE); } else { @@ -1760,10 +1758,16 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL { prev_id = LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ); } - if (prev_id.isNull()) return; - + if (prev_id.isNull()) + { + return; + } + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(prev_id); - if (!image) return; + if (!image) + { + return; + } gAgentAvatarp->setLocalTexture(te, image, FALSE, index); // [Legacy Bake] @@ -1776,7 +1780,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL void LLPanelEditWearable::updateAlphaCheckboxes() { - for(string_texture_index_map_t::iterator iter = mAlphaCheckbox2Index.begin(); + for (string_texture_index_map_t::iterator iter = mAlphaCheckbox2Index.begin(); iter != mAlphaCheckbox2Index.end(); ++iter ) { LLAvatarAppearanceDefines::ETextureIndex te = (LLAvatarAppearanceDefines::ETextureIndex)iter->second; @@ -1814,76 +1818,76 @@ void LLPanelEditWearable::onClickedImportBtn() void LLPanelEditWearable::onClickedImportBtnCallback(const std::vector& filenames) { - const std::string filename = filenames[0]; - LLXmlTree tree; - if (!tree.parseFile(filename, FALSE)) - { - LL_WARNS("ShapeImport") << "Parsing " << filename << "failed miserably." << LL_ENDL; - LLNotificationsUtil::add("ShapeImportGenericFail", LLSD().with("FILENAME", filename)); - return; - } - LLXmlTreeNode* root = tree.getRoot(); - if (!root || !root->hasName("linden_genepool")) - { - LL_WARNS("ShapeImport") << filename << " has an invaid root node (not linden_genepool). Are you sure this is an avatar file?" << LL_ENDL; - LLNotificationsUtil::add("ShapeImportVersionFail", LLSD().with("FILENAME", filename)); - return; - } - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if(!root->getFastAttributeString(version_string, version) || (version != "1.0") ) - { - LL_WARNS("ShapeImport") << "Invalid avatar file version: " << version << " in file: " << filename << LL_ENDL; - LLNotificationsUtil::add("ShapeImportVersionFail", LLSD().with("FILENAME", filename)); - return; - } - LLXmlTreeNode* archetype = root->getChildByName("archetype"); - if (archetype) - { - static const LLStdStringHandle id_handle = LLXmlTree::addAttributeString("id"); - static const LLStdStringHandle value_handle = LLXmlTree::addAttributeString("value"); - U32 parse_errors = 0; - - for (LLXmlTreeNode* child = archetype->getFirstChild(); child != NULL; child = archetype->getNextChild()) - { - if (!child->hasName("param")) continue; - S32 id; - F32 value; - std::string wearable; - if (child->getFastAttributeS32(id_handle, id) - && child->getFastAttributeF32(value_handle, value)) - { - LLVisualParam* visual_param = getWearable()->getVisualParam(id); - if (visual_param) - // [AIS Merge] Change back once legacy baking is re-added - //visual_param->setWeight(value); - visual_param->setWeight(value, FALSE); - } - else - { - LL_WARNS("ShapeImport") << "Failed to parse parameters in " << filename << LL_ENDL; - ++parse_errors; - } - } - if (parse_errors) - { - LLNotificationsUtil::add("ShapeImportGenericFail", LLSD().with("FILENAME", filename)); - } - if (isAgentAvatarValid()) - { - getWearable()->writeToAvatar(gAgentAvatarp); - gAgentAvatarp->updateVisualParams(); - updateScrollingPanelUI(); - LL_INFOS("ShapeImport") << "Shape import has finished with great success!" << LL_ENDL; - } - else - LL_WARNS("ShapeImport") << "Agent is not valid. Can't apply shape import changes" << LL_ENDL; - } - else - { - LL_WARNS("ShapeImport") << filename << " is missing the archetype." << LL_ENDL; - LLNotificationsUtil::add("ShapeImportGenericFail"); - } + const std::string filename = filenames[0]; + LLXmlTree tree; + if (!tree.parseFile(filename, FALSE)) + { + LL_WARNS("ShapeImport") << "Parsing " << filename << "failed miserably." << LL_ENDL; + LLNotificationsUtil::add("ShapeImportGenericFail", LLSD().with("FILENAME", filename)); + return; + } + LLXmlTreeNode* root = tree.getRoot(); + if (!root || !root->hasName("linden_genepool")) + { + LL_WARNS("ShapeImport") << filename << " has an invaid root node (not linden_genepool). Are you sure this is an avatar file?" << LL_ENDL; + LLNotificationsUtil::add("ShapeImportVersionFail", LLSD().with("FILENAME", filename)); + return; + } + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if(!root->getFastAttributeString(version_string, version) || (version != "1.0") ) + { + LL_WARNS("ShapeImport") << "Invalid avatar file version: " << version << " in file: " << filename << LL_ENDL; + LLNotificationsUtil::add("ShapeImportVersionFail", LLSD().with("FILENAME", filename)); + return; + } + LLXmlTreeNode* archetype = root->getChildByName("archetype"); + if (archetype) + { + static const LLStdStringHandle id_handle = LLXmlTree::addAttributeString("id"); + static const LLStdStringHandle value_handle = LLXmlTree::addAttributeString("value"); + U32 parse_errors = 0; + + for (LLXmlTreeNode* child = archetype->getFirstChild(); child != NULL; child = archetype->getNextChild()) + { + if (!child->hasName("param")) continue; + S32 id; + F32 value; + std::string wearable; + if (child->getFastAttributeS32(id_handle, id) + && child->getFastAttributeF32(value_handle, value)) + { + LLVisualParam* visual_param = getWearable()->getVisualParam(id); + if (visual_param) + // [AIS Merge] Change back once legacy baking is re-added + //visual_param->setWeight(value); + visual_param->setWeight(value, FALSE); + } + else + { + LL_WARNS("ShapeImport") << "Failed to parse parameters in " << filename << LL_ENDL; + ++parse_errors; + } + } + if (parse_errors) + { + LLNotificationsUtil::add("ShapeImportGenericFail", LLSD().with("FILENAME", filename)); + } + if (isAgentAvatarValid()) + { + getWearable()->writeToAvatar(gAgentAvatarp); + gAgentAvatarp->updateVisualParams(); + updateScrollingPanelUI(); + LL_INFOS("ShapeImport") << "Shape import has finished with great success!" << LL_ENDL; + } + else + LL_WARNS("ShapeImport") << "Agent is not valid. Can't apply shape import changes" << LL_ENDL; + } + else + { + LL_WARNS("ShapeImport") << filename << " is missing the archetype." << LL_ENDL; + LLNotificationsUtil::add("ShapeImportGenericFail"); + } } // [/FS:CR] FIRE-10986 diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 2d3b555069..5bccef3f07 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1120,9 +1120,15 @@ void LLTaskLSLBridge::openItem() LLSD floater_key; floater_key["taskid"] = mPanel->getTaskUUID(); floater_key["itemid"] = mUUID; + LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance("preview_scriptedit", floater_key, TAKE_FOCUS_YES); if (preview) { + LLSelectNode *node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(NULL, TRUE); + if (node && node->mValid) + { + preview->setObjectName(node->mName); + } preview->setObjectID(mPanel->getTaskUUID()); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index e5cb903b65..0d3c76113b 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -748,7 +748,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string) if (mSearchString == "") { mInventoryItemsPanel->setFilterSubString(LLStringUtil::null); - mWearableItemsList->setFilterSubString(LLStringUtil::null); + mWearableItemsList->setFilterSubString(LLStringUtil::null, true); // re-open folders that were initially open mSavedFolderState->setApply(TRUE); mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -778,8 +778,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string) // set new filter string mInventoryItemsPanel->setFilterSubString(mSearchString); - mWearableItemsList->setFilterSubString(mSearchString); - + mWearableItemsList->setFilterSubString(mSearchString, true); } void LLPanelOutfitEdit::onPlusBtnClicked(void) diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index daa87485fa..e2c287b5af 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -28,19 +28,19 @@ #include "llpaneloutfitsinventory.h" -#include "llnotificationsutil.h" -#include "lltabcontainer.h" - +#include "llagentwearables.h" +#include "llappearancemgr.h" #include "llfloatersidepanelcontainer.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" -#include "llagentwearables.h" -#include "llappearancemgr.h" -#include "lloutfitobserver.h" +#include "llnotificationsutil.h" #include "lloutfitgallery.h" +#include "lloutfitobserver.h" #include "lloutfitslist.h" +#include "llpanelappearancetab.h" #include "llpanelwearing.h" #include "llsidepanelappearance.h" +#include "lltabcontainer.h" #include "llviewercontrol.h" #include "llviewerfoldertype.h" @@ -176,25 +176,12 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string) { if (!mActivePanel) return; - mFilterSubString = string; - - if (string == "") - { - mActivePanel->setFilterSubString(LLStringUtil::null); - } - if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { llassert(false); // this should have been done on startup LLInventoryModelBackgroundFetch::instance().start(); } - if (mActivePanel->getFilterSubString().empty() && string.empty()) - { - // current filter and new filter empty, do nothing - return; - } - // set new filter string mActivePanel->setFilterSubString(string); } @@ -342,6 +329,7 @@ bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) { return mActivePanel && mActivePanel->isActionEnabled(userdata); } + // List Commands // ////////////////////////////////////////////////////////////////////////////////// @@ -370,7 +358,7 @@ void LLPanelOutfitsInventory::onTabChange() mActivePanel = dynamic_cast(mAppearanceTabs->getCurrentPanel()); if (!mActivePanel) return; - mActivePanel->setFilterSubString(mFilterSubString); + mActivePanel->checkFilterSubString(); mActivePanel->onOpen(LLSD()); updateVerbs(); @@ -397,8 +385,6 @@ bool LLPanelOutfitsInventory::isOutfitsGalleryPanelActive() const return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME; } - - void LLPanelOutfitsInventory::setWearablesLoading(bool val) { updateVerbs(); diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index 349cc5ea81..457f52bae8 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -76,7 +76,6 @@ protected: private: LLTabContainer* mAppearanceTabs; - std::string mFilterSubString; // FIRE-17626: Attachment count in appearance floater LLInventoryCategoriesObserver* mCategoriesObserver; diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 8bb7c06f91..2373f26be2 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -597,9 +597,7 @@ void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id) mPickName->setEnabled(TRUE); mPickDescription->setEnabled(TRUE); // Make sure the "Set Location" button is only visible when viewing own picks - // mSetCurrentLocationButton->setVisible(TRUE); childSetVisible("set_to_curr_location_btn_lp", true); - // } else { @@ -616,7 +614,7 @@ BOOL LLPanelProfilePick::postBuild() mSaveButton = getChild("save_changes_btn"); mCreateButton = getChild("create_changes_btn"); mCancelButton = getChild("cancel_changes_btn"); - mSetCurrentLocationButton = getChild("set_to_curr_location_btn"); + mSetCurrentLocationButton = getChild("set_to_curr_location_btn"); // Keep set location button mSnapshotCtrl = getChild("pick_snapshot"); mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this)); @@ -627,7 +625,7 @@ BOOL LLPanelProfilePick::postBuild() mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this)); - mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this)); + mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this)); // Keep set location button mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL); mPickName->setEnabled(FALSE); @@ -789,6 +787,7 @@ BOOL LLPanelProfilePick::isDirty() const return FALSE; } +// Keep set location button void LLPanelProfilePick::onClickSetLocation() { // Save location for later use. @@ -814,6 +813,7 @@ void LLPanelProfilePick::onClickSetLocation() mLocationChanged = true; enableSaveButton(TRUE); } +// void LLPanelProfilePick::onClickSave() { diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h index 34407d37d5..9bf6431a8b 100644 --- a/indra/newview/llpanelprofilepicks.h +++ b/indra/newview/llpanelprofilepicks.h @@ -208,10 +208,12 @@ protected: */ void resetDirty() override; + // Keep set location button /** * Callback for "Set Location" button click */ void onClickSetLocation(); + // /** * Callback for "Save" and "Create" button click @@ -235,7 +237,7 @@ protected: LLTextureCtrl* mSnapshotCtrl; LLLineEditor* mPickName; LLTextEditor* mPickDescription; - LLButton* mSetCurrentLocationButton; + LLButton* mSetCurrentLocationButton; // Keep set location button LLButton* mSaveButton; LLButton* mCreateButton; LLButton* mCancelButton; diff --git a/indra/newview/llpanelvoicedevicesettings.cpp b/indra/newview/llpanelvoicedevicesettings.cpp index 28631e2b7b..af57169f3b 100644 --- a/indra/newview/llpanelvoicedevicesettings.cpp +++ b/indra/newview/llpanelvoicedevicesettings.cpp @@ -32,6 +32,7 @@ // Viewer includes #include "llcombobox.h" #include "llsliderctrl.h" +#include "llstartup.h" #include "llviewercontrol.h" #include "llvoiceclient.h" #include "llvoicechannel.h" @@ -70,11 +71,14 @@ BOOL LLPanelVoiceDeviceSettings::postBuild() mCtrlInputDevices = getChild("voice_input_device"); mCtrlOutputDevices = getChild("voice_output_device"); + mUnmuteBtn = getChild("unmute_btn"); mCtrlInputDevices->setCommitCallback( boost::bind(&LLPanelVoiceDeviceSettings::onCommitInputDevice, this)); mCtrlOutputDevices->setCommitCallback( boost::bind(&LLPanelVoiceDeviceSettings::onCommitOutputDevice, this)); + mUnmuteBtn->setCommitCallback( + boost::bind(&LLPanelVoiceDeviceSettings::onCommitUnmute, this)); mLocalizedDeviceNames[DEFAULT_DEVICE] = getString("default_text"); mLocalizedDeviceNames["No Device"] = getString("name_no_device"); @@ -108,11 +112,27 @@ void LLPanelVoiceDeviceSettings::draw() // let user know that volume indicator is not yet available bool is_in_tuning_mode = LLVoiceClient::getInstance()->inTuningMode(); - getChildView("wait_text")->setVisible( !is_in_tuning_mode && mUseTuningMode); + bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled(); + if (voice_enabled) + { + getChildView("wait_text")->setVisible( !is_in_tuning_mode && mUseTuningMode); + getChildView("disabled_text")->setVisible(FALSE); + mUnmuteBtn->setVisible(FALSE); + } + else + { + getChildView("wait_text")->setVisible(FALSE); + + static LLCachedControl chat_enabled(gSavedSettings, "EnableVoiceChat"); + // If voice isn't enabled, it is either disabled or muted + bool voice_disabled = chat_enabled() || LLStartUp::getStartupState() <= STATE_LOGIN_WAIT; + getChildView("disabled_text")->setVisible(voice_disabled); + mUnmuteBtn->setVisible(!voice_disabled); + } LLPanel::draw(); - if (is_in_tuning_mode) + if (is_in_tuning_mode && voice_enabled) { const S32 num_bars = 5; F32 voice_power = LLVoiceClient::getInstance()->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL; @@ -339,3 +359,8 @@ void LLPanelVoiceDeviceSettings::onInputDevicesClicked() { LLVoiceClient::getInstance()->refreshDeviceLists(false); // fill in the pop up menus again if needed. } + +void LLPanelVoiceDeviceSettings::onCommitUnmute() +{ + gSavedSettings.setBOOL("EnableVoiceChat", TRUE); +} diff --git a/indra/newview/llpanelvoicedevicesettings.h b/indra/newview/llpanelvoicedevicesettings.h index 355bc02b05..e704394d4a 100644 --- a/indra/newview/llpanelvoicedevicesettings.h +++ b/indra/newview/llpanelvoicedevicesettings.h @@ -55,12 +55,14 @@ protected: void onCommitOutputDevice(); void onOutputDevicesClicked(); void onInputDevicesClicked(); + void onCommitUnmute(); F32 mMicVolume; std::string mInputDevice; std::string mOutputDevice; class LLComboBox *mCtrlInputDevices; class LLComboBox *mCtrlOutputDevices; + class LLButton *mUnmuteBtn; BOOL mDevicesUpdated; bool mUseTuningMode; std::map mLocalizedDeviceNames; diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp index 51e74a5a20..26a4d54ee2 100644 --- a/indra/newview/llpanelvolumepulldown.cpp +++ b/indra/newview/llpanelvolumepulldown.cpp @@ -54,7 +54,7 @@ LLPanelVolumePulldown::LLPanelVolumePulldown() /*// Handled centrally now mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this)); - mCommitCallbackRegistrar.add("Vol.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelVolumePulldown::updateMediaAutoPlayCheckbox, this, _1)); + mCommitCallbackRegistrar.add("Vol.updateCheckbox", boost::bind(&LLPanelVolumePulldown::updateCheckbox, this, _1, _2)); mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2)); */ @@ -107,19 +107,23 @@ void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data) control->set(LLSD(FALSE)); } -void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) +void LLPanelVolumePulldown::updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data) { - std::string name = ctrl->getName(); + std::string control_name = user_data.asString(); + if (control_name == "MediaAutoPlay") + { + std::string name = ctrl->getName(); - // Disable "Allow Media to auto play" only when both - // "Streaming Music" and "Media" are unchecked. STORM-513. - if ((name == "enable_music") || (name == "enable_media")) - { - bool music_enabled = getChild("enable_music")->get(); - bool media_enabled = getChild("enable_media")->get(); + // Disable "Allow Media to auto play" only when both + // "Streaming Music" and "Media" are unchecked. STORM-513. + if ((name == "enable_music") || (name == "enable_media")) + { + bool music_enabled = getChild("enable_music")->get(); + bool media_enabled = getChild("enable_media")->get(); - getChild("media_auto_play_combo")->setEnabled(music_enabled || media_enabled); - } + getChild("media_auto_play_combo")->setEnabled(music_enabled || media_enabled); + } + } } void LLPanelVolumePulldown::onClickSetSounds() diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h index 90e826e76b..16d7fecc20 100644 --- a/indra/newview/llpanelvolumepulldown.h +++ b/indra/newview/llpanelvolumepulldown.h @@ -44,7 +44,7 @@ class LLPanelVolumePulldown : public LLPanelPulldown void onClickSetSounds(); // Disables "Allow Media to auto play" check box only when both // "Streaming Music" and "Media" are unchecked. Otherwise enables it. - void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl); + void updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data); void onAdvancedButtonClick(const LLSD& user_data); */ diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 04baa9b0f1..84e59c4017 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -243,8 +243,6 @@ protected: ////////////////////////////////////////////////////////////////////////// -std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null; - static LLPanelInjector t_panel_wearing("panel_wearing"); LLPanelWearing::LLPanelWearing() @@ -368,10 +366,11 @@ void LLPanelWearing::startUpdateTimer() } // virtual -void LLPanelWearing::setFilterSubString(const std::string& string) +void LLPanelWearing::onFilterSubStringChanged(const std::string& new_string, const std::string& old_string) { - sFilterSubString = string; - mCOFItemsList->setFilterSubString(sFilterSubString); + mCOFItemsList->setFilterSubString(new_string, true); + + mAccordionCtrl->arrange(); } // virtual diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h index d1d5d04fd5..d3d23e4866 100644 --- a/indra/newview/llpanelwearing.h +++ b/indra/newview/llpanelwearing.h @@ -62,7 +62,7 @@ public: /*virtual*/ void onOpen(const LLSD& info); - /*virtual*/ void setFilterSubString(const std::string& string); + /*virtual*/ void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string); /*virtual*/ bool isActionEnabled(const LLSD& userdata); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index d2c82b05e0..6e3bf21510 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -88,6 +88,9 @@ #include "llexperiencecache.h" #include "llfloaterexperienceprofile.h" #include "llviewerassetupload.h" +//#include "lltoggleablemenu.h" // FIRE-20818: User-selectable font and size for script editor +//#include "llmenubutton.h" // FIRE-20818: User-selectable font and size for script editor +#include "llinventoryfunctions.h" #include "llloadingindicator.h" // Compile indicator #include "lliconctrl.h" // Compile indicator // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) @@ -365,6 +368,38 @@ void LLFloaterScriptSearch::onSearchBoxCommit() #endif // +/// --------------------------------------------------------------------------- + +class LLScriptMovedObserver : public LLInventoryObserver +{ + public: + LLScriptMovedObserver(LLPreviewLSL *floater) : mPreview(floater) { gInventory.addObserver(this); } + virtual ~LLScriptMovedObserver() { gInventory.removeObserver(this); } + virtual void changed(U32 mask); + + private: + LLPreviewLSL *mPreview; +}; + +void LLScriptMovedObserver::changed(U32 mask) +{ + const std::set &mChangedItemIDs = gInventory.getChangedIDs(); + std::set::const_iterator it; + + const LLUUID &item_id = mPreview->getScriptID(); + + for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++) + { + if (*it == item_id) + { + if ((mask & (LLInventoryObserver::STRUCTURE)) != 0) + { + mPreview->setDirty(); + } + } + } +} + /// --------------------------------------------------------------------------- /// LLScriptEdCore /// --------------------------------------------------------------------------- @@ -588,6 +623,15 @@ BOOL LLScriptEdCore::postBuild() LLSyntaxIdLSL::getInstance()->initialize(); processKeywords(); + // FIRE-20818: User-selectable font and size for script editor + //mCommitCallbackRegistrar.add("FontSize.Set", boost::bind(&LLScriptEdCore::onChangeFontSize, this, _2)); + //mEnableCallbackRegistrar.add("FontSize.Check", boost::bind(&LLScriptEdCore::isFontSizeChecked, this, _2)); + + //LLToggleableMenu *context_menu = LLUICtrlFactory::getInstance()->createFromFile( + // "menu_lsl_font_size.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + //getChild("font_btn")->setMenu(context_menu, LLMenuButton::MP_BOTTOM_LEFT, true); + // + return TRUE; } @@ -1267,7 +1311,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string) LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); - url_string.setArg("[LSL_STRING]", help_string); + url_string.setArg("[LSL_STRING]", help_string.empty() ? HELP_LSL_PORTAL_TOPIC : help_string); addHelpItemToHistory(help_string); @@ -1835,6 +1879,20 @@ LLUUID LLScriptEdCore::getAssociatedExperience()const } // FIRE-20818: User-selectable font and size for script editor +//void LLScriptEdCore::onChangeFontSize(const LLSD &userdata) +//{ +// const std::string font_name = userdata.asString(); +// gSavedSettings.setString("LSLFontSizeName", font_name); +//} +// +//bool LLScriptEdCore::isFontSizeChecked(const LLSD &userdata) +//{ +// const std::string current_size_name = LLScriptEditor::getScriptFontSize(); +// const std::string size_name = userdata.asString(); +// +// return (size_name == current_size_name); +//} + void LLScriptEdCore::onFontChanged() { LLFontGL* font = LLFontGL::getFont(LLFontDescriptor(gSavedSettings.getString("FSScriptingFontName"), gSavedSettings.getString("FSScriptingFontSize"), LLFontGL::NORMAL)); @@ -2112,6 +2170,21 @@ bool LLScriptEdContainer::onExternalChange(const std::string& filename) return true; } +BOOL LLScriptEdContainer::handleKeyHere(KEY key, MASK mask) +{ + if (('A' == key) && (MASK_CONTROL == (mask & MASK_MODIFIERS))) + { + mScriptEd->selectAll(); + return TRUE; + } + + if (!LLPreview::handleKeyHere(key, mask)) + { + return mScriptEd->handleKeyHere(key, mask); + } + return TRUE; +} + // FIRE-16740: Color syntax highlighting changes don't immediately appear in script window void LLScriptEdContainer::updateStyle() { @@ -2164,6 +2237,14 @@ LLPreviewLSL::LLPreviewLSL(const LLSD& key ) mPendingUploads(0) { mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); + + mItemObserver = new LLScriptMovedObserver(this); +} + +LLPreviewLSL::~LLPreviewLSL() +{ + delete mItemObserver; + mItemObserver = NULL; } // virtual @@ -2175,10 +2256,25 @@ BOOL LLPreviewLSL::postBuild() if (item) { getChild("desc")->setValue(item->getDescription()); + + std::string item_path = get_category_path(item->getParentUUID()); + // Make ugly location display better + //getChild("path_txt")->setValue(item_path); + //getChild("path_txt")->setToolTip(item_path); + getChild("path_txt")->setTextArg("[PATH]", LLStringExplicit(item_path)); + getChild("path_txt")->setToolTipArg(LLStringExplicit("[PATH]"), LLStringExplicit(item_path)); + // } + // Make ugly location display better + else + { + getChild("path_txt")->setTextArg("[PATH]", LLStringExplicit("-")); + getChild("path_txt")->setToolTipArg(LLStringExplicit("[PATH]"), LLStringExplicit("-")); + } + // childSetCommitCallback("desc", LLPreview::onText, this); getChild("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); - + return LLPreview::postBuild(); } @@ -2189,8 +2285,21 @@ void LLPreviewLSL::draw() { setTitle(LLTrans::getString("ScriptWasDeleted")); mScriptEd->setItemRemoved(TRUE); + // Make ugly location display better + getChild("path_txt")->setTextArg("[PATH]", LLStringExplicit("-")); + getChild("path_txt")->setToolTipArg(LLStringExplicit("[PATH]"), LLStringExplicit("-")); + // } - + else if (mDirty) + { + std::string item_path = get_category_path(item->getParentUUID()); + // Make ugly location display better + //getChild("path_txt")->setValue(item_path); + //getChild("path_txt")->setToolTip(item_path); + getChild("path_txt")->setTextArg("[PATH]", LLStringExplicit(item_path)); + getChild("path_txt")->setToolTipArg(LLStringExplicit("[PATH]"), LLStringExplicit(item_path)); + // + } LLPreview::draw(); } // virtual @@ -2608,7 +2717,8 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : mPendingUploads(0), mIsModifiable(FALSE), mIsNew(false), - mIsSaving(FALSE) + mIsSaving(FALSE), + mObjectName("") { mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); } @@ -2773,6 +2883,10 @@ void LLLiveLSLEditor::loadAsset() } refreshFromItem(); + // Make ugly location display better + //getChild("obj_name")->setValue(mObjectName); + getChild("obj_name")->setTextArg("[SOURCE_OBJECT]", LLStringExplicit(mObjectName) ); + // // This is commented out, because we don't completely // handle script exports yet. /* diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 661cc386ae..d34dd9ced7 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -36,6 +36,7 @@ #include "llfloatergotoline.h" #include "lllivefile.h" #include "llsyntaxid.h" +#include "llscripteditor.h" #include class LLLiveLSLFile; @@ -53,6 +54,7 @@ class LLViewerInventoryItem; class LLScriptEdContainer; class LLFloaterGotoLine; class LLFloaterExperienceProfile; +class LLScriptMovedObserver; // [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) class LLEventTimer; // [/SL:KB] @@ -167,7 +169,15 @@ public: void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; }; LLUUID getAssetID() { return mAssetID; } -private: + // FIRE-20818: User-selectable font and size for script editor + //bool isFontSizeChecked(const LLSD &userdata); + //void onChangeFontSize(const LLSD &size_name); + // + + virtual BOOL handleKeyHere(KEY key, MASK mask); + void selectAll() { mEditor->selectAll(); } + + private: // NaCl - LSL Preprocessor void onToggleProc(); boost::signals2::connection mTogglePreprocConnection; @@ -186,8 +196,6 @@ private: // Show keyword help on F1 void selectFirstError(); - virtual BOOL handleKeyHere(KEY key, MASK mask); - void enableSave(BOOL b) {mEnableSave = b;} // Advanced Script Editor @@ -287,6 +295,8 @@ public: // FIRE-16740: Color syntax highlighting changes don't immediately appear in script window void updateStyle(); + BOOL handleKeyHere(KEY key, MASK mask); + protected: std::string getTmpFileName(const std::string& script_name); // [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0 @@ -309,6 +319,12 @@ class LLPreviewLSL : public LLScriptEdContainer { public: LLPreviewLSL(const LLSD& key ); + ~LLPreviewLSL(); + + LLUUID getScriptID() { return mItemUUID; } + + void setDirty() { mDirty = true; } + virtual void callbackLSLCompileSucceeded(); virtual void callbackLSLCompileFailed(const LLSD& compile_errors); @@ -347,6 +363,8 @@ protected: // Can safely close only after both text and bytecode are uploaded S32 mPendingUploads; + LLScriptMovedObserver* mItemObserver; + }; @@ -383,6 +401,8 @@ public: void requestExperiences(); void experienceChanged(); void addAssociatedExperience(const LLSD& experience); + + void setObjectName(std::string name) { mObjectName = name; } private: virtual BOOL canClose(); @@ -444,6 +464,7 @@ private: LLSD mExperienceIds; LLHandle mExperienceProfile; + std::string mObjectName; }; #endif // LL_LLPREVIEWSCRIPT_H diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 7fd89ff4f8..7b1401c49a 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -657,19 +657,6 @@ void LLSceneMonitor::dumpToFile(const std::string &file_name) } } - typedef LLTrace::StatType trace_mem; - for (auto& it : trace_mem::instance_snapshot()) - { - os << it.getName() << "(KiB)"; - - for (S32 frame = 1; frame <= frame_count; frame++) - { - os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(it).valueInUnits(); - } - - os << '\n'; - } - os.flush(); os.close(); } diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index c12f29f82a..7870cf8c9f 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -30,6 +30,7 @@ #include "llsyntaxid.h" #include "lllocalcliprect.h" +#include "llviewercontrol.h" #include "llpreviewscript.h" @@ -40,13 +41,15 @@ const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 40; static LLDefaultChildRegistry::Register r("script_editor"); LLScriptEditor::Params::Params() -: show_line_numbers("show_line_numbers", true) +: show_line_numbers("show_line_numbers", true), + default_font_size("default_font_size", false) {} LLScriptEditor::LLScriptEditor(const Params& p) : LLTextEditor(p) -, mShowLineNumbers(p.show_line_numbers) +, mShowLineNumbers(p.show_line_numbers), + mUseDefaultFontSize(p.default_font_size) { if (mShowLineNumbers) { @@ -55,6 +58,13 @@ LLScriptEditor::LLScriptEditor(const Params& p) } } +BOOL LLScriptEditor::postBuild() +{ + // FIRE-20818: User-selectable font and size for script editor + //gSavedSettings.getControl("LSLFontSizeName")->getCommitSignal()->connect(boost::bind(&LLScriptEditor::onFontSizeChange, this)); + return LLTextEditor::postBuild(); +} + void LLScriptEditor::draw() { { @@ -117,15 +127,11 @@ void LLScriptEditor::drawLineNumbers() // draw the line numbers if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop) { - // Script editor ignoring font selection - //const LLFontGL *num_font = LLFontGL::getFontMonospace(); - const LLFontGL *num_font = getFont(); - // const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum )); BOOL is_cur_line = cursor_line == line.mLineNum; const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL; const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor; - num_font->render( + getFont()->render( ltext, // string to draw 0, // begin offset UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x @@ -153,8 +159,12 @@ void LLScriptEditor::loadKeywords() LL_PROFILE_ZONE_SCOPED; mKeywords.processTokens(); + // FIRE-20818: User-selectable font and size for script editor + //LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get())); + LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getFont()).color(mDefaultColor.get())); + segment_vec_t segment_list; - mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); + mKeywords.findSegments(&segment_list, getWText(), *this, style); mSegments.clear(); segment_set_t::iterator insert_it = mSegments.begin(); @@ -180,7 +190,8 @@ void LLScriptEditor::loadKeywords(const std::string& filename, mKeywords.addToken(LLKeywordToken::TT_WORD, name, color, tooltips[i] ); } segment_vec_t segment_list; - mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); + LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getFont()).color(mDefaultColor.get())); + mKeywords.findSegments(&segment_list, getWText(), *this, style); mSegments.clear(); segment_set_t::iterator insert_it = mSegments.begin(); @@ -197,9 +208,14 @@ void LLScriptEditor::updateSegments() if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly) { LL_PROFILE_ZONE_SCOPED; + + // FIRE-20818: User-selectable font and size for script editor + //LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get())); + LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getFont()).color(mDefaultColor.get())); + // HACK: No non-ascii keywords for now segment_vec_t segment_list; - mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); + mKeywords.findSegments(&segment_list, getWText(), *this, style); clearSegments(); for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) @@ -250,6 +266,28 @@ void LLScriptEditor::drawSelectionBackground() } } +// FIRE-20818: User-selectable font and size for script editor +//std::string LLScriptEditor::getScriptFontSize() +//{ +// static LLCachedControl size_name(gSavedSettings, "LSLFontSizeName", "Monospace"); +// return size_name; +//} +// +//LLFontGL* LLScriptEditor::getScriptFont() +//{ +// std::string font_size_name = mUseDefaultFontSize ? "Monospace" : getScriptFontSize(); +// return LLFontGL::getFont(LLFontDescriptor("Monospace", font_size_name, 0)); +//} +// +//void LLScriptEditor::onFontSizeChange() +//{ +// if (!mUseDefaultFontSize) +// { +// needsReflow(); +// } +//} +// + // Improved Home-key behavior //virtual void LLScriptEditor::startOfLine() diff --git a/indra/newview/llscripteditor.h b/indra/newview/llscripteditor.h index 088d9e7f10..438989fee1 100644 --- a/indra/newview/llscripteditor.h +++ b/indra/newview/llscripteditor.h @@ -37,7 +37,7 @@ public: struct Params : public LLInitParam::Block { Optional show_line_numbers; - + Optional default_font_size; Params(); }; @@ -45,6 +45,7 @@ public: // LLView override virtual void draw(); + BOOL postBuild(); // Improved Home-key behavior // LLTextBase override @@ -56,7 +57,13 @@ public: LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); } LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); } - // Re-add legacy format support + // FIRE-20818: User-selectable font and size for script editor + //static std::string getScriptFontSize(); + //LLFontGL* getScriptFont(); + //void onFontSizeChange(); + // + + // Re-add legacy format support void loadKeywords(const std::string& filename, const std::vector& funcs, const std::vector& tooltips, @@ -80,6 +87,7 @@ private: LLKeywords mKeywords; bool mShowLineNumbers; + bool mUseDefaultFontSize; }; #endif // LL_SCRIPTEDITOR_H diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp index 87c1330f8d..8087614d34 100644 --- a/indra/newview/llscrollingpanelparam.cpp +++ b/indra/newview/llscrollingpanelparam.cpp @@ -259,21 +259,17 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint ) // Make sure we're not taking the slider out of bounds // (this is where some simple UI limits are stored) - F32 new_percent = weightToPercent(new_weight); - LLSliderCtrl* slider = getChild("param slider"); - if (slider) + F32 new_percent = weightToSlider(new_weight); + if (mSlider->getMinValue() < new_percent + && new_percent < mSlider->getMaxValue()) { - if (slider->getMinValue() < new_percent - && new_percent < slider->getMaxValue()) - { - // [Legacy Bake] - //mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight); - mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE); - mWearable->writeToAvatar(gAgentAvatarp); - gAgentAvatarp->updateVisualParams(); + // [Legacy Bake] + //mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight); + mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE); + mWearable->writeToAvatar(gAgentAvatarp); + gAgentAvatarp->updateVisualParams(); - slider->setValue( weightToPercent( new_weight ) ); - } + mSlider->setValue( weightToSlider( new_weight ) ); } } } @@ -294,19 +290,15 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata ) F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight(); // step a fraction in the negative directiona F32 new_weight = current_weight - (range / 10.f); - F32 new_percent = self->weightToPercent(new_weight); - LLSliderCtrl* slider = self->getChild("param slider"); - if (slider) + F32 new_percent = self->weightToSlider(new_weight); + if (self->mSlider->getMinValue() < new_percent + && new_percent < self->mSlider->getMaxValue()) { - if (slider->getMinValue() < new_percent - && new_percent < slider->getMaxValue()) - { - // [Legacy Bake] - //self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); - self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); - self->mWearable->writeToAvatar(gAgentAvatarp); - slider->setValue( self->weightToPercent( new_weight ) ); - } + // [Legacy Bake] + //self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); + self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); + self->mWearable->writeToAvatar(gAgentAvatarp); + self->mSlider->setValue( self->weightToSlider( new_weight ) ); } } @@ -330,35 +322,18 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata ) F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight(); // step a fraction in the negative direction F32 new_weight = current_weight + (range / 10.f); - F32 new_percent = self->weightToPercent(new_weight); - LLSliderCtrl* slider = self->getChild("param slider"); - if (slider) + F32 new_percent = self->weightToSlider(new_weight); + if (self->mSlider->getMinValue() < new_percent + && new_percent < self->mSlider->getMaxValue()) { - if (slider->getMinValue() < new_percent - && new_percent < slider->getMaxValue()) - { - // [Legacy Bake] - //self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); - self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); - self->mWearable->writeToAvatar(gAgentAvatarp); - slider->setValue( self->weightToPercent( new_weight ) ); - } + // [Legacy Bake] + //self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); + self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE); + self->mWearable->writeToAvatar(gAgentAvatarp); + self->mSlider->setValue( self->weightToSlider( new_weight ) ); } } } LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax ); } - - -F32 LLScrollingPanelParam::weightToPercent( F32 weight ) -{ - LLViewerVisualParam* param = mParam; - return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f; -} - -F32 LLScrollingPanelParam::percentToWeight( F32 percent ) -{ - LLViewerVisualParam* param = mParam; - return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight(); -} diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h index c7a47d5c7a..dc344486fc 100644 --- a/indra/newview/llscrollingpanelparam.h +++ b/indra/newview/llscrollingpanelparam.h @@ -61,9 +61,6 @@ public: void onHintMouseDown( LLVisualParamHint* hint ); void onHintHeldDown( LLVisualParamHint* hint ); - F32 weightToPercent( F32 weight ); - F32 percentToWeight( F32 percent ); - public: // Constants for LLPanelVisualParam const static F32 PARAM_STEP_TIME_THRESHOLD; diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp index 97ef946b56..3c066cb590 100644 --- a/indra/newview/llscrollingpanelparambase.cpp +++ b/indra/newview/llscrollingpanelparambase.cpp @@ -43,6 +43,7 @@ LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& pan LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints) : LLScrollingPanel( panel_params ), mParam(param), + mSlider(nullptr), mAllowModify(allow_modify), mWearable(wearable) { @@ -50,13 +51,15 @@ LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& pan buildFromFile( "panel_scrolling_param.xml"); else buildFromFile( "panel_scrolling_param_base.xml"); - - getChild("param slider")->setValue(weightToPercent(param->getWeight())); + + mSlider = getChild("param slider"); + mSlider->setMaxValue(100.f * (mParam->getMaxWeight() - mParam->getMinWeight())); + mSlider->setValue(weightToSlider(param->getWeight())); std::string display_name = LLTrans::getString(param->getDisplayName()); - getChild("param slider")->setLabelArg("[DESC]", display_name); - getChildView("param slider")->setEnabled(mAllowModify); - childSetCommitCallback("param slider", LLScrollingPanelParamBase::onSliderMoved, this); + mSlider->setLabelArg("[DESC]", display_name); + mSlider->setEnabled(mAllowModify); + mSlider->setCommitCallback(boost::bind(LLScrollingPanelParamBase::onSliderMoved, mSlider, this)); setVisible(FALSE); setBorderVisible( FALSE ); @@ -77,9 +80,9 @@ void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify) } F32 current_weight = mWearable->getVisualParamWeight( param->getID() ); - getChild("param slider")->setValue(weightToPercent( current_weight ) ); + mSlider->setValue(weightToSlider( current_weight ) ); mAllowModify = allow_modify; - getChildView("param slider")->setEnabled(mAllowModify); + mSlider->setEnabled(mAllowModify); } // static @@ -90,7 +93,7 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata) LLViewerVisualParam* param = self->mParam; F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() ); - F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() ); + F32 new_weight = self->sliderToWeight( (F32)slider->getValue().asReal() ); if (current_weight != new_weight ) { // [Legacy Bake] @@ -101,14 +104,12 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata) } } -F32 LLScrollingPanelParamBase::weightToPercent( F32 weight ) +F32 LLScrollingPanelParamBase::weightToSlider(F32 weight) { - LLViewerVisualParam* param = mParam; - return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f; + return (weight - mParam->getMinWeight()) * 100.f; } -F32 LLScrollingPanelParamBase::percentToWeight( F32 percent ) +F32 LLScrollingPanelParamBase::sliderToWeight(F32 slider) { - LLViewerVisualParam* param = mParam; - return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight(); + return slider / 100.f + mParam->getMinWeight(); } diff --git a/indra/newview/llscrollingpanelparambase.h b/indra/newview/llscrollingpanelparambase.h index 9538826251..e7f88a21bd 100644 --- a/indra/newview/llscrollingpanelparambase.h +++ b/indra/newview/llscrollingpanelparambase.h @@ -36,6 +36,7 @@ class LLViewerVisualParam; class LLWearable; class LLVisualParamHint; class LLViewerVisualParam; +class LLSliderCtrl; class LLJoint; class LLScrollingPanelParamBase : public LLScrollingPanel @@ -49,11 +50,13 @@ public: static void onSliderMoved(LLUICtrl* ctrl, void* userdata); - F32 weightToPercent( F32 weight ); - F32 percentToWeight( F32 percent ); + F32 weightToSlider(F32 weight); + F32 sliderToWeight(F32 slider); public: LLViewerVisualParam* mParam; + LLSliderCtrl* mSlider; + protected: BOOL mAllowModify; LLWearable *mWearable; diff --git a/indra/newview/llsearchhistory.cpp b/indra/newview/llsearchhistory.cpp index 449e0080f0..66e377cb8d 100644 --- a/indra/newview/llsearchhistory.cpp +++ b/indra/newview/llsearchhistory.cpp @@ -75,6 +75,17 @@ bool LLSearchHistory::save() { // build filename for each user std::string resolved_filename = getHistoryFilePath(); + + // delete the file if it is empty or contains only empty entries + if (std::find_if(mSearchHistory.begin(), mSearchHistory.end(), [](const LLSearchHistoryItem& x) + { + return !x.search_query.empty(); + }) == mSearchHistory.end()) + { + remove(resolved_filename.c_str()); + return true; + } + // open a file for writing llofstream file(resolved_filename.c_str()); if (!file.is_open()) diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index e56fd60e94..458c46f8f1 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -4443,9 +4443,12 @@ BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& r BOOL LLSelectMgr::isMovableAvatarSelected() { - if (mAllowSelectAvatar) + if (mAllowSelectAvatar && getSelection()->getObjectCount() == 1) { - return (getSelection()->getObjectCount() == 1) && (getSelection()->getFirstRootObject()->isAvatar()) && getSelection()->getFirstMoveableNode(TRUE); + // nothing but avatar should be selected, so check that + // there is only one selected object and it is a root + LLViewerObject* obj = getSelection()->getFirstRootObject(); + return obj && obj->isAvatar() && getSelection()->getFirstMoveableNode(TRUE); } return FALSE; } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 8ed359fc0a..c94a4f7875 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -104,10 +104,7 @@ BOOL LLSidepanelAppearance::postBuild() childSetAction("edit_outfit_btn", boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); - // Don't filter outfits list on keypress - //mFilterEditor = getChild("Filter"); - mFilterEditor = findChild("Filter"); - // + mFilterEditor = getChild("Filter"); if (mFilterEditor) { mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2)); diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 75c6cc8edf..ed0ef60d47 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -33,10 +33,7 @@ #include "llinventory.h" #include "llpaneloutfitedit.h" -// Don't filter outfits list on keypress -//class LLFilterEditor; -class LLSearchEditor; -// +class LLFilterEditor; class LLCurrentlyWornFetchObserver; class LLPanelEditWearable; class LLViewerWearable; @@ -95,10 +92,7 @@ private: void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE); void toggleWearableEditPanel(BOOL visible, LLViewerWearable* wearable = NULL, BOOL disable_camera_switch = FALSE); - // Don't filter outfits list on keypress - //LLFilterEditor* mFilterEditor; - LLSearchEditor* mFilterEditor; - // + LLFilterEditor* mFilterEditor; LLPanelOutfitsInventory* mPanelOutfitsInventory; LLPanelOutfitEdit* mOutfitEdit; LLPanelEditWearable* mEditWearable; diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp index 89ec482d5c..7c5fba2d55 100644 --- a/indra/newview/llslurl.cpp +++ b/indra/newview/llslurl.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llurlsimstring.cpp (was llsimurlstring.cpp) * @brief Handles "SLURL fragments" like Ahern/123/45 for * startup processing, login screen, prefs, etc. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2010&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,13 +34,9 @@ #include "llviewernetwork.h" #include "llfiltersd2xmlrpc.h" #include "curl/curl.h" -// [RLVa:KB] - Checked: 2010-04-05 (RLVa-1.2.0d) -#include "rlvhandler.h" -// [/RLVa:KB] - const char* LLSLURL::SLURL_HTTP_SCHEME = "http"; const char* LLSLURL::SLURL_HTTPS_SCHEME = "https"; -const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife"; +const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife"; const char* LLSLURL::SLURL_SECONDLIFE_PATH = "secondlife"; const char* LLSLURL::SLURL_COM = "slurl.com"; // For DnD - even though www.slurl.com redirects to slurl.com in a browser, you can copy and drag @@ -58,486 +54,482 @@ const char* LLSLURL::SIM_LOCATION_LAST = "last"; // resolve a simstring from a slurl LLSLURL::LLSLURL(const std::string& slurl) { - // by default we go to agni. - mType = INVALID; + // by default we go to agni. + mType = INVALID; - if(slurl == SIM_LOCATION_HOME) - { - mType = HOME_LOCATION; - } - else if(slurl.empty() || (slurl == SIM_LOCATION_LAST)) - { - mType = LAST_LOCATION; - } - else - { - LLURI slurl_uri; - // parse the slurl as a uri - if(slurl.find(':') == std::string::npos) - { - // There may be no scheme ('secondlife:' etc.) passed in. In that case - // we want to normalize the slurl by putting the appropriate scheme - // in front of the slurl. So, we grab the appropriate slurl base - // from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or - // https:///region/ for Standalone grid (the word region, not the region name) - // these slurls are typically passed in from the 'starting location' box on the login panel, - // where the user can type in /// - std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase(); + if (slurl.empty() || (slurl == SIM_LOCATION_LAST)) + { + mType = LAST_LOCATION; + } + else if (slurl == SIM_LOCATION_HOME) + { + mType = HOME_LOCATION; + } + else + { + LLURI slurl_uri; + // parse the slurl as a uri + if (slurl.find(':') == std::string::npos) + { + // There may be no scheme ('secondlife:' etc.) passed in. In that case + // we want to normalize the slurl by putting the appropriate scheme + // in front of the slurl. So, we grab the appropriate slurl base + // from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or + // https:///region/ for Standalone grid (the word region, not the region name) + // these slurls are typically passed in from the 'starting location' box on the login panel, + // where the user can type in /// + std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase(); - // the slurl that was passed in might have a prepended /, or not. So, - // we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife//// - // or some such. - - if(slurl[0] == '/') - { - fixed_slurl += slurl.substr(1); - } - else - { - fixed_slurl += slurl; - } - // We then load the slurl into a LLURI form - slurl_uri = LLURI(fixed_slurl); - } - else - { - // as we did have a scheme, implying a URI style slurl, we - // simply parse it as a URI - slurl_uri = LLURI(slurl); - } - - LLSD path_array = slurl_uri.pathArray(); - - // determine whether it's a maingrid URI or an Standalone/open style URI - // by looking at the scheme. If it's a 'secondlife:' slurl scheme or - // 'sl:' scheme, we know it's maingrid - - // At the end of this if/else block, we'll have determined the grid, - // and the slurl type (APP or LOCATION) - if(slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) - { - // parse a maingrid style slurl. We know the grid is maingrid - // so grab it. - // A location slurl for maingrid (with the special schemes) can be in the form - // secondlife:///// - // or - // secondlife:///secondlife//// - // where if grid is empty, it specifies Agni - - // An app style slurl for maingrid can be - // secondlife:///app/ - // where an empty grid implies Agni - - // we'll start by checking the top of the 'path' which will be - // either 'app', 'secondlife', or . - - // default to maingrid - - mGrid = MAINGRID; - - if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) || - (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)) - { - // it's in the form secondlife:///(app|secondlife) - // so parse the grid name to derive the grid ID - if (!slurl_uri.hostName().empty()) - { - mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName()); - } - else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) - { - // If the slurl is in the form secondlife:///secondlife/ form, - // then we are in fact on maingrid. - mGrid = MAINGRID; - } - else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH) - { - // for app style slurls, where no grid name is specified, assume the currently - // selected or logged in grid. - mGrid = LLGridManager::getInstance()->getGridId(); - } + // the slurl that was passed in might have a prepended /, or not. So, + // we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife//// + // or some such. - if(mGrid.empty()) - { - // we couldn't find the grid in the grid manager, so bail - LL_WARNS("AppInit")<<"unable to find grid"</// + // or + // secondlife:///secondlife//// + // where if grid is empty, it specifies Agni + + // An app style slurl for maingrid can be + // secondlife:///app/ + // where an empty grid implies Agni + + // we'll start by checking the top of the 'path' which will be + // either 'app', 'secondlife', or . + + // default to maingrid + + mGrid = MAINGRID; + + if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) || + (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)) + { + // it's in the form secondlife:///(app|secondlife) + // so parse the grid name to derive the grid ID + if (!slurl_uri.hostName().empty()) + { + mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName()); + } + else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) + { + // If the slurl is in the form secondlife:///secondlife/ form, + // then we are in fact on maingrid. + mGrid = MAINGRID; + } + else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH) + { + // for app style slurls, where no grid name is specified, assume the currently + // selected or logged in grid. + mGrid = LLGridManager::getInstance()->getGridId(); + } + + if (mGrid.empty()) + { + // we couldn't find the grid in the grid manager, so bail + LL_WARNS("AppInit")<<"unable to find grid"< or /app/, so it must be secondlife:// - // therefore the hostname will be the region name, and it's a location type - mType = LOCATION; - // 'normalize' it so the region name is in fact the head of the path_array - path_array.insert(0, slurl_uri.hostName()); + // therefore the hostname will be the region name, and it's a location type + mType = LOCATION; + // 'normalize' it so the region name is in fact the head of the path_array + path_array.insert(0, slurl_uri.hostName()); + } + } + } + else if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) || + (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || + (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME)) + { + // We're dealing with either a Standalone style slurl or slurl.com slurl + if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) || + (slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) || + (slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM)) + { + // slurl.com implies maingrid + mGrid = MAINGRID; + } + else + { + // Don't try to match any old http:/// URL as a SLurl. + // SLE SLurls will have the grid hostname in the URL, so only + // match http URLs if the hostname matches the grid hostname + // (or its a slurl.com or maps.secondlife.com URL). + if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME || + slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) && + slurl_uri.hostName() != LLGridManager::getInstance()->getGrid()) + { + return; } - } - } - else if((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) || - (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || - (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME)) - { - // We're dealing with either a Standalone style slurl or slurl.com slurl - if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) || - (slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) || - (slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM)) - { - // slurl.com implies maingrid - mGrid = MAINGRID; - } - else - { - // Don't try to match any old http:/// URL as a SLurl. - // SLE SLurls will have the grid hostname in the URL, so only - // match http URLs if the hostname matches the grid hostname - // (or its a slurl.com or maps.secondlife.com URL). - if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME || - slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) && - slurl_uri.hostName() != LLGridManager::getInstance()->getGrid()) - { - return; - } - // As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style - // urls are properly formed, unlike the stinky maingrid style - mGrid = slurl_uri.hostName(); - } - if (path_array.size() == 0) - { - // um, we need a path... - return; - } - - // we need to normalize the urls so - // the path portion starts with the 'command' that we want to do - // it can either be region or app. - if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) || - (path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)) - { - // strip off 'region' or 'secondlife' - path_array.erase(0); - // it's a location - mType = LOCATION; - } - else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH) - { - mType = APP; - path_array.erase(0); - // leave app appended. - } - else - { - // not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL - return; - } - } - else - { - // invalid scheme, so bail - return; - } - - - if(path_array.size() == 0) - { - // we gotta have some stuff after the specifier as to whether it's a region or command - return; - } - - // now that we know whether it's an app slurl or a location slurl, - // parse the slurl into the proper data structures. - if(mType == APP) - { - // grab the app command type and strip it (could be a command to jump somewhere, - // or whatever ) - mAppCmd = path_array[0].asString(); - path_array.erase(0); - - // Grab the parameters - mAppPath = path_array; - // and the query - mAppQuery = slurl_uri.query(); - mAppQueryMap = slurl_uri.queryMap(); - return; - } - else if(mType == LOCATION) - { - // at this point, head of the path array should be [ , , , ] where x, y and z - // are collectively optional - // are optional + // As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style + // urls are properly formed, unlike the stinky maingrid style + mGrid = slurl_uri.hostName(); + } + if (path_array.size() == 0) + { + // um, we need a path... + return; + } - mRegion = LLURI::unescape(path_array[0].asString()); + // we need to normalize the urls so + // the path portion starts with the 'command' that we want to do + // it can either be region or app. + if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) || + (path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)) + { + // strip off 'region' or 'secondlife' + path_array.erase(0); + // it's a location + mType = LOCATION; + } + else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH) + { + mType = APP; + path_array.erase(0); + // leave app appended. + } + else + { + // not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL + return; + } + } + else + { + // invalid scheme, so bail + return; + } - if(LLStringUtil::containsNonprintable(mRegion)) - { - LLStringUtil::stripNonprintable(mRegion); - } + if (path_array.size() == 0) + { + // we gotta have some stuff after the specifier as to whether it's a region or command + return; + } - path_array.erase(0); - - // parse the x, y, and optionally z - if(path_array.size() >= 2) - { - - mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f) - if((F32(mPosition[VX]) < 0.f) || - (mPosition[VX] > REGION_WIDTH_METERS) || - (F32(mPosition[VY]) < 0.f) || - (mPosition[VY] > REGION_WIDTH_METERS) || - (F32(mPosition[VZ]) < 0.f) || - (mPosition[VZ] > REGION_HEIGHT_METERS)) - { - mType = INVALID; - return; - } - - } - else - { - // if x, y and z were not fully passed in, go to the middle of the region. - // teleport will adjust the actual location to make sure you're on the ground - // and such - mPosition = LLVector3(REGION_WIDTH_METERS/2, REGION_WIDTH_METERS/2, 0); - } - } - } + // now that we know whether it's an app slurl or a location slurl, + // parse the slurl into the proper data structures. + if (mType == APP) + { + // grab the app command type and strip it (could be a command to jump somewhere, + // or whatever ) + mAppCmd = path_array[0].asString(); + path_array.erase(0); + + // Grab the parameters + mAppPath = path_array; + // and the query + mAppQuery = slurl_uri.query(); + mAppQueryMap = slurl_uri.queryMap(); + return; + } + else if (mType == LOCATION) + { + // at this point, head of the path array should be [ , , , ] where x, y and z + // are collectively optional + // are optional + + mRegion = LLURI::unescape(path_array[0].asString()); + + if (LLStringUtil::containsNonprintable(mRegion)) + { + LLStringUtil::stripNonprintable(mRegion); + } + + path_array.erase(0); + + // parse the x, y, and optionally z + if (path_array.size() >= 2) + { + mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f) + if ((F32(mPosition[VX]) < 0.f) || (mPosition[VX] > REGION_WIDTH_METERS) || + (F32(mPosition[VY]) < 0.f) || (mPosition[VY] > REGION_WIDTH_METERS) || + (F32(mPosition[VZ]) < 0.f) || (mPosition[VZ] > REGION_HEIGHT_METERS)) + { + mType = INVALID; + return; + } + } + else + { + // if x, y and z were not fully passed in, go to the middle of the region. + // teleport will adjust the actual location to make sure you're on the ground + // and such + mPosition = LLVector3(REGION_WIDTH_METERS / 2, REGION_WIDTH_METERS / 2, 0); + } + } + } } - // Create a slurl for the middle of the region -LLSLURL::LLSLURL(const std::string& grid, - const std::string& region) +LLSLURL::LLSLURL(const std::string& grid, const std::string& region) { - mGrid = grid; - mRegion = region; - mType = LOCATION; - mPosition = LLVector3((F64)REGION_WIDTH_METERS/2, (F64)REGION_WIDTH_METERS/2, 0); + mGrid = grid; + mRegion = region; + mType = LOCATION; + mPosition = LLVector3((F64)REGION_WIDTH_METERS / 2, (F64)REGION_WIDTH_METERS / 2, 0); } - - // create a slurl given the position. The position will be modded with the region // width handling global positions as well -LLSLURL::LLSLURL(const std::string& grid, - const std::string& region, - const LLVector3& position) +LLSLURL::LLSLURL(const std::string& grid, + const std::string& region, + const LLVector3& position) { - mGrid = grid; - mRegion = region; - S32 x = ll_round( (F32)fmod( position[VX], (F32)REGION_WIDTH_METERS ) ); - S32 y = ll_round( (F32)fmod( position[VY], (F32)REGION_WIDTH_METERS ) ); - S32 z = ll_round( (F32)position[VZ] ); - mType = LOCATION; - mPosition = LLVector3(x, y, z); + mGrid = grid; + mRegion = region; + S32 x = ll_round((F32)fmod(position[VX], (F32)REGION_WIDTH_METERS)); + S32 y = ll_round((F32)fmod(position[VY], (F32)REGION_WIDTH_METERS)); + S32 z = ll_round((F32)position[VZ]); + mType = LOCATION; + mPosition = LLVector3(x, y, z); } - // create a simstring -LLSLURL::LLSLURL(const std::string& region, - const LLVector3& position) +LLSLURL::LLSLURL(const std::string& region, + const LLVector3& position) { - *this = LLSLURL(LLGridManager::getInstance()->getGridId(), - region, position); + *this = LLSLURL(LLGridManager::getInstance()->getGridId(), region, position); } // create a slurl from a global position -LLSLURL::LLSLURL(const std::string& grid, - const std::string& region, - const LLVector3d& , // FIRE-30768: SLURL's don't work in VarRegions *unused param in SL builds* - const LLVector3d& global_position) +LLSLURL::LLSLURL(const std::string& grid, + const std::string& region, + const LLVector3d& , // FIRE-30768: SLURL's don't work in VarRegions *unused param in SL builds* + const LLVector3d& global_position) { - *this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), - region, LLVector3(global_position.mdV[VX], - global_position.mdV[VY], - global_position.mdV[VZ])); + *this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), region, + LLVector3(global_position.mdV[VX], global_position.mdV[VY], global_position.mdV[VZ])); } // create a slurl from a global position -LLSLURL::LLSLURL(const std::string& region, - const LLVector3d& region_origin, // FIRE-30768: SLURL's don't work in VarRegions - const LLVector3d& global_position) +LLSLURL::LLSLURL(const std::string& region, + const LLVector3d& region_origin, // FIRE-30768: SLURL's don't work in VarRegions + const LLVector3d& global_position) { - // FIRE-30768: SLURL's don't work in VarRegions - // *this = LLSLURL(LLGridManager::getInstance()->getGridId(), - // region, global_position); - *this = LLSLURL(LLGridManager::getInstance()->getGridId(), - region, - region_origin, - global_position); - // + // FIRE-30768: SLURL's don't work in VarRegions + // *this = LLSLURL(LLGridManager::getInstance()->getGridId(), + // region, global_position); + *this = LLSLURL(LLGridManager::getInstance()->getGridId(), + region, + region_origin, + global_position); + // } LLSLURL::LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb) { - mType = APP; - mAppCmd = command; - mAppPath = LLSD::emptyArray(); - mAppPath.append(LLSD(id)); - mAppPath.append(LLSD(verb)); + mType = APP; + mAppCmd = command; + mAppPath = LLSD::emptyArray(); + mAppPath.append(LLSD(id)); + mAppPath.append(LLSD(verb)); } - std::string LLSLURL::getSLURLString() const { - switch(mType) - { - case HOME_LOCATION: - return SIM_LOCATION_HOME; - case LAST_LOCATION: - return SIM_LOCATION_LAST; - case LOCATION: - { - // lookup the grid - S32 x = ll_round( (F32)mPosition[VX] ); - S32 y = ll_round( (F32)mPosition[VY] ); - S32 z = ll_round( (F32)mPosition[VZ] ); -// return LLGridManager::getInstance()->getSLURLBase(mGrid) + -// LLURI::escape(mRegion) + llformat("/%d/%d/%d",x,y,z); + switch (mType) + { + case HOME_LOCATION: + return SIM_LOCATION_HOME; + case LAST_LOCATION: + return SIM_LOCATION_LAST; + case LOCATION: + { + // lookup the grid + S32 x = ll_round((F32)mPosition[VX]); + S32 y = ll_round((F32)mPosition[VY]); + S32 z = ll_round((F32)mPosition[VZ]); +// return LLGridManager::getInstance()->getSLURLBase(mGrid) + +// LLURI::escape(mRegion) + llformat("/%d/%d/%d", x, y, z); // [RLVa:KB] - Checked: 2010-04-05 (RLVa-1.2.0d) | Added: RLVa-1.2.0d - return LLGridManager::getInstance()->getSLURLBase(mGrid) + - ( ((!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) || (!RlvUtil::isNearbyRegion(mRegion))) - ? (LLURI::escape(mRegion) + llformat("/%d/%d/%d",x,y,z)) : RlvStrings::getString(RlvStringKeys::Hidden::Region) ); + return LLGridManager::getInstance()->getSLURLBase(mGrid) + + ( ((!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) || (!RlvUtil::isNearbyRegion(mRegion))) + ? (LLURI::escape(mRegion) + llformat("/%d/%d/%d", x, y, z)) : RlvStrings::getString(RlvStringKeys::Hidden::Region) ); // [/RLVa:KB] - } - case APP: - { - std::ostringstream app_url; - app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd; - for(LLSD::array_const_iterator i = mAppPath.beginArray(); - i != mAppPath.endArray(); - i++) - { - app_url << "/" << i->asString(); - } - if(mAppQuery.length() > 0) - { - app_url << "?" << mAppQuery; - } - return app_url.str(); - } - default: - LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL; - return std::string(); - } + } + case APP: + { + std::ostringstream app_url; + app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd; + for (LLSD::array_const_iterator i = mAppPath.beginArray(); + i != mAppPath.endArray(); + i++) + { + app_url << "/" << i->asString(); + } + if (mAppQuery.length() > 0) + { + app_url << "?" << mAppQuery; + } + return app_url.str(); + } + default: + LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL; + return std::string(); + } } std::string LLSLURL::getLoginString() const { - - std::stringstream unescaped_start; - switch(mType) - { - case LOCATION: - unescaped_start << "uri:" - << mRegion << "&" - << ll_round(mPosition[0]) << "&" - << ll_round(mPosition[1]) << "&" - << ll_round(mPosition[2]); - break; - case HOME_LOCATION: - unescaped_start << "home"; - break; - case LAST_LOCATION: - unescaped_start << "last"; - break; - default: - LL_WARNS("AppInit") << "Unexpected SLURL type ("<<(int)mType <<")for login string"<< LL_ENDL; - break; - } - return xml_escape_string(unescaped_start.str()); + std::stringstream unescaped_start; + switch (mType) + { + case LOCATION: + unescaped_start << "uri:" + << mRegion << "&" + << ll_round(mPosition[0]) << "&" + << ll_round(mPosition[1]) << "&" + << ll_round(mPosition[2]); + break; + case HOME_LOCATION: + unescaped_start << "home"; + break; + case LAST_LOCATION: + unescaped_start << "last"; + break; + default: + LL_WARNS("AppInit") << "Unexpected SLURL type (" << (int)mType << ")for login string" << LL_ENDL; + break; + } + return xml_escape_string(unescaped_start.str()); } -bool LLSLURL::operator==(const LLSLURL& rhs) +bool LLSLURL::operator ==(const LLSLURL& rhs) { - if(rhs.mType != mType) return false; - switch(mType) - { - case LOCATION: - return ((mGrid == rhs.mGrid) && - (mRegion == rhs.mRegion) && - (mPosition == rhs.mPosition)); - case APP: - return getSLURLString() == rhs.getSLURLString(); - - case HOME_LOCATION: - case LAST_LOCATION: - return true; - default: - return false; - } + if (rhs.mType != mType) + return false; + + switch (mType) + { + case LOCATION: + return (mGrid == rhs.mGrid) && + (mRegion == rhs.mRegion) && + (mPosition == rhs.mPosition); + + case APP: + return getSLURLString() == rhs.getSLURLString(); + + case HOME_LOCATION: + case LAST_LOCATION: + return true; + + default: + return false; + } } bool LLSLURL::operator !=(const LLSLURL& rhs) { - return !(*this == rhs); + return !(*this == rhs); } std::string LLSLURL::getLocationString() const { - return llformat("%s/%d/%d/%d", - mRegion.c_str(), - (int)ll_round(mPosition[0]), - (int)ll_round(mPosition[1]), - (int)ll_round(mPosition[2])); + return llformat("%s/%d/%d/%d", + mRegion.c_str(), + (int)ll_round(mPosition[0]), + (int)ll_round(mPosition[1]), + (int)ll_round(mPosition[2])); } // static -const std::string LLSLURL::typeName[NUM_SLURL_TYPES] = +const std::string LLSLURL::typeName[NUM_SLURL_TYPES] = { - "INVALID", - "LOCATION", - "HOME_LOCATION", - "LAST_LOCATION", - "APP", - "HELP" + "INVALID", + "LOCATION", + "HOME_LOCATION", + "LAST_LOCATION", + "APP", + "HELP", + "EMPTY" }; - + std::string LLSLURL::getTypeString(SLURL_TYPE type) { - std::string name; - if ( type >= INVALID && type < NUM_SLURL_TYPES ) - { - name = LLSLURL::typeName[type]; - } - else - { - name = llformat("Out of Range (%d)",type); - } - return name; + std::string name; + if (type >= INVALID && type < NUM_SLURL_TYPES) + { + name = LLSLURL::typeName[type]; + } + else + { + name = llformat("Out of Range (%d)", type); + } + return name; } - std::string LLSLURL::asString() const { std::ostringstream result; result - << " mType: " << LLSLURL::getTypeString(mType) - << " mGrid: " + getGrid() - << " mRegion: " + getRegion() - << " mPosition: " << mPosition - << " mAppCmd:" << getAppCmd() - << " mAppPath:" + getAppPath().asString() - << " mAppQueryMap:" + getAppQueryMap().asString() - << " mAppQuery: " + getAppQuery() - ; - + << " mType: " << LLSLURL::getTypeString(mType) + << " mGrid: " + getGrid() + << " mRegion: " + getRegion() + << " mPosition: " << mPosition + << " mAppCmd:" << getAppCmd() + << " mAppPath:" + getAppPath().asString() + << " mAppQueryMap:" + getAppQueryMap().asString() + << " mAppQuery: " + getAppQuery() + ; + return result.str(); } - diff --git a/indra/newview/llslurl.h b/indra/newview/llslurl.h index fd0db1837c..d53383e421 100644 --- a/indra/newview/llslurl.h +++ b/indra/newview/llslurl.h @@ -55,13 +55,14 @@ public: static const char* SLURL_REGION_PATH; // if you modify this enumeration, update typeName as well - enum SLURL_TYPE { - INVALID, + enum SLURL_TYPE { + INVALID, LOCATION, HOME_LOCATION, LAST_LOCATION, APP, HELP, + EMPTY, NUM_SLURL_TYPES // must be last }; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5803f7bc56..17cea711b7 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -864,10 +864,8 @@ void LLSpatialGroup::rebound() if (controlAvatar && controlAvatar->mDrawable && controlAvatar->mControlAVBridge && - controlAvatar->mControlAVBridge->mOctree)// FIRE-33367 toggling animesh state off causes a crash + controlAvatar->mControlAVBridge->mOctree) { - llassert(controlAvatar->mControlAVBridge->mOctree); - LLSpatialGroup* root = (LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0); if (this == root) { @@ -880,7 +878,7 @@ void LLSpatialGroup::rebound() } } -void LLSpatialGroup::destroyGLState(bool keep_occlusion) +void LLSpatialGroup::destroyGLState(bool keep_occlusion) { // Reset VB during TP bool is_tree_group = getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TREE; @@ -1347,17 +1345,8 @@ void drawBox(const LLVector4a& c, const LLVector4a& r) void drawBoxOutline(const LLVector3& pos, const LLVector3& size) { - - llassert(pos.isFinite()); - llassert(size.isFinite()); - - llassert(!llisnan(pos.mV[0])); - llassert(!llisnan(pos.mV[1])); - llassert(!llisnan(pos.mV[2])); - - llassert(!llisnan(size.mV[0])); - llassert(!llisnan(size.mV[1])); - llassert(!llisnan(size.mV[2])); + if (!pos.isFinite() || !size.isFinite()) + return; LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 42ca9e3150..09a17e97d4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3362,6 +3362,34 @@ void login_callback(S32 option, void *userdata) } } +void release_notes_coro(const std::string url) +{ + if (url.empty()) + { + return; + } + + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("releaseNotesCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); + + httpOpts->setHeadersOnly(true); // only making sure it isn't 404 or something like that + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + return; + } + + LLWeb::loadURLInternal(url); +} + /** * Check if user is running a new version of the viewer. * Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. @@ -3394,7 +3422,8 @@ void show_release_notes_if_required() LLEventPumps::instance().obtain("relnotes").listen( "showrelnotes", [](const LLSD& url) { - LLWeb::loadURLInternal(url.asString()); + LLCoros::instance().launch("releaseNotesCoro", + boost::bind(&release_notes_coro, url.asString())); return false; }); } @@ -3402,7 +3431,9 @@ void show_release_notes_if_required() #endif // LL_RELEASE_FOR_DOWNLOAD { LLSD info(LLAppViewer::instance()->getViewerInfo()); - LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); + std::string url = info["VIEWER_RELEASE_NOTES_URL"].asString(); + LLCoros::instance().launch("releaseNotesCoro", + boost::bind(&release_notes_coro, url)); } release_notes_shown = true; } diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index e93261f406..5e7134851e 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -350,6 +350,15 @@ BOOL LLStatusBar::postBuild() LLHints::getInstance()->registerHintTarget("linden_balance", getChild("balance_bg")->getHandle()); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2)); + // Fix LL voice disabled on 2nd instance nonsense + //gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&LLStatusBar::onVoiceChanged, this, _2)); + + //if (!gSavedSettings.getBOOL("EnableVoiceChat") && LLAppViewer::instance()->isSecondInstance()) + //{ + // // Indicate that second instance started without sound + // mBtnVolume->setImageUnselected(LLUI::getUIImage("VoiceMute_Off")); + //} + // // FIRE-19697: Add setting to disable graphics preset menu popup on mouse over gSavedSettings.getControl("FSStatusBarMenuButtonPopupOnRollover")->getSignal()->connect(boost::bind(&LLStatusBar::onPopupRolloverChanged, this, _2)); @@ -1125,6 +1134,18 @@ void LLStatusBar::onVolumeChanged(const LLSD& newvalue) refresh(); } +// Fix LL voice disabled on 2nd instance nonsense +//void LLStatusBar::onVoiceChanged(const LLSD& newvalue) +//{ +// if (newvalue.asBoolean()) +// { +// // Second instance starts with "VoiceMute_Off" icon, fix it +// mBtnVolume->setImageUnselected(LLUI::getUIImage("Audio_Off")); +// } +// refresh(); +//} +// + void LLStatusBar::onUpdateFilterTerm() { LLWString searchValue = utf8str_to_wstring( mFilterEdit->getValue() ); diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 81d427cfd4..f8d5b7deeb 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -164,13 +164,12 @@ private: void onClickBuyCurrency(); void onVolumeChanged(const LLSD& newvalue); + //void onVoiceChanged(const LLSD& newvalue); // Fix LL voice disabled on 2nd instance nonsense void onMouseEnterPresetsCamera(); void onMouseEnterPresets(); void onMouseEnterVolume(); void onMouseEnterNearbyMedia(); - // Does not exist 15-02-2021 - //void onClickScreen(S32 x, S32 y); static void onClickStreamToggle(void* data); // Media/Stream separation static void onClickMediaToggle(void* data); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 16a8d3d394..53a85b7126 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -352,13 +352,13 @@ private: } // Threads: Tid - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { - worker->callbackDecoded(success, raw, aux); + worker->callbackDecoded(success, raw, aux, request_id); } } private: @@ -402,7 +402,7 @@ public: void callbackCacheWrite(bool success); // Threads: Tid - void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); + void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id); // Threads: T* void setGetStatus(LLCore::HttpStatus status, const std::string& reason) @@ -1961,8 +1961,22 @@ bool LLTextureFetchWorker::doWork(S32 param) setState(DECODE_IMAGE_UPDATE); LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; - mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, discard, mNeedsAux, - new DecodeResponder(mFetcher, mID, this)); + + // In case worked manages to request decode, be shut down, + // then init and request decode again with first decode + // still in progress, assign a sufficiently unique id + mDecodeHandle = LLAppViewer::getImageDecodeThread()->decodeImage(mFormattedImage, + discard, + mNeedsAux, + new DecodeResponder(mFetcher, mID, this)); + if (mDecodeHandle == 0) + { + // Abort, failed to put into queue. + // Happens if viewer is shutting down + setState(DONE); + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: failed to post for decoding" << LL_ENDL; + return true; + } // fall though } @@ -2530,16 +2544,24 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) ////////////////////////////////////////////////////////////////////////////// // Threads: Tid -void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) +void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id) { LLMutexLock lock(&mWorkMutex); // +Mw if (mDecodeHandle == 0) { return; // aborted, ignore } + if (mDecodeHandle != decode_id) + { + // Queue doesn't support canceling old requests. + // This shouldn't normally happen, but in case it's possible that a worked + // will request decode, be aborted, reinited then start a new decode + LL_DEBUGS(LOG_TXT) << mID << " received obsolete decode's callback" << LL_ENDL; + return; // ignore + } if (mState != DECODE_IMAGE_UPDATE) { -// LL_WARNS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Decode callback for " << mID << " with state = " << mState << LL_ENDL; mDecodeHandle = 0; return; } diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 8966e851c6..9b8db4a7d6 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -254,7 +254,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s try { - res = this->parseResponse(httpResults, parseResult, body, translation, detected_lang, err_msg); + res = parseResponse(httpResults, parseResult, body, translation, detected_lang, err_msg); } catch (std::out_of_range&) { @@ -294,8 +294,6 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s if (!failure.empty()) failure(status, err_msg); } - - } //========================================================================= @@ -354,7 +352,6 @@ private: std::string& translation, std::string& detected_lang); static std::string getAPIKey(); - }; //------------------------------------------------------------------------- @@ -392,36 +389,37 @@ bool LLGoogleTranslationHandler::checkVerificationResponse( // virtual bool LLGoogleTranslationHandler::parseResponse( - const LLSD& http_response, + const LLSD& http_response, int& status, const std::string& body, std::string& translation, std::string& detected_lang, std::string& err_msg) const { + const std::string& text = !body.empty() ? body : http_response["error_body"].asStringRef(); + Json::Value root; Json::Reader reader; - if (!reader.parse(body, root)) + if (reader.parse(text, root)) { + if (root.isObject()) + { + // Request succeeded, extract translation from the XML body. + if (parseTranslation(root, translation, detected_lang)) + return true; + + // Request failed. Extract error message from the XML body. + parseErrorResponse(root, status, err_msg); + } + } + else + { + // XML parsing failed. Extract error message from the XML parser. err_msg = reader.getFormatedErrorMessages(); - return false; } - if (!root.isObject()) // empty response? should not happen - { - return false; - } - - if (status != HTTP_OK) - { - // Request failed. Extract error message from the response. - parseErrorResponse(root, status, err_msg); - return false; - } - - // Request succeeded, extract translation from the response. - return parseTranslation(root, translation, detected_lang); + return false; } // virtual @@ -494,7 +492,7 @@ void LLGoogleTranslationHandler::verifyKey(const LLSD &key, LLTranslate::KeyVeri /*virtual*/ void LLGoogleTranslationHandler::initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const { - headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); + headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_JSON); headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); } @@ -504,8 +502,7 @@ void LLGoogleTranslationHandler::initHttpHeader( const std::string& user_agent, const LLSD &key) const { - headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); - headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); + initHttpHeader(headers, user_agent); } LLSD LLGoogleTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, @@ -729,7 +726,7 @@ bool LLAzureTranslationHandler::parseResponse( return false; } - translation = first["text"].asString(); + translation = LLURI::unescape(first["text"].asString()); return true; } @@ -829,8 +826,13 @@ LLSD LLAzureTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCorout { LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray); LLCore::BufferArrayStream outs(rawbody.get()); + + static const std::string allowed_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " + "0123456789" + "-._~"; + outs << "[{\"text\":\""; - outs << msg; + outs << LLURI::escape(msg, allowed_chars); outs << "\"}]"; return adapter->postRawAndSuspend(request, url, rawbody, options, headers); @@ -1315,5 +1317,4 @@ LLTranslationAPIHandler& LLTranslate::getHandler(EService service) } return azure; - } diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 492e6579e9..97dc513583 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -140,6 +140,11 @@ bool LLURLDispatcherImpl::dispatch(const LLSLURL& slurl, LLMediaCtrl* web, bool trusted_browser) { + // SL-20422 : Clicking the "Bring it back" link on Aditi displays a teleport alert + // Stop further processing empty urls like [secondlife:/// Bring it back.] + if (slurl.getType() == LLSLURL::EMPTY) + return true; + const bool right_click = false; return dispatchCore(slurl, nav_type, right_click, web, trusted_browser); } diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 3e4accb2aa..87c1faee1e 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -988,9 +988,9 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti // // FIRE-22943: Don't switch away from the "Recent Items" tab. - //LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, serverInventoryItem, FALSE, TAKE_FOCUS_NO, (panel == NULL)); - BOOL show_main_panel = (!panel || panel->getName() != "Recent Items"); - LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, serverInventoryItem, show_main_panel, TAKE_FOCUS_NO, (panel == NULL)); + //LLInventoryPanel::openInventoryPanelAndSetSelection(true, serverInventoryItem, false, false, !panel); + bool show_main_panel = (!panel || panel->getName() != "Recent Items"); + LLInventoryPanel::openInventoryPanelAndSetSelection(true, serverInventoryItem, show_main_panel, false, !panel); // // restore keyboard focus diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 643a4da487..7ebcc181e1 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -356,6 +356,7 @@ void force_error_llerror_msg(void*); void force_error_bad_memory_access(void *); void force_error_infinite_loop(void *); void force_error_software_exception(void *); +void force_error_os_exception(void*); void force_error_driver_crash(void *); void force_error_coroutine_crash(void *); void force_error_thread_crash(void *); @@ -2784,6 +2785,15 @@ class LLAdvancedForceErrorSoftwareException : public view_listener_t } }; +class LLAdvancedForceOSException: public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + force_error_os_exception(NULL); + return true; + } +}; + class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -3937,6 +3947,15 @@ bool enable_object_select_in_pathfinding_characters() return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); } +bool enable_os_exception() +{ +#if LL_DARWIN + return true; +#else + return false; +#endif +} + class LLSelfRemoveAllAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -7498,8 +7517,9 @@ void toggle_debug_menus(void*) // bool handleEvent(const LLSD& userdata) // { // LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance(); -// bool nearby_visible = LLFloaterReg::getTypedInstance("nearby_chat")->isInVisibleChain(); -// if(nearby_visible && im_box->getSelectedSession() == LLUUID() && im_box->getConversationListItemSize() > 1) +// LLFloaterIMNearbyChat* floater_nearby = LLFloaterReg::getTypedInstance("nearby_chat"); +// if (floater_nearby->isInVisibleChain() && !floater_nearby->isTornOff() +// && im_box->getSelectedSession() == LLUUID() && im_box->getConversationListItemSize() > 1) // { // im_box->selectNextorPreviousConversation(false); // } @@ -10787,6 +10807,11 @@ void force_error_software_exception(void *) LLAppViewer::instance()->forceErrorSoftwareException(); } +void force_error_os_exception(void*) +{ + LLAppViewer::instance()->forceErrorOSSpecificException(); +} + void force_error_driver_crash(void *) { LLAppViewer::instance()->forceErrorDriverCrash(); @@ -12466,6 +12491,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); + view_listener_t::addMenu(new LLAdvancedForceOSException(), "Advanced.ForceErrorOSException"); view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro"); view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash"); // Wrongly merged back in by LL @@ -12697,6 +12723,7 @@ void initialize_menus() enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets)); commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects)); enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters)); + enable.add("Advanced.EnableErrorOSException", boost::bind(&enable_os_exception)); enable.add("EnableBridgeFunction", boost::bind(&enable_bridge_function)); // view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 949d759b5e..c112f79445 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1726,20 +1726,29 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam } else { - // Highlight item - // Only show if either ShowInInventory is true OR it is an inventory - // offer from an agent and the asset is not previewable - const BOOL auto_open = gSavedSettings.getBOOL("ShowInInventory") || (from_agent_manual && !check_asset_previewable(asset_type)); - //gSavedSettings.getBOOL("ShowInInventory") && // don't open if showininventory is false - //!from_name.empty(); // don't open if it's not from anyone. - // Use correct inventory floater - //if (auto_open) - //{ - // LLFloaterReg::showInstance("inventory"); - //} - // - if (auto_open) // Don't mess with open inventory panels when ShowInInventory is FALSE - LLInventoryPanel::openInventoryPanelAndSetSelection(auto_open, obj_id, true); + // Highlight item + // Only show if either ShowInInventory is true OR it is an inventory + // offer from an agent and the asset is not previewable + //bool show_in_inventory = gSavedSettings.get("ShowInInventory"); + //bool auto_open = + // show_in_inventory && // don't open if ShowInInventory is FALSE + // !from_name.empty(); // don't open if it's not from anyone + + //// SL-20419 : Don't change active tab if floater is visible + //LLFloater* instance = LLFloaterReg::findInstance("inventory"); + //bool use_main_panel = instance && instance->getVisible(); + + //if (auto_open) + //{ + // LLFloaterReg::showInstance("inventory"); + //} + + //LLInventoryPanel::openInventoryPanelAndSetSelection(auto_open, obj_id, use_main_panel); + + const bool auto_open = gSavedSettings.getBOOL("ShowInInventory") || (from_agent_manual && !check_asset_previewable(asset_type)); + if (auto_open) // Don't mess with open inventory panels when ShowInInventory is FALSE + LLInventoryPanel::openInventoryPanelAndSetSelection(auto_open, obj_id, true); + // } } } @@ -5362,7 +5371,7 @@ void process_object_animation(LLMessageSystem *mesgsys, void **user_data) LLObjectSignaledAnimationMap::instance().getMap()[uuid] = signaled_anims; LLViewerObject *objp = gObjectList.findObject(uuid); - if (!objp) + if (!objp || objp->isDead()) { LL_DEBUGS("AnimatedObjectsNotify") << "Received animation state for unknown object " << uuid << LL_ENDL; return; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 59f84a45fc..3ec3ccc4ca 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -410,6 +410,13 @@ LLViewerObject::~LLViewerObject() sNumObjects--; sNumZombieObjects--; llassert(mChildList.size() == 0); + llassert(mControlAvatar.isNull()); // Should have been cleaned by now + if (mControlAvatar.notNull()) + { + mControlAvatar->markForDeath(); + mControlAvatar = NULL; + LL_WARNS() << "Dead object owned a live control avatar" << LL_ENDL; + } clearInventoryListeners(); } @@ -3228,6 +3235,10 @@ void LLViewerObject::updateControlAvatar() return; } + // caller isn't supposed to operate on a dead object, + // avatar was already cleaned up + llassert(!isDead()); + bool should_have_control_avatar = false; if (is_animated_object) { @@ -3324,7 +3335,6 @@ void LLViewerObject::unlinkControlAvatar() if (mControlAvatar) { mControlAvatar->markForDeath(); - mControlAvatar->mRootVolp = NULL; mControlAvatar = NULL; } } @@ -5300,7 +5310,7 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) { LLUUID old_image_id = getTEref(te).getID(); - const LLUUID& uuid = image->getID(); + const LLUUID& uuid = image ? image->getID() : LLUUID::null; S32 retval = 0; if (uuid != getTEref(te).getID() || uuid == LLUUID::null) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f14060d667..edcb5b6783 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -83,7 +83,6 @@ #include "llcorehttputil.h" #include "llcallstack.h" #include "llsettingsdaycycle.h" - #include // Firestorm includes @@ -845,8 +844,13 @@ void LLViewerRegion::loadObjectCache() if(LLVOCache::instanceExists()) { LLVOCache & vocache = LLVOCache::instance(); - vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); - vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD); + // FIRE-33808 - Material Override Cache causes long delays + // vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); + // vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD); + // mark as dirty if read fails to force a rewrite. + mCacheDirty = !vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); + vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mImpl->mCacheMap); + // if (mImpl->mCacheMap.empty()) { @@ -880,10 +884,17 @@ void LLViewerRegion::saveObjectCache() mCacheDirty = FALSE; } - // Map of LLVOCacheEntry takes time to release, store map for cleanup on idle - sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end()); - mImpl->mCacheMap.clear(); - // TODO - probably need to do the same for overrides cache + if (LLAppViewer::instance()->isQuitting()) + { + mImpl->mCacheMap.clear(); + } + else + { + // Map of LLVOCacheEntry takes time to release, store map for cleanup on idle + sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end()); + mImpl->mCacheMap.clear(); + // TODO - probably need to do the same for overrides cache + } } void LLViewerRegion::sendMessage() @@ -1246,12 +1257,16 @@ void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering) } } + // Fix the missing kill on overrides + mImpl->mGLTFOverridesLLSD.erase(entry->getLocalID()); + // //will remove it from the object cache, real deletion entry->setState(LLVOCacheEntry::INACTIVE); entry->removeOctreeEntry(); entry->setValid(FALSE); - - // TODO kill extras/material overrides cache too + // Fix the missing kill on overrides + // // TODO kill extras/material overrides cache too + } //physically delete the cache entry @@ -2749,7 +2764,10 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry) //set parent id U32 parent_id = 0; - LLViewerObject::unpackParentID(entry->getDP(), parent_id); + if (entry->getDP()) // NULL if nothing cached + { + LLViewerObject::unpackParentID(entry->getDP(), parent_id); + } if(parent_id != entry->getParentID()) { entry->setParentID(parent_id); @@ -2769,7 +2787,7 @@ void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry) LLQuaternion rot; //decode spatial info and parent info - U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot); + U32 parent_id = entry->getDP() ? LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot) : entry->getParentID(); U32 old_parent_id = entry->getParentID(); bool same_old_parent = false; @@ -4003,6 +4021,12 @@ void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj) auto iter = mImpl->mGLTFOverridesLLSD.find(local_id); if (iter != mImpl->mGLTFOverridesLLSD.end()) { + // backfill the UUID if it was left empty + if (iter->second.mObjectId.isNull()) + { + iter->second.mObjectId = obj->getID(); + } + // llassert(iter->second.mGLTFMaterial.size() == iter->second.mSides.size()); for (auto& side : iter->second.mGLTFMaterial) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 90a5126194..f10e8df66c 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3613,7 +3613,10 @@ void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep) if(te && te->getID().notNull()) //should have a texture { - LL_ERRS() << "The face does not have a valid texture before media texture." << LL_ENDL; + LL_WARNS_ONCE() << "The face's texture " << te->getID() << " is not valid. Face must have a valid texture before media texture." << LL_ENDL; + // This might break the object, but it likely isn't a 'recoverable' situation. + LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(te->getID()); + mTextureList.push_back(tex); } } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 8d1a9aea36..c8db0876a0 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -700,7 +700,6 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) assert_main_thread(); llassert_always(mInitialized) ; llassert(image); - image->validateRefCount(); S32 count = 0; if (image->isInImageList()) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index ff652cfec6..da0449b2a8 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2724,7 +2724,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) { if (!mIsControlAvatar) { - idleUpdateNameTag( mLastRootPos ); + idleUpdateNameTag(idleCalcNameTagPosition(mLastRootPos)); } return; } @@ -2825,7 +2825,9 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) bool voice_enabled = (visualizers_in_calls || LLVoiceClient::getInstance()->inProximalChannel()) && LLVoiceClient::getInstance()->getVoiceEnabled(mID); - idleUpdateVoiceVisualizer( voice_enabled ); + LLVector3 hud_name_pos = idleCalcNameTagPosition(mLastRootPos); + + idleUpdateVoiceVisualizer(voice_enabled, hud_name_pos); idleUpdateMisc( detailed_update ); idleUpdateAppearanceAnimation(); if (detailed_update) @@ -2836,7 +2838,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) idleUpdateWindEffect(); } - idleUpdateNameTag( mLastRootPos ); + idleUpdateNameTag(hud_name_pos); // Complexity has stale mechanics, but updates still can be very rapid // so spread avatar complexity calculations over frames to lesen load from @@ -2876,7 +2878,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) idleUpdateDebugInfo(); } -void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) +void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled, const LLVector3 &position) { bool render_visualizer = voice_enabled; @@ -2978,24 +2980,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) } } } - - //-------------------------------------------------------------------------------------------- - // here we get the approximate head position and set as sound source for the voice symbol - // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) - //-------------------------------------------------------------------------------------------- - - if ( isSitting() ) - { - LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); - mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot->getWorldPosition() + headOffset ); - } - else - { - LLVector3 tagPos = mRoot->getWorldPosition(); - tagPos[VZ] -= mPelvisToFoot; - tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); // does not need mAvatarOffset -Nyx - mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); - } + mVoiceVisualizer->setPositionAgent(position); }//if ( voiceEnabled ) } @@ -3576,7 +3561,8 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) new_name = TRUE; } - idleUpdateNameTagPosition(root_pos_last); + mNameText->setPositionAgent(root_pos_last); + idleUpdateNameTagText(new_name); // Wolfspirit: Following thing is already handled in LLHUDNameTag::lineSegmentIntersect // Fixing bubblechat alpha flashing with commenting this out. @@ -4136,7 +4122,7 @@ void LLVOAvatar::invalidateNameTags() } // Compute name tag position during idle update -void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +LLVector3 LLVOAvatar::idleCalcNameTagPosition(const LLVector3 &root_pos_last) { LLQuaternion root_rot = mRoot->getWorldRotation(); LLQuaternion inv_root_rot = ~root_rot; @@ -4198,7 +4184,26 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) name_position[VZ] += fsNameTagOffset / 10.f; // - mNameText->setPositionAgent(name_position); + const F32 water_height = getRegion()->getWaterHeight(); + static const F32 WATER_HEIGHT_DELTA = 0.25f; + if (name_position[VZ] < water_height + WATER_HEIGHT_DELTA) + { + if (LLViewerCamera::getInstance()->getOrigin()[VZ] >= water_height) + { + name_position[VZ] = water_height; + } + else if (mNameText) // both camera and HUD are below watermark + { + F32 name_world_height = mNameText->getWorldHeight(); + F32 max_z_position = water_height - name_world_height; + if (name_position[VZ] > max_z_position) + { + name_position[VZ] = max_z_position; + } + } + } + + return name_position; } void LLVOAvatar::idleUpdateNameTagAlpha(bool new_name, F32 alpha) @@ -4321,6 +4326,10 @@ bool LLVOAvatar::isVisuallyMuted() // muted = true; //} // + else if (mIsControlAvatar) + { + muted = isTooSlow(); + } else { muted = isTooComplex(); // this should not trigger based on perfstats diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index b6d81d4383..0c1c03ca20 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -282,7 +282,7 @@ public: void updateTimeStep(); void updateRootPositionAndRotation(LLAgent &agent, F32 speed, bool was_sit_ground_constrained); - void idleUpdateVoiceVisualizer(bool voice_enabled); + void idleUpdateVoiceVisualizer(bool voice_enabled, const LLVector3 &position); void idleUpdateMisc(bool detailed_update); virtual void idleUpdateAppearanceAnimation(); void idleUpdateLipSync(bool voice_enabled); @@ -290,7 +290,6 @@ public: void idleUpdateWindEffect(); void idleUpdateNameTag(const LLVector3& root_pos_last); void idleUpdateNameTagText(bool new_name); - void idleUpdateNameTagPosition(const LLVector3& root_pos_last); void idleUpdateNameTagAlpha(bool new_name, F32 alpha); // Colorize tags //LLColor4 getNameTagColor(bool is_friend); @@ -359,6 +358,8 @@ public: static void updateNearbyAvatarCount(); + LLVector3 idleCalcNameTagPosition(const LLVector3 &root_pos_last); + //-------------------------------------------------------------------- // Static preferences (controlled by user settings/menus) //-------------------------------------------------------------------- diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 5bf990c806..bfcae9d3b4 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -34,6 +34,7 @@ #include "llagentcamera.h" #include "llsdserialize.h" #include "llagent.h" // For gAgent +#include "llworld.h" // For LLWorld::getInstance() //static variables U32 LLVOCacheEntry::sMinFrameRange = 0; @@ -55,6 +56,10 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) { return apr_file->write(src, n_bytes) == n_bytes ; } +// FIRE-33808 - Material Override Cache causes long delays +const std::string LLGLTFOverrideCacheEntry::VERSION_LABEL = {"GLTFCacheVer"}; +const int LLGLTFOverrideCacheEntry::VERSION = 1; +// bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data) { @@ -236,6 +241,8 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) } else { + // improve logging around vocache + LL_WARNS() << "Error loading cache entry for " << mLocalID << ", size " << size << " aborting!" << LL_ENDL; delete[] mBuffer ; mBuffer = NULL ; } @@ -1289,6 +1296,11 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry) { return; } + // FIRE-33808 - Material Override Cache causes long delays + std::string filename; + getObjectCacheFilename(entry->mHandle, filename); + LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL; + // header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry); if(iter != mHeaderEntryQueue.end()) @@ -1359,6 +1371,11 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry) std::string filename; getObjectCacheFilename(entry->mHandle, filename); LLAPRFile::remove(filename, mLocalAPRFilePoolp); + // FIRE-33808 - Material Override Cache causes long delays + // Note that removeFromCache should take responsibility for cleaning up all cache artefactgs specfic to the handle/entry. + // as such this now includes the generic extras + removeGenericExtrasForHandle(entry->mHandle); + // entry->mTime = INVALID_TIME ; updateEntry(entry) ; //update the head file. } @@ -1507,13 +1524,17 @@ BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; } - -void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) +// FIRE-33808 - Material Override Cache causes long delays +// void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) +// we now return bool to trigger dirty cache +// and force a rewrite after a partial read due to corruption. +bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) +// { if(!mEnabled) { LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; - return ; + return true; // FIRE-33808 - Material Override Cache causes long delays } llassert_always(mInitialized); @@ -1521,12 +1542,13 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca if(iter == mHandleEntryMap.end()) //no cache { LL_WARNS() << "No handle map entry for " << handle << LL_ENDL; - return ; + return false; // FIRE-33808 - Material Override Cache causes long delays } bool success = true ; + S32 num_entries=0; // FIRE-33808 - Material Override Cache causes long delays + std::string filename; { - std::string filename; LLUUID cache_id; getObjectCacheFilename(handle, filename); LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); @@ -1543,7 +1565,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca if(success) { - S32 num_entries; // if removal was enabled during write num_entries might be wrong + // S32 num_entries; // if removal was enabled during write num_entries might be wrong success = check_read(&apr_file, &num_entries, sizeof(S32)) ; if(success) @@ -1554,7 +1576,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca if (!entry->getLocalID()) { LL_WARNS() << "Aborting cache file load for " << filename << ", cache file corruption!" << LL_ENDL; - success = false ; + success = false ; break ; } cache_entry_map[entry->getLocalID()] = entry; @@ -1570,13 +1592,24 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca { removeEntry(iter->second) ; } - } - return ; + } + // FIRE-33808 - Material Override Cache causes long delays + // return ; + LL_DEBUGS("GLTF", "VOCache") << "Read " << cache_entry_map.size() << " entries from object cache " << filename << ", expected " << num_entries << ", success=" << (success?"True":"False") << LL_ENDL; + return success; + // } -void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map) +// FIRE-33808 - Material Override Cache causes long delays +// void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map) +void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) { + int loaded= 0; + int discarded = 0; + // get ViewerRegion pointer from handle + LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle); +// if(!mEnabled) { LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; @@ -1598,19 +1631,42 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac std::getline(in, line); if(!in.good()) { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + in.close(); + removeGenericExtrasForHandle(handle); + // return; } + // FIRE-33808 - Material Override Cache causes long delays + // file formats need versions, let's add one. legacy cache files will be considered version 0 + int versionNumber=0; + if (line.compare(0, LLGLTFOverrideCacheEntry::VERSION_LABEL.length(), LLGLTFOverrideCacheEntry::VERSION_LABEL) == 0) + { + std::string versionStr = line.substr(LLGLTFOverrideCacheEntry::VERSION_LABEL.length()+1); // skip the version label and ':' + versionNumber = std::stol(versionStr); + std::getline(in, line); // read the next line for the region UUID check + } + // if(!LLUUID::validate(line)) { LL_WARNS() << "Failed reading extras cache for handle" << handle << ". invalid uuid line: '" << line << "'" << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + in.close(); + removeGenericExtrasForHandle(handle); + // return; } LLUUID cache_id(line); if(cache_id != id) { - LL_INFOS() << "Cache ID doesn't match for this region, discarding" << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + // if the cache id doesn't match the expected region we should just kill the file. + LL_WARNS() << "Cache ID doesn't match for this region, deleting it" << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); + // return; } @@ -1618,6 +1674,10 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac std::getline(in, line); if(!in.good()) { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + in.close(); + removeGenericExtrasForHandle(handle); + // return; } try { @@ -1626,10 +1686,15 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac catch(std::logic_error&) // either invalid_argument or out_of_range { LL_WARNS() << "Failed reading extras cache for handle " << handle << ". unreadable num_entries" << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + in.close(); + removeGenericExtrasForHandle(handle); + // return; } - LL_DEBUGS("GLTF") << "Beginning reading extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + LL_DEBUGS("GLTF") << "Beginning reading extras cache for handle " << handle << " from " << getObjectCacheExtrasFilename(handle) << LL_ENDL; LLSD entry_llsd; for (U32 i = 0; i < num_entries && !in.eof(); i++) @@ -1638,46 +1703,77 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac bool success = LLSDSerialize::deserialize(entry_llsd, in, max_size); // check bool(in) this time since eof is not a failure condition here if(!success || !in) { - LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << LL_ENDL; - return; + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << " cache patrtial load only." << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); + break; + // } LLGLTFOverrideCacheEntry entry; entry.fromLLSD(entry_llsd); U32 local_id = entry_llsd["local_id"].asInteger(); - cache_extras_entry_map[local_id] = entry; + // FIRE-33808 - Material Override Cache causes long delays + // cache_extras_entry_map[local_id] = entry; + // only add entries that exist in the primary cache + // this is a self-healing test that avoids us polluting the cache with entries that are no longer valid. + if(cache_entry_map.find(local_id)!= cache_entry_map.end()) + { + // attempt to backfill a null objectId, though these shouldn't be in the persisted cache really + if(entry.mObjectId.isNull() && pRegion) + { + gObjectList.getUUIDFromLocal( entry.mObjectId, local_id, pRegion->getHost().getAddress(), pRegion->getHost().getPort() ); + } + cache_extras_entry_map[local_id] = entry; + loaded++; + } + else + { + discarded++; + } } - - LL_DEBUGS("GLTF") << "Completed reading extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + LL_DEBUGS("GLTF") << "Completed reading extras cache for handle " << handle << ", " << loaded << " loaded, " << discarded << " discarded" << LL_ENDL; + // } void LLVOCache::purgeEntries(U32 size) { + // FIRE-33808 - Material Override Cache causes long delays + LL_DEBUGS("VOCache","GLTF") << "Purging " << size << " entries from cache" << LL_ENDL; while(mHeaderEntryQueue.size() > size) { header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; HeaderEntryInfo* entry = *iter ; mHandleEntryMap.erase(entry->mHandle); - mHeaderEntryQueue.erase(iter) ; - removeFromCache(entry) ; + // FIRE-33808 - Material Override Cache causes long delays + mHeaderEntryQueue.erase(iter); + removeFromCache(entry); + // delete entry; - // TODO also delete extras + } mNumEntries = mHandleEntryMap.size() ; } void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled) { + // FIRE-33808 - Material Override Cache causes long delays + std::string filename; + getObjectCacheFilename(handle, filename); + // if(!mEnabled) { - LL_WARNS() << "Not writing cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently disabled." << LL_ENDL; return ; } llassert_always(mInitialized); if(mReadOnly) { - LL_WARNS() << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently in read-only mode." << LL_ENDL; return ; } @@ -1712,13 +1808,15 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: //update cache header if(!updateEntry(entry)) { - LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". " << filename << " handle = " << handle << LL_ENDL; return ; //update failed. } if(!dirty_cache) { - LL_WARNS() << "Skipping write to cache for handle " << handle << ": cache not dirty" << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Skipping write to cache for " << filename << " (handle:" << handle << "): cache not dirty" << LL_ENDL; return ; //nothing changed, no need to update. } @@ -1754,6 +1852,8 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: } else { + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Failed to write cache entry to buffer for " << filename << ", entry number " << iter->second->getLocalID() << LL_ENDL; success = false; break; } @@ -1765,6 +1865,8 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: size_in_buffer = 0; if (!success) { + // FIRE-33808 - Material Override Cache causes long delays + LL_WARNS() << "Failed to write cache to disk " << filename << LL_ENDL; break; } } @@ -1775,8 +1877,16 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: { // final write success = check_write(&apr_file, (void*)data_buffer, size_in_buffer); + // FIRE-33808 - Material Override Cache causes long delays + if(!success) + { + LL_WARNS() << "Failed to write cache entry to disk " << filename << LL_ENDL; + } + // size_in_buffer = 0; } + // FIRE-33808 - Material Override Cache causes long delays + LL_DEBUGS("VOCache") << "Wrote " << num_entries << " entries to the primary VOCache file " << filename << ". success = " << (success ? "True":"False") << LL_ENDL; } } } @@ -1788,6 +1898,18 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: return ; } +// FIRE-33808 - Material Override Cache causes long delays +void LLVOCache::removeGenericExtrasForHandle(U64 handle) +{ + if(mReadOnly) + { + LL_WARNS() << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << LL_ENDL; + return ; + } + LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << handle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL; + LLFile::remove(getObjectCacheExtrasFilename(handle)); +} +// void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled) { @@ -1804,46 +1926,106 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL return; } - std::string filename(getObjectCacheExtrasFilename(handle)); + // FIRE-33808 - Material Override Cache causes long delays + std::string filename = getObjectCacheExtrasFilename(handle); + // llofstream out(filename, std::ios::out | std::ios::binary); if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + // FIRE-33808 - Material Override Cache causes long delays + // return; + // // TODO - clean up broken cache file + // } + + // out << id << '\n'; + // if(!out.good()) + // { + // LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + // return; + // // TODO - clean up broken cache file + // } + + // U32 num_entries = cache_extras_entry_map.size(); + // out << num_entries << '\n'; + // if(!out.good()) + // { + // LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + // return; + // // TODO - clean up broken cache file + // } + removeGenericExtrasForHandle(handle); return; - // TODO - clean up broken cache file } + // It is good practice to version file formats so let's add one. + // legacy versions will be treated as version 0. + out << LLGLTFOverrideCacheEntry::VERSION_LABEL << ":" << LLGLTFOverrideCacheEntry::VERSION << '\n'; out << id << '\n'; if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); // FIRE-33808 - Material Override Cache causes long delays return; - // TODO - clean up broken cache file } - U32 num_entries = cache_extras_entry_map.size(); - out << num_entries << '\n'; + auto num_entries_placeholder = out.tellp(); + out << std::setw(10) << std::setfill('0') << 0 << '\n'; if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); return; - // TODO - clean up broken cache file } - for (auto const & entry : cache_extras_entry_map) + // get ViewerRegion pointer from handle + LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle); + + U32 num_entries = 0; + U32 inmem_entries = 0; + U32 skipped = 0; + inmem_entries = cache_extras_entry_map.size(); + for (auto [local_id, entry] : cache_extras_entry_map) { - S32 local_id = entry.first; - LLSD entry_llsd = entry.second.toLLSD(); - entry_llsd["local_id"] = local_id; - LLSDSerialize::serialize(entry_llsd, out, LLSDSerialize::LLSD_XML); - out << '\n'; - if(!out.good()) + // Only write out GLTFOverrides that we can actually apply again on import. + // worst case we have an extra cache miss. + // Note: mObjectId is valid in memory as we might have a data race between GLTF of the object itself. + // This remains a valid state to persist as it is consistent with the localid checks on import with the main cache. + if(entry.mObjectId.isNull() && pRegion) { - LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; - return; - // TODO - clean up broken cache file + gObjectList.getUUIDFromLocal( entry.mObjectId, local_id, pRegion->getHost().getAddress(), pRegion->getHost().getPort() ); + } + + if( /*entry.mObjectId.notNull() &&*/ + entry.mSides.size() > 0 && + entry.mSides.size() == entry.mGLTFMaterial.size() + ) + { + LLSD entry_llsd = entry.toLLSD(); + entry_llsd["local_id"] = (S32)local_id; + LLSDSerialize::serialize(entry_llsd, out, LLSDSerialize::LLSD_XML); + out << '\n'; + if(!out.good()) + { + // We're not in a good place when this happens so we might as well nuke the file. + LL_WARNS() << "Failed writing extras cache for handle " << handle << ". Corrupted cache file " << filename << " removed." << LL_ENDL; + removeGenericExtrasForHandle(handle); + return; + } + num_entries++; + } + else + { + skipped++; } } - - LL_DEBUGS("GLTF") << "Completed writing extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + out.seekp(num_entries_placeholder); + out << std::setw(10) << std::setfill('0') << num_entries << '\n'; + if(!out.good()) + { + LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); + return; + } + LL_DEBUGS("GLTF") << "Completed writing extras cache for handle " << handle << ", " << num_entries << " entries. Total in RAM: " << inmem_entries << " skipped (no persist): " << skipped << LL_ENDL; } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 8525edd121..c4db69ed48 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -43,6 +43,8 @@ class LLCamera; class LLGLTFOverrideCacheEntry { public: + static const std::string VERSION_LABEL; + static const int VERSION; bool fromLLSD(const LLSD& data); LLSD toLLSD() const; @@ -95,12 +97,13 @@ public: } } }; - - struct ExtrasEntry - { - LLSD extras; - std::string extras_raw; - }; + // Unused, remove to reduce cognitive load + // struct ExtrasEntry + // { + // LLSD extras; + // std::string extras_raw; + // }; + // protected: ~LLVOCacheEntry(); @@ -288,13 +291,17 @@ public: // We need this init to be separate from constructor, since we might construct cache, purge it, then init. void initCache(ELLPath location, U32 size, U32 cache_version); void removeCache(ELLPath location, bool started = false) ; - - void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; - void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map); + // FIRE-33808 - Material Override Cache causes long delays + // void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; + // void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map); + bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; + void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map); + // void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled); void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled); void removeEntry(U64 handle) ; + void removeGenericExtrasForHandle(U64 handle); // FIRE-33808 - Material Override Cache causes long delays U32 getCacheEntries() { return mNumEntries; } U32 getCacheEntriesMax() { return mCacheSize; } diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index ccbfe39328..122a2561cf 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -40,6 +40,7 @@ #include "llviewertexturelist.h" #include "llvoiceclient.h" #include "llrender.h" +#include "llagent.h" //brent's wave image //29de489d-0491-fb00-7dab-f9e686d31e83 @@ -349,7 +350,7 @@ void LLVoiceVisualizer::render() //--------------------------------------------------------------- // set the sound symbol position over the source (avatar's head) //--------------------------------------------------------------- - mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; + mSoundSymbol.mPosition = gAgent.getPosAgentFromGlobal(mPositionGlobal) + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; //--------------------------------------------------------------- // some gl state diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 7f9ca41925..a53e783d07 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -595,9 +595,6 @@ void LLVivoxVoiceClient::connectorCreate() << "" << mVoiceAccountServerURI << "" << "Normal" << strConnectorHandle - // Voice in multiple instances; by Latif Khalifa - << (gSavedSettings.getBOOL("VoiceMultiInstance") ? "3000050000" : "") - // << "" << "" << logdir << "" << "Connector" @@ -1039,30 +1036,44 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() // cause SLVoice's bind() call to fail with EADDRINUSE. We expect // that eventually the OS will time out previous ports, which is // why we cycle instead of incrementing indefinitely. - // Unfail voice connection failures - //U32 portbase = gSavedSettings.getU32("VivoxVoicePort"); - //static U32 portoffset = 0; - //static const U32 portrange = 100; - //std::string host(gSavedSettings.getString("VivoxVoiceHost")); - //U32 port = portbase + portoffset; - //portoffset = (portoffset + 1) % portrange; - //params.args.add("-i"); - //params.args.add(STRINGIZE(host << ':' << port)); - // - - std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); - if (loglevel.empty()) - { - loglevel = "0"; - } - params.args.add("-ll"); - params.args.add(loglevel); + static LLCachedControl portbase(gSavedSettings, "VivoxVoicePort"); + static LLCachedControl host(gSavedSettings, "VivoxVoiceHost"); + static LLCachedControl loglevel(gSavedSettings, "VivoxDebugLevel"); + // Strip trailing directory delimiter + //static LLCachedControl log_folder(gSavedSettings, "VivoxLogDirectory"); std::string log_folder = gSavedSettings.getString("VivoxLogDirectory"); + // + static LLCachedControl shutdown_timeout(gSavedSettings, "VivoxShutdownTimeout"); + static const U32 portrange = 100; + static U32 portoffset = 0; + U32 port = 0; - if (log_folder.empty()) + if (LLAppViewer::instance()->isSecondInstance()) { - log_folder = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + // Ideally need to know amount of instances and + // to increment instance_offset on EADDRINUSE. + // But for now just use rand + static U32 instance_offset = portrange * ll_rand(20); + port = portbase + portoffset + instance_offset; + } + else + { + // leave main thread with exclusive port set + port = portbase + portoffset; + } + portoffset = (portoffset + 1) % portrange; + params.args.add("-i"); + params.args.add(STRINGIZE(host() << ':' << port)); + + params.args.add("-ll"); + if (loglevel().empty()) + { + params.args.add("0"); + } + else + { + params.args.add(loglevel); } // Strip trailing directory delimiter @@ -1072,7 +1083,17 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() } // params.args.add("-lf"); - params.args.add(log_folder); + // Strip trailing directory delimiter + //if (log_folder().empty()) + if (log_folder.empty()) + // + { + params.args.add(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")); + } + else + { + params.args.add(log_folder); + } // set log file basename and .log params.args.add("-lp"); @@ -1088,27 +1109,11 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() LLFile::rename(new_log, old_log); } - std::string shutdown_timeout = gSavedSettings.getString("VivoxShutdownTimeout"); - if (!shutdown_timeout.empty()) + if (!shutdown_timeout().empty()) { params.args.add("-st"); params.args.add(shutdown_timeout); } - - // Voice in multiple instances; by Latif Khalifa - if (gSavedSettings.getBOOL("VoiceMultiInstance")) - { - S32 port_nr = 30000 + ll_rand(20000); - LLControlVariable* voice_port = gSavedSettings.getControl("VivoxVoicePort"); - if (voice_port) - { - voice_port->setValue(LLSD(port_nr), false); - params.args.add("-i"); - params.args.add(llformat("127.0.0.1:%u", gSavedSettings.getU32("VivoxVoicePort"))); - } - } - // - params.cwd = gDirUtilp->getAppRODataDir(); // Check if using the old SLVoice for Linux. the SDK in that version is too old to handle the extra args @@ -1130,9 +1135,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() sGatewayPtr = LLProcess::create(params); - // Unfail voice connection failures - //mDaemonHost = LLHost(host.c_str(), port); - mDaemonHost = LLHost(gSavedSettings.getString("VivoxVoiceHost").c_str(), gSavedSettings.getU32("VivoxVoicePort")); + mDaemonHost = LLHost(host().c_str(), port); } else { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 01674a9512..5ec0db0f93 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5824,6 +5824,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; llassert(!gCubeSnapshot); + if (group->isDead()) + { + return; + } + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -5911,7 +5916,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLVOVolume* vobj = drawablep->getVOVolume(); - if (!vobj) + if (!vobj || vobj->isDead()) { continue; } diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 3f0da307f2..9f5d0b3a16 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -979,35 +979,27 @@ void LLWearableItemsList::updateList(const LLUUID& category_id) void LLWearableItemsList::updateChangedItems(const uuid_vec_t& changed_items_uuids) { // nothing to update - if (changed_items_uuids.empty()) return; + if (changed_items_uuids.empty()) + return; - typedef std::vector item_panel_list_t; - - item_panel_list_t items; - getItems(items); - - for (item_panel_list_t::iterator items_iter = items.begin(); - items_iter != items.end(); - ++items_iter) + uuid_vec_t::const_iterator uuids_begin = changed_items_uuids.begin(), uuids_end = changed_items_uuids.end(); + pairs_const_iterator_t pairs_iter = getItemPairs().begin(), pairs_end = getItemPairs().end(); + while (pairs_iter != pairs_end) { - LLPanelInventoryListItemBase* item = dynamic_cast(*items_iter); - if (!item) continue; + LLPanel* panel = (*(pairs_iter++))->first; + LLPanelInventoryListItemBase* item = dynamic_cast(panel); + if (!item) + continue; LLViewerInventoryItem* inv_item = item->getItem(); - if (!inv_item) continue; + if (!inv_item) + continue; - LLUUID linked_uuid = inv_item->getLinkedUUID(); - - for (uuid_vec_t::const_iterator iter = changed_items_uuids.begin(); - iter != changed_items_uuids.end(); - ++iter) - { - if (linked_uuid == *iter) - { - item->setNeedsRefresh(true); - break; - } - } + const LLUUID& linked_uuid = inv_item->getLinkedUUID(); + if (std::find(uuids_begin, uuids_end, linked_uuid) != uuids_end) + { + item->setNeedsRefresh(true); + } } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index bb13672958..a6c5f3d81d 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1799,17 +1799,23 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); - iter != gPipeline.mNearbyLights.end(); iter++) - { - const LLViewerObject *vobj = iter->drawable->getVObj(); - if (vobj && vobj->getAvatar() - && vobj->isAttachment() && vobj->getAvatar() == muted_avatar) - { - gPipeline.mLights.erase(iter->drawable); - gPipeline.mNearbyLights.erase(iter); - } - } + light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); + while (iter != gPipeline.mNearbyLights.end()) + { + const LLViewerObject* vobj = iter->drawable->getVObj(); + if (vobj + && vobj->getAvatar() + && vobj->isAttachment() + && vobj->getAvatar() == muted_avatar) + { + gPipeline.mLights.erase(iter->drawable); + iter = gPipeline.mNearbyLights.erase(iter); + } + else + { + iter++; + } + } } U32 LLPipeline::addObject(LLViewerObject *vobj) diff --git a/indra/newview/skins/ansastorm/xui/en/sidepanel_appearance.xml b/indra/newview/skins/ansastorm/xui/en/sidepanel_appearance.xml index cf76ace7be..01421f6099 100644 --- a/indra/newview/skins/ansastorm/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/ansastorm/xui/en/sidepanel_appearance.xml @@ -108,8 +108,7 @@ width="415"> top="6" width="24" /> - + @@ -1077,6 +1078,8 @@ with the same filename but different name + + diff --git a/indra/newview/skins/default/xui/az/panel_preferences_sound.xml b/indra/newview/skins/default/xui/az/panel_preferences_sound.xml index 59fa3606c3..7ea84d21e5 100644 --- a/indra/newview/skins/default/xui/az/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/az/panel_preferences_sound.xml @@ -98,7 +98,6 @@ Avtomatik oxutma - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Please wait @@ -136,7 +137,7 @@ layout="topleft" left_delta="0" name="bar0" - top_delta="-2" + top_delta="-5" width="20" /> + + Disabled + +