diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 44f32c1c5d329f77b8584dbee495c1645f1a6ebd..4785273b78b582fb166ad6280009db971e374a5a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -5,7 +5,7 @@ on: pull_request: push: branches: ["main", "release/*", "project/*"] - tags: ["Second_Life_*"] + tags: ["Second_Life*"] jobs: build: @@ -176,16 +176,22 @@ jobs: # seen before, so numerous tests don't know about it. [[ "$arch" == "MINGW6" ]] && arch=CYGWIN export AUTOBUILD="$(which autobuild)" - # Build with a tag like "Second_Life_Project_Shiny#abcdef0" to get a - # viewer channel "Second Life Project Shiny" (ignoring "#hash", - # needed to disambiguate tags). - if [[ "$GITHUB_REF_TYPE" == "tag" && "${GITHUB_REF_NAME:0:12}" == "Second_Life_" ]] - then viewer_channel="${GITHUB_REF_NAME%#*}" - export viewer_channel="${viewer_channel//_/ }" - else export viewer_channel="Second Life Test" + + # determine the viewer channel from the branch name + branch=$AUTOBUILD_VCS_BRANCH + IFS='/' read -ra ba <<< $branch + prefix=${ba[0]} + if [ "$prefix" == "project" ]; then + IFS='_' read -ra prj <<< "${ba[1]}" + # uppercase first letter of each word + export viewer_channel="Second Life Project ${prj[*]^}" + elif [[ "$prefix" == "release" || "$prefix" == "main" ]]; + then + export viewer_channel="Second Life Release" + else + export viewer_channel="Second Life Test" fi echo "viewer_channel=$viewer_channel" >> "$GITHUB_OUTPUT" - # On windows we need to point the build to the correct python # as neither CMake's FindPython nor our custom Python.cmake module # will resolve the correct interpreter location. @@ -354,7 +360,8 @@ jobs: release: needs: [build, sign-and-package-windows, sign-and-package-mac] runs-on: ubuntu-latest - if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life_') + # Build with a tag like "Second_Life#abcdef0" to generate a release page (used for builds we are planning to deploy). + if: github.ref_type == 'tag' && startsWith(github.ref_name, 'Second_Life') steps: - uses: actions/download-artifact@v4 with: diff --git a/build.sh b/build.sh index 46a287ea32764f95e134d1867e7e4c6ede5d59d4..e025b731708483055e6b8e4c2933850c32ab36d8 100755 --- a/build.sh +++ b/build.sh @@ -178,6 +178,7 @@ pre_build() "$autobuild" configure --quiet -c $variant \ ${eval_autobuild_configure_parameters:---} \ + -DLL_TESTS:BOOL=ON \ -DPACKAGE:BOOL=ON \ -DHAVOK:BOOL="$HAVOK" \ -DRELEASE_CRASH_REPORTING:BOOL="$RELEASE_CRASH_REPORTING" \ diff --git a/doc/contributions.txt b/doc/contributions.txt index a14ffa24fd177e436dcd5a270019d7472f1a1c20..ffee07c38314e92db7ba4face68896ada73ba51a 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -245,6 +245,7 @@ Ansariel Hiller SL-19623 SL-4126 SL-20224 + SL-20524 Aralara Rajal Arare Chantilly CHUIBUG-191 @@ -388,6 +389,7 @@ Chaser Zaks BUG-225599 BUG-227485 SL-16874 + SL-20442 Cherry Cheevers ChickyBabes Zuzu Chorazin Allen diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 7b14e9dc0379e4e1b720fe130f628b2833dabe0a..48f4adccf19caf57d3bc40564b12a142245a16ba 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -25,7 +25,6 @@ set(cmake_SOURCE_FILES FreeType.cmake GLEXT.cmake Hunspell.cmake - ICU4C.cmake LibXML2.cmake LLAddBuildTest.cmake LLAppearance.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c83b36dffcd40d96d3f906de72bdffd98f7653ae..c9266b8f7934b1b97e46fb8beee0a73a6178d923 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -52,7 +52,7 @@ if(WINDOWS) endif (ADDRESS_SIZE EQUAL 64) #******************************* - # Misc shared libs + # Misc shared libs set(addrsfx "-x${ADDRESS_SIZE}") @@ -66,13 +66,6 @@ if(WINDOWS) openjp2.dll ) - # ICU4C (same filenames for 32 and 64 bit builds) - set(release_files ${release_files} icudt75.dll) - set(release_files ${release_files} icuin75.dll) - set(release_files ${release_files} icuio75.dll) - set(release_files ${release_files} icutu75.dll) - set(release_files ${release_files} icuuc75.dll) - # Filenames are different for 32/64 bit BugSplat file and we don't # have any control over them so need to branch. if (TARGET al::sentry) diff --git a/indra/cmake/ICU4C.cmake b/indra/cmake/ICU4C.cmake deleted file mode 100644 index ca6fafc493ed8110465f926bacf40d7baad5a496..0000000000000000000000000000000000000000 --- a/indra/cmake/ICU4C.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - -include_guard() - -add_library( ll::icu4c INTERFACE IMPORTED ) - -use_system_binary(icu4c) -use_prebuilt_binary(icu4c) -if (WINDOWS) - target_link_libraries( ll::icu4c INTERFACE icuuc) -elseif(DARWIN) - target_link_libraries( ll::icu4c INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libicudata.a ${ARCH_PREBUILT_DIRS_RELEASE}/libicuuc.a) -elseif(LINUX) - target_link_libraries( ll::icu4c INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libicudata.a ${ARCH_PREBUILT_DIRS_RELEASE}/libicuuc.a) -else() - message(FATAL_ERROR "Invalid platform") -endif() - -target_include_directories( ll::icu4c SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/unicode ) - -use_prebuilt_binary(dictionaries) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 2b0fd1078ec1104a103b1e4c0c2701e418525105..e9718d95c59b1fbafc8eb071526811326a114334 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -495,70 +495,45 @@ void LLAvatarAppearance::computeBodySize() mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale(); mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition(); - LLVector3 pelvis_scale = mPelvisp->getScale(); - - // some of the joints have not been cached - LLVector3 skull = mSkullp->getPosition(); - //LLVector3 skull_scale = mSkullp->getScale(); - - LLVector3 neck = mNeckp->getPosition(); - LLVector3 neck_scale = mNeckp->getScale(); - - LLVector3 chest = mChestp->getPosition(); - LLVector3 chest_scale = mChestp->getScale(); - - // the rest of the joints have been cached - LLVector3 head = mHeadp->getPosition(); - LLVector3 head_scale = mHeadp->getScale(); - - LLVector3 torso = mTorsop->getPosition(); - LLVector3 torso_scale = mTorsop->getScale(); - - LLVector3 hip = mHipLeftp->getPosition(); - LLVector3 hip_scale = mHipLeftp->getScale(); - - LLVector3 knee = mKneeLeftp->getPosition(); - LLVector3 knee_scale = mKneeLeftp->getScale(); - - LLVector3 ankle = mAnkleLeftp->getPosition(); - LLVector3 ankle_scale = mAnkleLeftp->getScale(); - - LLVector3 foot = mFootLeftp->getPosition(); - + F32 old_height = mBodySize.mV[VZ]; F32 old_offset = mAvatarOffset.mV[VZ]; - mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER); - - mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - - knee.mV[VZ] * hip_scale.mV[VZ] - - ankle.mV[VZ] * knee_scale.mV[VZ] - - foot.mV[VZ] * ankle_scale.mV[VZ]; + // TODO: Measure the real depth and width + mPelvisToFoot = computePelvisToFoot(); + F32 new_height = computeBodyHeight(); + mBodySize.set(DEFAULT_AGENT_DEPTH, DEFAULT_AGENT_WIDTH, new_height); + F32 new_offset = getVisualParamWeight(AVATAR_HOVER); + mAvatarOffset.set(0, 0, new_offset); - LLVector3 new_body_size; - new_body_size.mV[VZ] = mPelvisToFoot + - // the sqrt(2) correction below is an approximate - // correction to get to the top of the head - F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + - head.mV[VZ] * neck_scale.mV[VZ] + - neck.mV[VZ] * chest_scale.mV[VZ] + - chest.mV[VZ] * torso_scale.mV[VZ] + - torso.mV[VZ] * pelvis_scale.mV[VZ]; - - // TODO -- measure the real depth and width - new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; - new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; - - mAvatarOffset.mV[VX] = 0.0f; - mAvatarOffset.mV[VY] = 0.0f; - - if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ]) + if (mBodySize.mV[VZ] != old_height || new_offset != old_offset) { - mBodySize = new_body_size; - compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState); } } +F32 LLAvatarAppearance::computeBodyHeight() +{ + F32 result = mPelvisToFoot + + // all these relative positions usually are positive + mPelvisp->getScale().mV[VZ] * mTorsop->getPosition().mV[VZ] + + mTorsop->getScale().mV[VZ] * mChestp->getPosition().mV[VZ] + + mChestp->getScale().mV[VZ] * mNeckp->getPosition().mV[VZ] + + mNeckp->getScale().mV[VZ] * mHeadp->getPosition().mV[VZ] + + mHeadp->getScale().mV[VZ] * mSkullp->getPosition().mV[VZ] * 2; + return result; +} + +F32 LLAvatarAppearance::computePelvisToFoot() +{ + F32 result = + // all these relative positions usually are negative + mPelvisp->getScale().mV[VZ] * mHipLeftp->getPosition().mV[VZ] + + mHipLeftp->getScale().mV[VZ] * mKneeLeftp->getPosition().mV[VZ] + + mKneeLeftp->getScale().mV[VZ] * mAnkleLeftp->getPosition().mV[VZ] + + mAnkleLeftp->getScale().mV[VZ] * mFootLeftp->getPosition().mV[VZ] / 2; + return -result; +} + //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 55cf7707be8116401fcc4b61aa29f0d855eb56a1..f777c743226e6c5bf321d44c77041b309692f9d2 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -149,7 +149,9 @@ class LLAvatarAppearance : public LLCharacter joint_state_map_t mCurrBodySizeState; void compareJointStateMaps(joint_state_map_t& last_state, joint_state_map_t& curr_state); - void computeBodySize(); + void computeBodySize(); + F32 computeBodyHeight(); + F32 computePelvisToFoot(); public: typedef std::vector<LLAvatarJoint*> avatar_joint_list_t; diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 7ad156506a40af8b5b348f26e36db202e228e0b6..e9789730e268a93983b6649ed27c38350116d9e0 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -550,7 +550,7 @@ void LLWearable::revertValues() if(param) { F32 value = vp_pair.second; - setVisualParamWeight(id, value); + param->setWeight(value); mSavedVisualParamMap[id] = param->getWeight(); } } diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index e57775dc3bf1eb90825db4cc4832893bb7fdf299..f0b79d622a15d93ffe775e6c51d3639caf258b9c 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -42,16 +42,6 @@ const S32 GESTURE_VERSION = 2; // LLMultiGesture //--------------------------------------------------------------------------- LLMultiGesture::LLMultiGesture() -: mKey(), - mMask(), - mName(), - mTrigger(), - mReplaceText(), - mSteps(), - mPlaying(FALSE), - mCurrentStep(0), - mDoneCallback(NULL), - mCallbackData(NULL) { reset(); } @@ -67,8 +57,11 @@ void LLMultiGesture::reset() mPlaying = FALSE; mCurrentStep = 0; mWaitTimer.reset(); - mWaitingTimer = FALSE; mWaitingAnimations = FALSE; + mWaitingKeyRelease = FALSE; + mWaitingTimer = FALSE; + mTriggeredByKey = FALSE; + mKeyReleased = FALSE; mWaitingAtEnd = FALSE; mRequestedAnimIDs.clear(); mPlayingAnimIDs.clear(); diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index 31fab5d67bfa9bbf30d6f7770389f8bf6efd65ba..950fcf2e827e9ddc429b5b0808ce5f47024b9210 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -59,8 +59,8 @@ class LLMultiGesture const LLMultiGesture& operator=(const LLMultiGesture& rhs); public: - KEY mKey; - MASK mMask; + KEY mKey { 0 }; + MASK mMask { 0 }; // This name can be empty if the inventory item is not around and // the gesture manager has not yet set the name @@ -75,25 +75,34 @@ class LLMultiGesture std::vector<LLGestureStep*> mSteps; // Is the gesture currently playing? - BOOL mPlaying; + BOOL mPlaying { FALSE }; // "instruction pointer" for steps - S32 mCurrentStep; + S32 mCurrentStep { 0 }; // We're waiting for triggered animations to stop playing - BOOL mWaitingAnimations; + BOOL mWaitingAnimations { FALSE }; + + // We're waiting for key release + BOOL mWaitingKeyRelease { FALSE }; // We're waiting a fixed amount of time - BOOL mWaitingTimer; + BOOL mWaitingTimer { FALSE }; + + // We're waiting for triggered animations to stop playing + BOOL mTriggeredByKey { FALSE }; + + // Has the key been released? + BOOL mKeyReleased { FALSE }; // Waiting after the last step played for all animations to complete - BOOL mWaitingAtEnd; + BOOL mWaitingAtEnd { FALSE }; // Timer for waiting LLFrameTimer mWaitTimer; - void (*mDoneCallback)(LLMultiGesture* gesture, void* data); - void* mCallbackData; + void (*mDoneCallback)(LLMultiGesture* gesture, void* data) { NULL }; + void* mCallbackData { NULL }; // Animations that we requested to start std::set<LLUUID> mRequestedAnimIDs; @@ -210,6 +219,7 @@ class LLGestureStepChat : public LLGestureStep const U32 WAIT_FLAG_TIME = 0x01; const U32 WAIT_FLAG_ALL_ANIM = 0x02; +const U32 WAIT_FLAG_KEY_RELEASE = 0x04; class LLGestureStepWait : public LLGestureStep { diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 59876094058547e4a1923457ddcc3cd217dd04df..b2bc5956225197e5e89cec59e463666817776111 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -3,7 +3,6 @@ project(llcommon) include(00-Common) -include(ICU4C) include(LLCommon) include(LLMath) include(Linking) @@ -289,7 +288,6 @@ target_link_libraries( ll::uriparser ll::oslibraries ll::tracy - ll::icu4c ll::xxhash fmt::fmt ) diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index f481ba4ef15a1409590b5d5696881d396c3ec4a9..7636884f679708c39765087efa8915753e4b152f 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(900*1024), + mStackSize(1024*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/llstring.cpp b/indra/llcommon/llstring.cpp index b08e70a1229f9f80b49b545753d5c8436428b698..a2f3cd424912f7aa69f063654402b5703aea8885 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -30,7 +30,6 @@ #include "llerror.h" #include "llfasttimer.h" #include "llsd.h" -#include <unicode/uchar.h> #include <vector> #if LL_WINDOWS @@ -830,6 +829,43 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str) return result; } +// Search for any emoji symbol, return true if found +bool wstring_has_emoji(const LLWString& wstr) +{ + for (const llwchar& wch : wstr) + { + if (LLStringOps::isEmoji(wch)) + return true; + } + + return false; +} + +// Cut emoji symbols if exist +bool wstring_remove_emojis(LLWString& wstr) +{ + bool found = false; + for (size_t i = 0; i < wstr.size(); ++i) + { + if (LLStringOps::isEmoji(wstr[i])) + { + wstr.erase(i--, 1); + found = true; + } + } + return found; +} + +// Cut emoji symbols if exist +bool utf8str_remove_emojis(std::string& utf8str) +{ + LLWString wstr = utf8str_to_wstring(utf8str); + if (!wstring_remove_emojis(wstr)) + return false; + utf8str = wstring_to_utf8str(wstr); + return true; +} + #if LL_WINDOWS unsigned int ll_wstring_default_code_page() { @@ -1083,44 +1119,18 @@ std::string LLStringOps::sAM; std::string LLStringOps::sPM; // static -bool LLStringOps::isEmoji(llwchar wch) -{ - int ublock = ublock_getCode(wch); - switch (ublock) - { - case UBLOCK_GENERAL_PUNCTUATION: - case UBLOCK_LETTERLIKE_SYMBOLS: - case UBLOCK_ARROWS: - case UBLOCK_MISCELLANEOUS_TECHNICAL: - case UBLOCK_ENCLOSED_ALPHANUMERICS: - case UBLOCK_GEOMETRIC_SHAPES: - case UBLOCK_MISCELLANEOUS_SYMBOLS: - case UBLOCK_DINGBATS: - case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION: - case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS: - case UBLOCK_MAHJONG_TILES: - case UBLOCK_ENCLOSED_ALPHANUMERIC_SUPPLEMENT: - case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: - case UBLOCK_EMOTICONS: - case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS: - case UBLOCK_GEOMETRIC_SHAPES_EXTENDED: -#if U_ICU_VERSION_MAJOR_NUM > 56 - // Boost uses ICU so we can't update it independently - case UBLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS: -#endif // U_ICU_VERSION_MAJOR_NUM > 56 - case UBLOCK_SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A: - return true; - default: -#if U_ICU_VERSION_MAJOR_NUM > 56 - return false; +bool LLStringOps::isEmoji(llwchar a) +{ +#if 0 // Do not consider special characters that might have a corresponding + // glyph in the monochorme fallback fonts as a "genuine" emoji. HB + return a == 0xa9 || a == 0xae || (a >= 0x2000 && a < 0x3300) || + (a >= 0x1f000 && a < 0x20000); #else - // See https://en.wikipedia.org/wiki/Supplemental_Symbols_and_Pictographs - return wch >= 0x1F900 && wch <= 0x1F9FF; -#endif // U_ICU_VERSION_MAJOR_NUM > 56 - } + // These are indeed "genuine" emojis, we *do want* rendered as such. HB + return a >= 0x1f000 && a < 0x20000; +#endif } - S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7882d8a2a9c4bd4e62c64c6b1e4c6338e614b766..3d72baa880bc84a9878c56e44746b1c385efe20a 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -214,7 +214,8 @@ class LL_COMMON_API LLStringOps static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } - static bool isEmoji(llwchar wch); + // Returns true when 'a' corresponds to a "genuine" emoji. HB + static bool isEmoji(llwchar a); static S32 collate(const char* a, const char* b) { return strcoll(a, b); } static S32 collate(const llwchar* a, const llwchar* b); @@ -780,6 +781,12 @@ LL_COMMON_API llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset LL_COMMON_API std::string utf8str_showBytesUTF8(const std::string& utf8str); +LL_COMMON_API bool wstring_has_emoji(const LLWString& wstr); + +LL_COMMON_API bool wstring_remove_emojis(LLWString& wstr); + +LL_COMMON_API bool utf8str_remove_emojis(std::string& utf8str); + #if LL_WINDOWS /* @name Windows string helpers */ diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index f0439ec48dba82ea6a758cd58605064ee0f394ba..25391310a3f886039035aecdb35101c3e475f533 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -1383,6 +1383,10 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile) } while(gzeof(src) == 0); fclose(dst); dst = NULL; +#if LL_WINDOWS + // Rename in windows needs the dstfile to not exist. + LLFile::remove(dstfile, ENOENT); +#endif if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */ retval = TRUE; err: diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 81f89e374ac88dc9e464a3d62897ef0e1929356c..64efbe0cfe2bd2afacf4424214f9fe490d45b69a 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -587,8 +587,7 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src //--------------------------------------------------------------------------- //static -std::string LLImage::sLastErrorMessage; -LLMutex* LLImage::sMutex = NULL; +thread_local std::string LLImage::sLastThreadErrorMessage; bool LLImage::sUseNewByteRange = false; S32 LLImage::sMinimalReverseByteRangePercent = 75; @@ -597,28 +596,24 @@ void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_ { sUseNewByteRange = use_new_byte_range; sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; - sMutex = new LLMutex(); } //static void LLImage::cleanupClass() { - delete sMutex; - sMutex = NULL; } //static -const std::string& LLImage::getLastError() +const std::string& LLImage::getLastThreadError() { static const std::string noerr("No Error"); - return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; + return sLastThreadErrorMessage.empty() ? noerr : sLastThreadErrorMessage; } //static void LLImage::setLastError(const std::string& message) { - LLMutexLock m(sMutex); - sLastErrorMessage = message; + sLastThreadErrorMessage = message; } //--------------------------------------------------------------------------- diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 4c63d59d9819042e98a0a1e6d4104d9509dc3583..78062da0089d2faadce543f977bdbe2551a35eb6 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -96,15 +96,14 @@ class LLImage static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); static void cleanupClass(); - static const std::string& getLastError(); + static const std::string& getLastThreadError(); static void setLastError(const std::string& message); static bool useNewByteRange() { return sUseNewByteRange; } static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; } protected: - static LLMutex* sMutex; - static std::string sLastErrorMessage; + static thread_local std::string sLastThreadErrorMessage; static bool sUseNewByteRange; static S32 sMinimalReverseByteRangePercent; }; diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index 5d7f0bfa95a5a1148c2ff80b8f38588a7b4cd8bc..7eb7c172c2866f46a48b9f6e6911b96bf1b1c429 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -27,6 +27,7 @@ #include "linden_common.h" #include "stdtypes.h" #include "llerror.h" +#include "llexception.h" #include "llimage.h" #include "llpngwrapper.h" @@ -47,30 +48,45 @@ bool LLImagePNG::updateData() { resetLastError(); - // Check to make sure that this instance has been initialized with data - if (!getData() || (0 == getDataSize())) + try { - setLastError("Uninitialized instance of LLImagePNG"); - return false; + // Check to make sure that this instance has been initialized with data + if (!getData() || (0 == getDataSize())) + { + setLastError("Uninitialized instance of LLImagePNG"); + return false; + } + + // Decode the PNG data and extract sizing information + LLPngWrapper pngWrapper; + if (!pngWrapper.isValidPng(getData())) + { + setLastError("LLImagePNG data does not have a valid PNG header!"); + return false; + } + + LLPngWrapper::ImageInfo infop; + if (!pngWrapper.readPng(getData(), getDataSize(), NULL, &infop)) + { + setLastError(pngWrapper.getErrorMessage()); + return false; + } + + setSize(infop.mWidth, infop.mHeight, infop.mComponents); } - - // Decode the PNG data and extract sizing information - LLPngWrapper pngWrapper; - if (!pngWrapper.isValidPng(getData())) + catch (const LLContinueError& msg) { - setLastError("LLImagePNG data does not have a valid PNG header!"); + setLastError(msg.what()); + LOG_UNHANDLED_EXCEPTION(""); return false; } - - LLPngWrapper::ImageInfo infop; - if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop)) + catch (...) { - setLastError(pngWrapper.getErrorMessage()); + setLastError("LLImagePNG"); + LOG_UNHANDLED_EXCEPTION(""); return false; } - setSize(infop.mWidth, infop.mHeight, infop.mComponents); - return true; } diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index ace2ebe52ad7ca001674084a2eaf098aa703538e..c16df7a449ddb1eac3507b52d9f7586e1a74ec3a 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -58,6 +58,7 @@ class ImageRequest BOOL mDecodedRaw; BOOL mDecodedAux; LLPointer<LLImageDecodeThread::Responder> mResponder; + std::string mErrorString; }; @@ -156,6 +157,7 @@ bool ImageRequest::processRequest() LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; const F32 decode_time_slice = 0.f; //disable time slicing bool done = true; + mErrorString.clear(); if (!mDecodedRaw && mFormattedImage.notNull()) { // Decode primary channels @@ -164,10 +166,13 @@ bool ImageRequest::processRequest() // parse formatted header if (!mFormattedImage->updateData()) { + // Pick up errors from updateData + mErrorString = LLImage::getLastThreadError(); return true; // done (failed) } if ((mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()) <= 0) { + mErrorString = "Invalid image size"; return true; // done (failed) } if (mDiscardLevel >= 0) @@ -181,6 +186,9 @@ bool ImageRequest::processRequest() done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // some decoders are removing data when task is complete and there were errors mDecodedRaw = done && mDecodedImageRaw->getData(); + + // Pick up errors from decoding + mErrorString = LLImage::getLastThreadError(); } if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull()) { @@ -193,6 +201,9 @@ bool ImageRequest::processRequest() } done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); mDecodedAux = done && mDecodedImageAux->getData(); + + // Pick up errors from decoding + mErrorString = LLImage::getLastThreadError(); } return done; @@ -204,7 +215,7 @@ void ImageRequest::finishRequest(bool completed) if (mResponder.notNull()) { bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); - mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux, mRequestId); + mResponder->completed(success, mErrorString, mDecodedImageRaw, mDecodedImageAux, mRequestId); } // Will automatically be deleted } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 92d70b451d051b9fd7986a106ce97877ab1d8fa2..8c43a7c32c678ec0c4aad7c2d9a047f6fa547c3d 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -39,7 +39,7 @@ class LLImageDecodeThread protected: virtual ~Responder(); public: - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0; + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) = 0; }; public: diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index af4f7e3a6e169c1b1d0b88c1822d21b7d3e50c8b..78a7b7c259e863d4871bca4af51cc2327e7898e8 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -216,6 +216,13 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf releaseResources(); return (FALSE); } + catch (...) + { + mErrorMessage = "LLPngWrapper"; + releaseResources(); + LOG_UNHANDLED_EXCEPTION(""); + return (FALSE); + } // Clean up and return releaseResources(); diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 49fc1afd82ae5c310adf1635258c7a6839ec0ae2..2568adf89e4b5ceb7c773ce9c3aa5a901f1a7168 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -68,6 +68,7 @@ U8* LLImageRaw::allocateData(S32 size) { return NULL; } U8* LLImageRaw::reallocateData(S32 size) { return NULL; } const U8* LLImageBase::getData() const { return NULL; } U8* LLImageBase::getData() { return NULL; } +const std::string& LLImage::getLastThreadError() { static std::string msg; return msg; } // End Stubbing // ------------------------------------------------------------------------------------------- @@ -98,7 +99,7 @@ namespace tut done = res; *done = false; } - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32) + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { *done = true; } diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 9ecaac58ea23cb05a4c2bc2434145511d34a8d4b..067acb6f1f664c357157df45acab7fe6e7302dff 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -722,7 +722,7 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position) dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000f, 0.5260f, 1.0000f, 0.0f).getValue(); dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000f, 0.5260f, 1.0000f, 0.0f).getValue(); dfltsetting[SETTING_CLOUD_SCALE] = LLSD::Real(0.4199); - dfltsetting[SETTING_CLOUD_SCROLL_RATE] = llsd::array(0.0f, 0.0f); + dfltsetting[SETTING_CLOUD_SCROLL_RATE] = llsd::array(0.2, 0.01); dfltsetting[SETTING_CLOUD_SHADOW] = LLSD::Real(0.2699); dfltsetting[SETTING_CLOUD_VARIANCE] = LLSD::Real(0.0); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 7330ece890bebd130719c37b5ef3e55ad96d40c6..d2801752edcb513b65f4d0e07d12a0935fa57465 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -122,7 +122,7 @@ const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f; const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE; const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE; -const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e"; +const LLUUID SCULPT_DEFAULT_TEXTURE("be293869-d0d9-0a69-5989-ad27f1946fd4"); // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e"; // Texture rotations are sent over the wire as a S16. This is used to scale the actual float // value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it @@ -2083,7 +2083,7 @@ bool LLFlexibleObjectData::fromLLSD(LLSD& sd) LLSculptParams::LLSculptParams() { mType = PARAMS_SCULPT; - mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptTexture = SCULPT_DEFAULT_TEXTURE; mSculptType = LL_SCULPT_TYPE_SPHERE; } @@ -2169,7 +2169,7 @@ void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type) U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) { - mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptTexture = SCULPT_DEFAULT_TEXTURE; mSculptType = LL_SCULPT_TYPE_SPHERE; } else diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 29bd184cd5cae833957028b1c26d16714745ccfd..42ff945d787d8241a6b16774dbc6180b35b0bb83 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -93,7 +93,7 @@ extern const F32 OBJECT_REV_MIN; extern const F32 OBJECT_REV_MAX; extern const F32 OBJECT_REV_INC; -extern const char *SCULPT_DEFAULT_TEXTURE; +extern const LLUUID SCULPT_DEFAULT_TEXTURE; //============================================================================ diff --git a/indra/llprimitive/tests/llgltfmaterial_test.cpp b/indra/llprimitive/tests/llgltfmaterial_test.cpp index 9ca190087b5b6f21f361c7c60fc19e4f1e39fca2..7f89a11160f5c2f1b61bba32b5d4b05f6219e2e7 100644 --- a/indra/llprimitive/tests/llgltfmaterial_test.cpp +++ b/indra/llprimitive/tests/llgltfmaterial_test.cpp @@ -153,7 +153,7 @@ namespace tut #if LL_WINDOWS // If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial) // This test result will vary between compilers, so only test a single platform - ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 232); + ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 224); #endif #endif ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4); diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 9b023462f66832f5634732d8891a956c55aebb8e..f8961e92c74f079e3a65ebe30ef124cd3203d763 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -336,11 +336,10 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename) return num_faces; } -void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor) +void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, + const char_functor_t& functor) { - // Insert functor fallbacks before generic fallbacks - mFallbackFonts.insert((functor) ? std::find_if(mFallbackFonts.begin(), mFallbackFonts.end(), [](const fallback_font_t& fe) { return !fe.second; }) : mFallbackFonts.end(), - std::make_pair(fallback_font, functor)); + mFallbackFonts.emplace_back(fallback_font, functor); } F32 LLFontFreetype::getLineHeight() const @@ -430,50 +429,95 @@ BOOL LLFontFreetype::hasGlyph(llwchar wch) const LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type) const { - if (mFTFace == NULL) - return FALSE; + if (!mFTFace) + { + return NULL; + } llassert(!mIsFallback); llassert(glyph_type < EFontGlyphType::Count); - //LL_DEBUGS() << "Adding new glyph for " << wstring_to_utf8str(LLWString(1, wch)) << " to font " << mName << LL_ENDL; - - FT_UInt glyph_index; + //LL_DEBUGS() << "Adding new glyph for " << wch << " to font" << LL_ENDL; - // Fallback fonts with a functor have precedence over everything else - fallback_font_vector_t::const_iterator it_fallback = mFallbackFonts.cbegin(); - /* This leads to a bug SL-19831 "Check marks in the menu are less visible." - ** Also, LLFontRegistry::createFont() says: "Fallback fonts don't render" - for (; it_fallback != mFallbackFonts.cend() && it_fallback->second; ++it_fallback) + // Initialize char to glyph map + FT_UInt glyph_index = FT_Get_Char_Index(mFTFace, wch); + if (glyph_index == 0) { - if (it_fallback->second(wch)) + // No corresponding glyph in this font: look for a glyph in fallback + // fonts. + size_t count = mFallbackFonts.size(); + if (LLStringOps::isEmoji(wch)) + { + // This is a "genuine" emoji (in the range 0x1f000-0x20000): print + // it using the emoji font(s) if possible. HB + for (size_t i = 0; i < count; ++i) + { + const fallback_font_t& pair = mFallbackFonts[i]; + if (!pair.second || !pair.second(wch)) + { + // If this font does not have a functor, or the character + // does not pass the functor, reject it. Note: we keep the + // functor test (despite the fact we already tested for + // LLStringOps::isEmoji(wch) above), in case we would use + // different, more restrictive or partionned functors in + // the future with several different emoji fonts. HB + continue; + } + glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch); + if (glyph_index) + { + return addGlyphFromFont(pair.first, wch, glyph_index, + glyph_type); + } + } + } + // Then try and find a monochrome fallback font that could print this + // glyph: such fonts do *not* have a functor. We give priority to + // monochrome fonts for non-genuine emojis so that UI elements which + // used to render with them before the emojis font introduction (e.g. + // check marks in menus, or LSL dialogs text and buttons) do render the + // same way as they always did. HB + std::vector<size_t> emoji_fonts_idx; + for (size_t i = 0; i < count; ++i) { - glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch); + const fallback_font_t& pair = mFallbackFonts[i]; + if (pair.second) + { + // If this font got a functor, remember the index for later and + // try the next fallback font. HB + emoji_fonts_idx.push_back(i); + continue; + } + glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch); if (glyph_index) { - return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type); + return addGlyphFromFont(pair.first, wch, glyph_index, + glyph_type); } } - } - */ - - // Initialize char to glyph map - glyph_index = FT_Get_Char_Index(mFTFace, wch); - if (glyph_index == 0) - { - //LL_INFOS() << "Trying to add glyph from fallback font!" << LL_ENDL; - for (; it_fallback != mFallbackFonts.cend(); ++it_fallback) + // Everything failed so far: this character is not a genuine emoji, + // neither a special character known from our monochrome fallback + // fonts: make a last try, using the emoji font(s), but ignoring the + // functor to render using whatever (colorful) glyph that might be + // available in such fonts for this character. HB + for (size_t j = 0, count2 = emoji_fonts_idx.size(); j < count2; ++j) { - glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch); + const fallback_font_t& pair = mFallbackFonts[emoji_fonts_idx[j]]; + glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch); if (glyph_index) { - return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type); + return addGlyphFromFont(pair.first, wch, glyph_index, + glyph_type); } } } - std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch); + auto range_it = mCharGlyphInfoMap.equal_range(wch); char_glyph_info_map_t::iterator iter = - std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; }); + std::find_if(range_it.first, range_it.second, + [&glyph_type](const char_glyph_info_map_t::value_type& entry) + { + return entry.second->mGlyphType == glyph_type; + }); if (iter == range_it.second) { return addGlyphFromFont(this, wch, glyph_index, glyph_type); diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 7dc4812d5a8253c2812f80fb7b1f97db9a7740dc..23e2d645894522c3d740c44081cf0e7048eaeada 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -270,6 +270,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons static LLColor4U colors[GLYPH_BATCH_SIZE * GLYPH_VERTICES]; LLColor4U text_color(color); + // Preserve the transparency to render fading emojis in fading text (e.g. + // for the chat console)... HB + LLColor4U emoji_color(255, 255, 255, text_color.mV[VW]); std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1); S32 glyph_count = 0; @@ -338,9 +341,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons glyph_count = 0; } - - LLColor4U glyph_color = (bitmap_entry.first == EFontGlyphType::Grayscale) ? text_color : LLColor4U(255,255,255, text_color.mV[3]); - drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, glyph_color, style_to_add, shadow, drop_shadow_strength); + const LLColor4U& col = + bitmap_entry.first == EFontGlyphType::Grayscale ? text_color + : emoji_color; + drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, + col, style_to_add, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; @@ -1036,12 +1041,26 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) } //static -LLFontGL* LLFontGL::getFontEmoji() +LLFontGL* LLFontGL::getFontEmojiSmall() +{ + static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Small", 0)); + return fontp;; +} + +//static +LLFontGL* LLFontGL::getFontEmojiMedium() { static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Medium", 0)); return fontp;; } +//static +LLFontGL* LLFontGL::getFontEmojiLarge() +{ + static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Large", 0)); + return fontp;; +} + //static LLFontGL* LLFontGL::getFontEmojiHuge() { diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 81bab78c81cfda3cc8f9718861834b964b0566c7..f6520749147063f727d87b1db2dfd6c6a7a58d9b 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -194,7 +194,9 @@ class LLFontGL static void setFontDisplay(BOOL flag) { sDisplayFont = flag; } - static LLFontGL* getFontEmoji(); + static LLFontGL* getFontEmojiSmall(); + static LLFontGL* getFontEmojiMedium(); + static LLFontGL* getFontEmojiLarge(); static LLFontGL* getFontEmojiHuge(); static LLFontGL* getFontMonospace(); static LLFontGL* getFontSansSerifSmall(); diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index cb99641435684e7b70c0b99d86b8ccfcb25c85d2..7ec01b3903899b05169751906a398f7e74e8715a 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -943,3 +943,20 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl expanded_tab_height /= num_expanded; return expanded_tab_height; } + +void LLAccordionCtrl::collapseAllTabs() +{ + if (mAccordionTabs.size() > 0) + { + for (size_t i = 0; i < mAccordionTabs.size(); ++i) + { + LLAccordionCtrlTab *tab = mAccordionTabs[i]; + + if (tab->getDisplayChildren()) + { + tab->setDisplayChildren(false); + } + } + arrange(); + } +} diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h index d8caafd4cb66ca005610aeafcca90d43354d574c..b6dd559ffba7408f9826d0644bab9b0dbcdaddca 100644 --- a/indra/llui/llaccordionctrl.h +++ b/indra/llui/llaccordionctrl.h @@ -125,6 +125,8 @@ class LLAccordionCtrl: public LLPanel void setComparator(const LLTabComparator* comp) { mTabComparator = comp; } void sort(); + void collapseAllTabs(); + /** * Sets filter substring as a search_term for help text when there are no any visible tabs. */ diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 66ad8cc95bb81663e3a769e794fa1ab7995bb807..5d07e8bd13cb28b9b0dfdb9e0a93aaf163fc9344 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -57,10 +57,11 @@ static LLDefaultChildRegistry::Register<LLButton> r("button"); template class LLButton* LLView::getChild<class LLButton>( std::string_view name, BOOL recurse) const; -// globals loaded from settings.xml +// globals S32 LLBUTTON_H_PAD = 4; -S32 BTN_HEIGHT_SMALL= 0; -S32 BTN_HEIGHT = 0; +S32 BTN_HEIGHT_SMALL= 23; +S32 BTN_HEIGHT = 23; +S32 BTN_DROP_SHADOW = 2; LLButton::Params::Params() : label_selected("label_selected"), // requires is_toggle true diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index b59e01f2b52f7ddad0e23906adc4cba69ef44daf..591e293f3b722653c7f9de483c536021adda9f28 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -43,10 +43,10 @@ // // PLEASE please use these "constants" when building your own buttons. -// They are loaded from settings.xml at run time. extern S32 LLBUTTON_H_PAD; extern S32 BTN_HEIGHT_SMALL; extern S32 BTN_HEIGHT; +extern S32 BTN_DROP_SHADOW; // // Helpful functions @@ -252,7 +252,7 @@ class LLButton void setFont(const LLFontGL *font) { mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); } const LLFontGL* getFont() const { return mGLFont; } - + const std::string& getText() const { return getCurrentLabel().getString(); } S32 getLastDrawCharsCount() const { return mLastDrawCharsCount; } bool labelIsTruncated() const; diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 845f2379bbba1414abbe22430ed58566b77f11b5..58098cb166ddf03c38edfa98ace9451f30adc6eb 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -117,7 +117,7 @@ class LLCheckBoxCtrl std::string getLabel() const; void setFont( const LLFontGL* font ) { mFont = font; } - const LLFontGL* getFont() { return mFont; } + const LLFontGL* getFont() const { return mFont; } virtual void setControlName(std::string_view control_name, LLView* context); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 86c8893171cc6a47a8ed1d630fe72dc5574638ae..feae74e1f0b39c29cbaa4f74255ffd39feb216b3 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -188,6 +188,8 @@ LLComboBox::~LLComboBox() // explicitly disconect this signal, since base class destructor might fire top lost mTopLostSignalConnection.disconnect(); mImageLoadedConnection.disconnect(); + + LLUI::getInstance()->removePopup(this); } @@ -482,8 +484,6 @@ void LLComboBox::onFocusLost() void LLComboBox::setButtonVisible(BOOL visible) { - static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0); - mButton->setVisible(visible); if (mTextEntry) { @@ -491,7 +491,7 @@ void LLComboBox::setButtonVisible(BOOL visible) if (visible) { S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; } //mTextEntry->setRect(text_entry_rect); mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); @@ -530,19 +530,18 @@ void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled) void LLComboBox::createLineEditor(const LLComboBox::Params& p) { - static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0); LLRect rect = getLocalRect(); if (mAllowTextEntry) { S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - S32 shadow_size = drop_shadow_button; + S32 shadow_size = BTN_DROP_SHADOW; mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); mButton->setTabStop(FALSE); mButton->setHAlign(LLFontGL::HCENTER); LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; // clear label on button std::string cur_label = mButton->getLabelSelected(); LLLineEditor::Params params = p.combo_editor; @@ -1082,13 +1081,11 @@ void LLComboBox::onSetHighlight() const void LLComboBox::imageLoaded() { - static LLUICachedControl<S32> drop_shadow_button("DropShadowButton", 0); - if (mAllowTextEntry) { LLRect rect = getLocalRect(); S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; - S32 shadow_size = drop_shadow_button; + S32 shadow_size = BTN_DROP_SHADOW; mButton->setRect(LLRect(getRect().getWidth() - llmax(8, arrow_width) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); if (mButton->getVisible()) @@ -1097,7 +1094,7 @@ void LLComboBox::imageLoaded() if (mTextEntry) { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8, arrow_width) + 2 * BTN_DROP_SHADOW; mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); } } diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 19031711207c15918709e41a9a3e6acff34b978b..826b0ba6de8bd8a5ecb92a9b7484086e4ee58c67 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2203,10 +2203,9 @@ void LLFloater::drawShadow(LLPanel* panel) S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH; S32 bottom = LLPANEL_BORDER_WIDTH; - static LLUICachedControl<S32> shadow_offset_S32 ("DropShadowFloater", 0); static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow"); LLColor4 shadow_color = shadow_color_cached; - F32 shadow_offset = (F32)shadow_offset_S32; + F32 shadow_offset = (F32)DROP_SHADOW_FLOATER; if (!panel->isBackgroundOpaque()) { @@ -2659,8 +2658,8 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) void LLFloaterView::restoreAll() { // make sure all subwindows aren't minimized - child_list_t child_list = *(getChildList()); // Copy as list order can change during visibility - for (auto child : child_list) + child_list_t child_list = *(getChildList()); + for (LLView* child : child_list) { LLFloater* floaterp = dynamic_cast<LLFloater*>(child); if (floaterp) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 3b39ed4a452a67068789a2eaa35e5dcfaddc7e61..afd57b2898b50864085697f1174a50a95f3f77a9 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -61,6 +61,10 @@ const BOOL CLOSE_NO = FALSE; const BOOL ADJUST_VERTICAL_YES = TRUE; const BOOL ADJUST_VERTICAL_NO = FALSE; +const F32 CONTEXT_CONE_IN_ALPHA = 0.f; +const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +const F32 CONTEXT_CONE_FADE_TIME = .08f; + namespace LLFloaterEnums { enum EOpenPositioning diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 26e2620673c4509844adaf691aec3258092c7bca..85b38ec2f5dea2aa6b2e97f2da43d203c386ae21 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -222,7 +222,7 @@ LLFolderView::LLFolderView(const Params& p) params.font(getLabelFontForStyle(LLFontGL::NORMAL)); params.max_length.bytes(DB_INV_ITEM_NAME_STR_LEN); params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2)); - params.prevalidate_callback(&LLTextValidate::validateASCIIPrintableNoPipe); + params.prevalidator(&LLTextValidate::validateASCIIPrintableNoPipe); params.commit_on_focus_lost(true); params.visible(false); mRenamer = LLUICtrlFactory::create<LLLineEditor> (params); @@ -258,7 +258,13 @@ LLFolderView::LLFolderView(const Params& p) // Destroys the object LLFolderView::~LLFolderView( void ) { - closeRenamer(); + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + // instead of using closeRenamer remove it directly, + // since it might already be hidden + LLUI::getInstance()->removePopup(mRenamer); + } // The release focus call can potentially call the // scrollcontainer, which can potentially be called with a partly @@ -344,9 +350,9 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height ) void LLFolderView::filter( LLFolderViewFilter& filter ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - static LLUICachedControl<S32> time_visible("FilterItemsMaxTimePerFrameVisible", 10); - static LLUICachedControl<S32> time_invisible("FilterItemsMaxTimePerFrameUnvisible", 1); - filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? time_visible() : time_invisible(), 1, 100)); + const S32 TIME_VISIBLE = 10; // in milliseconds + const S32 TIME_INVISIBLE = 1; + filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? TIME_VISIBLE : TIME_INVISIBLE), 1, 100)); // Note: we filter the model, not the view getViewModelItem()->filter(filter); @@ -774,7 +780,7 @@ void LLFolderView::removeSelectedItems() } else { - LL_INFOS() << "Cannot delete " << item->getName() << LL_ENDL; + LL_DEBUGS() << "Cannot delete " << item->getName() << LL_ENDL; return; } } @@ -1087,7 +1093,10 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setVisible( TRUE ); // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + if (!mRenamerTopLostSignalConnection.connected()) + { + mRenamerTopLostSignalConnection = mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + } LLUI::getInstance()->addPopup(mRenamer); } } @@ -1615,7 +1624,11 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderView::deleteAllChildren() { - closeRenamer(); + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + LLUI::getInstance()->removePopup(mRenamer); + } if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mPopupMenuHandle.markDead(); mScrollContainer = NULL; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index d844848e6f56bd5399a24246422075aad17421cb..a2ffcaf45aae722b5295d472437ee3565ddc0165 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -346,6 +346,8 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; + boost::signals2::connection mRenamerTopLostSignalConnection; + bool mForceArrange; public: diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index fae0ef3f88b2c2360b062a39d8dce7a49029ba58..5fa05cc20852da6b524534f2dd6f155ef95ce678 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -605,15 +605,13 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) { - static LLUICachedControl<S32> drag_and_drop_threshold("DragAndDropDistanceThreshold", 3); - mIsMouseOverTitle = (y > (getRect().getHeight() - mItemHeight)); if( hasMouseCapture() && isMovable() ) { LLFolderView* root = getRoot(); - if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() + if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD && root->getAllowDrag() && root->getCurSelectedItem() && root->startDrag()) diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp index 545bae8bdc686846b483cbe592dc9a4a753e8590..b24615bce5b009f434b1d93c5adb76ac633eb309 100644 --- a/indra/llui/llfolderviewmodel.cpp +++ b/indra/llui/llfolderviewmodel.cpp @@ -49,8 +49,8 @@ std::string LLFolderViewModelCommon::getStatusText(bool is_empty_folder) void LLFolderViewModelCommon::filter() { - static LLUICachedControl<S32> max_time("FilterItemsMaxTimePerFrameVisible", 10); - getFilter().resetTime(llclamp(max_time(), 1, 100)); + const S32 MAX_FILTER_TIME = 10; + getFilter().resetTime(MAX_FILTER_TIME); mFolderView->getViewModelItem()->filter(getFilter()); } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index f26cf63a87f184b559622b50bebf780545f40198..d11e8c61080f6756119d11126143d90be4ed19f6 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -171,7 +171,7 @@ class LLFolderViewModelItem : public LLRefCount virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder virtual void move( LLFolderViewModelItem* parent_listener ) = 0; - virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed + virtual BOOL isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed virtual BOOL removeItem() = 0; virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index d09d7ba6158fa90d03359217c11a34c42a3953db..f8fd2f08862d90f59f2912003a14ee6565be2683 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -83,8 +83,8 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>( LLLineEditor::Params::Params() : max_length(""), keystroke_callback("keystroke_callback"), - prevalidate_callback("prevalidate_callback"), - prevalidate_input_callback("prevalidate_input_callback"), + prevalidator("prevalidator"), + input_prevalidator("input_prevalidator"), background_image("background_image"), background_image_disabled("background_image_disabled"), background_image_focused("background_image_focused"), @@ -96,6 +96,7 @@ LLLineEditor::Params::Params() commit_on_focus_lost("commit_on_focus_lost", true), ignore_tab("ignore_tab", true), is_password("is_password", false), + allow_emoji("allow_emoji", true), cursor_color("cursor_color"), use_bg_color("use_bg_color", false), bg_color("bg_color"), @@ -111,6 +112,8 @@ LLLineEditor::Params::Params() default_text("default_text") { changeDefault(mouse_opaque, true); + addSynonym(prevalidator, "prevalidate_callback"); + addSynonym(input_prevalidator, "prevalidate_input_callback"); addSynonym(select_on_focus, "select_all_on_focus_received"); addSynonym(border, "border"); addSynonym(label, "watermark_text"); @@ -142,6 +145,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mIgnoreArrowKeys( FALSE ), mIgnoreTab( p.ignore_tab ), mDrawAsterixes( p.is_password ), + mAllowEmoji( p.allow_emoji ), mSpellCheck( p.spellcheck ), mSpellCheckStart(-1), mSpellCheckEnd(-1), @@ -157,6 +161,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mUseBgColor(p.use_bg_color), mHaveHistory(FALSE), mReplaceNewlinesWithSpaces( TRUE ), + mPrevalidator(p.prevalidator()), + mInputPrevalidator(p.input_prevalidator()), mLabel(p.label), mCursorColor(p.cursor_color()), mBgColor(p.bg_color()), @@ -211,8 +217,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) } mSpellCheckTimer.reset(); - setPrevalidateInput(p.prevalidate_input_callback()); - setPrevalidate(p.prevalidate_callback()); + updateAllowingLanguageInput(); } LLLineEditor::~LLLineEditor() @@ -417,6 +422,11 @@ void LLLineEditor::setText(const LLStringExplicit &new_text, bool use_size_limit all_selected = all_selected || (len == 0 && hasFocus() && mSelectAllonFocusReceived); std::string truncated_utf8 = new_text; + if (!mAllowEmoji) + { + // Cut emoji symbols if exist + utf8str_remove_emojis(truncated_utf8); + } if (use_size_limit && truncated_utf8.size() > (U32)mMaxLengthBytes) { truncated_utf8 = utf8str_truncate(new_text, mMaxLengthBytes); @@ -590,13 +600,21 @@ void LLLineEditor::replaceWithSuggestion(U32 index) { if ( (it->first <= (U32)mCursorPos) && (it->second >= (U32)mCursorPos) ) { + LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); + if (!mAllowEmoji) + { + // Cut emoji symbols if exist + wstring_remove_emojis(suggestion); + } + if (suggestion.empty()) + return; + deselect(); // Delete the misspelled word mText.erase(it->first, it->second - it->first); // Insert the suggestion in its place - LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); mText.insert(it->first, suggestion); setCursor(it->first + (S32)suggestion.length()); @@ -992,6 +1010,9 @@ void LLLineEditor::removeWord(bool prev) void LLLineEditor::addChar(const llwchar uni_char) { + if (!mAllowEmoji && LLStringOps::isEmoji(uni_char)) + return; + llwchar new_c = uni_char; if (hasSelection()) { @@ -1241,11 +1262,12 @@ void LLLineEditor::cut() deleteSelection(); // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) + BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { rollback.doRollback( this ); LLUI::reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } else { @@ -1308,6 +1330,11 @@ void LLLineEditor::pasteHelper(bool is_primary) if (!paste.empty()) { + if (!mAllowEmoji) + { + wstring_remove_emojis(paste); + } + if (!prevalidateInput(paste)) return; @@ -1369,11 +1396,12 @@ void LLLineEditor::pasteHelper(bool is_primary) deselect(); // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) + BOOL need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { rollback.doRollback( this ); LLUI::reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } else { @@ -1627,19 +1655,27 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) deselect(); } - BOOL need_to_rollback = FALSE; + bool prevalidator_failed = false; // If read-only, don't allow changes - need_to_rollback |= (mReadOnly && (mText.getString() == rollback.getText())); + bool need_to_rollback = mReadOnly && (mText.getString() == rollback.getText()); // Validate new string and rollback the keystroke if needed. - need_to_rollback |= (mPrevalidateFunc && !mPrevalidateFunc(mText.getWString())); + if (!need_to_rollback && mPrevalidator) + { + prevalidator_failed = !mPrevalidator.validate(mText.getWString()); + need_to_rollback |= prevalidator_failed; + } if (need_to_rollback) { rollback.doRollback(this); LLUI::reportBadKeystroke(); + if (prevalidator_failed) + { + mPrevalidator.showLastErrorUsingTimeout(); + } } // Notify owner if requested @@ -1686,20 +1722,18 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char) deselect(); - BOOL need_to_rollback = FALSE; - // Validate new string and rollback the keystroke if needed. - need_to_rollback |= ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - - if( need_to_rollback ) + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { rollback.doRollback( this ); LLUI::reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } // Notify owner if requested - if( !need_to_rollback && handled ) + if (!need_to_rollback && handled) { // HACK! The only usage of this callback doesn't do anything with the character. // We'll have to do something about this if something ever changes! - Doug @@ -1742,11 +1776,12 @@ void LLLineEditor::doDelete() } // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); - if( need_to_rollback ) + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); + if (need_to_rollback) { - rollback.doRollback( this ); + rollback.doRollback(this); LLUI::reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); } else { @@ -1798,19 +1833,6 @@ void LLLineEditor::drawBackground() } } -//virtual -const std::string LLLineEditor::getToolTip() const -{ - if (sDebugUnicode) - { - std::string text = getText(); - std::string tooltip = utf8str_showBytesUTF8(text); - return tooltip; - } - - return LLUICtrl::getToolTip(); -} - //virtual void LLLineEditor::draw() { @@ -2286,7 +2308,12 @@ void LLLineEditor::setFocus( BOOL new_state ) if (new_state) { - getWindow()->allowLanguageTextInput(this, TRUE); + // Allow Language Text Input only when this LineEditor has + // no prevalidate function attached. This criterion works + // fine on 1.15.0.2, since all prevalidate func reject any + // non-ASCII characters. I'm not sure on future versions, + // however. + getWindow()->allowLanguageTextInput(this, !mPrevalidator); } } @@ -2305,26 +2332,21 @@ void LLLineEditor::setRect(const LLRect& rect) } } -void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func) +void LLLineEditor::setPrevalidate(LLTextValidate::Validator validator) { - mPrevalidateFunc = func; + mPrevalidator = validator; updateAllowingLanguageInput(); } -void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func) +void LLLineEditor::setPrevalidateInput(LLTextValidate::Validator validator) { - mPrevalidateInputFunc = func; + mInputPrevalidator = validator; updateAllowingLanguageInput(); } bool LLLineEditor::prevalidateInput(const LLWString& wstr) { - if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr)) - { - return false; - } - - return true; + return mInputPrevalidator.validate(wstr); } // static @@ -2460,7 +2482,7 @@ void LLLineEditor::updateAllowingLanguageInput() // test app, no window available return; } - if (hasFocus() && !mReadOnly && !mDrawAsterixes) + if (hasFocus() && !mReadOnly && !mDrawAsterixes && !mPrevalidator) { window->allowLanguageTextInput(this, TRUE); } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index b9d946023f6985ff1c2b88982982fdf5b88795ab..a5b3844a75a634b4bbae04ed503f31c4e9986b20 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -76,8 +76,8 @@ class LLLineEditor Optional<MaxLength> max_length; Optional<keystroke_callback_t> keystroke_callback; - Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback; - Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_input_callback; + Optional<LLTextValidate::Validator, LLTextValidate::Validators> prevalidator; + Optional<LLTextValidate::Validator, LLTextValidate::Validators> input_prevalidator; Optional<LLViewBorder::Params> border; @@ -93,6 +93,7 @@ class LLLineEditor bg_image_always_focused, show_label_focused, is_password, + allow_emoji, use_bg_color; // colors @@ -175,7 +176,6 @@ class LLLineEditor void onSpellCheckSettingsChange(); // view overrides - /*virtual*/ const std::string getToolTip() const override; /*virtual*/ void draw() override; /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; /*virtual*/ void onFocusReceived() override; @@ -203,7 +203,7 @@ class LLLineEditor void setText(const LLStringExplicit &new_text); - const std::string& getText() const { return mText.getString(); } + const std::string& getText() const override { return mText.getString(); } LLWString getWText() const { return mText.getWString(); } LLWString getConvertedText() const; // trimmed text with paragraphs converted to newlines @@ -235,12 +235,13 @@ class LLLineEditor const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); } const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } - const LLFontGL* getFont() const { return mGLFont; } + const LLFontGL* getFont() const override { return mGLFont; } void setFont(const LLFontGL* font); void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; } void setIgnoreTab(BOOL b) { mIgnoreTab = b; } void setPassDelete(BOOL b) { mPassDelete = b; } + void setAllowEmoji(BOOL b) { mAllowEmoji = b; } void setDrawAsterixes(BOOL b); // get the cursor position of the beginning/end of the prev/next word in the text @@ -267,12 +268,12 @@ class LLLineEditor void setTextPadding(S32 left, S32 right); // Prevalidation controls which keystrokes can affect the editor - void setPrevalidate( LLTextValidate::validate_func_t func ); + void setPrevalidate(LLTextValidate::Validator validator); // This method sets callback that prevents from: // - deleting, selecting, typing, cutting, pasting characters that are not valid. // Also callback that this method sets differs from setPrevalidate in a way that it validates just inputed // symbols, before existing text is modified, but setPrevalidate validates line after it was modified. - void setPrevalidateInput(LLTextValidate::validate_func_t func); + void setPrevalidateInput(LLTextValidate::Validator validator); static BOOL postvalidateFloat(const std::string &str); bool prevalidateInput(const LLWString& wstr); @@ -381,8 +382,8 @@ class LLLineEditor std::list<std::pair<U32, U32> > mMisspellRanges; std::vector<std::string> mSuggestionList; - LLTextValidate::validate_func_t mPrevalidateFunc; - LLTextValidate::validate_func_t mPrevalidateInputFunc; + LLTextValidate::Validator mPrevalidator; + LLTextValidate::Validator mInputPrevalidator; LLFrameTimer mKeystrokeTimer; LLTimer mTripleClickTimer; @@ -410,6 +411,7 @@ class LLLineEditor BOOL mShowImageFocused; BOOL mShowLabelFocused; + bool mAllowEmoji; bool mUseBgColor; LLWString mPreeditWString; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index bcb8e24601674f2f133dacae5a0f75401b56492b..6986a01c4627e34836169a55cf80b33f7eadf108 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -65,8 +65,8 @@ LLMenuHolderGL *LLMenuGL::sMenuContainer = NULL; view_listener_t::listener_map_t view_listener_t::sListeners; -S32 MENU_BAR_HEIGHT = 0; -S32 MENU_BAR_WIDTH = 0; +S32 MENU_BAR_HEIGHT = 18; +S32 MENU_BAR_WIDTH = 410; ///============================================================================ /// Local function declarations, constants, enums, and typedefs @@ -3233,10 +3233,9 @@ void LLMenuGL::draw( void ) } if (mDropShadowed && !mTornOff) { - static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0); static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow"); gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - color_drop_shadow, drop_shadow_floater ); + color_drop_shadow, DROP_SHADOW_FLOATER); } if( mBgVisible ) diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index e98eda006d7b2c1234d453a8ec19d2628d446751..2d66fe79d463537a073661bd1ce05591198f1a1b 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -68,6 +68,8 @@ LLModalDialog::~LLModalDialog() { LL_ERRS() << "Attempt to delete dialog while still in sModalStack!" << LL_ENDL; } + + LLUI::getInstance()->removePopup(this); } // virtual @@ -297,10 +299,9 @@ BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask ) void LLModalDialog::draw() { static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow"); - static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 0); gl_drop_shadow( 0, getRect().getHeight(), getRect().getWidth(), 0, - shadow_color, shadow_lines); + shadow_color, DROP_SHADOW_FLOATER); LLFloater::draw(); diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index f2f7fe8b7cef30bf1198098a575edd27805a17b5..c0048a17946f4941ef444627d65c68b775337134 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p) params.font(p.font); params.max_length.bytes(MAX_STRING_LENGTH); params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit); - params.prevalidate_callback(&LLTextValidate::validateFloat); + params.prevalidator(&LLTextValidate::validateFloat); params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); mEditor = LLUICtrlFactory::create<LLLineEditor> (params); mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) ); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index cb71113cc3062f7bd6ced4c5615ddd14620dd3f2..5f1bb19104c4751a8638d7fa10d7d7394f6bfe55 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -87,6 +87,7 @@ LLNotificationForm::FormInput::FormInput() : type("type"), text("text"), max_length_chars("max_length_chars"), + allow_emoji("allow_emoji"), width("width", 0), value("value") {} @@ -1549,6 +1550,11 @@ bool LLNotifications::loadTemplates() // specific skin. std::vector<std::string> search_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + if (search_paths.empty()) + { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); + LL_ERRS() << "Problem finding notifications.xml" << LL_ENDL; + } std::string base_filename = search_paths.front(); LLXMLNodePtr root; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 722405417fbbb8dcb464e65da920c8ec6d52f160..1ac12d0f56119152da8a85c8f22d447f861d102c 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -201,6 +201,7 @@ class LLNotificationForm Mandatory<std::string> type; Optional<S32> width; Optional<S32> max_length_chars; + Optional<bool> allow_emoji; Optional<std::string> text; Optional<std::string> value; diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 0acf4164af444d059c953dda161996d3c8771eaa..7d684a217e3d6e88b480ec14f8f768f13aa6cb61 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -105,7 +105,7 @@ class LLScrollListCell alt_value("alt_value", ""), label("label"), tool_tip("tool_tip", ""), - font("font", LLFontGL::getFontSansSerifSmall()), + font("font", LLFontGL::getFontEmojiSmall()), font_color("font_color", LLColor4::black), color("color", LLColor4::white), font_halign("halign", LLFontGL::LEFT), diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 2e62dfc97a25e2458b3846df8cba1dbbfaddfe7d..729c94ce55ad093426b19699135177f152c65288 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1949,7 +1949,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask) // display tooltip exactly over original cell, in same font LLToolTipMgr::instance().show(LLToolTip::Params() .message(hit_cell->getToolTip()) - .font(LLFontGL::getFontSansSerifSmall()) + .font(LLFontGL::getFontEmojiSmall()) .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6)) .delay_time(0.2f) .sticky_rect(sticky_rect)); @@ -3496,7 +3496,7 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E item_params.value(entry_id); item_params.columns.add() .value(value) - .font(LLFontGL::getFontSansSerifSmall()); + .font(LLFontGL::getFontEmojiSmall()); return addRow(item_params, pos); } diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 53eb667a1d141ae7a4ef015a09e6dc18abb4c919..e16ba9408eaeb61ea8e085742beea68cd26239fa 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -167,7 +167,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) } line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit); - line_p.prevalidate_callback(&LLTextValidate::validateFloat); + line_p.prevalidator(&LLTextValidate::validateFloat); mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p); mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this )); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index a2b5e76bffa67bda32129bd633d48d21632a4dd6..be4a940fbaecadb5daab305ffbcc83c3c8e9be1a 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -224,7 +224,8 @@ LLTabContainer::Params::Params() tabs_flashing_color("tabs_flashing_color"), tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0), use_ellipses("use_ellipses"), - font_halign("halign") + font_halign("halign"), + use_tab_offset("use_tab_offset", false) {} LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) @@ -263,7 +264,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) mTabIconCtrlPad(p.tab_icon_ctrl_pad), mEnableTabsFlashing(p.enable_tabs_flashing), mTabsFlashingColor(p.tabs_flashing_color), - mUseTabEllipses(p.use_ellipses) + mUseTabEllipses(p.use_ellipses), + mUseTabOffset(p.use_tab_offset) { static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0); @@ -1028,10 +1030,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } else { - tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3, - tab_panel_top, - getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2, - tab_panel_bottom ); + S32 left_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 3 : LLPANEL_BORDER_WIDTH; + S32 right_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 2 : LLPANEL_BORDER_WIDTH; + tab_panel_rect = LLRect(left_offset, tab_panel_top, getRect().getWidth() - right_offset, tab_panel_bottom); } child->setFollowsAll(); child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom); diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 536343abf8e1271edde7026f77e91c4ae60bc13c..29c9d3f77a732f8ebaeb366a082d6be1bfd13dbb 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -121,6 +121,8 @@ class LLTabContainer : public LLPanel */ Optional<S32> tab_icon_ctrl_pad; + Optional<bool> use_tab_offset; + Params(); }; @@ -324,6 +326,8 @@ class LLTabContainer : public LLPanel S32 mTabIconCtrlPad; bool mUseTabEllipses; LLFrameTimer mMouseDownTimer; + + bool mUseTabOffset; }; #endif // LL_TABCONTAINER_H diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index f43cbc40d6c5ed5b66c8bb957c7e354cdd878e1f..02e9eddb95e7cc3051d0c2531b85cd3f07d5c259 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -175,6 +175,7 @@ LLTextBase::Params::Params() trusted_content("trusted_content", true), always_show_icons("always_show_icons", false), use_ellipses("use_ellipses", false), + use_emoji("use_emoji", true), use_color("use_color", true), parse_urls("parse_urls", false), force_urls_external("force_urls_external", false), @@ -237,6 +238,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mPlainText ( p.plain_text ), mWordWrap(p.wrap), mUseEllipses( p.use_ellipses ), + mUseEmoji(p.use_emoji), mUseColor(p.use_color), mParseHTML(p.parse_urls), mForceUrlsExternal(p.force_urls_external), @@ -958,6 +960,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s } // Insert special segments where necessary (insertSegment takes care of splitting normal text segments around them for us) + if (mUseEmoji) { LLStyleSP emoji_style; LLEmojiDictionary* ed = LLEmojiDictionary::instanceExists() ? LLEmojiDictionary::getInstance() : NULL; @@ -970,7 +973,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s if (!emoji_style) { emoji_style = new LLStyle(getStyleParams()); - LLFontGL* fontp = style ? LLFontGL::getFont(LLFontDescriptor("Emoji", style->font()->getFontDesc().getSize(), 0)) : LLFontGL::getFontEmoji(); + LLFontGL* fontp = style ? LLFontGL::getFont(LLFontDescriptor("Emoji", style->font()->getFontDesc().getSize(), 0)) : LLFontGL::getFontEmojiLarge(); emoji_style->setFont(fontp); } @@ -1343,19 +1346,6 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask) return LLUICtrl::handleToolTip(x, y, mask); } -//virtual -const std::string LLTextBase::getToolTip() const -{ - if (sDebugUnicode) - { - std::string text = getText(); - std::string tooltip = utf8str_showBytesUTF8(text); - return tooltip; - } - - return LLUICtrl::getToolTip(); -} - //virtual void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent) { @@ -2265,10 +2255,10 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& onValueChange(0, getLength()); } -//virtual -std::string LLTextBase::getText() const +// virtual +const std::string& LLTextBase::getText() const { - return getViewModel()->getValue().asString(); + return getViewModel()->getStringValue(); } // IDEVO - icons can be UI image names or UUID sent from diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 04e04e1a6375267b5bdc58be6b2e63cad1c12d2e..0a051b5932ccdcd205c8f99f9b45d11c2beaf873 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -334,6 +334,7 @@ class LLTextBase plain_text, wrap, use_ellipses, + use_emoji, use_color, parse_urls, force_urls_external, @@ -372,7 +373,6 @@ class LLTextBase /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask) override; // LLView interface - /*virtual*/ const std::string getToolTip() const override; /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; /*virtual*/ void draw() override; @@ -414,12 +414,15 @@ class LLTextBase virtual void onSpellCheckPerformed(){} // used by LLTextSegment layout code - bool getWordWrap() { return mWordWrap; } - bool getUseEllipses() { return mUseEllipses; } - bool getUseColor() { return mUseColor; } + bool getWordWrap() const { return mWordWrap; } + bool getUseEllipses() const { return mUseEllipses; } + bool getUseEmoji() const { return mUseEmoji; } + void setUseEmoji(bool value) { mUseEmoji = value; } + bool getUseColor() const { return mUseColor; } + void setUseColor(bool value) { mUseColor = value; } bool truncate(); // returns true of truncation occurred - bool isContentTrusted() {return mTrustedContent;} + bool isContentTrusted() const { return mTrustedContent; } void setContentTrusted(bool trusted_content) { mTrustedContent = trusted_content; } // TODO: move into LLTextSegment? @@ -428,7 +431,7 @@ class LLTextBase // Text accessors // TODO: add optional style parameter virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style - virtual std::string getText() const; + /*virtual*/ const std::string& getText() const override; void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } S32 getMaxTextLength() { return mMaxTextByteLength; } @@ -511,7 +514,7 @@ class LLTextBase void setHighlightWord(const std::string& strHighlight, bool fCaseInsensitive); // [/SL:KB] - const LLFontGL* getFont() const { return mFont; } + const LLFontGL* getFont() const override { return mFont; } virtual void appendLineBreakSegment(const LLStyle::Params& style_params); virtual void appendImageSegment(const LLStyle::Params& style_params); @@ -773,6 +776,7 @@ class LLTextBase // [/SL:KB] bool mWordWrap; bool mUseEllipses; + bool mUseEmoji; bool mUseColor; bool mTrackEnd; // if true, keeps scroll position at end of document during resize bool mReadOnly; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 14411f03970473567fb63742b6683815e9206af9..284252a48d4f4f24b97ab480f5a5c493ac53daf0 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -232,7 +232,7 @@ class LLTextEditor::TextCmdRemove : public LLTextBase::TextCmd /////////////////////////////////////////////////////////////////// LLTextEditor::Params::Params() : default_text("default_text"), - prevalidate_callback("prevalidate_callback"), + prevalidator("prevalidator"), embedded_items("embedded_items", false), ignore_tab("ignore_tab", true), auto_indent("auto_indent", true), @@ -242,7 +242,8 @@ LLTextEditor::Params::Params() show_emoji_helper("show_emoji_helper"), enable_tooltip_paste("enable_tooltip_paste") { - addSynonym(prevalidate_callback, "text_type"); + addSynonym(prevalidator, "prevalidate_callback"); + addSynonym(prevalidator, "text_type"); } LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : @@ -253,16 +254,17 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mLastCmd( NULL ), mDefaultColor( p.default_color() ), mAutoIndent(p.auto_indent), + mParseOnTheFly(false), mCommitOnFocusLost( p.commit_on_focus_lost), mAllowEmbeddedItems( p.embedded_items ), mMouseDownX(0), mMouseDownY(0), mTabsToNextField(p.ignore_tab), - mPrevalidateFunc(p.prevalidate_callback()), + mPrevalidator(p.prevalidator()), mShowContextMenu(p.show_context_menu), mShowEmojiHelper(p.show_emoji_helper), mEnableTooltipPaste(p.enable_tooltip_paste), - mPassDelete(FALSE), + mPassDelete(false), mKeepSelectionOnReturn(false) { mSourceID.generate(); @@ -278,7 +280,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : addChild( mBorder ); setText(p.default_text()); - mParseOnTheFly = TRUE; + mParseOnTheFly = true; } void LLTextEditor::initFromParams( const LLTextEditor::Params& p) @@ -319,11 +321,13 @@ LLTextEditor::~LLTextEditor() void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params) { // validate incoming text if necessary - if (mPrevalidateFunc) + if (mPrevalidator) { - LLWString test_text = utf8str_to_wstring(utf8str); - if (!mPrevalidateFunc(test_text)) + if (!mPrevalidator.validate(utf8str)) { + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); + // not valid text, nothing to do return; } @@ -332,9 +336,9 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Param blockUndo(); deselect(); - mParseOnTheFly = FALSE; + mParseOnTheFly = false; LLTextBase::setText(utf8str, input_params); - mParseOnTheFly = TRUE; + mParseOnTheFly = true; resetDirty(); } @@ -666,7 +670,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) // Disabling parsing on the fly to avoid updating text segments // until all indentation commands are executed. - mParseOnTheFly = FALSE; + mParseOnTheFly = false; // Find each start-of-line and indent it do @@ -693,7 +697,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces ) } while( cur < right ); - mParseOnTheFly = TRUE; + mParseOnTheFly = true; if( (right < getLength()) && (text[right] == '\n') ) { @@ -743,6 +747,8 @@ void LLTextEditor::insertEmoji(llwchar emoji) LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; auto styleParams = getStyleParams(); styleParams.font = LLFontGL::getFont(LLFontDescriptor("Emoji", mFont->getFontDesc().getSize(), 0).normalize()); + // ALCHEMY + // styleParams.font = LLFontGL::getFontEmojiLarge(); auto segment = new LLEmojiTextSegment(new LLStyle(styleParams), mCursorPos, mCursorPos + 1, *this); insert(mCursorPos, LLWString(1, emoji), false, segment); setCursorPos(mCursorPos + 1); @@ -1045,10 +1051,12 @@ S32 LLTextEditor::execute( TextCmd* cmd ) mUndoStack.push_front(cmd); mLastCmd = cmd; - bool need_to_rollback = mPrevalidateFunc - && !mPrevalidateFunc(getViewModel()->getDisplay()); + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(getViewModel()->getDisplay()); if (need_to_rollback) { + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); + // get rid of this last command and clean up undo stack undo(); @@ -1211,16 +1219,15 @@ void LLTextEditor::removeWord(bool prev) // Add a single character to the text S32 LLTextEditor::addChar(S32 pos, llwchar wc) { - if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength) + if ((wstring_utf8_length(getWText()) + wchar_utf8_length(wc)) > mMaxTextByteLength) { - make_ui_sound("UISndBadKeystroke"); + LLUI::getInstance()->reportBadKeystroke(); return 0; } if (mLastCmd && mLastCmd->canExtend(pos)) { - S32 delta = 0; - if (mPrevalidateFunc) + if (mPrevalidator) { // get a copy of current text contents LLWString test_string(getViewModel()->getDisplay()); @@ -1228,28 +1235,31 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc) // modify text contents as if this addChar succeeded llassert(pos <= (S32)test_string.size()); test_string.insert(pos, 1, wc); - if (!mPrevalidateFunc( test_string)) + if (!mPrevalidator.validate(test_string)) { + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); return 0; } } + + S32 delta = 0; mLastCmd->extendAndExecute(this, pos, wc, &delta); return delta; } - else - { - return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); - } + + return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr())); } void LLTextEditor::addChar(llwchar wc) { - if( !getEnabled() ) + if (!getEnabled()) { return; } - if( hasSelection() ) + + if (hasSelection()) { deleteSelection(TRUE); } @@ -1593,7 +1603,13 @@ void LLTextEditor::pastePrimary() // paste from primary (itsprimary==true) or clipboard (itsprimary==false) void LLTextEditor::pasteHelper(bool is_primary) { - mParseOnTheFly = FALSE; + struct BoolReset + { + BoolReset(bool& value) : mValuePtr(&value) { *mValuePtr = false; } + ~BoolReset() { *mValuePtr = true; } + bool* mValuePtr; + } reset(mParseOnTheFly); + bool can_paste_it; if (is_primary) { @@ -1635,7 +1651,6 @@ void LLTextEditor::pasteHelper(bool is_primary) deselect(); onKeyStroke(); - mParseOnTheFly = TRUE; } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index a98ff1c8eb53f86730663034fa7a2528270b20bb..741e4775a9a61d6e6351a22380b2cd9147f63b9d 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -54,7 +54,7 @@ class LLTextEditor : struct Params : public LLInitParam::Block<Params, LLTextBase::Params> { Optional<std::string> default_text; - Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback; + Optional<LLTextValidate::Validator, LLTextValidate::Validators> prevalidator; Optional<bool> embedded_items, ignore_tab, @@ -349,7 +349,7 @@ class LLTextEditor : LLCoordGL mLastIMEPosition; // Last position of the IME editor keystroke_signal_t mKeystrokeSignal; - LLTextValidate::validate_func_t mPrevalidateFunc; + LLTextValidate::Validator mPrevalidator; LLHandle<LLContextMenu> mContextMenuHandle; }; // end class LLTextEditor diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp index 3c9a7f9bf5e6ef564c7139da069c3ed25cd4e2a1..9e27ed6232fabe03bf9d10a0f071fdb977fe4bfa 100644 --- a/indra/llui/lltextvalidate.cpp +++ b/indra/llui/lltextvalidate.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lltextvalidate.cpp * @brief Text validation helper functions * * $LicenseInfo:firstyear=2001&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$ */ @@ -29,328 +29,450 @@ #include "linden_common.h" #include "lltextvalidate.h" + +#include "llnotificationsutil.h" +#include "lltrans.h" + #include "llresmgr.h" // for LLLocale namespace LLTextValidate { - void ValidateTextNamedFuncs::declareValues() + +static S32 strtol(const std::string& str) { return ::strtol(str.c_str(), NULL, 10); } +static S32 strtol(const LLWString& str) { return ::strtol(wstring_to_utf8str(str).c_str(), NULL, 10); } + +static LLSD llsd(const std::string& str) { return LLSD(str); } +static LLSD llsd(const LLWString& str) { return LLSD(wstring_to_utf8str(str)); } +template <class CHAR> +LLSD llsd(CHAR ch) { return llsd(std::basic_string<CHAR>(1, ch)); } + +void ValidatorImpl::setLastErrorShowTime() +{ + mLastErrorShowTime = (U32Seconds)LLTimer::getTotalTime(); +} + +void Validator::showLastErrorUsingTimeout(U32 timeout) +{ + if (mImpl && (U32Seconds)LLTimer::getTotalTime() >= mImpl->getLastErrorShowTime() + timeout) { - declare("ascii", validateASCII); - declare("float", validateFloat); - declare("int", validateInt); - declare("positive_s32", validatePositiveS32); - declare("non_negative_s32", validateNonNegativeS32); - declare("alpha_num", validateAlphaNum); - declare("alpha_num_space", validateAlphaNumSpace); - declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe); - declare("ascii_printable_no_space", validateASCIIPrintableNoSpace); - declare("ascii_with_newline", validateASCIIWithNewLine); + mImpl->setLastErrorShowTime(); + std::string reason = LLTrans::getString(mImpl->getLastErrorName(), mImpl->getLastErrorValues()); + LLNotificationsUtil::add("InvalidKeystroke", LLSD().with("REASON", reason)); } +} - // Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. - // Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for - // the simple reasons that intermediate states may be invalid even if the final result is valid. - // - bool validateFloat(const LLWString &str) +// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. +// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for +// the simple reasons that intermediate states may be invalid even if the final result is valid. +class ValidatorFloat : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR> &str) { LLLocale locale(LLLocale::USER_LOCALE); - bool success = TRUE; - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); + std::basic_string<CHAR> trimmed = str; + LLStringUtilBase<CHAR>::trim(trimmed); S32 len = trimmed.length(); - if( 0 < len ) + if (0 < len) { // May be a comma or period, depending on the locale - llwchar decimal_point = (llwchar)LLResMgr::getDecimalPoint(); + CHAR decimal_point = LLResMgr::getInstance()->getDecimalPoint(); S32 i = 0; // First character can be a negative sign - if( '-' == trimmed[0] ) + if ('-' == trimmed.front()) { i++; } - for( ; i < len; i++ ) + for (; i < len; i++) { - if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) ) + CHAR ch = trimmed[i]; + if ((decimal_point != ch) && !LLStringOps::isDigit(ch)) { - success = FALSE; - break; + return setError("Validator_ShouldBeDigitOrDot", LLSD().with("NR", i + 1).with("CH", llsd(ch))); } } } - return success; + return resetError(); } - // Limits what characters can be used to [1234567890-] with [-] only valid in the first position. - // Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for - // the simple reasons that intermediate states may be invalid even if the final result is valid. - // - bool validateInt(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorFloatImpl; +Validator validateFloat(validatorFloatImpl); + +// Limits what characters can be used to [1234567890-] with [-] only valid in the first position. +// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for +// the simple reasons that intermediate states may be invalid even if the final result is valid. +class ValidatorInt : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR> &str) { LLLocale locale(LLLocale::USER_LOCALE); - bool success = TRUE; - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); + std::basic_string<CHAR> trimmed = str; + LLStringUtilBase<CHAR>::trim(trimmed); S32 len = trimmed.length(); - if( 0 < len ) + if (0 < len) { S32 i = 0; // First character can be a negative sign - if( '-' == trimmed[0] ) + if ('-' == trimmed.front()) { i++; } - for( ; i < len; i++ ) + for (; i < len; i++) { - if( !LLStringOps::isDigit( trimmed[i] ) ) + CHAR ch = trimmed[i]; + if (!LLStringOps::isDigit(ch)) { - success = FALSE; - break; + return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch))); } } } - return success; + return resetError(); } - bool validatePositiveS32(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorIntImpl; +Validator validateInt(validatorIntImpl); + +class ValidatorPositiveS32 : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { LLLocale locale(LLLocale::USER_LOCALE); - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); + std::basic_string<CHAR> trimmed = str; + LLStringUtilBase<CHAR>::trim(trimmed); S32 len = trimmed.length(); - bool success = TRUE; - if(0 < len) + if (0 < len) { - if(('-' == trimmed[0]) || ('0' == trimmed[0])) + CHAR ch = trimmed.front(); + + if (('-' == ch) || ('0' == ch)) { - success = FALSE; + return setError("Validator_ShouldNotBeMinusOrZero", LLSD().with("CH", llsd(ch))); } - S32 i = 0; - while(success && (i < len)) + + for (S32 i = 0; i < len; ++i) { - if(!LLStringOps::isDigit(trimmed[i++])) + ch = trimmed[i]; + if (!LLStringOps::isDigit(ch)) { - success = FALSE; + return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch))); } } } - if (success) + + S32 val = strtol(trimmed); + if (val <= 0) { - S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); - if (val <= 0) - { - success = FALSE; - } + return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed))); } - return success; + + return resetError(); } - bool validateNonNegativeS32(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorPositiveS32Impl; +Validator validatePositiveS32(validatorPositiveS32Impl); + +class ValidatorNonNegativeS32 : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { LLLocale locale(LLLocale::USER_LOCALE); - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); + std::basic_string<CHAR> trimmed = str; + LLStringUtilBase<CHAR>::trim(trimmed); S32 len = trimmed.length(); - bool success = TRUE; - if(0 < len) + if (0 < len) { - if('-' == trimmed[0]) + CHAR ch = trimmed.front(); + + if ('-' == ch) { - success = FALSE; + return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch))); } - S32 i = 0; - while(success && (i < len)) + + for (S32 i = 0; i < len; ++i) { - if(!LLStringOps::isDigit(trimmed[i++])) + ch = trimmed[i]; + if (!LLStringOps::isDigit(ch)) { - success = FALSE; + return setError("Validator_ShouldBeDigit", LLSD().with("NR", i + 1).with("CH", llsd(ch))); } } } - if (success) + + S32 val = strtol(trimmed); + if (val < 0) { - S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); - if (val < 0) - { - success = FALSE; - } + return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(trimmed))); } - return success; + + return resetError(); } - bool validateNonNegativeS32NoSpace(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorNonNegativeS32Impl; +Validator validateNonNegativeS32(validatorNonNegativeS32Impl); + +class ValidatorNonNegativeS32NoSpace : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { LLLocale locale(LLLocale::USER_LOCALE); - LLWString test_str = str; + std::basic_string<CHAR> test_str = str; S32 len = test_str.length(); - bool success = TRUE; - if(0 < len) + if (0 < len) { - if('-' == test_str[0]) + CHAR ch = test_str.front(); + + if ('-' == ch) { - success = FALSE; + return setError("Validator_ShouldNotBeMinus", LLSD().with("CH", llsd(ch))); } - S32 i = 0; - while(success && (i < len)) + + for (S32 i = 0; i < len; ++i) { - if(!LLStringOps::isDigit(test_str[i]) || LLStringOps::isSpace(test_str[i++])) + ch = test_str[i]; + if (!LLStringOps::isDigit(ch) || LLStringOps::isSpace(ch)) { - success = FALSE; + return setError("Validator_ShouldBeDigitNotSpace", LLSD().with("NR", i + 1).with("CH", llsd(ch))); } } } - if (success) + + S32 val = strtol(test_str); + if (val < 0) { - S32 val = strtol(wstring_to_utf8str(test_str).c_str(), NULL, 10); - if (val < 0) - { - success = FALSE; - } + return setError("Validator_InvalidNumericString", LLSD().with("STR", llsd(test_str))); } - return success; + + return resetError(); } - bool validateAlphaNum(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorNonNegativeS32NoSpaceImpl; +Validator validateNonNegativeS32NoSpace(validatorNonNegativeS32NoSpaceImpl); + +class ValidatorAlphaNum : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { LLLocale locale(LLLocale::USER_LOCALE); - bool rv = TRUE; S32 len = str.length(); - if(len == 0) return rv; - while(len--) + while (len--) { - if( !LLStringOps::isAlnum((char)str[len]) ) + CHAR ch = str[len]; + + if (!LLStringOps::isAlnum(ch)) { - rv = FALSE; - break; + return setError("Validator_ShouldBeDigitOrAlpha", LLSD().with("NR", len + 1).with("CH", llsd(ch))); } } - return rv; + + return resetError(); } - bool validateAlphaNumSpace(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorAlphaNumImpl; +Validator validateAlphaNum(validatorAlphaNumImpl); + +class ValidatorAlphaNumSpace : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { LLLocale locale(LLLocale::USER_LOCALE); - bool rv = TRUE; S32 len = str.length(); - if(len == 0) return rv; - while(len--) + while (len--) { - if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len]))) + CHAR ch = str[len]; + + if (!LLStringOps::isAlnum(ch) && (' ' != ch)) { - rv = FALSE; - break; + return setError("Validator_ShouldBeDigitOrAlphaOrSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch))); } } - return rv; + + return resetError(); } - // Used for most names of things stored on the server, due to old file-formats - // that used the pipe (|) for multiline text storage. Examples include - // inventory item names, parcel names, object names, etc. - bool validateASCIIPrintableNoPipe(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorAlphaNumSpaceImpl; +Validator validateAlphaNumSpace(validatorAlphaNumSpaceImpl); + +// Used for most names of things stored on the server, due to old file-formats +// that used the pipe (|) for multiline text storage. Examples include +// inventory item names, parcel names, object names, etc. +class ValidatorASCIIPrintableNoPipe : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { - bool rv = TRUE; S32 len = str.length(); - if(len == 0) return rv; - while(len--) + while (len--) { - llwchar wc = str[len]; - if (wc < 0x20 - || wc > 0x7f - || wc == '|') - { - rv = FALSE; - break; - } - if(!(wc == ' ' - || LLStringOps::isAlnum((char)wc) - || LLStringOps::isPunct((char)wc) ) ) + CHAR ch = str[len]; + + if (ch < 0x20 || ch > 0x7f || ch == '|' || + (ch != ' ' && !LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch))) { - rv = FALSE; - break; + return setError("Validator_ShouldBeDigitOrAlphaOrPunct", LLSD().with("NR", len + 1).with("CH", llsd(ch))); } } - return rv; + + return resetError(); } +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorASCIIPrintableNoPipeImpl; +Validator validateASCIIPrintableNoPipe(validatorASCIIPrintableNoPipeImpl); - // Used for avatar names - bool validateASCIIPrintableNoSpace(const LLWString &str) +// Used for avatar names +class ValidatorASCIIPrintableNoSpace : public ValidatorImpl +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { - bool rv = TRUE; S32 len = str.length(); - if(len == 0) return rv; - while(len--) + while (len--) { - llwchar wc = str[len]; - if (wc < 0x20 - || wc > 0x7f - || LLStringOps::isSpace(wc)) - { - rv = FALSE; - break; - } - if( !(LLStringOps::isAlnum((char)str[len]) || - LLStringOps::isPunct((char)str[len]) ) ) + CHAR ch = str[len]; + + if (ch <= 0x20 || ch > 0x7f || LLStringOps::isSpace(ch) || + (!LLStringOps::isAlnum(ch) && !LLStringOps::isPunct(ch))) { - rv = FALSE; - break; + return setError("Validator_ShouldBeDigitOrAlphaOrPunctNotSpace", LLSD().with("NR", len + 1).with("CH", llsd(ch))); } } - return rv; + + return resetError(); } - bool validateASCII(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorASCIIPrintableNoSpaceImpl; +Validator validateASCIIPrintableNoSpace(validatorASCIIPrintableNoSpaceImpl); + +class ValidatorASCII : public ValidatorImpl +{ +protected: + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { - bool rv = TRUE; S32 len = str.length(); - while(len--) + while (len--) { - if (str[len] < 0x20 || str[len] > 0x7f) + CHAR ch = str[len]; + + if (ch < 0x20 || ch > 0x7f) { - rv = FALSE; - break; + return setError("Validator_ShouldBeASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch))); } } - return rv; + + return resetError(); } - bool validateASCIINoLeadingSpace(const LLWString &str) +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorASCIIImpl; +Validator validateASCII(validatorASCIIImpl); + +class ValidatorASCIINoLeadingSpace : public ValidatorASCII +{ + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { - if (LLStringOps::isSpace(str[0])) + if (LLStringOps::isSpace(str.front())) { - return FALSE; + return false; } - return validateASCII(str); + + return ValidatorASCII::validate<CHAR>(str); } +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorASCIINoLeadingSpaceImpl; +Validator validateASCIINoLeadingSpace(validatorASCIINoLeadingSpaceImpl); + +class ValidatorASCIIWithNewLine : public ValidatorImpl +{ // Used for multiline text stored on the server. // Example is landmark description in Places SP. - bool validateASCIIWithNewLine(const LLWString &str) + template <class CHAR> + bool validate(const std::basic_string<CHAR>& str) { - bool rv = TRUE; S32 len = str.length(); - while(len--) + while (len--) { - if ((str[len] < 0x20 && str[len] != 0xA) || str[len] > 0x7f) + CHAR ch = str[len]; + + if ((ch < 0x20 && ch != 0xA) || ch > 0x7f) { - rv = FALSE; - break; + return setError("Validator_ShouldBeNewLineOrASCII", LLSD().with("NR", len + 1).with("CH", llsd(ch))); } } - return rv; + + return resetError(); } + +public: + /*virtual*/ bool validate(const std::string& str) override { return validate<char>(str); } + /*virtual*/ bool validate(const LLWString& str) override { return validate<llwchar>(str); } +} validatorASCIIWithNewLineImpl; +Validator validateASCIIWithNewLine(validatorASCIIWithNewLineImpl); + +void Validators::declareValues() +{ + declare("ascii", validateASCII); + declare("float", validateFloat); + declare("int", validateInt); + declare("positive_s32", validatePositiveS32); + declare("non_negative_s32", validateNonNegativeS32); + declare("alpha_num", validateAlphaNum); + declare("alpha_num_space", validateAlphaNumSpace); + declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe); + declare("ascii_printable_no_space", validateASCIIPrintableNoSpace); + declare("ascii_with_newline", validateASCIIWithNewLine); } + +} // namespace LLTextValidate diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h index 0dfec1b612b735353016e1997e778b80ee5dd8a4..2c2941de7f3850d997ad69f6e5974d66ffeb204f 100644 --- a/indra/llui/lltextvalidate.h +++ b/indra/llui/lltextvalidate.h @@ -1,4 +1,4 @@ -/** +/** * @file lltextbase.h * @author Martin Reddy * @brief The base class of text box/editor, providing Url handling support @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2009&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,27 +34,68 @@ namespace LLTextValidate { - typedef boost::function<BOOL (const LLWString &wstr)> validate_func_t; + class ValidatorImpl + { + public: + ValidatorImpl() {} + virtual ~ValidatorImpl() {} + + virtual bool validate(const std::string& str) = 0; + virtual bool validate(const LLWString& str) = 0; + + bool setError(std::string name, LLSD values = LLSD()) { return mLastErrorName = name, mLastErrorValues = values, false; } + bool resetError() { return mLastErrorName.clear(), mLastErrorValues.clear(), true; } + const std::string& getLastErrorName() const { return mLastErrorName; } + const LLSD& getLastErrorValues() const { return mLastErrorValues; } + + void setLastErrorShowTime(); + U32 getLastErrorShowTime() const { return mLastErrorShowTime; } + + protected: + std::string mLastErrorName; + LLSD mLastErrorValues; + U32 mLastErrorShowTime { 0 }; + }; - struct ValidateTextNamedFuncs - : public LLInitParam::TypeValuesHelper<validate_func_t, ValidateTextNamedFuncs> + class Validator { - static void declareValues(); + public: + Validator() : mImpl(nullptr) {} + Validator(ValidatorImpl& impl) : mImpl(&impl) {} + Validator(const Validator& validator) : mImpl(validator.mImpl) {} + Validator(const Validator* validator) : mImpl(validator->mImpl) {} + + bool validate(const std::string& str) const { return !mImpl || mImpl->validate(str); } + bool validate(const LLWString& str) const { return !mImpl || mImpl->validate(str); } + + operator bool() const { return mImpl; } + + static const U32 SHOW_LAST_ERROR_TIMEOUT_SEC = 30; + void showLastErrorUsingTimeout(U32 timeout = SHOW_LAST_ERROR_TIMEOUT_SEC); + + private: + ValidatorImpl* mImpl; }; - bool validateFloat(const LLWString &str ); - bool validateInt(const LLWString &str ); - bool validatePositiveS32(const LLWString &str); - bool validateNonNegativeS32(const LLWString &str); - bool validateNonNegativeS32NoSpace(const LLWString &str); - bool validateAlphaNum(const LLWString &str ); - bool validateAlphaNumSpace(const LLWString &str ); - bool validateASCIIPrintableNoPipe(const LLWString &str); - bool validateASCIIPrintableNoSpace(const LLWString &str); - bool validateASCII(const LLWString &str); - bool validateASCIINoLeadingSpace(const LLWString &str); - bool validateASCIIWithNewLine(const LLWString &str); -} + // Available validators + extern Validator validateFloat; + extern Validator validateInt; + extern Validator validatePositiveS32; + extern Validator validateNonNegativeS32; + extern Validator validateNonNegativeS32NoSpace; + extern Validator validateAlphaNum; + extern Validator validateAlphaNumSpace; + extern Validator validateASCIIPrintableNoPipe; + extern Validator validateASCIIPrintableNoSpace; + extern Validator validateASCII; + extern Validator validateASCIINoLeadingSpace; + extern Validator validateASCIIWithNewLine; + // Add available validators to the internal map + struct Validators : public LLInitParam::TypeValuesHelper<Validator, Validators> + { + static void declareValues(); + }; +}; #endif diff --git a/indra/llui/lltimectrl.cpp b/indra/llui/lltimectrl.cpp index 38f92b12ddb19494869660f16508c1f04e93c5e6..3e5643996afa8c8e1b445a1aa841d73c43a311f7 100644 --- a/indra/llui/lltimectrl.cpp +++ b/indra/llui/lltimectrl.cpp @@ -49,6 +49,36 @@ const U32 HOURS_MAX = 12; const U32 MINUTES_PER_HOUR = 60; const U32 MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR; +class LLTimeValidatorImpl : public LLTextValidate::ValidatorImpl +{ +public: + // virtual + bool validate(const std::string& str) override + { + std::string hours = LLTimeCtrl::getHoursString(str); + if (!LLTimeCtrl::isHoursStringValid(hours)) + return setError("ValidatorInvalidHours", LLSD().with("STR", hours)); + + std::string minutes = LLTimeCtrl::getMinutesString(str); + if (!LLTimeCtrl::isMinutesStringValid(minutes)) + return setError("ValidatorInvalidMinutes", LLSD().with("STR", minutes)); + + std::string ampm = LLTimeCtrl::getAMPMString(str); + if (!LLTimeCtrl::isPMAMStringValid(ampm)) + return setError("ValidatorInvalidAMPM", LLSD().with("STR", ampm)); + + return resetError(); + } + + // virtual + bool validate(const LLWString& wstr) override + { + std::string str = wstring_to_utf8str(wstr); + + return validate(str); + } +} validateTimeImpl; +LLTextValidate::Validator validateTime(validateTimeImpl); LLTimeCtrl::Params::Params() : label_width("label_width"), @@ -111,7 +141,7 @@ LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p) params.keystroke_callback(boost::bind(&LLTimeCtrl::onTextEntry, this, _1)); mEditor = LLUICtrlFactory::create<LLLineEditor> (params); mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace); - mEditor->setPrevalidate(boost::bind(&LLTimeCtrl::isTimeStringValid, this, _1)); + mEditor->setPrevalidate(validateTime); mEditor->setText(LLStringExplicit("12:00 AM")); addChild(mEditor); @@ -247,15 +277,6 @@ void LLTimeCtrl::onTextEntry(LLLineEditor* line_editor) mTime = h24 * MINUTES_PER_HOUR + m; } -bool LLTimeCtrl::isTimeStringValid(const LLWString &wstr) -{ - std::string str = wstring_to_utf8str(wstr); - - return isHoursStringValid(getHoursString(str)) && - isMinutesStringValid(getMinutesString(str)) && - isPMAMStringValid(getAMPMString(str)); -} - void LLTimeCtrl::increaseMinutes() { mTime = (mTime + mSnapToMin) % MINUTES_PER_DAY - (mTime % mSnapToMin); diff --git a/indra/llui/lltimectrl.h b/indra/llui/lltimectrl.h index ff46bc76ca0b55afc3e03845ac89c1e2cf5b6f45..a2c016ab6f4a30801990360adbcf5b7a745bfdc0 100644 --- a/indra/llui/lltimectrl.h +++ b/indra/llui/lltimectrl.h @@ -60,6 +60,18 @@ class LLTimeCtrl void setTime24(F32 time); // 0.0 - 23.98(3) + static std::string getHoursString(const std::string& str); + static std::string getMinutesString(const std::string& str); + static std::string getAMPMString(const std::string& str); + + static bool isHoursStringValid(const std::string& str); + static bool isMinutesStringValid(const std::string& str); + static bool isPMAMStringValid(const std::string& str); + + static U32 parseHours(const std::string& str); + static U32 parseMinutes(const std::string& str); + static bool parseAMPM(const std::string& str); + protected: LLTimeCtrl(const Params&); friend class LLUICtrlFactory; @@ -87,8 +99,6 @@ class LLTimeCtrl void onDownBtn(); void onTextEntry(LLLineEditor* line_editor); - bool isTimeStringValid(const LLWString& wstr); - void increaseMinutes(); void increaseHours(); @@ -102,18 +112,6 @@ class LLTimeCtrl EEditingPart getEditingPart(); - static std::string getHoursString(const std::string& str); - static std::string getMinutesString(const std::string& str); - static std::string getAMPMString(const std::string& str); - - static bool isHoursStringValid(const std::string& str); - static bool isMinutesStringValid(const std::string& str); - static bool isPMAMStringValid(const std::string& str); - - static U32 parseHours(const std::string& str); - static U32 parseMinutes(const std::string& str); - static bool parseAMPM(const std::string& str); - class LLTextBox* mLabelBox; class LLLineEditor* mEditor; diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index f04feacbbc398b4283b21f8bcc9f4d576feae7eb..7069321e4dc8504353c3701c68410fdee18cd53f 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -1285,8 +1285,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask) BOOL handled = FALSE; S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY); - static LLUICachedControl<S32> drag_threshold("DragAndDropDistanceThreshold", 3); - if (mouse_distance_squared > drag_threshold * drag_threshold + if (mouse_distance_squared > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD && hasMouseCapture() && mStartDragItemCallback && mHandleDragItemCallback) { diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 7bbfa0632a06f918760ab7e20fa8ad95f6776323..8fa2b7778d2788ca3e0f76f5f8f34d3f082a0ef4 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -51,7 +51,7 @@ class LLWindow; class LLView; class LLHelp; - +const S32 DRAG_N_DROP_DISTANCE_THRESHOLD = 3; // this enum is used by the llview.h (viewer) and the llassetstorage.h (viewer and sim) enum EDragAndDropType { diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 41ff93609954ab51a570436bd3edbe88da151ff6..fadd366a93271d76dd17f87e965d0a1ebfb653b9 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -79,7 +79,7 @@ LLUICtrl::Params::Params() mouseenter_callback("mouseenter_callback"), mouseleave_callback("mouseleave_callback"), control_name("control_name"), - font("font", LLFontGL::getFontSansSerif()), + font("font", LLFontGL::getFontEmojiMedium()), font_halign("halign"), font_valign("valign"), length("length"), // ignore LLXMLNode cruft diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index bb7ae910cefcf942f538e72e1694f65887cc21ca..7d9c6c7b408a08b40942cc98dc60e1e7be0f3eb5 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -41,6 +41,7 @@ const BOOL TAKE_FOCUS_YES = TRUE; const BOOL TAKE_FOCUS_NO = FALSE; +const S32 DROP_SHADOW_FLOATER = 5; class LLUICtrl : public LLView, public boost::signals2::trackable diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 21139555a43e0ac1429b0de8088684e955051710..818317b4b06e48a8e237b494701d38879c02a4b7 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -912,6 +912,34 @@ F32 LLView::getTooltipTimeout() : tooltip_delay); } +// virtual +const std::string LLView::getToolTip() const +{ + if (sDebugUnicode) + { + std::string text = getText(); + if (!text.empty()) + { + const std::string& name = getName(); + std::string tooltip = llformat("Name: \"%s\"", name.c_str()); + + if (const LLFontGL* font = getFont()) + { + tooltip += llformat("\nFont: %s (%s)", + font->getFontDesc().getName().c_str(), + font->getFontDesc().getSize().c_str() + ); + } + + tooltip += "\n\n" + utf8str_showBytesUTF8(text); + + return tooltip; + } + } + + return mToolTipMsg.getString(); +} + BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 145d19ed140eb05945b5507f2229afb7f1af1473..6d4d2bdd88ddf531ba9c6189412e58108403188e 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -249,7 +249,9 @@ class LLView ECursorType getHoverCursor() { return mHoverCursor; } static F32 getTooltipTimeout(); - virtual const std::string getToolTip() const { return mToolTipMsg.getString(); } + virtual const std::string getToolTip() const; + virtual const std::string& getText() const { return LLStringUtil::null; } + virtual const LLFontGL* getFont() const { return nullptr; } void sendChildToFront(LLView* child); void sendChildToBack(LLView* child); diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp index 5b95b7c4287347e23d50211b3867d3e93a8d0cb8..57179cf7daaffa6693e4371b6e4e8f58259359ef 100644 --- a/indra/llui/llviewmodel.cpp +++ b/indra/llui/llviewmodel.cpp @@ -81,7 +81,7 @@ void LLTextViewModel::setValue(const LLSD& value) { // approximate LLSD storage usage LLViewModel::setValue(value); - mDisplay = utf8str_to_wstring(value.asString()); + mDisplay = utf8str_to_wstring(mStringValue = value.asString()); // mDisplay and mValue agree mUpdateFromDisplay = false; @@ -101,23 +101,34 @@ void LLTextViewModel::setDisplay(const LLWString& value) mUpdateFromDisplay = true; } -LLSD LLTextViewModel::getValue() const +inline void updateFromDisplayIfNeeded(const LLTextViewModel* model) { - // Has anyone called setDisplay() since the last setValue()? If so, have - // to convert mDisplay back to UTF8. - if (mUpdateFromDisplay) + // Has anyone called setDisplay() since the last setValue()? + // If so, have to convert mDisplay back to UTF8. + if (model->mUpdateFromDisplay) { - // The fact that we're lazily updating fields in this object should be - // transparent to clients, which is why this method is left - // conventionally const. Nor do we particularly want to make these - // members mutable. Just cast away constness in this one place. - LLTextViewModel* nthis = const_cast<LLTextViewModel*>(this); + // The fact that we're lazily updating fields + // in this object should be transparent to clients, + // which is why this method is left conventionally const. + // Nor do we particularly want to make these members mutable. + // Just cast away constness in this one place. + LLTextViewModel* nthis = const_cast<LLTextViewModel*>(model); nthis->mUpdateFromDisplay = false; - nthis->mValue = wstring_to_utf8str(mDisplay); + nthis->mValue = nthis->mStringValue = wstring_to_utf8str(model->mDisplay); } - return LLViewModel::getValue(); } +LLSD LLTextViewModel::getValue() const +{ + updateFromDisplayIfNeeded(this); + return mValue; +} + +const std::string& LLTextViewModel::getStringValue() const +{ + updateFromDisplayIfNeeded(this); + return mStringValue; +} //////////////////////////////////////////////////////////////////////////// diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index 81ef16c85ff3321cbf46013f869964b12a4aa448..8a015b71897ee9fbd69f4e7938acc61351b2089c 100644 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -100,6 +100,7 @@ class LLTextViewModel: public LLViewModel // LLViewModel functions virtual void setValue(const LLSD& value); virtual LLSD getValue() const; + const std::string& getStringValue() const; // New functions /// Get the stored value in string form @@ -114,12 +115,17 @@ class LLTextViewModel: public LLViewModel void setDisplay(const LLWString& value); private: + std::string mStringValue; + /// To avoid converting every widget's stored value from LLSD to LLWString /// every frame, cache the converted value LLWString mDisplay; + /// As the user edits individual characters (setDisplay()), defer /// LLWString-to-UTF8 conversions until s/he's done. bool mUpdateFromDisplay; + + friend void updateFromDisplayIfNeeded(const LLTextViewModel* model); }; /** diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index cb7771a5fa5ab8f3136f45c2e910b912a0362090..e37985df6f90eb11fbb9610f565655972ee2bfc1 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -198,7 +198,13 @@ class LLWindow : public LLInstanceTracker<LLWindow> // windows only DirectInput8 for joysticks virtual void* getDirectInput8() { return NULL; }; - virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; }; + virtual bool getInputDevices(U32 device_type_filter, + std::function<bool(std::string&, LLSD&, void*)> osx_callback, + void* win_callback, + void* userdata) + { + return false; + }; virtual S32 getRefreshRate() { return mRefreshRate; } protected: diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b0c3bff64539d866bf3bdc0b2c04b6db91162ef2..dc382312c1bd926d96733980d4362d32867a9181 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -25,6 +25,7 @@ * $/LicenseInfo$ */ +#include <errno.h> #import "llopenglview-objc.h" #import "llwindowmacosx-objc.h" #import "llappdelegate-objc.h" diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 1fbe48fa91c110966a389b5bd0e53839875e002b..ead3f631b8b5bf6af7d8ae9427f9e07e4f2920c2 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -42,6 +42,13 @@ #include <CoreServices/CoreServices.h> #include <CoreGraphics/CGDisplayConfiguration.h> +#include <IOKit/IOCFPlugIn.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOMessage.h> +#include <IOKit/hid/IOHIDUsageTables.h> +#include <IOKit/hid/IOHIDLib.h> +#include <IOKit/usb/IOUSBLib.h> + extern BOOL gDebugWindowProc; BOOL gHiDPISupport = TRUE; @@ -211,13 +218,16 @@ bool callKeyUp(NSKeyEventRef event, unsigned int key, unsigned int mask) bool callKeyDown(NSKeyEventRef event, unsigned int key, unsigned int mask, wchar_t character) { - if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y')) - { - key = gKeyboard->inverseTranslateKey('Y'); - } - else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z')) + //if (mask!=MASK_NONE) { - key = gKeyboard->inverseTranslateKey('Z'); + if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y')) + { + key = gKeyboard->inverseTranslateKey('Y'); + } + else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z')) + { + key = gKeyboard->inverseTranslateKey('Z'); + } } mRawKeyEvent = event; @@ -1823,6 +1833,486 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) } } +// String should match ndof, so string mapping code was copied as is +static char mapChar( char c ) +{ + unsigned char uc = ( unsigned char ) c; + + switch( uc ) + { + case '/': return '-'; // use dash instead of slash + + case 0x7F: return ' '; + case 0x80: return 'A'; + case 0x81: return 'A'; + case 0x82: return 'C'; + case 0x83: return 'E'; + case 0x84: return 'N'; + case 0x85: return 'O'; + case 0x86: return 'U'; + case 0x87: return 'a'; + case 0x88: return 'a'; + case 0x89: return 'a'; + case 0x8A: return 'a'; + case 0x8B: return 'a'; + case 0x8C: return 'a'; + case 0x8D: return 'c'; + case 0x8E: return 'e'; + case 0x8F: return 'e'; + case 0x90: return ' '; + case 0x91: return ' '; // ? ' + case 0x92: return ' '; // ? ' + case 0x93: return ' '; // ? " + case 0x94: return ' '; // ? " + case 0x95: return ' '; + case 0x96: return ' '; + case 0x97: return ' '; + case 0x98: return ' '; + case 0x99: return ' '; + case 0x9A: return ' '; + case 0x9B: return 0x27; + case 0x9C: return 0x22; + case 0x9D: return ' '; + case 0x9E: return ' '; + case 0x9F: return ' '; + case 0xA0: return ' '; + case 0xA1: return ' '; + case 0xA2: return ' '; + case 0xA3: return ' '; + case 0xA4: return ' '; + case 0xA5: return ' '; + case 0xA6: return ' '; + case 0xA7: return ' '; + case 0xA8: return ' '; + case 0xA9: return ' '; + case 0xAA: return ' '; + case 0xAB: return ' '; + case 0xAC: return ' '; + case 0xAD: return ' '; + case 0xAE: return ' '; + case 0xAF: return ' '; + case 0xB0: return ' '; + case 0xB1: return ' '; + case 0xB2: return ' '; + case 0xB3: return ' '; + case 0xB4: return ' '; + case 0xB5: return ' '; + case 0xB6: return ' '; + case 0xB7: return ' '; + case 0xB8: return ' '; + case 0xB9: return ' '; + case 0xBA: return ' '; + case 0xBB: return ' '; + case 0xBC: return ' '; + case 0xBD: return ' '; + case 0xBE: return ' '; + case 0xBF: return ' '; + case 0xC0: return ' '; + case 0xC1: return ' '; + case 0xC2: return ' '; + case 0xC3: return ' '; + case 0xC4: return ' '; + case 0xC5: return ' '; + case 0xC6: return ' '; + case 0xC7: return ' '; + case 0xC8: return ' '; + case 0xC9: return ' '; + case 0xCA: return ' '; + case 0xCB: return 'A'; + case 0xCC: return 'A'; + case 0xCD: return 'O'; + case 0xCE: return ' '; + case 0xCF: return ' '; + case 0xD0: return '-'; + case 0xD1: return '-'; + case 0xD2: return 0x22; + case 0xD3: return 0x22; + case 0xD4: return 0x27; + case 0xD5: return 0x27; + case 0xD6: return '-'; // use dash instead of slash + case 0xD7: return ' '; + case 0xD8: return 'y'; + case 0xD9: return 'Y'; + case 0xDA: return '-'; // use dash instead of slash + case 0xDB: return ' '; + case 0xDC: return '<'; + case 0xDD: return '>'; + case 0xDE: return ' '; + case 0xDF: return ' '; + case 0xE0: return ' '; + case 0xE1: return ' '; + case 0xE2: return ','; + case 0xE3: return ','; + case 0xE4: return ' '; + case 0xE5: return 'A'; + case 0xE6: return 'E'; + case 0xE7: return 'A'; + case 0xE8: return 'E'; + case 0xE9: return 'E'; + case 0xEA: return 'I'; + case 0xEB: return 'I'; + case 0xEC: return 'I'; + case 0xED: return 'I'; + case 0xEE: return 'O'; + case 0xEF: return 'O'; + case 0xF0: return ' '; + case 0xF1: return 'O'; + case 0xF2: return 'U'; + case 0xF3: return 'U'; + case 0xF4: return 'U'; + case 0xF5: return '|'; + case 0xF6: return ' '; + case 0xF7: return ' '; + case 0xF8: return ' '; + case 0xF9: return ' '; + case 0xFA: return '.'; + case 0xFB: return ' '; + case 0xFC: return ' '; + case 0xFD: return 0x22; + case 0xFE: return ' '; + case 0xFF: return ' '; + } + return c; +} + +// String should match ndof for manufacturer based search to work +static void sanitizeString( char* inCStr ) +{ + char* charIt = inCStr; + while ( *charIt ) + { + *charIt = mapChar( *charIt ); + charIt++; + } +} + +struct HidDevice +{ + long mAxis; + long mLocalID; + char mProduct[256]; + char mManufacturer[256]; + long mUsage; + long mUsagePage; +}; + +static void populate_device_info( io_object_t io_obj_p, CFDictionaryRef device_dic, HidDevice* devicep ) +{ + CFMutableDictionaryRef io_properties = nil; + io_registry_entry_t entry1; + io_registry_entry_t entry2; + kern_return_t rc; + + // Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also + // get dictionary for usb properties: step up two levels and get CF dictionary for USB properties + // try to get parent1 + rc = IORegistryEntryGetParentEntry( io_obj_p, kIOServicePlane, &entry1 ); + if ( KERN_SUCCESS == rc ) + { + rc = IORegistryEntryGetParentEntry( entry1, kIOServicePlane, &entry2 ); + + IOObjectRelease( entry1 ); + + if ( KERN_SUCCESS == rc ) + { + rc = IORegistryEntryCreateCFProperties( entry2, &io_properties, kCFAllocatorDefault, kNilOptions ); + // either way, release parent2 + IOObjectRelease( entry2 ); + } + } + if ( KERN_SUCCESS == rc ) + { + // IORegistryEntryCreateCFProperties() succeeded + if ( io_properties != nil ) + { + CFTypeRef dict_element = 0; + // get device info + // try hid dictionary first, if fail then go to usb dictionary + + + dict_element = CFDictionaryGetValue( device_dic, CFSTR(kIOHIDProductKey) ); + if ( !dict_element ) + { + dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Product Name" ) ); + } + if ( dict_element ) + { + bool res = CFStringGetCString((CFStringRef)dict_element, devicep->mProduct, 256, kCFStringEncodingUTF8); + sanitizeString(devicep->mProduct); + if ( !res ) + { + LL_WARNS("Joystick") << "Failed to populate mProduct" << LL_ENDL; + } + } + + dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDManufacturerKey ) ); + if ( !dict_element ) + { + dict_element = CFDictionaryGetValue( io_properties, CFSTR( "USB Vendor Name" ) ); + } + if ( dict_element ) + { + bool res = CFStringGetCString( (CFStringRef)dict_element, devicep->mManufacturer, 256, kCFStringEncodingUTF8 ); + sanitizeString(devicep->mManufacturer); + if ( !res ) + { + LL_WARNS("Joystick") << "Failed to populate mManufacturer" << LL_ENDL; + } + } + + dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDLocationIDKey ) ); + if ( !dict_element ) + { + dict_element = CFDictionaryGetValue( io_properties, CFSTR( "locationID" ) ); + } + if ( dict_element ) + { + bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mLocalID ); + if ( !res ) + { + LL_WARNS("Joystick") << "Failed to populate mLocalID" << LL_ENDL; + } + } + + dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsagePageKey ) ); + if ( dict_element ) + { + bool res = CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsagePage ); + if ( !res ) + { + LL_WARNS("Joystick") << "Failed to populate mUsagePage" << LL_ENDL; + } + dict_element = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDPrimaryUsageKey ) ); + if ( dict_element ) + { + if ( !CFNumberGetValue( (CFNumberRef)dict_element, kCFNumberLongType, &devicep->mUsage ) ) + { + LL_WARNS("Joystick") << "Failed to populate mUsage" << LL_ENDL; + } + } + } + + //Add axis, because ndof lib checks sutability by axises as well as other elements + devicep->mAxis = 0; + CFTypeRef hid_elements = CFDictionaryGetValue( device_dic, CFSTR( kIOHIDElementKey ) ); + if ( hid_elements && CFGetTypeID( hid_elements ) == CFArrayGetTypeID( ) ) + { + long count = CFArrayGetCount( (CFArrayRef) hid_elements ); + for (int i = 0; i < count; ++i) + { + CFTypeRef element = CFArrayGetValueAtIndex((CFArrayRef) hid_elements, i); + if (element && CFGetTypeID( element ) == CFDictionaryGetTypeID( )) + { + long type = 0, usage_page = 0, usage = 0; + + CFTypeRef ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementTypeKey ) ); + if ( ref_value ) + { + CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &type ); + } + + ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementUsagePageKey ) ); + if ( ref_value ) + { + CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &usage_page ); + } + + ref_value = CFDictionaryGetValue( (CFDictionaryRef) element, CFSTR( kIOHIDElementUsageKey ) ); + if ( ref_value ) + { + CFNumberGetValue( (CFNumberRef)ref_value, kCFNumberLongType, &usage ); + } + if ( type != 0 + && type != kIOHIDElementTypeCollection + && usage_page == kHIDPage_GenericDesktop) + { + switch( usage ) + { + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + devicep->mAxis++; + break; + default: + break; + } + } + } + } + } + + CFRelease(io_properties); + } + else + { + LL_WARNS("Joystick") << "Failed to populate fields" << LL_ENDL; + } + } +} + +HidDevice populate_device( io_object_t io_obj ) +{ + void* interfacep = nullptr; + HidDevice device; + memset( &device, 0, sizeof( HidDevice ) ); + CFMutableDictionaryRef device_dic = 0; + kern_return_t result = IORegistryEntryCreateCFProperties( io_obj, &device_dic, kCFAllocatorDefault, kNilOptions ); + + if ( KERN_SUCCESS == result + && device_dic ) + { + IOReturn io_result = kIOReturnSuccess; + HRESULT query_result = S_OK; + SInt32 the_score = 0; + IOCFPlugInInterface **the_interface = NULL; + + + io_result = IOCreatePlugInInterfaceForService( io_obj, kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &the_interface, &the_score ); + if ( io_result == kIOReturnSuccess ) + { + query_result = ( *the_interface )->QueryInterface( the_interface, CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ), ( LPVOID * ) & ( interfacep ) ); + if ( query_result != S_OK ) + { + LL_WARNS("Joystick") << "QueryInterface failed" << LL_ENDL; + } + IODestroyPlugInInterface( the_interface ); + } + else + { + LL_WARNS("Joystick") << "IOCreatePlugInInterfaceForService failed" << LL_ENDL; + } + + if ( interfacep ) + { + result = ( *( IOHIDDeviceInterface** )interfacep )->open( interfacep, 0 ); + + if ( result != kIOReturnSuccess) + { + LL_WARNS("Joystick") << "open failed" << LL_ENDL; + } + } + // extract needed fields + populate_device_info( io_obj, device_dic, &device ); + + // Release interface + if ( interfacep ) + { + ( *( IOHIDDeviceInterface** ) interfacep )->close( interfacep ); + + ( *( IOHIDDeviceInterface** ) interfacep )->Release( interfacep ); + + interfacep = NULL; + } + + CFRelease( device_dic ); + } + else + { + LL_WARNS("Joystick") << "populate_device failed" << LL_ENDL; + } + + return device; +} + +static void get_devices(std::list<HidDevice> &list_of_devices, + io_iterator_t inIODeviceIterator) +{ + IOReturn result = kIOReturnSuccess; // assume success( optimist! ) + io_object_t io_obj = 0; + + while ( 0 != (io_obj = IOIteratorNext( inIODeviceIterator ) ) ) + { + HidDevice device = populate_device( io_obj ); + + // Should match ndof + if (device.mAxis >= 3 + || (device.mUsagePage == kHIDPage_GenericDesktop + && (device.mUsage == kHIDUsage_GD_MultiAxisController + || device.mUsage == kHIDUsage_GD_GamePad + || device.mUsage == kHIDUsage_GD_Joystick)) + || (device.mUsagePage == kHIDPage_Game + && device.mUsage == kHIDUsage_Game_3DGameController) + || strstr(device.mManufacturer, "3Dconnexion")) + { + list_of_devices.push_back(device); + } + else + { + LL_DEBUGS("Joystick"); + list_of_devices.push_back(device); + LL_CONT << "Device axes: " << (S32)device.mAxis + << " Device HIDUsepage: " << (S32)device.mUsagePage + << " Device HIDUsage: " << (S32)device.mUsage; + LL_ENDL; + } + + + // release the device object, it is no longer needed + result = IOObjectRelease( io_obj ); + if ( KERN_SUCCESS != result ) + { + LL_WARNS("Joystick") << "IOObjectRelease failed" << LL_ENDL; + } + } +} + +bool LLWindowMacOSX::getInputDevices(U32 device_type_filter, + std::function<bool(std::string&, LLSD&, void*)> osx_callback, + void* win_callback, + void* userdata) +{ + bool return_value = false; + CFMutableDictionaryRef device_dict_ref; + IOReturn result = kIOReturnSuccess; // assume success( optimist! ) + + // Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error. + + // A dictionary to match devices to? + device_dict_ref = IOServiceMatching( kIOHIDDeviceKey ); + + // BUG FIX! one reference is consumed by IOServiceGetMatchingServices + CFRetain( device_dict_ref ); + io_iterator_t io_iter = 0; + + // create an IO object iterator + result = IOServiceGetMatchingServices( kIOMasterPortDefault, device_dict_ref, &io_iter ); + if ( kIOReturnSuccess != result ) + { + LL_WARNS("Joystick") << "IOServiceGetMatchingServices failed" << LL_ENDL; + } + + if ( io_iter ) + { + // add all existing devices + std::list<HidDevice> device_list; + + get_devices(device_list, io_iter); + + std::list<HidDevice>::iterator iter; + + for (iter = device_list.begin(); iter != device_list.end(); ++iter) + { + std::string label(iter->mProduct); + LLSD data; + data["manufacturer"] = std::string(iter->mManufacturer); + data["product"] = label; + + if (osx_callback(label, data, userdata)) + { + break; //found device + } + } + return_value = true; + } + + CFRelease( device_dict_ref ); + return return_value; +} + LLSD LLWindowMacOSX::getNativeKeyData() { LLSD result = LLSD::emptyMap(); diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 5d664c27cc19e94b5e6b40facae886499a4ff49b..8377f102ed057ad8c4fc0d38fe709c5ec6d66ea3 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -117,6 +117,11 @@ class LLWindowMacOSX : public LLWindow void spawnWebBrowser(const std::string& escaped_url, bool async) override; F32 getSystemUISize() override; + bool getInputDevices(U32 device_type_filter, + std::function<bool(std::string&, LLSD&, void*)> osx_callback, + void* win_callback, + void* userdata) override; + static std::vector<std::string> getDisplaysResolutionList(); static std::vector<std::string> getDynamicFallbackFontList(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 773f855b7853a9439c8881b4e3dfa7469f8fb68b..bdf56c1e6a062e127bae0098a079199a6f3987ec 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1650,7 +1650,9 @@ const S32 max_format = (S32)num_formats - 1; } else { - LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL; + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr")); + // mWindowHandle is 0, going to crash either way + LL_ERRS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL; } // Verify what pixel format we actually received. @@ -4439,7 +4441,10 @@ void* LLWindowWin32::getDirectInput8() return &gDirectInput8; } -bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata) +bool LLWindowWin32::getInputDevices(U32 device_type_filter, + std::function<bool(std::string&, LLSD&, void*)> osx_callback, + void * di8_devices_callback, + void* userdata) { if (gDirectInput8 != NULL) { diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 221eb2b96351f77fa9067d1025becaa261f52c38..4bab37903f1702bdb839b8f6640fd11b7bd32712 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -130,7 +130,10 @@ class LLWindowWin32 final : public LLWindow static std::vector<std::string> getDynamicFallbackFontList(); /*virtual*/ void* getDirectInput8(); - /*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata); + /*virtual*/ bool getInputDevices(U32 device_type_filter, + std::function<bool(std::string&, LLSD&, void*)> osx_callback, + void* win_callback, + void* userdata); U32 getRawWParam() { return mRawWParam; } diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 974c8a5c2dc06896295eafb31e186e2a33697eeb..36f723e29c4f5a52b039a35138fe522ba8e51cc9 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -1654,8 +1654,6 @@ DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255)); LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"]; DECL_LLCC(LLSD, test_llsd); -static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment"); - void test_cached_control() { #define TEST_LLCC(T, V) if((T)mySetting_##T != V) LL_ERRS() << "Fail "#T << LL_ENDL @@ -1672,8 +1670,6 @@ void test_cached_control() TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f)); TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255)); //There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd); - - if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL; } #endif // TEST_CACHED_CONTROL diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 05cf20c97e100981354ca18ade3626f40361bc17..c4438211cd800047e40c6051a867feb984a8db0c 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -834,7 +834,7 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, if (!LLXMLNode::parseFile(filename, root, NULL)) { - LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL; + LL_WARNS() << "Problem reading UI description file: " << filename << " " << errno << LL_ENDL; return false; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 31f329229eadee0a03d864b08da08fc49d48609e..179390bd291f63b7b49fa8615b953cc497369975 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -17,7 +17,6 @@ include(DragDrop) include(EXPAT) include(FMODSTUDIO) include(Hunspell) -include(ICU4C) include(JPEGEncoderBasic) include(LibXML2) include(LLAppearance) @@ -1782,6 +1781,7 @@ set(viewer_APPSETTINGS_FILES app_settings/cmd_line.xml app_settings/commands.xml app_settings/emoji_groups.xml + app_settings/foldertypes.xml app_settings/grass.xml app_settings/ignorable_dialogs.xml app_settings/key_bindings.xml @@ -2127,9 +2127,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} llprimitive llappearance ${LLPHYSICSEXTENSIONS_LIBRARIES} - ll::icu4c ll::tracy - ll::sdbus-cpp ll::versioninfo ) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 2380dcfd47328403cb6f1238721f9a3d9cccc5e7..2fe040f4247d45250f5b0545fbb60f54d8c43f12 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.1.7 +7.1.8 diff --git a/indra/newview/ao.cpp b/indra/newview/ao.cpp index ef731a80f5c3bf794f4b85d16436d9a93ccdd2eb..11d6b9861c17384a1ba48fd2093c4b595fe2abcd 100644 --- a/indra/newview/ao.cpp +++ b/indra/newview/ao.cpp @@ -394,8 +394,9 @@ void FloaterAO::onRenameSet() if (!name.empty()) { + LLTextValidate::Validator validator(LLTextValidate::validateASCIIPrintableNoPipe); if ( - LLTextValidate::validateASCIIPrintableNoPipe(new_set_name.getWString()) && // only allow ASCII + validator.validate(new_set_name.getWString()) && // only allow ASCII name.find_first_of(":|") == std::string::npos) // don't allow : or | { if (AOEngine::instance().renameSet(mSelectedSet, name)) @@ -513,13 +514,13 @@ bool FloaterAO::newSetCallback(const LLSD& notification, const LLSD& response) LLStringUtil::trim(newSetName); LLUIString new_set_name = newSetName; - + LLTextValidate::Validator validator(LLTextValidate::validateASCIIPrintableNoPipe); if (newSetName.empty()) { return false; } else if ( - !LLTextValidate::validateASCIIPrintableNoPipe(new_set_name.getWString()) || // only allow ASCII + !validator.validate(new_set_name.getWString()) || // only allow ASCII newSetName.find_first_of(":|") != std::string::npos) // don't allow : or | { LLSD args; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 86c8a4714bbae4344e61e4120a1c79ce07333a34..5f20825bd5f8bbe21d649111bf4c764bfe6ea3f8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -449,17 +449,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AdvanceOutfitSnapshot</key> - <map> - <key>Comment</key> - <string>Display advanced parameter settings in outfit snaphot interface</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>AgentPause</key> <map> <key>Comment</key> @@ -526,17 +515,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AnimationDebug</key> - <map> - <key>Comment</key> - <string>Show active animations in a bubble above avatars head</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>AppearanceCameraMovement</key> <map> <key>Comment</key> @@ -581,17 +559,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>AskedAboutCrashReports</key> - <map> - <key>Comment</key> - <string>Turns off dialog asking if you want to enable crash reporting</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>AuctionShowFence</key> <map> <key>Comment</key> @@ -614,17 +581,6 @@ <key>Value</key> <real>0.5</real> </map> - <key>AudioLevelDoppler</key> - <map> - <key>Comment</key> - <string>Scale of doppler effect on moving audio sources (1.0 = normal, <1.0 = diminished doppler effect, >1.0 = enhanced doppler effect)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> <key>AudioLevelMaster</key> <map> <key>Comment</key> @@ -669,28 +625,6 @@ <key>Value</key> <real>0.3</real> </map> - <key>AudioLevelRolloff</key> - <map> - <key>Comment</key> - <string>Controls the distance-based dropoff of audio volume (fraction or multiple of default audio rolloff)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> - <key>AudioLevelUnderwaterRolloff</key> - <map> - <key>Comment</key> - <string>Controls the distance-based dropoff of audio volume underwater(fraction or multiple of default audio rolloff)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>5.0</real> - </map> <key>AudioLevelSFX</key> <map> <key>Comment</key> @@ -723,17 +657,6 @@ <string>F32</string> <key>Value</key> <real>0.5</real> - </map> - <key>AudioLevelWind</key> - <map> - <key>Comment</key> - <string>Audio level of wind noise when standing still</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.5</real> </map> <key>AudioStreamingMedia</key> <map> @@ -768,7 +691,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>AutoAcceptNewInventory</key> + <key>AutoAcceptNewInventory</key> <map> <key>Comment</key> <string>Automatically accept new notecards/textures/landmarks</string> @@ -790,17 +713,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AutoLoadWebProfiles</key> - <map> - <key>Comment</key> - <string>Automatically load ALL profile webpages without asking first.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>AutoLogin</key> <map> <key>Comment</key> @@ -999,17 +911,6 @@ <key>Value</key> <real>1.0</real> </map> - <key>AvatarBacklight</key> - <map> - <key>Comment</key> - <string>Add rim lighting to avatar rendering to approximate shininess of skin</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>AvatarFeathering</key> <map> <key>Comment</key> @@ -1021,32 +922,6 @@ <key>Value</key> <real>16.0</real> </map> - <key>AvatarPickerSortOrder</key> - <map> - <key>Comment</key> - <string>Specifies sort key for textures in avatar picker (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>2</integer> - </map> - <key>AvatarPosFinalOffset</key> - <map> - <key>Comment</key> - <string>After-everything-else fixup for avatar position.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>0.0</real> - <real>0.0</real> - <real>0.0</real> - </array> - </map> <key>AvatarPickerURL</key> <map> <key>Comment</key> @@ -1058,50 +933,6 @@ <key>Value</key> <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/avatars.html</string> </map> - <key>AvatarRotateThresholdSlow</key> - <map> - <key>Comment</key> - <string>Angle between avatar facing and camera facing at which avatar turns to face same direction as camera, when moving slowly (degrees)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <integer>60</integer> - </map> - <key>AvatarRotateThresholdFast</key> - <map> - <key>Comment</key> - <string>Angle between avatar facing and camera facing at which avatar turns to face same direction as camera, when moving fast (degrees)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <integer>2</integer> - </map> - <key>AvatarBakedTextureUploadTimeout</key> - <map> - <key>Comment</key> - <string>Specifes the maximum time in seconds to wait before sending your baked textures for avatar appearance. Set to 0 to disable and wait until all baked textures are at highest resolution.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>60</integer> - </map> - <key>AvatarBakedLocalTextureUpdateTimeout</key> - <map> - <key>Comment</key> - <string>Specifes the maximum time in seconds to wait before updating your appearance during appearance mode.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>10</integer> - </map> <key>AvatarPhysics</key> <map> <key>Comment</key> @@ -1135,28 +966,6 @@ <key>Value</key> <integer>40</integer> </map> - <key>BottomPanelNew</key> - <map> - <key>Comment</key> - <string>Enable the new bottom panel</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>BrowserHomePage</key> - <map> - <key>Comment</key> - <string>[NOT USED]</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>http://www.secondlife.com</string> - </map> <key>BrowserIgnoreSSLCertErrors</key> <map> <key>Comment</key> @@ -1234,17 +1043,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>BlockSomeAvatarAppearanceVisualParams</key> - <map> - <key>Comment</key> - <string>Drop around 50% of VisualParam occurances in appearance messages (for simulating Ruth)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>BrowserProxyAddress</key> <map> <key>Comment</key> @@ -1267,17 +1065,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>BrowserProxyExclusions</key> - <map> - <key>Comment</key> - <string>[NOT USED]</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string /> - </map> <key>BrowserProxyPort</key> <map> <key>Comment</key> @@ -1289,17 +1076,6 @@ <key>Value</key> <integer>3128</integer> </map> - <key>BrowserProxySocks45</key> - <map> - <key>Comment</key> - <string>[NOT USED]</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>5</integer> - </map> <key>Socks5ProxyEnabled</key> <map> <key>Comment</key> @@ -1685,39 +1461,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>ButtonHPad</key> - <map> - <key>Comment</key> - <string>Default horizontal spacing between buttons (pixels)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>4</integer> - </map> - <key>ButtonHeight</key> - <map> - <key>Comment</key> - <string>Default height for normal buttons (pixels)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>23</integer> - </map> - <key>ButtonHeightSmall</key> - <map> - <key>Comment</key> - <string>Default height for small buttons (pixels)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>23</integer> - </map> <key>EnableDiskCacheDebugInfo</key> <map> <key>Comment</key> @@ -1773,17 +1516,6 @@ <key>Value</key> <string /> </map> - <key>CacheNumberOfRegionsForObjects</key> - <map> - <key>Comment</key> - <string>Controls number of regions to be cached for objects.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>128</integer> - </map> <key>DiskCacheSize</key> <map> <key>Comment</key> @@ -1891,100 +1623,55 @@ <real>0.75</real> </array> </map> - <key>CameraOffsetFrontView</key> + <key>CameraOffsetScale</key> <map> <key>Comment</key> - <string>Initial camera offset from avatar in Front View</string> + <string>Scales the default offset</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Vector3</string> + <string>F32</string> <key>Value</key> - <array> - <real>2.2</real> - <real>0.0</real> - <real>0.0</real> - </array> + <real>1.0</real> </map> - <key>CameraOffsetGroupView</key> + <key>CameraZoomFraction</key> <map> <key>Comment</key> - <string>Initial camera offset from avatar in Group View</string> + <string>Mousewheel driven fraction of zoom</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Vector3</string> + <string>F32</string> <key>Value</key> - <array> - <real>-1.0</real> - <real>0.7</real> - <real>0.5</real> - </array> + <real>0.9</real> </map> - <key>CameraOffsetCustomPreset</key> + <key>CameraPosOnLogout</key> <map> <key>Comment</key> - <string>Initial camera offset from avatar for the custom camera preset</string> + <string>Camera position when last logged out (global coordinates)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Vector3</string> + <string>Vector3D</string> <key>Value</key> <array> - <real>-3.0</real> <real>0.0</real> - <real>0.75</real> + <real>0.0</real> + <real>0.0</real> </array> </map> - <key>CameraOffsetScale</key> + <key>RestoreCameraPosOnLogin</key> <map> <key>Comment</key> - <string>Scales the default offset</string> + <string>Reset camera position to location at logout</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>F32</string> + <string>Boolean</string> <key>Value</key> - <real>1.0</real> + <integer>0</integer> </map> - <key>CameraZoomFraction</key> - <map> - <key>Comment</key> - <string>Mousewheel driven fraction of zoom</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.9</real> - </map> - <key>CameraPosOnLogout</key> - <map> - <key>Comment</key> - <string>Camera position when last logged out (global coordinates)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3D</string> - <key>Value</key> - <array> - <real>0.0</real> - <real>0.0</real> - <real>0.0</real> - </array> - </map> - <key>RestoreCameraPosOnLogin</key> - <map> - <key>Comment</key> - <string>Reset camera position to location at logout</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>CameraPositionSmoothing</key> + <key>CameraPositionSmoothing</key> <map> <key>Comment</key> <string>Smooths camera position over time</string> @@ -2090,17 +1777,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>ChatBarStealsFocus</key> - <map> - <key>Comment</key> - <string>Whenever keyboard focus is removed from the UI, and the chat bar is visible, the chat bar takes focus</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>LetterKeysFocusChatBar</key> <map> <key>Comment</key> @@ -2145,17 +1821,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>ChatHistoryTornOff</key> - <map> - <key>Comment</key> - <string>Show chat history window separately from Communicate window.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>ChatLoadGroupMaxMembers</key> <map> <key>Comment</key> @@ -2167,17 +1832,6 @@ <key>Value</key> <integer>100</integer> </map> - <key>ChatLoadGroupTimeout</key> - <map> - <key>Comment</key> - <string>Time we give the server to send group participants before we hit the server for group info (seconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>10.0</real> - </map> <key>ChatOnlineNotification</key> <map> <key>Comment</key> @@ -2189,28 +1843,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>ChatPersistTime</key> - <map> - <key>Comment</key> - <string>Time for which chat stays visible in console (seconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>20.0</real> - </map> - <key>ChatShowTimestamps</key> - <map> - <key>Comment</key> - <string>Show timestamps in chat</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>CheesyBeacon</key> <map> <key>Comment</key> @@ -2233,50 +1865,6 @@ <key>Value</key> <string /> </map> - <key>ContextConeInAlpha</key> - <map> - <key>Comment</key> - <string>Cone In Alpha</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.0</real> - </map> - <key>ContextConeOutAlpha</key> - <map> - <key>Comment</key> - <string>Cone Out Alpha</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> - <key>ContextConeFadeTime</key> - <map> - <key>Comment</key> - <string>Cone Fade Time</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>.08</real> - </map> - <key>ConversationHistoryPageSize</key> - <map> - <key>Comment</key> - <string>Chat history of conversation opened from call log is displayed by pages. So this is number of entries per page.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>100</integer> - </map> <key>ConversationSortOrder</key> <map> <key>Comment</key> @@ -2455,17 +2043,6 @@ <key>Value</key> <integer>40</integer> </map> - <key>ContactsTornOff</key> - <map> - <key>Comment</key> - <string>Show contacts window separately from Communicate window.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>CookiesEnabled</key> <map> <key>Comment</key> @@ -2510,17 +2087,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>ChatBarCustomWidth</key> - <map> - <key>Comment</key> - <string>Stores customized width of chat bar.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>CoroutineStackSize</key> <map> <key>Comment</key> @@ -2587,17 +2153,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>CurlMaximumNumberOfHandles</key> - <map> - <key>Comment</key> - <string>Maximum number of handles curl can use (requires restart)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>256</integer> - </map> <key>CurlRequestTimeOut</key> <map> <key>Comment</key> @@ -2608,17 +2163,6 @@ <string>F32</string> <key>Value</key> <real>120.0</real> - </map> - <key>CurlUseMultipleThreads</key> - <map> - <key>Comment</key> - <string>Use background threads for executing curl_multi_perform (requires restart)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> </map> <key>Cursor3D</key> <map> @@ -2653,17 +2197,6 @@ <key>Value</key> <string></string> </map> - <key>CustomServer</key> - <map> - <key>Comment</key> - <string>Specifies IP address or hostname of grid to which you connect</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string /> - </map> <key>DebugAnimatedObjects</key> <map> <key>Comment</key> @@ -2686,17 +2219,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>AnimatedObjectsIgnoreLimits</key> - <map> - <key>Comment</key> - <string>Ignore server-enforced limits on animated objects. This is only useful for server testing.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>AnimatedObjectsAllowLeftClick</key> <map> <key>Comment</key> @@ -2708,17 +2230,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>AnimatedObjectsGlobalScale</key> - <map> - <key>Comment</key> - <string>Temporary testing: allow an extra scale factor to be forced on animated objects.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.00</real> - </map> <key>AnimatedObjectsMaxLegalOffset</key> <map> <key>Comment</key> @@ -2741,17 +2252,6 @@ <key>Value</key> <real>64.0</real> </map> - <key>AvatarBoundingBoxComplexity</key> - <map> - <key>Comment</key> - <string>How many aspects to consider for avatar bounding box</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>3</integer> - </map> <key>AvatarExtentRefreshPeriodBatch</key> <map> <key>Comment</key> @@ -2884,17 +2384,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>DebugInventoryFilters</key> - <map> - <key>Comment</key> - <string>Turn on debugging display for inventory filtering</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>DebugPermissions</key> <map> <key>Comment</key> @@ -2961,18 +2450,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>DebugShowPrivateMem</key> - <!-- deprecated (see MAINT-8091) --> - <map> - <key>Comment</key> - <string>(Deprecated) Show Private Mem Info</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>DebugShowRenderInfo</key> <map> <key>Comment</key> @@ -3039,29 +2516,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>DebugSlshareLogTag</key> - <map> - <key>Comment</key> - <string>Request slshare-service debug logging</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string/> - </map> - <key>DebugStatModeFPS</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeBandwidth</key> + <key>SimPendingUploads</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3072,7 +2527,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModePacketLoss</key> + <key>DebugStatModeSimTotalUnackedBytes</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3083,7 +2538,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatMode</key> + <key>DebugStatModeSimFrameMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3094,7 +2549,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeKTrisDrawnFr</key> + <key>DebugStatModeSimNetMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3105,7 +2560,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeKTrisDrawnSec</key> + <key>DebugStatModeSimSimPhysicsMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3116,7 +2571,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeTotalObjs</key> + <key>DebugStatModeSimSimOtherMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3127,7 +2582,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeNewObjs</key> + <key>DebugStatModeSimAgentMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3138,7 +2593,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeTextureCount</key> + <key>DebugStatModeSimImagesMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3149,7 +2604,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeRawCount</key> + <key>DebugStatModeSimScriptMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3160,7 +2615,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeGLMem</key> + <key>DebugStatModeSimSpareMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3171,7 +2626,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeFormattedMem</key> + <key>DebugStatModeSimSimPhysicsStepMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3182,7 +2637,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeRawMem</key> + <key>DebugStatModeSimSimPhysicsShapeUpdateMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3193,7 +2648,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeBoundMem</key> + <key>DebugStatModeSimSimPhysicsOtherMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3204,7 +2659,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModePacketsIn</key> + <key>DebugStatModeSimSleepMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3215,7 +2670,7 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModePacketsOut</key> + <key>DebugStatModeSimPumpIOMsec</key> <map> <key>Comment</key> <string>Mode of stat in Statistics floater</string> @@ -3226,434 +2681,27 @@ <key>Value</key> <integer>-1</integer> </map> - <key>DebugStatModeObjects</key> + <key>DebugViews</key> <map> <key>Comment</key> - <string>Mode of stat in Statistics floater</string> + <string>Display debugging info for views.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>-1</integer> + <integer>0</integer> </map> - <key>DebugStatModeTexture</key> + <key>DebugWindowProc</key> <map> <key>Comment</key> - <string>Mode of stat in Statistics floater</string> + <string>Log windows messages</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeAsset</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeLayers</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeActualIn</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeActualOut</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeTimeDialation</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimFPS</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModePhysicsFPS</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModePinnedObjects</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeLowLODObjects</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeMemoryAllocated</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeAgentUpdatesSec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeMainAgents</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeChildAgents</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimObjects</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimActiveObjects</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimActiveScripts</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimScriptEvents</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimInPPS</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimOutPPS</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimPendingDownloads</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>SimPendingUploads</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimTotalUnackedBytes</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimFrameMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimNetMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSimPhysicsMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSimOtherMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimAgentMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimImagesMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimScriptMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSpareMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSimPhysicsStepMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSimPhysicsShapeUpdateMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSimPhysicsOtherMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimSleepMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugStatModeSimPumpIOMsec</key> - <map> - <key>Comment</key> - <string>Mode of stat in Statistics floater</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>-1</integer> - </map> - <key>DebugViews</key> - <map> - <key>Comment</key> - <string>Display debugging info for views.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>DebugWindowProc</key> - <map> - <key>Comment</key> - <string>Log windows messages</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> + <integer>0</integer> </map> <key>DefaultFemaleAvatar</key> <map> @@ -3688,208 +2736,21 @@ <key>Value</key> <string>Male Shape & Outfit</string> </map> - <key>DefaultUploadCost</key> - <map> - <key>Comment</key> - <string>Default sound/image/file upload cost(in case economy data is not available).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>10</integer> - </map> <key>DestinationGuideURL</key> <map> <key>Comment</key> - <string>Destination guide contents</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/guide.html</string> - </map> - <key>DisableCameraConstraints</key> - <map> - <key>Comment</key> - <string>Disable the normal bounds put on the camera by avatar position</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>DisableCrashLogger</key> - <map> - <key>Comment</key> - <string>Do not send crash report to Linden server</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>DisableMouseWarp</key> - <map> - <key>Comment</key> - <string>Disable warping of the mouse to the center of the screen during alt-zoom and mouse look. Useful with certain input devices, mouse sharing programs like Synergy, or running under Parallels.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>DisableExternalBrowser</key> - <map> - <key>Comment</key> - <string>Disable opening an external browser.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>HeadlessClient</key> - <map> - <key>Comment</key> - <string>Run in headless mode by disabling GL rendering, keyboard, etc</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>DisableTextHyperlinkActions</key> - <map> - <key>Comment</key> - <string>Disable highlighting and linking of URLs in XUI text boxes</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>RenderVSyncEnable</key> - <map> - <key>Comment</key> - <string>Update frames between display scans (FALSE = Update frames as fast as possible).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>EnableGroupChatPopups</key> - <map> - <key>Comment</key> - <string>Enable Incoming Group Chat Popups</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>EnableIMChatPopups</key> - <map> - <key>Comment</key> - <string>Enable Incoming IM Chat Popups</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>DisplayAvatarAgentTarget</key> - <map> - <key>Comment</key> - <string>Show avatar positioning locators (animation debug)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>DisplayChat</key> - <map> - <key>Comment</key> - <string>Display Latest Chat message on LCD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>DisplayDebug</key> - <map> - <key>Comment</key> - <string>Display Network Information on LCD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>DisplayDebugConsole</key> - <map> - <key>Comment</key> - <string>Display Console Debug Information on LCD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>DisplayIM</key> - <map> - <key>Comment</key> - <string>Display Latest IM message on LCD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>DisplayLinden</key> - <map> - <key>Comment</key> - <string>Display Account Information on LCD</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>DisplayRegion</key> - <map> - <key>Comment</key> - <string>Display Location information on LCD</string> + <string>Destination guide contents</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>String</string> <key>Value</key> - <integer>1</integer> + <string>http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/[GRID_LOWERCASE]/guide.html</string> </map> - <key>DisplayTimecode</key> + <key>DisableCameraConstraints</key> <map> <key>Comment</key> - <string>Display timecode on screen</string> + <string>Disable the normal bounds put on the camera by avatar position</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -3897,54 +2758,54 @@ <key>Value</key> <integer>0</integer> </map> - <key>Disregard128DefaultDrawDistance</key> + <key>DisableCrashLogger</key> <map> <key>Comment</key> - <string>Whether to use the auto default to 128 draw distance</string> + <string>Do not send crash report to Linden server</string> <key>Persist</key> - <integer>1</integer> + <integer>0</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> - <key>Disregard96DefaultDrawDistance</key> + <key>DisableMouseWarp</key> <map> <key>Comment</key> - <string>Whether to use the auto default to 96 draw distance</string> + <string>Disable warping of the mouse to the center of the screen during alt-zoom and mouse look. Useful with certain input devices, mouse sharing programs like Synergy, or running under Parallels.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> - <key>ClickActionBuyEnabled</key> + <key>DisableExternalBrowser</key> <map> <key>Comment</key> - <string>Enable click to buy actions in tool pie menu</string> + <string>Disable opening an external browser.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> - <key>ClickActionPayEnabled</key> + <key>HeadlessClient</key> <map> <key>Comment</key> - <string>Enable click to pay actions in tool pie menu</string> + <string>Run in headless mode by disabling GL rendering, keyboard, etc</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> - <key>DoubleClickAutoPilot</key> + <key>DisableTextHyperlinkActions</key> <map> <key>Comment</key> - <string>(Obsolete)Enable double-click auto pilot</string> + <string>Disable highlighting and linking of URLs in XUI text boxes</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -3952,21 +2813,21 @@ <key>Value</key> <integer>0</integer> </map> - <key>DoubleClickTeleport</key> + <key>RenderVSyncEnable</key> <map> <key>Comment</key> - <string>Enable double-click to teleport where allowed (afects minimap and people panel)</string> + <string>Update frames between display scans (FALSE = Update frames as fast as possible).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> - <key>DoubleClickShowWorldMap</key> + <key>EnableGroupChatPopups</key> <map> <key>Comment</key> - <string>Enable double-click to show world map from mini map</string> + <string>Enable Incoming Group Chat Popups</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -3974,71 +2835,71 @@ <key>Value</key> <integer>1</integer> </map> - <key>DragAndDropToolTipDelay</key> + <key>DisplayTimecode</key> <map> <key>Comment</key> - <string>Seconds before displaying tooltip when performing drag and drop operation</string> + <string>Display timecode on screen</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>F32</string> + <string>Boolean</string> <key>Value</key> - <real>0.10000000149</real> + <integer>0</integer> </map> - <key>DragAndDropDistanceThreshold</key> + <key>Disregard128DefaultDrawDistance</key> <map> <key>Comment</key> - <string>Number of pixels that mouse should move before triggering drag and drop mode</string> + <string>Whether to use the auto default to 128 draw distance</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>3</integer> + <integer>1</integer> </map> - <key>DropShadowButton</key> + <key>Disregard96DefaultDrawDistance</key> <map> <key>Comment</key> - <string>Drop shadow width for buttons (pixels)</string> + <string>Whether to use the auto default to 96 draw distance</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>2</integer> + <integer>1</integer> </map> - <key>DropShadowFloater</key> + <key>DoubleClickAutoPilot</key> <map> <key>Comment</key> - <string>Drop shadow width for floaters (pixels)</string> + <string>(Obsolete)Enable double-click auto pilot</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>5</integer> + <integer>0</integer> </map> - <key>DropShadowSlider</key> + <key>DoubleClickTeleport</key> <map> <key>Comment</key> - <string>Drop shadow width for sliders (pixels)</string> + <string>Enable double-click to teleport where allowed (afects minimap and people panel)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>3</integer> + <integer>1</integer> </map> - <key>DropShadowTooltip</key> + <key>DoubleClickShowWorldMap</key> <map> <key>Comment</key> - <string>Drop shadow width for tooltips (pixels)</string> + <string>Enable double-click to show world map from mini map</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>4</integer> + <integer>1</integer> </map> <key>DynamicCameraStrength</key> <map> @@ -4073,17 +2934,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>IncludeEnhancedSkeleton</key> - <map> - <key>Comment</key> - <string>Include extended skeleton joints when rendering skinned meshes.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>MinObjectsForUnlinkConfirm</key> <map> <key>Comment</key> @@ -4183,39 +3033,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>EnergyFromTop</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>20</integer> - </map> - <key>EnergyHeight</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>40</integer> - </map> - <key>EnergyWidth</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>175</integer> - </map> <key>EventURL</key> <map> <key>Comment</key> @@ -4227,61 +3044,6 @@ <key>Value</key> <string>http://events.[GRID]/viewer/embed/event/[EVENT_ID]</string> </map> - <key>FastCacheFetchEnabled</key> - <map> - <key>Comment</key> - <string>Enable texture fast cache fetching if set</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <string>1</string> - </map> - <key>FeatureManagerHTTPTable</key> - <map> - <key>Comment</key> - <string>Deprecated</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string></string> - </map> - <key>FPSLogFrequency</key> - <map> - <key>Comment</key> - <string>Seconds between display of FPS in log (0 for never)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>15.0</real> - </map> - <key>FilterItemsMaxTimePerFrameVisible</key> - <map> - <key>Comment</key> - <string>Max time devoted to items filtering per frame for visible inventory listings (in milliseconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>10</integer> - </map> - <key>FilterItemsMaxTimePerFrameUnvisible</key> - <map> - <key>Comment</key> - <string>Max time devoted to items filtering per frame for non visible inventory listings (in milliseconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1</integer> - </map> <key>MainWorkTime</key> <map> <key>Comment</key> @@ -4293,72 +3055,6 @@ <key>Value</key> <real>1.0</real> </map> - <key>QueueInventoryFetchTimeout</key> - <map> - <key>Comment</key> - <string>Max time llcompilequeue will wait for inventory fetch to complete (in seconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>300.0</real> - </map> - <key>FindLandArea</key> - <map> - <key>Comment</key> - <string>Enables filtering of land search results by area</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>FindLandPrice</key> - <map> - <key>Comment</key> - <string>Enables filtering of land search results by price</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>FindLandType</key> - <map> - <key>Comment</key> - <string>Controls which type of land you are searching for in Find Land interface ("All", "Auction", "For Sale")</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>All</string> - </map> - <key>FindPeopleOnline</key> - <map> - <key>Comment</key> - <string>Limits people search to only users who are logged on</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>FindPlacesPictures</key> - <map> - <key>Comment</key> - <string>Display only results of find places that have pictures</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>FirstName</key> <map> <key>Comment</key> @@ -4715,112 +3411,56 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.0</real> - </map> - <key>FlycamAxisScale6</key> - <map> - <key>Comment</key> - <string>Flycam axis 6 scaler.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> - <key>FlycamBuildModeScale</key> - <map> - <key>Comment</key> - <string>Scale factor to apply to flycam movements when in build mode.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> - <key>FlycamFeathering</key> - <map> - <key>Comment</key> - <string>Flycam feathering (less is softer)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>16.0</real> - </map> - <key>FlycamZoomDirect</key> - <map> - <key>Comment</key> - <string>Map flycam zoom axis directly to camera zoom.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> + <real>1.0</real> </map> - <key>FlyingAtExit</key> + <key>FlycamAxisScale6</key> <map> <key>Comment</key> - <string>Was flying when last logged out, so fly when logging in</string> + <string>Flycam axis 6 scaler.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>F32</string> <key>Value</key> - <integer>0</integer> + <real>1.0</real> </map> - <key>FocusOffsetRearView</key> + <key>FlycamBuildModeScale</key> <map> <key>Comment</key> - <string>Initial focus point offset relative to avatar for the camera preset Rear View (x-axis is forward)</string> + <string>Scale factor to apply to flycam movements when in build mode.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Vector3D</string> + <string>F32</string> <key>Value</key> - <array> - <real>1.0</real> - <real>0.0</real> - <real>1.0</real> - </array> + <real>1.0</real> </map> - <key>FocusOffsetFrontView</key> + <key>FlycamFeathering</key> <map> <key>Comment</key> - <string>Initial focus point offset relative to avatar for the camera preset Front View</string> + <string>Flycam feathering (less is softer)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Vector3D</string> + <string>F32</string> <key>Value</key> - <array> - <real>0.0</real> - <real>0.0</real> - <real>0.0</real> - </array> + <real>16.0</real> </map> - <key>FocusOffsetGroupView</key> + <key>FlyingAtExit</key> <map> <key>Comment</key> - <string>Initial focus point offset relative to avatar for the camera preset Group View</string> + <string>Was flying when last logged out, so fly when logging in</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Vector3D</string> + <string>Boolean</string> <key>Value</key> - <array> - <real>1.5</real> - <real>0.7</real> - <real>1.0</real> - </array> + <integer>0</integer> </map> - <key>FocusOffsetCustomPreset</key> + <key>FocusOffsetRearView</key> <map> <key>Comment</key> - <string>Initial focus point offset relative to avatar for the custom camera preset (x-axis is forward)</string> + <string>Initial focus point offset relative to avatar for the camera preset Rear View (x-axis is forward)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -4874,17 +3514,6 @@ <key>Value</key> <real>0.75</real> </map> - <key>FolderLoadingMessageWaitTime</key> - <map> - <key>Comment</key> - <string>Seconds to wait before showing the LOADING... text in folder views</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.5</real> - </map> <key>FontScreenDPI</key> <map> <key>Comment</key> @@ -4940,17 +3569,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>ForceMandatoryUpdate</key> - <map> - <key>Comment</key> - <string>For QA: On next startup, forces the auto-updater to run</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>ForceMissingType</key> <map> <key>Comment</key> @@ -5083,28 +3701,6 @@ <key>Value</key> <integer>32</integer> </map> - <key>GroupNotifyBoxHeight</key> - <map> - <key>Comment</key> - <string>Height of group notice messages</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>260</integer> - </map> - <key>GroupNotifyBoxWidth</key> - <map> - <key>Comment</key> - <string>Width of group notice messages</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>305</integer> - </map> <key>HelpURLFormat</key> <map> <key>Comment</key> @@ -5193,17 +3789,6 @@ <key>Value</key> <string /> </map> - <key>HtmlHelpLastPage</key> - <map> - <key>Comment</key> - <string>Last URL visited via help system</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string /> - </map> <key>HttpPipelining</key> <map> <key>Comment</key> @@ -5226,17 +3811,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>IMShowTimestamps</key> - <map> - <key>Comment</key> - <string>Show timestamps in IM</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>IMShowControlPanel</key> <map> <key>Comment</key> @@ -5247,17 +3821,6 @@ <string>Boolean</string> <key>Value</key> <integer>1</integer> - </map> - <key>IMShowContentPanel</key> - <map> - <key>Comment</key> - <string>Show Toolbar and Body Panels</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> </map> <key>IgnoreFOVZoomForLODs</key> <map> @@ -5324,28 +3887,6 @@ <string>F32</string> <key>Value</key> <real>0.0</real> - </map> - <key>InspectorFadeTime</key> - <map> - <key>Comment</key> - <string>Fade out timing for inspectors</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.5</real> - </map> - <key>InspectorShowTime</key> - <map> - <key>Comment</key> - <string>Stay timing for inspectors</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>3.0</real> </map> <key>InstallLanguage</key> <map> @@ -5413,17 +3954,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>InventoryOutboxDisplayBoth</key> - <map> - <key>Comment</key> - <string>(Deprecated) Show the legacy Merchant Outbox UI as well as the Marketplace Listings UI</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>InventoryOutboxLogging</key> <map> <key>Comment</key> @@ -5673,7 +4203,7 @@ <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>String</string> + <string>LLSD</string> <key>Value</key> <string /> </map> @@ -5754,17 +4284,6 @@ <key>Value</key> <real>2.0</real> </map> - <key>LCDDestination</key> - <map> - <key>Comment</key> - <string>Which LCD to use</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>LeapCommand</key> <map> <key>Comment</key> @@ -5986,105 +4505,6 @@ <string>0.0.0</string> </map> - <key>LastSnapshotToProfileHeight</key> - <map> - <key>Comment</key> - <string>The height of the last profile snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>768</integer> - </map> - <key>LastSnapshotToEmailHeight</key> - <map> - <key>Comment</key> - <string>The height of the last email snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>768</integer> - </map> - <key>LastSnapshotToProfileWidth</key> - <map> - <key>Comment</key> - <string>The width of the last profile snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1024</integer> - </map> - <key>LastSnapshotToEmailWidth</key> - <map> - <key>Comment</key> - <string>The width of the last email snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1024</integer> - </map> - <key>LastSnapshotToDiskHeight</key> - <map> - <key>Comment</key> - <string>The height of the last disk snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>768</integer> - </map> - <key>LastSnapshotToDiskWidth</key> - <map> - <key>Comment</key> - <string>The width of the last disk snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>1024</integer> - </map> - <key>LastSnapshotToInventoryHeight</key> - <map> - <key>Comment</key> - <string>The height of the last texture snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>512</integer> - </map> - <key>LastSnapshotToInventoryWidth</key> - <map> - <key>Comment</key> - <string>The width of the last texture snapshot, in px</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>512</integer> - </map> - <key>LeftClickShowMenu</key> - <map> - <key>Comment</key> - <string>Unused obsolete setting</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>LimitDragDistance</key> <map> <key>Comment</key> @@ -6249,18 +4669,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>60.0</real> - </map> - <key>LoginSRVPump</key> - <map> - <key>Comment</key> - <string>(Deprecated) Name of the message pump that handles SRV request)</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>LLAres</string> + <real>40.0</real> </map> <key>LogMessages</key> <map> @@ -6350,17 +4759,6 @@ <key>Value</key> <real>60.0</real> </map> - <key>MapOverlayIndex</key> - <map> - <key>Comment</key> - <string>Currently selected world map type</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>MapScale</key> <map> <key>Comment</key> @@ -7100,28 +5498,6 @@ <key>Value</key> <real>0.25</real> </map> - <key>MenuBarHeight</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>18</integer> - </map> - <key>MenuBarWidth</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>410</integer> - </map> <key>MePanelOpened</key> <map> <key>Comment</key> @@ -7631,28 +6007,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>NotifyBoxHeight</key> - <map> - <key>Comment</key> - <string>Height of notification messages</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>200</integer> - </map> - <key>NotifyBoxWidth</key> - <map> - <key>Comment</key> - <string>Width of notification messages</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>305</integer> - </map> <key>NotificationCanEmbedInIM</key> <map> <key>Comment</key> @@ -7874,17 +6228,6 @@ <key>Value</key> <integer>90</integer> </map> - <key>ChannelBottomPanelMargin</key> - <map> - <key>Comment</key> - <string>Space from a lower toast to the Bottom Tray</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>35</integer> - </map> <key>NotificationChannelRightMargin</key> <map> <key>Comment</key> @@ -8595,17 +6938,6 @@ <string>F32</string> <key>Value</key> <real>6.0</real> - </map> - <key>ClothingLoadingDelay</key> - <map> - <key>Comment</key> - <string>Time to wait for avatar appearance to resolve before showing world (seconds)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>10.0</real> </map> <key>PreferredMaturity</key> <map> @@ -9083,17 +7415,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>RadioLandBrushSize</key> - <map> - <key>Comment</key> - <string>Size of land modification brush (0 = small, 1 = medium, 2 = large)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>LandBrushForce</key> <map> <key>Comment</key> @@ -9105,17 +7426,6 @@ <key>Value</key> <real>1.0</real> </map> - <key>MediaBrowserWindowLimit</key> - <map> - <key>Comment</key> - <string>Maximum number of media brower windows that can be open at once in the media browser floater (0 for no limit)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>5</integer> - </map> <key>WebContentWindowLimit</key> <map> <key>Comment</key> @@ -9405,17 +7715,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderAvatar</key> - <map> - <key>Comment</key> - <string>Render Avatars</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>RenderAvatarCloth</key> <map> <key>Comment</key> @@ -11266,7 +9565,7 @@ <key>Value</key> <real>1.0</real> </map> - <key>RendeSkyAutoAdjustBlueHorizonScale</key> + <key>RenderSkyAutoAdjustBlueHorizonScale</key> <map> <key>Comment</key> <string>Blue Horizon Scale value to use when auto-adjusting legacy skies</string> @@ -11277,7 +9576,7 @@ <key>Value</key> <real>1.0</real> </map> - <key>RendeSkyAutoAdjustBlueDensityScale</key> + <key>RenderSkyAutoAdjustBlueDensityScale</key> <map> <key>Comment</key> <string>Blue Horizon Scale value to use when auto-adjusting legacy skies</string> @@ -12175,17 +10474,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>SecondLifeEnterprise</key> - <map> - <key>Comment</key> - <string>Enables Second Life Enterprise features</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>SelectMovableOnly</key> <map> <key>Comment</key> @@ -12461,17 +10749,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>ShowEmptyFoldersWhenSearching</key> - <map> - <key>Comment</key> - <string>Shows folders that do not have any visible contents when applying a filter to inventory</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>ShowEventRecorderMenuItems</key> <map> <key>Comment</key> @@ -12824,136 +11101,6 @@ <key>Value</key> <boolean>1</boolean> </map> - <key>ShowPGSearchAll</key> - <map> - <key>Comment</key> - <string>Display results of search All that are flagged as general</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>ShowMatureSearchAll</key> - <map> - <key>Comment</key> - <string>Display results of search All that are flagged as moderate</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>ShowAdultSearchAll</key> - <map> - <key>Comment</key> - <string>Display results of search All that are flagged as adult</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>ShowPGGroups</key> - <map> - <key>Comment</key> - <string>Display results of find groups that are flagged as general</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>ShowMatureGroups</key> - <map> - <key>Comment</key> - <string>Display results of find groups that are flagged as moderate</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>ShowAdultGroups</key> - <map> - <key>Comment</key> - <string>Display results of find groups that are flagged as adult</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>ShowPGClassifieds</key> - <map> - <key>Comment</key> - <string>Display results of find classifieds that are flagged as general</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>ShowMatureClassifieds</key> - <map> - <key>Comment</key> - <string>Display results of find classifieds that are flagged as moderate</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>ShowAdultClassifieds</key> - <map> - <key>Comment</key> - <string>Display results of find classifieds that are flagged as adult</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>ShowPGEvents</key> - <map> - <key>Comment</key> - <string>Display results of find events that are flagged as general</string> - <key>Persist</key> - <integer>1</integer> - <key>HideFromEditor</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>ShowMatureEvents</key> <map> <key>Comment</key> @@ -13189,17 +11336,6 @@ <string>Boolean</string> <key>Value</key> <integer>0</integer> - </map> - <key>ShowToolBar</key> - <map> - <key>Comment</key> - <string>Show toolbar at bottom of screen</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> </map> <key>ShowTutorial</key> <map> @@ -13642,28 +11778,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>TexturePickerShowFolders</key> - <map> - <key>Comment</key> - <string>Show folders with no texures in texture picker</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>TexturePickerSortOrder</key> - <map> - <key>Comment</key> - <string>Specifies sort key for textures in texture picker (+0 = name, +1 = date, +2 = folders always by name, +4 = system folders to top)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>2</integer> - </map> <key>TextureReverseByteRange</key> <map> <key>Comment</key> @@ -13713,17 +11827,6 @@ <key>Value</key> <real>3000.0</real> </map> - <key>UpdaterMaximumBandwidth</key> - <map> - <key>Comment</key> - <string>Obsolete: this parameter is no longer used.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>500.0</real> - </map> <key>ToolTipDelay</key> <map> <key>Comment</key> @@ -13856,17 +11959,6 @@ <key>Value</key> <string></string> </map> - <key>BingTranslateAPIKey</key> - <map> - <key>Comment</key> - <string>(Deprecated) Bing AppID to use with the Microsoft Translator API</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string></string> - </map> <key>AzureTranslateAPIKey</key> <map> <key>Comment</key> @@ -13909,51 +12001,29 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.5</real> - </map> - <key>UIAutoScale</key> - <map> - <key>Comment</key> - <string>Keep UI scale consistent across different resolutions</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>UIButtonOrigHPad</key> - <map> - <key>Comment</key> - <string>UI Button Original Horizontal Pad</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>6</integer> + <real>1.5</real> </map> - <key>UICheckboxctrlBtnSize</key> + <key>UIAutoScale</key> <map> <key>Comment</key> - <string>UI Checkbox Control Button Size</string> + <string>Keep UI scale consistent across different resolutions</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>S32</string> + <string>Boolean</string> <key>Value</key> - <integer>13</integer> + <integer>1</integer> </map> - <key>UICheckboxctrlHeight</key> + <key>UIButtonOrigHPad</key> <map> <key>Comment</key> - <string>UI Checkbox Control Height</string> + <string>UI Button Original Horizontal Pad</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>S32</string> <key>Value</key> - <integer>16</integer> + <integer>6</integer> </map> <key>UICheckboxctrlHPad</key> <map> @@ -14186,50 +12256,6 @@ <key>Value</key> <string>5748decc-f629-461c-9a36-a35a221fe21f</string> </map> - <key>StartUpChannelUUID</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>B56AF90D-6684-48E4-B1E4-722D3DEB2CB6</string> - </map> - <key>NearByChatChannelUUID</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>E1158BD6-661C-4981-9DAD-4DCBFF062502</string> - </map> - <key>NotificationChannelUUID</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>AEED3193-8709-4693-8558-7452CCA97AE5</string> - </map> - <key>AlertChannelUUID</key> - <map> - <key>Comment</key> - <string /> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string> - </map> <key>UILineEditorCursorThickness</key> <map> <key>Comment</key> @@ -14406,17 +12432,6 @@ <key>Value</key> <real>1.0</real> </map> - <key>LastSystemUIScaleFactor</key> - <map> - <key>Comment</key> - <string>OBSOLETE: System UI scale factor is now automatically and independently from UIScaleFactor applied</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.0</real> - </map> <key>UIScrollbarSize</key> <map> <key>Comment</key> @@ -14736,17 +12751,6 @@ <key>Value</key> <integer>16</integer> </map> - <key>UISpinctrlDefaultLabelWidth</key> - <map> - <key>Comment</key> - <string>UI spin control default label width</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>10</integer> - </map> <key>UISpinctrlSpacing</key> <map> <key>Comment</key> @@ -14868,39 +12872,6 @@ <key>Value</key> <integer>3</integer> </map> - <key>UpdaterServiceCheckPeriod</key> - <map> - <key>Comment</key> - <string>Obsolete; no longer used.</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>3600</integer> - </map> - <key>UpdaterServiceURL</key> - <map> - <key>Comment</key> - <string>Obsolete; no longer used.</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>https://update.secondlife.com</string> - </map> - <key>UpdaterServicePath</key> - <map> - <key>Comment</key> - <string>Obsolete: no longer used</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>update</string> - </map> <key>UpdaterWillingToTest</key> <map> <key>Comment</key> @@ -15033,17 +13004,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>UseEnvironmentFromRegion</key> - <map> - <key>Comment</key> - <string>Choose whether to use the region's environment settings, or override them with the local settings.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>EnvironmentPersistAcrossLogin</key> <map> <key>Comment</key> @@ -15055,62 +13015,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>UseDayCycle</key> - <map> - <key>Comment</key> - <string>Whether to use use a day cycle or a fixed sky.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>WaterPresetName</key> - <map> - <key>Comment</key> - <string>Water preset to use. May be superseded by region settings.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>Default</string> - </map> - <key>SkyPresetName</key> - <map> - <key>Comment</key> - <string>Sky preset to use. May be superseded by region settings or by a day cycle (see DayCycleName).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>Default</string> - </map> - <key>DayCycleName</key> - <map> - <key>Comment</key> - <string>Day cycle to use. May be superseded by region settings.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>Default</string> - </map> - <key>UseExternalBrowser</key> - <!-- deprecated (see MAINT-4127) --> - <map> - <key>Comment</key> - <string>(Deprecated) Use default browser when opening web pages instead of in-world browser.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <boolean>1</boolean> - </map> <key>PreferredBrowserBehavior</key> <map> <key>Comment</key> @@ -15166,6 +13070,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderDelayVBUpdate</key> + <map> + <key>Comment</key> + <string>Delay vertex buffer updates until just before rendering</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>SocialPhotoResolution</key> <map> <key>Comment</key> @@ -15971,17 +13886,6 @@ <key>Value</key> <real>-1.0</real> </map> - <key>ForcePeriodicRenderingTime</key> - <map> - <key>Comment</key> - <string>Periodically enable all rendering masks for a single frame.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>-1.0</real> - </map> <key>ZoomDirect</key> <map> <key>Comment</key> @@ -16147,17 +14051,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>AssetStorageLogFrequency</key> - <map> - <key>Comment</key> - <string>Seconds between display of AssetStorage info in log (0 for never)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>60.0</real> - </map> <key>LogWearableAssetSave</key> <map> <key>Comment</key> @@ -16405,28 +14298,6 @@ <key>Value</key> <real>120.0</real> </map> - <key>DestinationGuideHintTimeout</key> - <map> - <key>Comment</key> - <string>Number of seconds to wait before telling resident about destination guide.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1200.0</real> - </map> - <key>SidePanelHintTimeout</key> - <map> - <key>Comment</key> - <string>Number of seconds to wait before telling resident about side panel.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>300.0</real> - </map> <key>GroupMembersSortOrder</key> <map> <key>Comment</key> @@ -16471,17 +14342,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>AvatarInspectorTooltipDelay</key> - <map> - <key>Comment</key> - <string>Seconds before displaying avatar inspector tooltip</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.35</real> - </map> <key>ObjectInspectorTooltipDelay</key> <map> <key>Comment</key> @@ -16515,17 +14375,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>EnableGroupInfo</key> - <map> - <key>Comment</key> - <string>Enable viewing and editing of group info from web link</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>EnablePlaceProfile</key> <map> <key>Comment</key> @@ -16537,28 +14386,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>EnablePicks</key> - <map> - <key>Comment</key> - <string>Enable editing of picks from web link</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>EnableWorldMap</key> - <map> - <key>Comment</key> - <string>Enable opening world map from web link</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>EnableAvatarPay</key> <map> <key>Comment</key> @@ -16570,17 +14397,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>EnableVoiceCall</key> - <map> - <key>Comment</key> - <string>Enable voice calls from web link</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>EnableAvatarShare</key> <map> <key>Comment</key> @@ -16603,17 +14419,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>EnableSearch</key> - <map> - <key>Comment</key> - <string>Enable opening search from web link</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>EnableAppearance</key> <map> <key>Comment</key> @@ -16701,17 +14506,6 @@ <string>Boolean</string> <key>Value</key> <integer>0</integer> - </map> - <key>AllowBottomTrayButtonReordering</key> - <map> - <key>Comment</key> - <string>Allow user to move and hide bottom tray buttons</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> </map> <key>AllowSelectAvatar</key> <map> @@ -17604,17 +15398,6 @@ <key>Value</key> <integer>7000</integer> </map> - <key>DisablePrecacheDelayAfterTeleporting</key> - <map> - <key>Comment</key> - <string>Disables the artificial delay in the viewer that precaches some incoming assets</string> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>VersionChannelName</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/alchemy/DLSF.glsl b/indra/newview/app_settings/shaders/class1/alchemy/DLSF.glsl index a1cb61aa43752d619eaa6684a502ff1d97bdad8f..f92e8b92ea396ba054c0c2a2096c035fd01bf76a 100644 --- a/indra/newview/app_settings/shaders/class1/alchemy/DLSF.glsl +++ b/indra/newview/app_settings/shaders/class1/alchemy/DLSF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file DLSF.glsl * * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Alchemy Viewer Source Code * Copyright (C) 2021, Rye Mutt<rye@alchemyviewer.org> - * + * * 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$ */ @@ -55,7 +55,7 @@ void main() { /** Image sharpening filter from GeForce Experience. Provided by NVIDIA Corporation. - + Copyright 2019 Suketu J. Shah. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -123,7 +123,7 @@ void main() // float kernelDenoise = 1.0 / (kDenoiseMin + (kDenoiseMax - kDenoiseMin) * min(max(denoise, 0.0), 1.0)); // where kernelDenoise is the value to be passed in to this shader (the amount of noise suppression is inversely proportional to this value), // denoise is the value chosen by the user, in the range (0, 1) - float kernelDenoise = 1.0 / (kDenoiseMin + (kDenoiseMax - kDenoiseMin) * sharpen_params.y); + float kernelDenoise = 1.0 / (kDenoiseMin + (kDenoiseMax - kDenoiseMin) * sharpen_params.y); float nw = Square((lmax - lmin) * kernelDenoise); // pick conservative boost @@ -153,7 +153,7 @@ void main() // normalize (divide the accumulator by the sum of convolution weights) accum /= 1.0 + 6.0 * k; - // accumulator is in linear light space + // accumulator is in linear light space float delta = accum - lx; x.x += delta; x.y += delta; diff --git a/indra/newview/app_settings/shaders/class1/alchemy/colorCorrectF.glsl b/indra/newview/app_settings/shaders/class1/alchemy/colorCorrectF.glsl index 3ac24596497ef19d87e0ee95303c4a0f7334a96c..14f988f5ccc4062b90ca2090ae50fae0092442a1 100644 --- a/indra/newview/app_settings/shaders/class1/alchemy/colorCorrectF.glsl +++ b/indra/newview/app_settings/shaders/class1/alchemy/colorCorrectF.glsl @@ -39,38 +39,38 @@ vec3 linear_to_srgb(vec3 cl); //================================= // borrowed noise from: -// <https://www.shadertoy.com/view/4dS3Wd> -// By Morgan McGuire @morgan3d, http://graphicscodex.com +// <https://www.shadertoy.com/view/4dS3Wd> +// By Morgan McGuire @morgan3d, http://graphicscodex.com // float hash(float n) { return fract(sin(n) * 1e4); } float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } float noise(float x) { - float i = floor(x); - float f = fract(x); - float u = f * f * (3.0 - 2.0 * f); - return mix(hash(i), hash(i + 1.0), u); + float i = floor(x); + float f = fract(x); + float u = f * f * (3.0 - 2.0 * f); + return mix(hash(i), hash(i + 1.0), u); } float noise(vec2 x) { - vec2 i = floor(x); - vec2 f = fract(x); - - // Four corners in 2D of a tile - float a = hash(i); - float b = hash(i + vec2(1.0, 0.0)); - float c = hash(i + vec2(0.0, 1.0)); - float d = hash(i + vec2(1.0, 1.0)); - - // Simple 2D lerp using smoothstep envelope between the values. - // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), - // mix(c, d, smoothstep(0.0, 1.0, f.x)), - // smoothstep(0.0, 1.0, f.y))); - - // Same code, with the clamps in smoothstep and common subexpressions - // optimized away. - vec2 u = f * f * (3.0 - 2.0 * f); - return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; + vec2 i = floor(x); + vec2 f = fract(x); + + // Four corners in 2D of a tile + float a = hash(i); + float b = hash(i + vec2(1.0, 0.0)); + float c = hash(i + vec2(0.0, 1.0)); + float d = hash(i + vec2(1.0, 1.0)); + + // Simple 2D lerp using smoothstep envelope between the values. + // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), + // mix(c, d, smoothstep(0.0, 1.0, f.x)), + // smoothstep(0.0, 1.0, f.y))); + + // Same code, with the clamps in smoothstep and common subexpressions + // optimized away. + vec2 u = f * f * (3.0 - 2.0 * f); + return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; } //============================= diff --git a/indra/newview/app_settings/shaders/class1/alchemy/postNoTCV.glsl b/indra/newview/app_settings/shaders/class1/alchemy/postNoTCV.glsl index fbb8eceba41bcb79f72e82ebc3bb1e4bbe1b36e7..a463dff60945b006580771410e6b982e6115bf6e 100644 --- a/indra/newview/app_settings/shaders/class1/alchemy/postNoTCV.glsl +++ b/indra/newview/app_settings/shaders/class1/alchemy/postNoTCV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file postNoTCV.glsl * * $LicenseInfo:firstyear=2021&license=viewerlgpl$ * Alchemy Viewer Source Code * Copyright (C) 2021, Rye Mutt<rye@alchemyviewer.org> - * + * * 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 - * + * * $/LicenseInfo$ */ @@ -27,8 +27,8 @@ out vec2 vary_fragcoord; void main() { - //transform vertex - vec4 pos = vec4(position.xyz, 1.0); - gl_Position = pos; - vary_fragcoord = (pos.xy*0.5+0.5); + //transform vertex + vec4 pos = vec4(position.xyz, 1.0); + gl_Position = pos; + vary_fragcoord = (pos.xy*0.5+0.5); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index be15eba702e009f1f55e044f8092442ec1fb9d3c..58075c42b45c687b745b71f3d852f7486f37f8aa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -1,24 +1,24 @@ -/** +/** * @file class1/deferred/deferredUtil.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -148,7 +148,7 @@ vec3 getNorm(vec2 screenpos) { vec2 f = texture(normalMap, screenpos.xy).xy; f = f * 2.0 - 1.0; - + vec3 n = vec3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y)); float t = max(-n.z, 0.0); n.x += n.x >= 0.0 ? -t : t; @@ -366,7 +366,7 @@ vec2 BRDF(float NoV, float roughness) } // Lagarde and de Rousiers 2014, "Moving Frostbite to PBR" -float computeSpecularAO(float NoV, float ao, float roughness) +float computeSpecularAO(float NoV, float ao, float roughness) { return clamp(pow(NoV + ao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ao, 0.0, 1.0); } @@ -381,15 +381,15 @@ vec3 pbrIbl(vec3 diffuseColor, float perceptualRough) { // retrieve a scale and bias to F0. See [1], Figure 3 - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough); - vec3 diffuseLight = irradiance; - vec3 specularLight = radiance; - - vec3 diffuse = diffuseLight * diffuseColor; - vec3 specular = specularLight * (specularColor * brdf.x + brdf.y); + vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough); + vec3 diffuseLight = irradiance; + vec3 specularLight = radiance; - specular *= computeSpecularAO(nv, ao, perceptualRough * perceptualRough); - return (diffuse * ao) + specular; + vec3 diffuse = diffuseLight * diffuseColor; + vec3 specular = specularLight * (specularColor * brdf.x + brdf.y); + + specular *= computeSpecularAO(nv, ao, perceptualRough * perceptualRough); + return (diffuse * ao) + specular; } @@ -398,18 +398,18 @@ vec3 pbrIbl(vec3 diffuseColor, // of the shading terms, outlined in the Readme.MD Appendix. struct PBRInfo { - float NdotL; // cos angle between normal and light direction - float NdotV; // cos angle between normal and view direction - float NdotH; // cos angle between normal and half vector - float LdotH; // cos angle between light direction and half vector - float VdotH; // cos angle between view direction and half vector - float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) - float metalness; // metallic value at the surface - vec3 reflectance0; // full reflectance color (normal incidence angle) - vec3 reflectance90; // reflectance color at grazing angle - float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) - vec3 diffuseColor; // color contribution from diffuse lighting - vec3 specularColor; // color contribution from specular lighting + float NdotL; // cos angle between normal and light direction + float NdotV; // cos angle between normal and view direction + float NdotH; // cos angle between normal and half vector + float LdotH; // cos angle between light direction and half vector + float VdotH; // cos angle between view direction and half vector + float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) + float metalness; // metallic value at the surface + vec3 reflectance0; // full reflectance color (normal incidence angle) + vec3 reflectance90; // reflectance color at grazing angle + float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) + vec3 diffuseColor; // color contribution from diffuse lighting + vec3 specularColor; // color contribution from specular lighting }; // Basic Lambertian diffuse @@ -417,14 +417,14 @@ struct PBRInfo // See also [1], Equation 1 vec3 diffuse(PBRInfo pbrInputs) { - return pbrInputs.diffuseColor / M_PI; + return pbrInputs.diffuseColor / M_PI; } // The following equation models the Fresnel reflectance term of the spec equation (aka F()) // Implementation of fresnel from [4], Equation 15 vec3 specularReflection(PBRInfo pbrInputs) { - return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); + return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); } // This calculates the specular geometric attenuation (aka G()), @@ -433,13 +433,13 @@ vec3 specularReflection(PBRInfo pbrInputs) // alphaRoughness as input as originally proposed in [2]. float geometricOcclusion(PBRInfo pbrInputs) { - float NdotL = pbrInputs.NdotL; - float NdotV = pbrInputs.NdotV; - float r = pbrInputs.alphaRoughness; + float NdotL = pbrInputs.NdotL; + float NdotV = pbrInputs.NdotV; + float r = pbrInputs.alphaRoughness; - float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); - float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); - return attenuationL * attenuationV; + float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); + float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); + return attenuationL * attenuationV; } // The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D()) @@ -447,13 +447,13 @@ float geometricOcclusion(PBRInfo pbrInputs) // Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3. float microfacetDistribution(PBRInfo pbrInputs) { - float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; - float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; - return roughnessSq / (M_PI * f * f); + float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; + float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; + return roughnessSq / (M_PI * f * f); } -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, - float perceptualRoughness, +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, + float perceptualRoughness, float metallic, vec3 n, // normal vec3 v, // surface point to camera @@ -461,53 +461,53 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, { // make sure specular highlights from punctual lights don't fall off of polished surfaces perceptualRoughness = max(perceptualRoughness, MIN_PBR_ROUGHNESS); - - float alphaRoughness = perceptualRoughness * perceptualRoughness; - - // Compute reflectance. - float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); - - // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. - // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. - float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); - vec3 specularEnvironmentR0 = specularColor.rgb; - vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; - - vec3 h = normalize(l+v); // Half vector between both l and v - vec3 reflection = -normalize(reflect(v, n)); - reflection.y *= -1.0f; - - float NdotL = clamp(dot(n, l), 0.001, 1.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float LdotH = clamp(dot(l, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); - - PBRInfo pbrInputs = PBRInfo( - NdotL, - NdotV, - NdotH, - LdotH, - VdotH, - perceptualRoughness, - metallic, - specularEnvironmentR0, - specularEnvironmentR90, - alphaRoughness, - diffuseColor, - specularColor - ); - - // Calculate the shading terms for the microfacet specular shading model - vec3 F = specularReflection(pbrInputs); - float G = geometricOcclusion(pbrInputs); - float D = microfacetDistribution(pbrInputs); - - // Calculation of analytical lighting contribution - vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); - vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); - // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) - vec3 color = NdotL * (diffuseContrib + specContrib); + + float alphaRoughness = perceptualRoughness * perceptualRoughness; + + // Compute reflectance. + float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); + + // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. + // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. + float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); + vec3 specularEnvironmentR0 = specularColor.rgb; + vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; + + vec3 h = normalize(l+v); // Half vector between both l and v + vec3 reflection = -normalize(reflect(v, n)); + reflection.y *= -1.0f; + + float NdotL = clamp(dot(n, l), 0.001, 1.0); + float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); + float NdotH = clamp(dot(n, h), 0.0, 1.0); + float LdotH = clamp(dot(l, h), 0.0, 1.0); + float VdotH = clamp(dot(v, h), 0.0, 1.0); + + PBRInfo pbrInputs = PBRInfo( + NdotL, + NdotV, + NdotH, + LdotH, + VdotH, + perceptualRoughness, + metallic, + specularEnvironmentR0, + specularEnvironmentR90, + alphaRoughness, + diffuseColor, + specularColor + ); + + // Calculate the shading terms for the microfacet specular shading model + vec3 F = specularReflection(pbrInputs); + float G = geometricOcclusion(pbrInputs); + float D = microfacetDistribution(pbrInputs); + + // Calculation of analytical lighting contribution + vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); + vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); + // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) + vec3 color = NdotL * (diffuseContrib + specContrib); return clamp(color, vec3(0), vec3(10)); } @@ -526,9 +526,9 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 color = vec3(0); float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0); - + color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness); - + color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir)) * sunlit * 3.0 * scol; //magic number to balance with legacy materials color += colorEmissive; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index 3494f0dae95d2675db70da9097e00df4793a91d9..1e20c55a647914c1cd0004427815113932ba63ed 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file fxaaF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -67,11 +67,11 @@ Example, Or, #define FXAA_360 1 - + Or, #define FXAA_PS3 1 - + Etc. (2.) @@ -82,7 +82,7 @@ Then include this file, (3.) Then call the FXAA pixel shader from within your desired shader. Look at the FXAA Quality FxaaPixelShader() for docs on inputs. -As for FXAA 3.11 all inputs for all shaders are the same +As for FXAA 3.11 all inputs for all shaders are the same to enable easy porting between platforms. return FxaaPixelShader(...); @@ -113,7 +113,7 @@ Look at the FXAA Quality FxaaPixelShader() for docs on inputs. (6.) Have FXAA vertex shader run as a full screen triangle, -and output "pos" and "fxaaConsolePosPos" +and output "pos" and "fxaaConsolePosPos" such that inputs in the pixel shader provide, // {xy} = center of pixel @@ -130,7 +130,7 @@ Insure the texture sampler(s) used by FXAA are set to bilinear filtering. ------------------------------------------------------------------------------ INTEGRATION - RGBL AND COLORSPACE ------------------------------------------------------------------------------ -FXAA3 requires RGBL as input unless the following is set, +FXAA3 requires RGBL as input unless the following is set, #define FXAA_GREEN_AS_LUMA 1 @@ -183,7 +183,7 @@ Getting luma correct is required for the algorithm to work correctly. ------------------------------------------------------------------------------ Applying FXAA to a framebuffer with linear RGB color will look worse. This is very counter intuitive, but happends to be true in this case. -The reason is because dithering artifacts will be more visiable +The reason is because dithering artifacts will be more visiable in a linear colorspace. @@ -282,7 +282,7 @@ A. Or use FXAA_GREEN_AS_LUMA. // Might want to lower the settings for both, // fxaaConsoleEdgeThresholdMin // fxaaQualityEdgeThresholdMin - // In order to insure AA does not get turned off on colors + // In order to insure AA does not get turned off on colors // which contain a minor amount of green. // // 1 = On. @@ -350,16 +350,16 @@ A. Or use FXAA_GREEN_AS_LUMA. #define FXAA_GATHER4_ALPHA 1 #endif #ifndef FXAA_GATHER4_ALPHA - #ifdef GL_ARB_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifndef FXAA_GATHER4_ALPHA - #define FXAA_GATHER4_ALPHA 0 - #endif - #endif + #ifdef GL_ARB_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifdef GL_NV_gpu_shader5 + #define FXAA_GATHER4_ALPHA 1 + #endif + #ifndef FXAA_GATHER4_ALPHA + #define FXAA_GATHER4_ALPHA 0 + #endif + #endif #endif /*============================================================================ @@ -422,14 +422,14 @@ NOTE the other tuning knobs are now in the shader function inputs! // // Choose the quality preset. // This needs to be compiled into the shader as it effects code. - // Best option to include multiple presets is to + // Best option to include multiple presets is to // in each shader define the preset, then include this file. - // + // // OPTIONS // ----------------------------------------------------------------------- // 10 to 15 - default medium dither (10=fastest, 15=highest quality) // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) - // 39 - no dither, very expensive + // 39 - no dither, very expensive // // NOTES // ----------------------------------------------------------------------- @@ -438,7 +438,7 @@ NOTE the other tuning knobs are now in the shader function inputs! // 23 = closest to FXAA 3.9 visually and performance wise // _ = the lowest digit is directly related to performance // _ = the highest digit is directly related to style - // + // #define FXAA_QUALITY__PRESET 12 #endif @@ -812,28 +812,28 @@ FxaaFloat4 FxaaPixelShader( // Where N ranges between, // N = 0.50 (default) // N = 0.33 (sharper) - // {x___} = -N/screenWidthInPixels + // {x___} = -N/screenWidthInPixels // {_y__} = -N/screenHeightInPixels - // {__z_} = N/screenWidthInPixels - // {___w} = N/screenHeightInPixels + // {__z_} = N/screenWidthInPixels + // {___w} = N/screenHeightInPixels FxaaFloat4 fxaaConsoleRcpFrameOpt, // // Only used on FXAA Console. // Not used on 360, but used on PS3 and PC. // This must be from a constant/uniform. - // {x___} = -2.0/screenWidthInPixels + // {x___} = -2.0/screenWidthInPixels // {_y__} = -2.0/screenHeightInPixels - // {__z_} = 2.0/screenWidthInPixels - // {___w} = 2.0/screenHeightInPixels + // {__z_} = 2.0/screenWidthInPixels + // {___w} = 2.0/screenHeightInPixels FxaaFloat4 fxaaConsoleRcpFrameOpt2, // // Only used on FXAA Console. // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. // This must be from a constant/uniform. - // {x___} = 8.0/screenWidthInPixels + // {x___} = 8.0/screenWidthInPixels // {_y__} = 8.0/screenHeightInPixels - // {__z_} = -4.0/screenWidthInPixels - // {___w} = -4.0/screenHeightInPixels + // {__z_} = -4.0/screenWidthInPixels + // {___w} = -4.0/screenHeightInPixels FxaaFloat4 fxaaConsole360RcpFrameOpt2, // // Only used on FXAA Quality. @@ -855,7 +855,7 @@ FxaaFloat4 FxaaPixelShader( // 0.333 - too little (faster) // 0.250 - low quality // 0.166 - default - // 0.125 - high quality + // 0.125 - high quality // 0.063 - overkill (slower) FxaaFloat fxaaQualityEdgeThreshold, // @@ -873,7 +873,7 @@ FxaaFloat4 FxaaPixelShader( // Tune by looking at mostly non-green content, // then start at zero and increase until aliasing is a problem. FxaaFloat fxaaQualityEdgeThresholdMin, - // + // // Only used on FXAA Console. // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. // It is here now to allow easier tuning. @@ -908,7 +908,7 @@ FxaaFloat4 FxaaPixelShader( // Trims the algorithm from processing darks. // The console setting has a different mapping than the quality setting. // This only applies when FXAA_EARLY_EXIT is 1. - // This does not apply to PS3, + // This does not apply to PS3, // PS3 was simplified to avoid more shader instructions. // 0.06 - faster but more aliasing in darks // 0.05 - default @@ -920,7 +920,7 @@ FxaaFloat4 FxaaPixelShader( // Tune by looking at mostly non-green content, // then start at zero and increase until aliasing is a problem. FxaaFloat fxaaConsoleEdgeThresholdMin, - // + // // Extra constants for 360 FXAA Console only. // Use zeros or anything else for other platforms. // These must be in physical constant registers and NOT immedates. @@ -1297,11 +1297,11 @@ FxaaFloat4 FxaaPixelShader( /*============================================================================ FXAA3 CONSOLE - PC VERSION - + ------------------------------------------------------------------------------ Instead of using this on PC, I'd suggest just using FXAA Quality with #define FXAA_QUALITY__PRESET 10 -Or +Or #define FXAA_QUALITY__PRESET 20 Either are higher qualilty and almost as fast as this on modern PC GPUs. ============================================================================*/ @@ -1390,7 +1390,7 @@ FxaaFloat4 FxaaPixelShader( /*============================================================================ - FXAA3 CONSOLE - 360 PIXEL SHADER + FXAA3 CONSOLE - 360 PIXEL SHADER ------------------------------------------------------------------------------ This optimized version thanks to suggestions from Andy Luedke. @@ -1425,14 +1425,14 @@ float4 FxaaPixelShader( /*--------------------------------------------------------------------------*/ float4 lumaNwNeSwSe; #if (FXAA_GREEN_AS_LUMA == 0) - asm { + asm { tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false }; #else - asm { + asm { tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false @@ -1453,7 +1453,7 @@ float4 FxaaPixelShader( #else float lumaMinM = min(lumaMin, rgbyM.y); float lumaMaxM = max(lumaMax, rgbyM.y); - #endif + #endif if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; /*--------------------------------------------------------------------------*/ float2 dir; @@ -1602,7 +1602,7 @@ Pass | Unit | uOp | PC: Op | | | 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; - + Pass SCT TEX SCB 1: 0% 100% 25% 2: 0% 100% 25% @@ -1688,7 +1688,7 @@ half4 FxaaPixelShader( #else dir.x += lumaSw.y; dir.z += lumaSw.y; - #endif + #endif /*--------------------------------------------------------------------------*/ // (3) half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); @@ -1751,7 +1751,7 @@ half4 FxaaPixelShader( #else half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); - #endif + #endif rgby2 = (rgby2 + rgby1) * 0.5; /*--------------------------------------------------------------------------*/ // (12) @@ -1907,7 +1907,7 @@ Pass | Unit | uOp | PC: Op | | | 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; - + Pass SCT TEX SCB 1: 0% 100% 25% 2: 0% 100% 25% @@ -2107,28 +2107,28 @@ uniform vec4 rcp_frame_opt2; in vec2 vary_fragcoord; in vec2 vary_tc; -void main() +void main() { - vec4 diff = FxaaPixelShader(vary_tc, //pos - vec4(vary_fragcoord.xy, 0, 0), //fxaaConsolePosPos - diffuseMap, //tex - diffuseMap, - diffuseMap, - rcp_screen_res, //fxaaQualityRcpFrame - vec4(0,0,0,0), //fxaaConsoleRcpFrameOpt - rcp_frame_opt, //fxaaConsoleRcpFrameOpt2 - rcp_frame_opt2, //fxaaConsole360RcpFrameOpt2 - 0.75, //fxaaQualitySubpix - 0.07, //fxaaQualityEdgeThreshold - 0.03, //fxaaQualityEdgeThresholdMin - 8.0, //fxaaConsoleEdgeSharpness - 0.125, //fxaaConsoleEdgeThreshold - 0.05, //fxaaConsoleEdgeThresholdMin - vec4(0,0,0,0)); //fxaaConsole360ConstDir + vec4 diff = FxaaPixelShader(vary_tc, //pos + vec4(vary_fragcoord.xy, 0, 0), //fxaaConsolePosPos + diffuseMap, //tex + diffuseMap, + diffuseMap, + rcp_screen_res, //fxaaQualityRcpFrame + vec4(0,0,0,0), //fxaaConsoleRcpFrameOpt + rcp_frame_opt, //fxaaConsoleRcpFrameOpt2 + rcp_frame_opt2, //fxaaConsole360RcpFrameOpt2 + 0.75, //fxaaQualitySubpix + 0.07, //fxaaQualityEdgeThreshold + 0.03, //fxaaQualityEdgeThresholdMin + 8.0, //fxaaConsoleEdgeSharpness + 0.125, //fxaaConsoleEdgeThreshold + 0.05, //fxaaConsoleEdgeThresholdMin + vec4(0,0,0,0)); //fxaaConsole360ConstDir frag_color = diff; - + gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl index efc38b3020b62419085580d10426cdd8a65dcfce..7d69b2eba3dec5c30f02f67addbbaa38b96af450 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/genbrdflutF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file class1/deferred/genbrdflut.glsl * * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2022, 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$ */ @@ -60,42 +60,42 @@ const float PI = 3.1415926536; // Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ float random(vec2 co) { - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,vec2(a,b)); - float sn= mod(dt,3.14); - return fract(sin(sn) * c); + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,vec2(a,b)); + float sn= mod(dt,3.14); + return fract(sin(sn) * c); } -vec2 hammersley2d(uint i, uint N) +vec2 hammersley2d(uint i, uint N) { - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return vec2(float(i) /float(N), rdi); + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return vec2(float(i) /float(N), rdi); } // Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -vec3 importanceSample_GGX(vec2 Xi, float a2, vec3 normal) +vec3 importanceSample_GGX(vec2 Xi, float a2, vec3 normal) { - // Maps a 2D point to a hemisphere with spread based on roughness - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a2 - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangentX = normalize(cross(up, normal)); - vec3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); + // Maps a 2D point to a hemisphere with spread based on roughness + float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a2 - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangentX = normalize(cross(up, normal)); + vec3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); } // Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs" @@ -108,32 +108,32 @@ float V_SmithGGXCorrelated(float NoV, float NoL, float a2) vec2 BRDF(float NoV, float roughness) { - // Normal always points along z-axis for the 2D lookup - const vec3 N = vec3(0.0, 0.0, 1.0); - vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV); - float a2 = pow(roughness, 4.0); - - vec2 LUT = vec2(0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - vec2 Xi = hammersley2d(i, NUM_SAMPLES); - vec3 H = importanceSample_GGX(Xi, a2, N); - vec3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = V_SmithGGXCorrelated(NoV, dotNL, a2); - float G_Vis = G * dotVH / dotNH; - float Fc = pow(1.0 - dotVH, 5.0); - LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); + // Normal always points along z-axis for the 2D lookup + const vec3 N = vec3(0.0, 0.0, 1.0); + vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV); + float a2 = pow(roughness, 4.0); + + vec2 LUT = vec2(0.0); + for(uint i = 0u; i < NUM_SAMPLES; i++) { + vec2 Xi = hammersley2d(i, NUM_SAMPLES); + vec3 H = importanceSample_GGX(Xi, a2, N); + vec3 L = 2.0 * dot(V, H) * H - V; + + float dotNL = max(dot(N, L), 0.0); + float dotVH = max(dot(V, H), 0.0); + float dotNH = max(dot(H, N), 0.0); + + if (dotNL > 0.0) { + float G = V_SmithGGXCorrelated(NoV, dotNL, a2); + float G_Vis = G * dotVH / dotNH; + float Fc = pow(1.0 - dotVH, 5.0); + LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis); + } + } + return LUT / float(NUM_SAMPLES); } -void main() +void main() { - outColor = vec4(BRDF(vary_uv.s, 1.0-vary_uv.t), 0.0, 1.0); + outColor = vec4(BRDF(vary_uv.s, 1.0-vary_uv.t), 0.0, 1.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 667bdf6f6b1b63f4b292e8e873e12e16e4414a18..bfc90a028cf0eb2f0c1559bd4e807ad7ad3d8844 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file postDeferredF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -38,91 +38,91 @@ in vec2 vary_fragcoord; void dofSample(inout vec4 diff, inout float w, float min_sc, vec2 tc) { - vec4 s = texture(diffuseRect, tc); - - float sc = abs(s.a*2.0-1.0)*max_cof; - - if (sc > min_sc) //sampled pixel is more "out of focus" than current sample radius - { - float wg = 0.25; - - // de-weight dull areas to make highlights 'pop' - wg += s.r+s.g+s.b; - - diff += wg*s; - - w += wg; - } + vec4 s = texture(diffuseRect, tc); + + float sc = abs(s.a*2.0-1.0)*max_cof; + + if (sc > min_sc) //sampled pixel is more "out of focus" than current sample radius + { + float wg = 0.25; + + // de-weight dull areas to make highlights 'pop' + wg += s.r+s.g+s.b; + + diff += wg*s; + + w += wg; + } } void dofSampleNear(inout vec4 diff, inout float w, float min_sc, vec2 tc) { - vec4 s = texture(diffuseRect, tc); + vec4 s = texture(diffuseRect, tc); - float wg = 0.25; + float wg = 0.25; - // de-weight dull areas to make highlights 'pop' - wg += s.r+s.g+s.b; + // de-weight dull areas to make highlights 'pop' + wg += s.r+s.g+s.b; - diff += wg*s; - - w += wg; + diff += wg*s; + + w += wg; } -void main() +void main() { - vec2 tc = vary_fragcoord.xy; - - vec4 diff = texture(diffuseRect, vary_fragcoord.xy); - - { - float w = 1.0; - - float sc = (diff.a*2.0-1.0)*max_cof; - - float PI = 3.14159265358979323846264; - - // sample quite uniformly spaced points within a circle, for a circular 'bokeh' + vec2 tc = vary_fragcoord.xy; + + vec4 diff = texture(diffuseRect, vary_fragcoord.xy); + + { + float w = 1.0; + + float sc = (diff.a*2.0-1.0)*max_cof; + + float PI = 3.14159265358979323846264; + + // sample quite uniformly spaced points within a circle, for a circular 'bokeh' #if FRONT_BLUR - if (sc > 0.5) - { - while (sc > 0.5) - { - int its = int(max(1.0,(sc*3.7))); - for (int i=0; i<its; ++i) - { - float ang = sc+i*2*PI/its; // sc is added for rotary perturbance - float samp_x = sc*sin(ang); - float samp_y = sc*cos(ang); - // you could test sample coords against an interesting non-circular aperture shape here, if desired. - dofSampleNear(diff, w, sc, vary_fragcoord.xy + (vec2(samp_x,samp_y) / screen_res)); - } - sc -= 1.0; - } - } - else if (sc < -0.5) + if (sc > 0.5) + { + while (sc > 0.5) + { + int its = int(max(1.0,(sc*3.7))); + for (int i=0; i<its; ++i) + { + float ang = sc+i*2*PI/its; // sc is added for rotary perturbance + float samp_x = sc*sin(ang); + float samp_y = sc*cos(ang); + // you could test sample coords against an interesting non-circular aperture shape here, if desired. + dofSampleNear(diff, w, sc, vary_fragcoord.xy + (vec2(samp_x,samp_y) / screen_res)); + } + sc -= 1.0; + } + } + else if (sc < -0.5) #else - if (sc < -0.5) + if (sc < -0.5) #endif - { - sc = abs(sc); - while (sc > 0.5) - { - int its = int(max(1.0,(sc*3.7))); - for (int i=0; i<its; ++i) - { - float ang = sc+i*2*PI/its; // sc is added for rotary perturbance - float samp_x = sc*sin(ang); - float samp_y = sc*cos(ang); - // you could test sample coords against an interesting non-circular aperture shape here, if desired. - dofSample(diff, w, sc, vary_fragcoord.xy + (vec2(samp_x,samp_y) / screen_res)); - } - sc -= 1.0; - } - } - - diff /= w; - } - - frag_color = diff; + { + sc = abs(sc); + while (sc > 0.5) + { + int its = int(max(1.0,(sc*3.7))); + for (int i=0; i<its; ++i) + { + float ang = sc+i*2*PI/its; // sc is added for rotary perturbance + float samp_x = sc*sin(ang); + float samp_y = sc*cos(ang); + // you could test sample coords against an interesting non-circular aperture shape here, if desired. + dofSample(diff, w, sc, vary_fragcoord.xy + (vec2(samp_x,samp_y) / screen_res)); + } + sc -= 1.0; + } + } + + diff /= w; + } + + frag_color = diff; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index cf2aeda6ad097dfbb62cfa61a1610ec51679373c..d56e4ed370f05d8db430b565e5c682ea2ed125a6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -1,28 +1,28 @@ -/** +/** * @file postDeferredGammaCorrect.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ - + /*[EXTRA_CODE_HERE]*/ out vec4 frag_color; @@ -79,7 +79,7 @@ vec3 RRTAndODTFit(vec3 color) } -// tone mapping +// tone mapping vec3 toneMapACES_Hill(vec3 color) { color = ACESInputMat * color; @@ -102,7 +102,7 @@ vec3 toneMap(vec3 color) { #ifndef NO_POST float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; - + color *= exposure * exp_scale; // mix ACES and Linear here as a compromise to avoid over-darkening legacy content @@ -116,38 +116,38 @@ vec3 toneMap(vec3 color) //================================= // borrowed noise from: -// <https://www.shadertoy.com/view/4dS3Wd> -// By Morgan McGuire @morgan3d, http://graphicscodex.com +// <https://www.shadertoy.com/view/4dS3Wd> +// By Morgan McGuire @morgan3d, http://graphicscodex.com // float hash(float n) { return fract(sin(n) * 1e4); } float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } float noise(float x) { - float i = floor(x); - float f = fract(x); - float u = f * f * (3.0 - 2.0 * f); - return mix(hash(i), hash(i + 1.0), u); + float i = floor(x); + float f = fract(x); + float u = f * f * (3.0 - 2.0 * f); + return mix(hash(i), hash(i + 1.0), u); } float noise(vec2 x) { - vec2 i = floor(x); - vec2 f = fract(x); - - // Four corners in 2D of a tile - float a = hash(i); - float b = hash(i + vec2(1.0, 0.0)); - float c = hash(i + vec2(0.0, 1.0)); - float d = hash(i + vec2(1.0, 1.0)); - - // Simple 2D lerp using smoothstep envelope between the values. - // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), - // mix(c, d, smoothstep(0.0, 1.0, f.x)), - // smoothstep(0.0, 1.0, f.y))); - - // Same code, with the clamps in smoothstep and common subexpressions - // optimized away. - vec2 u = f * f * (3.0 - 2.0 * f); - return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; + vec2 i = floor(x); + vec2 f = fract(x); + + // Four corners in 2D of a tile + float a = hash(i); + float b = hash(i + vec2(1.0, 0.0)); + float c = hash(i + vec2(0.0, 1.0)); + float d = hash(i + vec2(1.0, 1.0)); + + // Simple 2D lerp using smoothstep envelope between the values. + // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), + // mix(c, d, smoothstep(0.0, 1.0, f.x)), + // smoothstep(0.0, 1.0, f.y))); + + // Same code, with the clamps in smoothstep and common subexpressions + // optimized away. + vec2 u = f * f * (3.0 - 2.0 * f); + return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; } //============================= @@ -170,7 +170,7 @@ vec3 legacyGamma(vec3 color) return c; } -void main() +void main() { //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB) vec4 diff = texture(diffuseRect, vary_fragcoord); diff --git a/indra/newview/app_settings/shaders/class1/deferred/rlvF.glsl b/indra/newview/app_settings/shaders/class1/deferred/rlvF.glsl index 048e1c863195710859e574251076b1e95eef6f4a..14b6d87a09484664bd5f0256901664970526e642 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/rlvF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/rlvF.glsl @@ -31,14 +31,14 @@ uniform bvec2 rlvEffectParam3; // Min/max dist extend uniform vec4 rlvEffectParam4; // Sphere params (=color when using blend) uniform vec2 rlvEffectParam5; // Blur direction (not used for blend) -#define SPHERE_ORIGIN rlvEffectParam1.xyz -#define SPHERE_DISTMIN rlvEffectParam2.y -#define SPHERE_DISTMAX rlvEffectParam2.w -#define SPHERE_DISTEXTEND rlvEffectParam3 -#define SPHERE_VALUEMIN rlvEffectParam2.x -#define SPHERE_VALUEMAX rlvEffectParam2.z -#define SPHERE_PARAMS rlvEffectParam4 -#define BLUR_DIRECTION rlvEffectParam5.xy +#define SPHERE_ORIGIN rlvEffectParam1.xyz +#define SPHERE_DISTMIN rlvEffectParam2.y +#define SPHERE_DISTMAX rlvEffectParam2.w +#define SPHERE_DISTEXTEND rlvEffectParam3 +#define SPHERE_VALUEMIN rlvEffectParam2.x +#define SPHERE_VALUEMAX rlvEffectParam2.z +#define SPHERE_PARAMS rlvEffectParam4 +#define BLUR_DIRECTION rlvEffectParam5.xy vec4 getPositionWithDepth(vec2 pos_screen, float depth); float getDepth(vec2 pos_screen); @@ -86,10 +86,10 @@ vec3 blurVariable(sampler2D source, vec2 tc, float kernelSize, vec2 direction, f // Go through the remaining 8 vertical samples (4 on each side of the center) for (float i = 1.0; i <= numBlurPixelsPerSide; i++) { - avgValue += texture(source, tc - i * direction / screen_res) * incrementalGaussian.x; - avgValue += texture(source, tc + i * direction / screen_res) * incrementalGaussian.x; - coefficientSum += 2.0 * incrementalGaussian.x; - incrementalGaussian.xy *= incrementalGaussian.yz; + avgValue += texture(source, tc - i * direction / screen_res) * incrementalGaussian.x; + avgValue += texture(source, tc + i * direction / screen_res) * incrementalGaussian.x; + coefficientSum += 2.0 * incrementalGaussian.x; + incrementalGaussian.xy *= incrementalGaussian.yz; } return (avgValue / coefficientSum).rgb; @@ -97,57 +97,57 @@ vec3 blurVariable(sampler2D source, vec2 tc, float kernelSize, vec2 direction, f vec3 chromaticAberration(sampler2D source, vec2 tc, vec2 redDrift, vec2 blueDrift, float strength) { - vec3 sourceColor = texture(source, tc).rgb; + vec3 sourceColor = texture(source, tc).rgb; - // Sample the color components - vec3 driftColor; - driftColor.r = texture(source, tc + redDrift / screen_res).r; - driftColor.g = sourceColor.g; - driftColor.b = texture(source, tc + blueDrift / screen_res).b; + // Sample the color components + vec3 driftColor; + driftColor.r = texture(source, tc + redDrift / screen_res).r; + driftColor.g = sourceColor.g; + driftColor.b = texture(source, tc + blueDrift / screen_res).b; - // Adjust the strength of the effect - return mix(sourceColor, driftColor, strength); + // Adjust the strength of the effect + return mix(sourceColor, driftColor, strength); } void main() { - vec2 fragTC = vary_fragcoord.xy; - vec3 fragPosLocal = getPositionWithDepth(fragTC, getDepth(fragTC)).xyz; - float distance = length(fragPosLocal.xyz - SPHERE_ORIGIN); - - // Linear non-branching interpolation of the strength of the sphere effect (replaces if/elseif/else for x < min, min <= x <= max and x > max) - float effectStrength = SPHERE_VALUEMIN + mix(0.0, SPHERE_VALUEMAX - SPHERE_VALUEMIN, (distance - SPHERE_DISTMIN) / (SPHERE_DISTMAX - SPHERE_DISTMIN)); - effectStrength = mix(effectStrength, mix(0.0, SPHERE_VALUEMIN, SPHERE_DISTEXTEND.x), distance < SPHERE_DISTMIN); - effectStrength = mix(effectStrength, mix(0.0, SPHERE_VALUEMAX, SPHERE_DISTEXTEND.y), distance > SPHERE_DISTMAX); - - vec3 fragColor ; - switch (rlvEffectMode) - { - case 0: // Blend - fragColor = texture(diffuseRect, fragTC).rgb; - fragColor = mix(fragColor, SPHERE_PARAMS.rgb, effectStrength); - break; - case 1: // Blur (fixed) - fragColor = blur13(diffuseRect, fragTC, BLUR_DIRECTION * vec2(effectStrength)); - break; - case 2: // Blur (variable) - fragColor = texture(diffuseRect, fragTC).rgb; - fragColor = mix(fragColor, blurVariable(diffuseRect, fragTC, SPHERE_PARAMS.x, BLUR_DIRECTION, effectStrength), bvec3(effectStrength > 0.0)); - break; - case 3: // ChromaticAberration - fragColor = chromaticAberration(diffuseRect, fragTC, SPHERE_PARAMS.xy, SPHERE_PARAMS.zw, effectStrength); - break; - case 4: // Pixelate - { - effectStrength = sign(effectStrength); - float pixelWidth = max(1.0, round(SPHERE_PARAMS.x * effectStrength)) / screen_res.x; - float pixelHeight = max(1.0, round(SPHERE_PARAMS.y * effectStrength)) / screen_res.y; - fragTC = vec2(pixelWidth * floor(fragTC.x / pixelWidth), pixelHeight * floor(fragTC.y / pixelHeight)); - fragColor = texture(diffuseRect, fragTC).rgb; - } - break; - } - - frag_color.rgb = fragColor; - frag_color.a = 0.0; + vec2 fragTC = vary_fragcoord.xy; + vec3 fragPosLocal = getPositionWithDepth(fragTC, getDepth(fragTC)).xyz; + float distance = length(fragPosLocal.xyz - SPHERE_ORIGIN); + + // Linear non-branching interpolation of the strength of the sphere effect (replaces if/elseif/else for x < min, min <= x <= max and x > max) + float effectStrength = SPHERE_VALUEMIN + mix(0.0, SPHERE_VALUEMAX - SPHERE_VALUEMIN, (distance - SPHERE_DISTMIN) / (SPHERE_DISTMAX - SPHERE_DISTMIN)); + effectStrength = mix(effectStrength, mix(0.0, SPHERE_VALUEMIN, SPHERE_DISTEXTEND.x), distance < SPHERE_DISTMIN); + effectStrength = mix(effectStrength, mix(0.0, SPHERE_VALUEMAX, SPHERE_DISTEXTEND.y), distance > SPHERE_DISTMAX); + + vec3 fragColor ; + switch (rlvEffectMode) + { + case 0: // Blend + fragColor = texture(diffuseRect, fragTC).rgb; + fragColor = mix(fragColor, SPHERE_PARAMS.rgb, effectStrength); + break; + case 1: // Blur (fixed) + fragColor = blur13(diffuseRect, fragTC, BLUR_DIRECTION * vec2(effectStrength)); + break; + case 2: // Blur (variable) + fragColor = texture(diffuseRect, fragTC).rgb; + fragColor = mix(fragColor, blurVariable(diffuseRect, fragTC, SPHERE_PARAMS.x, BLUR_DIRECTION, effectStrength), bvec3(effectStrength > 0.0)); + break; + case 3: // ChromaticAberration + fragColor = chromaticAberration(diffuseRect, fragTC, SPHERE_PARAMS.xy, SPHERE_PARAMS.zw, effectStrength); + break; + case 4: // Pixelate + { + effectStrength = sign(effectStrength); + float pixelWidth = max(1.0, round(SPHERE_PARAMS.x * effectStrength)) / screen_res.x; + float pixelHeight = max(1.0, round(SPHERE_PARAMS.y * effectStrength)) / screen_res.y; + fragTC = vec2(pixelWidth * floor(fragTC.x / pixelWidth), pixelHeight * floor(fragTC.y / pixelHeight)); + fragColor = texture(diffuseRect, fragTC).rgb; + } + break; + } + + frag_color.rgb = fragColor; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/rlvFLegacy.glsl b/indra/newview/app_settings/shaders/class1/deferred/rlvFLegacy.glsl index 60720e71820fddd50695aba5b39664c402ee71b5..c7437feeb251636fffe20a5caac8f4f477ae0b80 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/rlvFLegacy.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/rlvFLegacy.glsl @@ -31,14 +31,14 @@ uniform bvec2 rlvEffectParam3; // Min/max dist extend uniform vec4 rlvEffectParam4; // Sphere params (=color when using blend) uniform vec2 rlvEffectParam5; // Blur direction (not used for blend) -#define SPHERE_ORIGIN rlvEffectParam1.xyz -#define SPHERE_DISTMIN rlvEffectParam2.y -#define SPHERE_DISTMAX rlvEffectParam2.w -#define SPHERE_DISTEXTEND rlvEffectParam3 -#define SPHERE_VALUEMIN rlvEffectParam2.x -#define SPHERE_VALUEMAX rlvEffectParam2.z -#define SPHERE_PARAMS rlvEffectParam4 -#define BLUR_DIRECTION rlvEffectParam5.xy +#define SPHERE_ORIGIN rlvEffectParam1.xyz +#define SPHERE_DISTMIN rlvEffectParam2.y +#define SPHERE_DISTMAX rlvEffectParam2.w +#define SPHERE_DISTEXTEND rlvEffectParam3 +#define SPHERE_VALUEMIN rlvEffectParam2.x +#define SPHERE_VALUEMAX rlvEffectParam2.z +#define SPHERE_PARAMS rlvEffectParam4 +#define BLUR_DIRECTION rlvEffectParam5.xy vec4 getPositionWithDepth(vec2 pos_screen, float depth); float getDepth(vec2 pos_screen); @@ -86,10 +86,10 @@ vec3 blurVariable(sampler2D source, vec2 tc, float kernelSize, vec2 direction, f // Go through the remaining 8 vertical samples (4 on each side of the center) for (float i = 1.0; i <= numBlurPixelsPerSide; i++) { - avgValue += texture(source, tc - i * direction / screen_res) * incrementalGaussian.x; - avgValue += texture(source, tc + i * direction / screen_res) * incrementalGaussian.x; - coefficientSum += 2.0 * incrementalGaussian.x; - incrementalGaussian.xy *= incrementalGaussian.yz; + avgValue += texture(source, tc - i * direction / screen_res) * incrementalGaussian.x; + avgValue += texture(source, tc + i * direction / screen_res) * incrementalGaussian.x; + coefficientSum += 2.0 * incrementalGaussian.x; + incrementalGaussian.xy *= incrementalGaussian.yz; } return (avgValue / coefficientSum).rgb; @@ -97,66 +97,66 @@ vec3 blurVariable(sampler2D source, vec2 tc, float kernelSize, vec2 direction, f vec3 chromaticAberration(sampler2D source, vec2 tc, vec2 redDrift, vec2 blueDrift, float strength) { - vec3 sourceColor = texture(source, tc).rgb; + vec3 sourceColor = texture(source, tc).rgb; - // Sample the color components - vec3 driftColor; - driftColor.r = texture(source, tc + redDrift / screen_res).r; - driftColor.g = sourceColor.g; - driftColor.b = texture(source, tc + blueDrift / screen_res).b; + // Sample the color components + vec3 driftColor; + driftColor.r = texture(source, tc + redDrift / screen_res).r; + driftColor.g = sourceColor.g; + driftColor.b = texture(source, tc + blueDrift / screen_res).b; - // Adjust the strength of the effect - return mix(sourceColor, driftColor, strength); + // Adjust the strength of the effect + return mix(sourceColor, driftColor, strength); } void main() { - vec2 fragTC = vary_fragcoord.xy; - vec3 fragPosLocal = getPositionWithDepth(fragTC, getDepth(fragTC)).xyz; - float distance = length(fragPosLocal.xyz - SPHERE_ORIGIN); - - // Linear non-branching interpolation of the strength of the sphere effect (replaces if/elseif/else for x < min, min <= x <= max and x > max) - float effectStrength = SPHERE_VALUEMIN + mix(0.0, SPHERE_VALUEMAX - SPHERE_VALUEMIN, (distance - SPHERE_DISTMIN) / (SPHERE_DISTMAX - SPHERE_DISTMIN)); - if (distance < SPHERE_DISTMIN) - { - effectStrength = SPHERE_DISTEXTEND.x ? SPHERE_VALUEMIN : 0.0; - } - else if (distance > SPHERE_DISTMAX) - { - effectStrength = SPHERE_DISTEXTEND.y ? SPHERE_VALUEMAX : 0.0; - } - - vec3 fragColor; - if (rlvEffectMode == 0) // Blend - { - fragColor = texture(diffuseRect, fragTC).rgb; - fragColor = mix(fragColor, SPHERE_PARAMS.rgb, effectStrength); - } - else if (rlvEffectMode == 1) // Blur (fixed) - { - fragColor = blur13(diffuseRect, fragTC, BLUR_DIRECTION * vec2(effectStrength)); - } - else if (rlvEffectMode == 2) // Blur (variable) - { - fragColor = texture(diffuseRect, fragTC).rgb; - if (effectStrength > 0) - { - fragColor = blurVariable(diffuseRect, fragTC, SPHERE_PARAMS.x, BLUR_DIRECTION, effectStrength); - } - } - else if (rlvEffectMode == 3) // ChromaticAberration - { - fragColor = chromaticAberration(diffuseRect, fragTC, SPHERE_PARAMS.xy, SPHERE_PARAMS.zw, effectStrength); - } - else if (rlvEffectMode == 4) // Pixelate - { - effectStrength = sign(effectStrength); - float pixelWidth = max(1, round(SPHERE_PARAMS.x * effectStrength)) / screen_res.x; - float pixelHeight = max(1, round(SPHERE_PARAMS.y * effectStrength)) / screen_res.y; - fragTC = vec2(pixelWidth * floor(fragTC.x / pixelWidth), pixelHeight * floor(fragTC.y / pixelHeight)); - fragColor = texture(diffuseRect, fragTC).rgb; - } - - frag_color.rgb = fragColor; - frag_color.a = 0.0; + vec2 fragTC = vary_fragcoord.xy; + vec3 fragPosLocal = getPositionWithDepth(fragTC, getDepth(fragTC)).xyz; + float distance = length(fragPosLocal.xyz - SPHERE_ORIGIN); + + // Linear non-branching interpolation of the strength of the sphere effect (replaces if/elseif/else for x < min, min <= x <= max and x > max) + float effectStrength = SPHERE_VALUEMIN + mix(0.0, SPHERE_VALUEMAX - SPHERE_VALUEMIN, (distance - SPHERE_DISTMIN) / (SPHERE_DISTMAX - SPHERE_DISTMIN)); + if (distance < SPHERE_DISTMIN) + { + effectStrength = SPHERE_DISTEXTEND.x ? SPHERE_VALUEMIN : 0.0; + } + else if (distance > SPHERE_DISTMAX) + { + effectStrength = SPHERE_DISTEXTEND.y ? SPHERE_VALUEMAX : 0.0; + } + + vec3 fragColor; + if (rlvEffectMode == 0) // Blend + { + fragColor = texture(diffuseRect, fragTC).rgb; + fragColor = mix(fragColor, SPHERE_PARAMS.rgb, effectStrength); + } + else if (rlvEffectMode == 1) // Blur (fixed) + { + fragColor = blur13(diffuseRect, fragTC, BLUR_DIRECTION * vec2(effectStrength)); + } + else if (rlvEffectMode == 2) // Blur (variable) + { + fragColor = texture(diffuseRect, fragTC).rgb; + if (effectStrength > 0) + { + fragColor = blurVariable(diffuseRect, fragTC, SPHERE_PARAMS.x, BLUR_DIRECTION, effectStrength); + } + } + else if (rlvEffectMode == 3) // ChromaticAberration + { + fragColor = chromaticAberration(diffuseRect, fragTC, SPHERE_PARAMS.xy, SPHERE_PARAMS.zw, effectStrength); + } + else if (rlvEffectMode == 4) // Pixelate + { + effectStrength = sign(effectStrength); + float pixelWidth = max(1, round(SPHERE_PARAMS.x * effectStrength)) / screen_res.x; + float pixelHeight = max(1, round(SPHERE_PARAMS.y * effectStrength)) / screen_res.y; + fragTC = vec2(pixelWidth * floor(fragTC.x / pixelWidth), pixelHeight * floor(fragTC.y / pixelHeight)); + fragColor = texture(diffuseRect, fragTC).rgb; + } + + frag_color.rgb = fragColor; + frag_color.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/rlvV.glsl b/indra/newview/app_settings/shaders/class1/deferred/rlvV.glsl index e34ed060e37cbc1dc77bedaa2df2dcfbcb052ac6..8dfc88d4fd93529786c092d01644ec45d556516e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/rlvV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/rlvV.glsl @@ -22,9 +22,9 @@ out vec2 vary_fragcoord; void main() { - //transform vertex - vec4 pos = vec4(position.xyz, 1.0); - gl_Position = pos; + //transform vertex + vec4 pos = vec4(position.xyz, 1.0); + gl_Position = pos; - vary_fragcoord = (pos.xy*0.5+0.5); + vary_fragcoord = (pos.xy*0.5+0.5); } diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAA.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAA.glsl index c287ac08da172a780d678fe7473354cb54c90b01..4cd0a1131e6a64224a021e319a2af2d5fd9eccc8 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAA.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAA.glsl @@ -46,14 +46,14 @@ uniform vec4 SMAA_RT_METRICS; * \ \ | |\/| | / /_\ \ / /_\ \ * ----) | | | | | / _____ \ / _____ \ * |_______/ |__| |__| /__/ \__\ /__/ \__\ - * + * * E N H A N C E D * S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G * * http://www.iryoku.com/smaa/ * * Hi, welcome aboard! - * + * * Here you'll find instructions to get the shader up and running as fast as * possible. * @@ -142,14 +142,14 @@ uniform vec4 SMAA_RT_METRICS; * this last pass are not possible, the technique will work anyway, but * will perform antialiasing in gamma space. * - * IMPORTANT: for best results the input read for the color/luma edge + * IMPORTANT: for best results the input read for the color/luma edge * detection should *NOT* be sRGB. * * 6. Before including SMAA.h you'll have to setup the render target metrics, * the target and any optional configuration defines. Optionally you can * use a preset. * - * You have the following targets available: + * You have the following targets available: * SMAA_HLSL_3 * SMAA_HLSL_4 * SMAA_HLSL_4_1 @@ -342,7 +342,7 @@ uniform vec4 SMAA_RT_METRICS; /** * SMAA_THRESHOLD specifies the threshold or sensitivity to edges. * Lowering this value you will be able to detect more edges at the expense of - * performance. + * performance. * * Range: [0, 0.5] * 0.1 is a reasonable value, and allows to catch most visible edges. @@ -357,7 +357,7 @@ uniform vec4 SMAA_RT_METRICS; /** * SMAA_DEPTH_THRESHOLD specifies the threshold for depth edge detection. - * + * * Range: depends on the depth range of the scene. */ #ifndef SMAA_DEPTH_THRESHOLD @@ -385,7 +385,7 @@ uniform vec4 SMAA_RT_METRICS; * * Range: [0, 20] * - * On high-end machines it is cheap (between a 0.8x and 0.9x slower for 16 + * On high-end machines it is cheap (between a 0.8x and 0.9x slower for 16 * steps), but it can have a significant impact on older machines. * * Define SMAA_DISABLE_DIAG_DETECTION to disable diagonal processing. @@ -427,16 +427,16 @@ uniform vec4 SMAA_RT_METRICS; * It locally decreases the luma or color threshold if an edge is found in an * additional buffer (so the global threshold can be higher). * - * This method was developed by Playstation EDGE MLAA team, and used in + * This method was developed by Playstation EDGE MLAA team, and used in * Killzone 3, by using the light accumulation buffer. More information here: - * http://iryoku.com/aacourse/downloads/06-MLAA-on-PS3.pptx + * http://iryoku.com/aacourse/downloads/06-MLAA-on-PS3.pptx */ #ifndef SMAA_PREDICATION #define SMAA_PREDICATION 0 #endif /** - * Threshold to be used in the additional predication buffer. + * Threshold to be used in the additional predication buffer. * * Range: depends on the input, so you'll have to find the magic number that * works for you. @@ -632,15 +632,15 @@ SamplerState PointSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Clamp; Addres #define API_V_DIR(v) -(v) #define API_V_COORD(v) (1.0 - v) -#define API_V_BELOW(v1, v2) v1 < v2 -#define API_V_ABOVE(v1, v2) v1 > v2 +#define API_V_BELOW(v1, v2) v1 < v2 +#define API_V_ABOVE(v1, v2) v1 > v2 #else // VULKAN_FLIP #define API_V_DIR(v) v #define API_V_COORD(v) v -#define API_V_BELOW(v1, v2) v1 > v2 -#define API_V_ABOVE(v1, v2) v1 < v2 +#define API_V_BELOW(v1, v2) v1 > v2 +#define API_V_ABOVE(v1, v2) v1 < v2 #endif // VULKAN_FLIP @@ -924,7 +924,7 @@ float4 SMAADecodeDiagBilinearAccess(float4 e) { * These functions allows to perform diagonal pattern searches. */ float2 SMAASearchDiag1(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { - dir.y = API_V_DIR(dir.y); + dir.y = API_V_DIR(dir.y); float4 coord = float4(texcoord, -1.0, 1.0); float3 t = float3(SMAA_RT_METRICS.xy, 1.0); while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && @@ -937,7 +937,7 @@ float2 SMAASearchDiag1(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out } float2 SMAASearchDiag2(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { - dir.y = API_V_DIR(dir.y); + dir.y = API_V_DIR(dir.y); float4 coord = float4(texcoord, -1.0, 1.0); coord.x += 0.25 * SMAA_RT_METRICS.x; // See @SearchDiag2Optimization float3 t = float3(SMAA_RT_METRICS.xy, 1.0); @@ -959,7 +959,7 @@ float2 SMAASearchDiag2(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out return coord.zw; } -/** +/** * Similar to SMAAArea, this calculates the area corresponding to a certain * diagonal distance and crossing edges 'e'. */ @@ -975,7 +975,7 @@ float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float offset) // Move to proper place, according to the subpixel offset: texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset; - texcoord.y = API_V_COORD(texcoord.y); + texcoord.y = API_V_COORD(texcoord.y); // Do it! return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); @@ -1058,7 +1058,7 @@ float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex), SMAATexture2D(areaTex), /** * This allows to determine how much length should we add in the last step - * of the searches. It takes the bilinearly interpolated edge (see + * of the searches. It takes the bilinearly interpolated edge (see * @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and * crossing edges are active. */ @@ -1077,8 +1077,8 @@ float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset) { scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; - float2 coord = mad(scale, e, bias); - coord.y = API_V_COORD(coord.y); + float2 coord = mad(scale, e, bias); + coord.y = API_V_COORD(coord.y); // Lookup the search texture: return SMAA_SEARCHTEX_SELECT(SMAASampleLevelZero(searchTex, coord)); @@ -1096,7 +1096,7 @@ float SMAASearchXLeft(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 * which edges are active from the four fetched ones. */ float2 e = float2(0.0, 1.0); - while (texcoord.x > end && + while (texcoord.x > end && e.g > 0.8281 && // Is there some edge not activated? e.r == 0.0) { // Or is there a crossing edge that breaks the line? e = SMAASampleLevelZero(edgesTex, texcoord).rg; @@ -1121,7 +1121,7 @@ float SMAASearchXLeft(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 float SMAASearchXRight(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { float2 e = float2(0.0, 1.0); - while (texcoord.x < end && + while (texcoord.x < end && e.g > 0.8281 && // Is there some edge not activated? e.r == 0.0) { // Or is there a crossing edge that breaks the line? e = SMAASampleLevelZero(edgesTex, texcoord).rg; @@ -1133,7 +1133,7 @@ float SMAASearchXRight(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 float SMAASearchYUp(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { float2 e = float2(1.0, 0.0); - while (API_V_BELOW(texcoord.y, end) && + while (API_V_BELOW(texcoord.y, end) && e.r > 0.8281 && // Is there some edge not activated? e.g == 0.0) { // Or is there a crossing edge that breaks the line? e = SMAASampleLevelZero(edgesTex, texcoord).rg; @@ -1145,7 +1145,7 @@ float SMAASearchYUp(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 te float SMAASearchYDown(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { float2 e = float2(1.0, 0.0); - while (API_V_ABOVE(texcoord.y, end) && + while (API_V_ABOVE(texcoord.y, end) && e.r > 0.8281 && // Is there some edge not activated? e.g == 0.0) { // Or is there a crossing edge that breaks the line? e = SMAASampleLevelZero(edgesTex, texcoord).rg; @@ -1155,21 +1155,21 @@ float SMAASearchYDown(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 return mad(-SMAA_RT_METRICS.y, API_V_DIR(offset), texcoord.y); } -/** +/** * Ok, we have the distance and both crossing edges. So, what are the areas * at each side of current edge? */ float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset) { // Rounding prevents precision errors of bilinear filtering: float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE), round(4.0 * float2(e1, e2)), dist); - + // We do a scale and bias for mapping to texel space: texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); // Move to proper place, according to the subpixel offset: texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y); - texcoord.y = API_V_COORD(texcoord.y); + texcoord.y = API_V_COORD(texcoord.y); // Do it! return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); @@ -1233,7 +1233,7 @@ float4 SMAABlendingWeightCalculationPS(float2 texcoord, // one of the boundaries is enough. weights.rg = SMAACalculateDiagWeights(SMAATexturePass2D(edgesTex), SMAATexturePass2D(areaTex), texcoord, e, subsampleIndices); - // We give priority to diagonals, so if we find a diagonal we skip + // We give priority to diagonals, so if we find a diagonal we skip // horizontal/vertical processing. SMAA_BRANCH if (weights.r == -weights.g) { // weights.r + weights.g == 0.0 @@ -1301,7 +1301,7 @@ float4 SMAABlendingWeightCalculationPS(float2 texcoord, // We want the distances to be in pixel units: d = abs(round(mad(SMAA_RT_METRICS.ww, d, -pixcoord.yy))); - // SMAAArea below needs a sqrt, as the areas texture is compressed + // SMAAArea below needs a sqrt, as the areas texture is compressed // quadratically: float2 sqrt_d = sqrt(d); diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsF.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsF.glsl index 2b1a2803756fbb1a70afb7bdcad0e9ac0ce5d4b3..cd669c457a0878561fd41eaa4712de81de742952 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsF.glsl @@ -1,4 +1,4 @@ -/** +/** * @file SMAABlurWeightsF.glsl */ @@ -28,13 +28,13 @@ float4 SMAABlendingWeightCalculationPS(float2 texcoord, void main() { - frag_color = SMAABlendingWeightCalculationPS(vary_texcoord0, - vary_pixcoord, - vary_offset, - tex0, - tex1, - tex2, - float4(0.0) - ); + frag_color = SMAABlendingWeightCalculationPS(vary_texcoord0, + vary_pixcoord, + vary_offset, + tex0, + tex1, + tex2, + float4(0.0) + ); } diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsV.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsV.glsl index 29bc82134ef26dfacbbe5236eb789f93e6d7c1bb..22fa116446d1679050e34c04c9de6d60090e757f 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAABlendWeightsV.glsl @@ -1,4 +1,4 @@ -/** +/** * @file SMAABlurWeightsV.glsl */ @@ -20,11 +20,11 @@ void SMAABlendingWeightCalculationVS(float2 texcoord, void main() { - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = (gl_Position.xy*0.5+0.5); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = (gl_Position.xy*0.5+0.5); - SMAABlendingWeightCalculationVS(vary_texcoord0, - vary_pixcoord, - vary_offset); + SMAABlendingWeightCalculationVS(vary_texcoord0, + vary_pixcoord, + vary_offset); } diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectF.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectF.glsl index 67d5692c0f8c2b1d2aa73d3759b95a61e6198edd..d7ca4e8ebe87950f21b21ffcaf3c48c722334540 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectF.glsl @@ -1,6 +1,6 @@ -/** +/** * @file SMAAEdgeDetectF.glsl - */ + */ /*[EXTRA_CODE_HERE]*/ @@ -28,12 +28,12 @@ float2 SMAAColorEdgeDetectionPS(float2 texcoord, void main() { - vec2 val = SMAAColorEdgeDetectionPS(vary_texcoord0, - vary_offset, - tex0 - #if SMAA_PREDICATION - , tex1 - #endif - ); - frag_color = float4(val,0.0,0.0); + vec2 val = SMAAColorEdgeDetectionPS(vary_texcoord0, + vary_offset, + tex0 + #if SMAA_PREDICATION + , tex1 + #endif + ); + frag_color = float4(val,0.0,0.0); } diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectV.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectV.glsl index 9b12a04dcf31aacd35815f9501f3016a046db4ac..5eccac45a241a88cca0e75b4578a539aca1eace6 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAAEdgeDetectV.glsl @@ -1,4 +1,4 @@ -/** +/** * @file SMAAEdgeDetectV.glsl */ @@ -15,11 +15,11 @@ out vec4 vary_offset[3]; #define float2 vec2 void SMAAEdgeDetectionVS(float2 texcoord, out float4 offset[3]); - + void main() { - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = (gl_Position.xy*0.5+0.5); - - SMAAEdgeDetectionVS(vary_texcoord0, vary_offset); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = (gl_Position.xy*0.5+0.5); + + SMAAEdgeDetectionVS(vary_texcoord0, vary_offset); } diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendF.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendF.glsl index 1d82dfca43ce998059e8bbc46d83ad48bc7a74f0..4a7aef5102a3a2334b26eb8f708e9da7bf576c07 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendF.glsl @@ -1,4 +1,4 @@ -/** +/** * @file SMAANeighborhoodBlendF.glsl */ @@ -30,13 +30,13 @@ float4 SMAANeighborhoodBlendingPS(float2 texcoord, void main() { - frag_color = SMAANeighborhoodBlendingPS(vary_texcoord0, - vary_offset, - tex0, - tex1 - #if SMAA_REPROJECTION - , tex2 - #endif - ); + frag_color = SMAANeighborhoodBlendingPS(vary_texcoord0, + vary_offset, + tex0, + tex1 + #if SMAA_REPROJECTION + , tex2 + #endif + ); } diff --git a/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendV.glsl b/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendV.glsl index ea2212fd99b420117db0f250c6817162b58d88b9..4f117b202c65e9b4afcd0ae656fd15980921f26e 100644 --- a/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/SMAANeighborhoodBlendV.glsl @@ -1,4 +1,4 @@ -/** +/** * @file SMAANeighborhoodBlendV.glsl */ @@ -18,9 +18,9 @@ void SMAANeighborhoodBlendingVS(float2 texcoord, void main() { - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = (gl_Position.xy*0.5+0.5); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = (gl_Position.xy*0.5+0.5); - SMAANeighborhoodBlendingVS(vary_texcoord0, vary_offset); + SMAANeighborhoodBlendingVS(vary_texcoord0, vary_offset); } diff --git a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl index 87201cae89665667d83e3f0f3451a4160be161b4..89940627ea0ba9283f4fbd834cfb123991b2227b 100644 --- a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl @@ -4,21 +4,21 @@ * $LicenseInfo:firstyear=2018&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2018, 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$ */ @@ -31,7 +31,7 @@ vec2 encode_normal(vec3 n) { n *= 1.0 / max(dot(abs(n), vec3(1.0)), 1e-6); float t = clamp(-n.z, 0.0, 1.0); - n.x += n.x >= 0.0 ? t : -t; - n.y += n.y >= 0.0 ? t : -t; + n.x += n.x >= 0.0 ? t : -t; + n.y += n.y >= 0.0 ? t : -t; return n.xy * 0.5 + 0.5; } diff --git a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl index 57243e6e4c55cc679ce3a65805af1dc571868e03..8073dfa7698b4e9df30ac0b99196d3102caeef82 100644 --- a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file srgbF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -27,21 +27,21 @@ vec3 srgb_to_linear(vec3 cs) { - vec3 low_range = cs / vec3(12.92); - vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); - bvec3 lte = lessThanEqual(cs,vec3(0.04045)); + vec3 low_range = cs / vec3(12.92); + vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4)); + bvec3 lte = lessThanEqual(cs,vec3(0.04045)); - return mix(high_range, low_range, lte); + return mix(high_range, low_range, lte); } vec3 linear_to_srgb(vec3 cl) { - cl = clamp(cl, vec3(0), vec3(1)); - vec3 low_range = cl * 12.92; - vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; - bvec3 lt = lessThan(cl,vec3(0.0031308)); + cl = clamp(cl, vec3(0), vec3(1)); + vec3 low_range = cl * 12.92; + vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055; + bvec3 lt = lessThan(cl,vec3(0.0031308)); - return mix(high_range, low_range, lt); + return mix(high_range, low_range, lt); } vec3 ColorFromRadiance(vec3 radiance) diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index f4c59c538873638f9a886672be16cd67547b028e..c66a44e53b4825a6d844b3f121dea192f6a01b1f 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file alphaF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -60,7 +60,7 @@ uniform vec2 screen_res; uniform int sun_up_factor; uniform vec4 light_position[8]; uniform vec3 light_direction[8]; -uniform vec4 light_attenuation[8]; +uniform vec4 light_attenuation[8]; uniform vec3 light_diffuse[8]; void waterClip(vec3 pos); @@ -90,15 +90,15 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec float falloff_factor = (12.0 * fa) - 9.0; float inverted_la = falloff_factor / la; // Yes, it makes me want to cry as well. DJH - + vec3 col = vec3(0); - //get light vector - vec3 lv = lp.xyz-v; + //get light vector + vec3 lv = lp.xyz-v; - //get distance - float dist = length(lv); - float da = 1.0; + //get distance + float dist = length(lv); + float da = 1.0; /*if (dist > inverted_la) { @@ -111,23 +111,23 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec if (proj_tc.z < 0 || proj_tc.z > 1 || proj_tc.x < 0 - || proj_tc.x > 1 + || proj_tc.x > 1 || proj_tc.y < 0 || proj_tc.y > 1) { return col; }*/ - if (dist > 0.0 && inverted_la > 0.0) - { + if (dist > 0.0 && inverted_la > 0.0) + { dist /= inverted_la; - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); - dist_atten *= dist_atten; + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; dist_atten *= 2.0f; if (dist_atten <= 0.0) @@ -135,20 +135,20 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec return col; } - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 - //angular attenuation - da *= dot(n, lv); + //angular attenuation + da *= dot(n, lv); da = max(0.0, da); - float lit = 0.0f; + float lit = 0.0f; float amb_da = 0.0;//ambiance; if (da > 0) { - lit = max(da * dist_atten,0.0); + lit = max(da * dist_atten,0.0); col = lit * light_col * diffuse; amb_da += (da*0.5+0.5) * ambiance; } @@ -165,10 +165,10 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec return col; } -void main() +void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - + vec4 pos = vec4(vary_position, 1.0); #ifndef IS_AVATAR_SKIN // clip against water plane unless this is a legacy avatar skin @@ -199,7 +199,7 @@ void main() float final_alpha = diffuse_srgb.a * vertex_color.a; diffuse_srgb.rgb *= vertex_color.rgb; - + // Insure we don't pollute depth with invis pixels in impostor rendering // if (final_alpha < minimum_alpha) @@ -222,7 +222,7 @@ void main() final_alpha *= vertex_color.a; if (final_alpha < minimum_alpha) - { // TODO: figure out how to get invisible faces out of + { // TODO: figure out how to get invisible faces out of // render batches without breaking glow discard; } @@ -245,7 +245,7 @@ void main() vec3 glossenv; vec3 legacyenv; sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, frag, pos.xyz, norm.xyz, 0.0, 0.0, true, amblit_linear); - + float final_da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); @@ -262,7 +262,7 @@ void main() color.rgb *= diffuse_linear.rgb; vec4 light = vec4(0,0,0,0); - + #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diffuse_linear.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w); LIGHT_LOOP(1) diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 35d98f0a8c2e6d8de904e86d413720b313faa47e..8fe956715f1c9dc2c6fc04b5d5b602d39eadf82e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -93,7 +93,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float falloff_factor = (12.0 * fa) - 9.0; float inverted_la = falloff_factor / la; // Yes, it makes me want to cry as well. DJH - + vec3 col = vec3(0); //get light vector @@ -215,19 +215,19 @@ vec2 encode_normal(vec3 n); vec3 getNormal(inout float glossiness) { #ifdef HAS_NORMAL_MAP - vec4 vNt = texture(bumpMap, vary_texcoord1.xy); + vec4 vNt = texture(bumpMap, vary_texcoord1.xy); glossiness *= vNt.a; - vNt.xyz = vNt.xyz * 2 - 1; + vNt.xyz = vNt.xyz * 2 - 1; float sign = vary_sign; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; - + vec3 vB = sign * cross(vN, vT); vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); - return tnorm; + return tnorm; #else - return normalize(vary_normal); + return normalize(vary_normal); #endif } @@ -264,9 +264,9 @@ void waterClip() float getEmissive(vec4 diffcol) { #if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE) - return emissive_brightness; + return emissive_brightness; #else - return max(diffcol.a, emissive_brightness); + return max(diffcol.a, emissive_brightness); #endif } @@ -289,7 +289,7 @@ void main() // diffcol == diffuse map combined with vertex color vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy); - diffcol.rgb *= vertex_color.rgb; + diffcol.rgb *= vertex_color.rgb; alphaMask(diffcol.a); @@ -323,7 +323,7 @@ void main() vec3 additive; vec3 atten; calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten); - + vec3 sunlit_linear = srgb_to_linear(sunlit); vec3 amblit_linear = amblit; @@ -331,7 +331,7 @@ void main() vec3 glossenv; vec3 legacyenv; sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xy*0.5+0.5, pos.xyz, norm.xyz, glossiness, env, true, amblit_linear); - + color = ambenv; float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); @@ -401,7 +401,7 @@ void main() frag_color = max(vec4(color, al), vec4(0)); -#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer +#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index 02c547b7c7482eff48d67e574bdadbbb023cd566..22fde09eb8e003e7d5550be474332abab99068aa 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -50,7 +50,7 @@ LLAccountingCostManager::LLAccountingCostManager() // Do not call directly. See documentation in lleventcoro.h and llcoro.h for // further explanation. void LLAccountingCostManager::accountingCostCoro(std::string url, - eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle, uuid_set_t object_list) + eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle) { LL_DEBUGS("LLAccountingCostManager") << "Entering coroutine " << LLCoros::getName() << " with url '" << url << LL_ENDL; @@ -62,15 +62,20 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, try { + LLAccountingCostManager* self = LLAccountingCostManager::getInstance(); uuid_set_t diffSet; - std::set_difference(object_list.begin(), object_list.end(), - mPendingObjectQuota.begin(), mPendingObjectQuota.end(), - std::inserter(diffSet, diffSet.begin())); + std::set_difference(self->mObjectList.begin(), + self->mObjectList.end(), + self->mPendingObjectQuota.begin(), + self->mPendingObjectQuota.end(), + std::inserter(diffSet, diffSet.begin())); if (diffSet.empty()) return; + self->mObjectList.clear(); + std::string keystr; if (selectionType == Roots) { @@ -93,19 +98,25 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, objectList.append(*it); } - mPendingObjectQuota.insert(diffSet.begin(), diffSet.end()); + self->mPendingObjectQuota.insert(diffSet.begin(), diffSet.end()); LLSD dataToPost = LLSD::emptyMap(); dataToPost[keystr.c_str()] = objectList; - LLAccountingCostObserver* observer = NULL; - LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost); LLSD httpResults = results["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - LL_INFOS() << results << LL_ENDL; + if (LLApp::isQuitting() + || observerHandle.isDead() + || !LLAccountingCostManager::instanceExists()) + { + return; + } + + LLAccountingCostObserver* observer = NULL; + // do/while(false) allows error conditions to break out of following // block while normal flow goes forward once. do @@ -154,10 +165,6 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, } while (false); - for (const auto& id : diffSet) - { - mPendingObjectQuota.erase(id); - } } catch (...) { @@ -165,72 +172,32 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, << "('" << url << "')")); throw; } + + // self can be obsolete by this point + LLAccountingCostManager::getInstance()->mPendingObjectQuota.clear(); } //=============================================================================== void LLAccountingCostManager::fetchCosts( eSelectionType selectionType, + const std::string& url, const LLHandle<LLAccountingCostObserver>& observer_handle ) { - if (mObjectList.empty()) return; - - boost::unordered_map<LLViewerRegion*, uuid_set_t> regionObjectMap{}; - - // Swap it for thread safety since we're going to iterate over it - uuid_set_t staleObjectCostIds{}; - staleObjectCostIds.swap(mObjectList); - - for (const auto& staleObjectId : staleObjectCostIds) + // Invoking system must have already determined capability availability + if ( !url.empty() ) { - LLViewerObject* staleObject = gObjectList.findObject(staleObjectId); - if (staleObject && staleObject->getRegion() && staleObject->getRegion()->capabilitiesReceived()) - { - if (regionObjectMap.find(staleObject->getRegion()) == regionObjectMap.end()) - { - regionObjectMap.insert(std::make_pair(staleObject->getRegion(), uuid_set_t())); - } + std::string coroname = + LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", + boost::bind(accountingCostCoro, url, selectionType, observer_handle)); + LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL; - regionObjectMap[staleObject->getRegion()].insert(staleObjectId); - } } - - for (const auto& region : regionObjectMap) + else { - std::string url; - if(region.first->capabilitiesReceived()) - url = region.first->getCapability("ResourceCostSelected"); - - if (!url.empty()) - { - std::string coroname = - LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", - boost::bind(&LLAccountingCostManager::accountingCostCoro, this, url, selectionType, observer_handle, region.second)); - LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL; - } - else - { - for (const auto& objectId : region.second) - { - mPendingObjectQuota.erase(objectId); - } - } + //url was empty - warn & continue + LL_WARNS()<<"Supplied url is empty "<<LL_ENDL; + mObjectList.clear(); + mPendingObjectQuota.clear(); } - - //// Invoking system must have already determined capability availability - //if ( !url.empty() ) - //{ - // std::string coroname = - // LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", - // boost::bind(&LLAccountingCostManager::accountingCostCoro, this, url, selectionType, observer_handle)); - // LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL; - - //} - //else - //{ - // //url was empty - warn & continue - // LL_WARNS()<<"Supplied url is empty "<<LL_ENDL; - // mObjectList.clear(); - // mPendingObjectQuota.clear(); - //} } //=============================================================================== void LLAccountingCostManager::addObject( const LLUUID& objectID ) diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index 490052babbb61f7a8e21cfe669d039dca37d03d3..281d657d2badefa9225441167af09eff9fd302f3 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -58,7 +58,8 @@ class LLAccountingCostManager final : public LLSingleton<LLAccountingCostManager //Store an object that will be eventually fetched void addObject( const LLUUID& objectID ); //Request quotas for object list - void fetchCosts( eSelectionType selectionType, const LLHandle<LLAccountingCostObserver>& observer_handle); + void fetchCosts( eSelectionType selectionType, const std::string& url, + const LLHandle<LLAccountingCostObserver>& observer_handle ); //Delete a specific object from the pending list void removePendingObject( const LLUUID& objectID ); @@ -69,7 +70,7 @@ class LLAccountingCostManager final : public LLSingleton<LLAccountingCostManager //a fetch has been instigated. uuid_set_t mPendingObjectQuota; - void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle, uuid_set_t object_list); + static void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle); }; //=============================================================================== diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 2a7ff1def32e7c219de6ead1a941b63e8122426b..1016432452ef0adb2a76abcac327981936a522ec 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2041,8 +2041,8 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } else { - static const LLCachedControl<F32> dyn_cam_strength(gSavedSettings, "DynamicCameraStrength"); - target_lag = vel * dyn_cam_strength / 30.f; + LLCachedControl<F32> dynamic_camera_strength(gSavedSettings, "DynamicCameraStrength"); + target_lag = vel * dynamic_camera_strength / 30.f; } mCameraLag = lerp(mCameraLag, target_lag, lag_interp); diff --git a/indra/newview/llagentpicksinfo.cpp b/indra/newview/llagentpicksinfo.cpp index 54224824fcc2ba5707ecfa86cd0acefcc65dd29e..efd5f223ddb5d99e684d75f23119109e311b7772 100644 --- a/indra/newview/llagentpicksinfo.cpp +++ b/indra/newview/llagentpicksinfo.cpp @@ -50,10 +50,10 @@ class LLAgentPicksInfo::LLAgentPicksObserver : public LLAvatarPropertiesObserver void sendAgentPicksRequest() { - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(gAgent.getID()); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgent.getID()); } - typedef boost::function<void(LLAvatarPicks*)> server_respond_callback_t; + typedef boost::function<void(LLAvatarData*)> server_respond_callback_t; void setServerRespondCallback(const server_respond_callback_t& cb) { @@ -62,10 +62,10 @@ class LLAgentPicksInfo::LLAgentPicksObserver : public LLAvatarPropertiesObserver virtual void processProperties(void* data, EAvatarProcessorType type) { - if(APT_PICKS == type) + if(APT_PROPERTIES == type) { - LLAvatarPicks* picks = static_cast<LLAvatarPicks*>(data); - if(picks && gAgent.getID() == picks->target_id) + LLAvatarData* picks = static_cast<LLAvatarData*>(data); + if(picks && gAgent.getID() == picks->avatar_id) { if(mServerRespondCallback) { @@ -116,7 +116,7 @@ bool LLAgentPicksInfo::isPickLimitReached() return getNumberOfPicks() >= LLAgentBenefitsMgr::current().getPicksLimit(); } -void LLAgentPicksInfo::onServerRespond(LLAvatarPicks* picks) +void LLAgentPicksInfo::onServerRespond(LLAvatarData* picks) { if(!picks) { diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h index e9e7eebdad3c9364d3eb292690597484c80f6bd5..18253952e6f2e900e0539b9621025336820f2166 100644 --- a/indra/newview/llagentpicksinfo.h +++ b/indra/newview/llagentpicksinfo.h @@ -29,7 +29,7 @@ #include "llsingleton.h" -struct LLAvatarPicks; +struct LLAvatarData; /** * Class that provides information about Agent Picks @@ -74,7 +74,7 @@ class LLAgentPicksInfo final : public LLSingleton<LLAgentPicksInfo> void decrementNumberOfPicks() { --mNumberOfPicks; } - void onServerRespond(LLAvatarPicks* picks); + void onServerRespond(LLAvatarData* picks); private: diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 05270566376ceaa7f12d8cd180ea4fbd75fc5516..18864ece77e07a57fefc7c8ba2d131e6c19836ef 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1432,7 +1432,7 @@ const std::string LLAppearanceMgr::sExpectedTextureName = "OutfitPreview"; const LLUUID LLAppearanceMgr::getCOF() const { - return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + return mCOFID; } S32 LLAppearanceMgr::getCOFVersion() const @@ -1448,6 +1448,11 @@ S32 LLAppearanceMgr::getCOFVersion() const } } +void LLAppearanceMgr::initCOFID() +{ + mCOFID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); +} + const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() { const LLUUID& current_outfit_cat = getCOF(); @@ -4074,6 +4079,14 @@ LLSD LLAppearanceMgr::dumpCOF() const return result; } +void LLAppearanceMgr::cleanup() +{ + mIsInUpdateAppearanceFromCOF = false; + mOutstandingAppearanceBakeRequest = false; + mRerequestAppearanceBake = false; + mCOFID.setNull(); +} + // static void LLAppearanceMgr::onIdle(void *) { @@ -4539,9 +4552,9 @@ void LLAppearanceMgr::wearBaseOutfit() updateCOF(base_outfit_id); } -//void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) +//void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nullary_func_t post_update_func) // [SL:KB] - Patch: Appearance-Misc | Checked: 2015-05-05 (Catznip-3.7) -void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/) +void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nullary_func_t post_update_func, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/) // [/SL:KB] { if (ids_to_remove.empty()) @@ -4550,7 +4563,7 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLP return; } // [RLVa:KB] - Checked: 2013-02-12 (RLVa-1.4.8) -// LLPointer<LLInventoryCallback> cb = NULL; +// LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy(true, true, post_update_func); for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it) { const LLUUID& id_to_remove = *it; @@ -4572,7 +4585,7 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLP } if (!cb) - cb = new LLUpdateAppearanceOnDestroy(); + cb = new LLUpdateAppearanceOnDestroy(true, true, post_update_func); removeCOFItemLinks(linked_item_id, cb, immediate_delete); // [SL:KB] - Patch: Appearance-SyncAttach | Checked: Catznip-3.7 LLAttachmentsMgr::instance().clearPendingAttachmentLink(linked_item_id); @@ -4599,17 +4612,17 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLP // } } -//void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) +//void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove, nullary_func_t post_update_func) // [SL:KB] - Patch: Appearance-Misc | Checked: 2015-05-05 (Catznip-3.7) -void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/) +void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove, nullary_func_t post_update_func, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/) // [/SL:KB] { uuid_vec_t ids_to_remove; ids_to_remove.push_back(id_to_remove); // [SL:KB] - Patch: Appearance-Misc | Checked: 2015-05-05 (Catznip-3.7) - removeItemsFromAvatar(ids_to_remove, cb, immediate_delete); + removeItemsFromAvatar(ids_to_remove, post_update_func, cb, immediate_delete); // [/SL:KB] -// removeItemsFromAvatar(ids_to_remove); +// removeItemsFromAvatar(ids_to_remove, post_update_func); } @@ -4846,20 +4859,45 @@ BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const return FALSE; } -BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const +bool LLAppearanceMgr::getIsInCOF(const LLInventoryObject* obj) const { - if (!getIsInCOF(obj_id)) return FALSE; + const LLUUID& cof = getCOF(); + if (obj->getUUID() == cof) + return true; + if (obj && obj->getParentUUID() == cof) + return true; + return false; +} + +bool LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const +{ + if (!getIsInCOF(obj_id)) return false; // If a non-link somehow ended up in COF, allow deletion. const LLInventoryObject *obj = gInventory.getObject(obj_id); if (obj && !obj->getIsLinkType()) { - return FALSE; + return false; } // For now, don't allow direct deletion from the COF. Instead, force users // to choose "Detach" or "Take Off". - return TRUE; + return true; +} + +bool LLAppearanceMgr::getIsProtectedCOFItem(const LLInventoryObject* obj) const +{ + if (!getIsInCOF(obj)) return false; + + // If a non-link somehow ended up in COF, allow deletion. + if (obj && !obj->getIsLinkType()) + { + return false; + } + + // For now, don't allow direct deletion from the COF. Instead, force users + // to choose "Detach" or "Take Off". + return true; } class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index a7f336468e464856e2d7fc860c3bc7a8677a0788..8f621a4a575a72755efbf1d664b6a2144acf798b 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -116,9 +116,11 @@ class LLAppearanceMgr final : public LLSingleton<LLAppearanceMgr> // Find the Current Outfit folder. const LLUUID getCOF() const; S32 getCOFVersion() const; + void initCOFID(); // Debugging - get truncated LLSD summary of COF contents. LLSD dumpCOF() const; + void cleanup(); // Finds the folder link to the currently worn outfit const LLViewerInventoryItem *getBaseOutfitLink(); @@ -207,14 +209,14 @@ class LLAppearanceMgr final : public LLSingleton<LLAppearanceMgr> //Remove clothing or detach an object from the agent (a bodypart cannot be removed) // [SL:KB] - Patch: Appearance-Misc | Checked: 2015-05-05 (Catznip-3.7) - void removeItemFromAvatar(const LLUUID& id_to_remove) { removeItemFromAvatar(id_to_remove, NULL, false); } - void removeItemFromAvatar(const LLUUID& id_to_remove, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/); + void removeItemFromAvatar(const LLUUID& id_to_remove, nullary_func_t post_update_func = no_op) { removeItemFromAvatar(id_to_remove, post_update_func, NULL, false); } + void removeItemFromAvatar(const LLUUID& id_to_remove, nullary_func_t post_update_func /*= no_op*/, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/); - void removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) { removeItemsFromAvatar(ids_to_remove, NULL, false); } - void removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/); + void removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nullary_func_t post_update_func = no_op) { removeItemsFromAvatar(ids_to_remove, post_update_func, NULL, false); } + void removeItemsFromAvatar(const uuid_vec_t& ids_to_remove, nullary_func_t post_update_func /*= no_op*/, LLPointer<LLInventoryCallback> cb /*= NULL*/, bool immediate_delete /*= false*/); // [/SL:KB] -// void removeItemsFromAvatar(const uuid_vec_t& item_ids); -// void removeItemFromAvatar(const LLUUID& item_id); +// void removeItemsFromAvatar(const uuid_vec_t& item_ids, nullary_func_t post_update_func = no_op); +// void removeItemFromAvatar(const LLUUID& item_id, nullary_func_t post_update_func = no_op); void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel); @@ -284,7 +286,6 @@ class LLAppearanceMgr final : public LLSingleton<LLAppearanceMgr> static void onOutfitRename(const LLSD& notification, const LLSD& response); - bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. @@ -302,6 +303,7 @@ class LLAppearanceMgr final : public LLSingleton<LLAppearanceMgr> attachments_changed_signal_t mAttachmentsChangeSignal; LLUUID mCOFImageID; + LLUUID mCOFID; std::unique_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; @@ -316,8 +318,10 @@ class LLAppearanceMgr final : public LLSingleton<LLAppearanceMgr> public: // Is this in the COF? BOOL getIsInCOF(const LLUUID& obj_id) const; + bool getIsInCOF(const LLInventoryObject* obj) const; // Is this in the COF and can the user delete it from the COF? - BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const; + bool getIsProtectedCOFItem(const LLUUID& obj_id) const; + bool getIsProtectedCOFItem(const LLInventoryObject* obj) const; // Outfits will prioritize textures with such name to use for preview in gallery static const std::string sExpectedTextureName; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3d34601dd226e971ce9808fcbda6b360f3037f2a..6d4e490da00382155c17086ba9c09b657529ee7b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -541,13 +541,6 @@ bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* ba // or for things that are performance critical. JC static void settings_to_globals() { - LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad"); - BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); - BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); - - MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight"); - MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth"); - LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); #if LL_DARWIN @@ -4184,7 +4177,8 @@ bool LLAppViewer::initCache() LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); } - LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); + const U32 CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS = 128; + LLVOCache::getInstance()->initCache(LL_PATH_CACHE, CACHE_NUMBER_OF_REGIONS_FOR_OBJECTS, getObjectCacheVersion()); return true; } diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index e462d89855131224f82f56b24309fa21db16e3c2..7b1070dd08a5d101eddcc3ce6df2f52529934e74 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -245,7 +245,7 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) // messages. People API already hits the user table. LLIconCtrl::setValue(mDefaultIconName, LLViewerFetchedTexture::BOOST_UI); app->addObserver(mAvatarId, this); - app->sendAvatarPropertiesRequest(mAvatarId); + app->sendAvatarLegacyPropertiesRequest(mAvatarId); } else if (gAgentID == mAvatarId) { @@ -300,7 +300,27 @@ bool LLAvatarIconCtrl::updateFromCache() //virtual void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type) { - if (APT_PROPERTIES == type) + // Both APT_PROPERTIES_LEGACY and APT_PROPERTIES have icon data. + // 'Legacy' is cheaper to request so LLAvatarIconCtrl issues that, + // but own icon should track any source for the sake of timely updates. + // + // If this needs to change, make sure to update onCommitProfileImage + // to issue right kind of request + if (APT_PROPERTIES_LEGACY == type) + { + LLAvatarLegacyData* avatar_data = static_cast<LLAvatarLegacyData*>(data); + if (avatar_data) + { + if (avatar_data->avatar_id != mAvatarId) + { + return; + } + + LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id); + updateFromCache(); + } + } + else if (APT_PROPERTIES == type) { LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); if (avatar_data) @@ -314,7 +334,7 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type) LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this); // [/SL:KB] - LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id); + LLAvatarIconIDCache::getInstance()->add(mAvatarId, avatar_data->image_id); updateFromCache(); } } diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 58f81d18195c583833163543d5811deea0913307..715649e8443917fe7e9924aaee3b4a15267d7548 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -52,24 +52,23 @@ LLAvatarPropertiesProcessor::~LLAvatarPropertiesProcessor() void LLAvatarPropertiesProcessor::addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer) { + if (!observer) + return; + // Check if that observer is already in mObservers for that avatar_id - observer_multimap_t::iterator it; + using pair = std::pair<LLUUID, LLAvatarPropertiesObserver*>; + observer_multimap_t::iterator begin = mObservers.begin(); + observer_multimap_t::iterator end = mObservers.end(); + observer_multimap_t::iterator it = std::find_if(begin, end, [&](const pair& p) + { + return p.first == avatar_id && p.second == observer; + }); // IAN BUG this should update the observer's UUID if this is a dupe - sent to PE - it = mObservers.find(avatar_id); - while (it != mObservers.end()) + if (it == end) { - if (it->second == observer) - { - return; - } - else - { - ++it; - } + mObservers.emplace(avatar_id, observer); } - - mObservers.insert(std::pair<LLUUID, LLAvatarPropertiesObserver*>(avatar_id, observer)); } void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer) @@ -79,19 +78,18 @@ void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvat return; } - observer_multimap_t::iterator it; - it = mObservers.find(avatar_id); - while (it != mObservers.end()) - { - if (it->second == observer) - { - mObservers.erase(it); - break; - } - else + // Check if that observer is in mObservers for that avatar_id + using pair = std::pair<LLUUID, LLAvatarPropertiesObserver*>; + observer_multimap_t::iterator begin = mObservers.begin(); + observer_multimap_t::iterator end = mObservers.end(); + observer_multimap_t::iterator it = std::find_if(begin, end, [&](const pair& p) { - ++it; - } + return p.first == avatar_id && p.second == observer; + }); + + if (it != end) + { + mObservers.erase(it); } } @@ -116,32 +114,30 @@ void LLAvatarPropertiesProcessor::sendRequest(const LLUUID& avatar_id, EAvatarPr return; } - std::string cap; - - switch (type) + // Try to send HTTP request if cap_url is available + if (type == APT_PROPERTIES) { - case APT_PROPERTIES: - // indicate we're going to make a request - sendAvatarPropertiesRequestMessage(avatar_id); - // can use getRegionCapability("AgentProfile"), but it is heavy - // initAgentProfileCapRequest(avatar_id, cap); - break; - case APT_PICKS: - case APT_GROUPS: - case APT_NOTES: - if (cap.empty()) + std::string cap_url = gAgent.getRegionCapability("AgentProfile"); + if (!cap_url.empty()) { - // indicate we're going to make a request - sendGenericRequest(avatar_id, type, method); + initAgentProfileCapRequest(avatar_id, cap_url, type); } else { - initAgentProfileCapRequest(avatar_id, cap); + // Don't sent UDP request for APT_PROPERTIES + LL_WARNS() << "No cap_url for APT_PROPERTIES, request for " << avatar_id << " is not sent" << LL_ENDL; } - break; - default: + return; + } + + // Send UDP request + if (type == APT_PROPERTIES_LEGACY) + { + sendAvatarPropertiesRequestMessage(avatar_id); + } + else + { sendGenericRequest(avatar_id, type, method); - break; } } @@ -150,33 +146,29 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA // indicate we're going to make a request addPendingRequest(avatar_id, type); - std::vector<std::string> strings; - strings.push_back(avatar_id.asString()); + std::vector<std::string> strings{ avatar_id.asString() }; send_generic_message(method, strings); } void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id) { - addPendingRequest(avatar_id, APT_PROPERTIES); + addPendingRequest(avatar_id, APT_PROPERTIES_LEGACY); LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast( _PREHASH_AvatarID, avatar_id); + msg->addUUIDFast(_PREHASH_AgentID, gAgentID); + msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + msg->addUUIDFast(_PREHASH_AvatarID, avatar_id); gAgent.sendReliableMessage(); } -void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url) +void LLAvatarPropertiesProcessor::initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url, EAvatarProcessorType type) { - addPendingRequest(avatar_id, APT_PROPERTIES); - addPendingRequest(avatar_id, APT_PICKS); - addPendingRequest(avatar_id, APT_GROUPS); - addPendingRequest(avatar_id, APT_NOTES); - LLCoros::instance().launch("requestAvatarPropertiesCoro", - boost::bind(requestAvatarPropertiesCoro, cap_url, avatar_id)); + addPendingRequest(avatar_id, type); + LLCoros::instance().launch("requestAgentUserInfoCoro", + [cap_url, avatar_id, type]() { requestAvatarPropertiesCoro(cap_url, avatar_id, type); }); } void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id) @@ -184,19 +176,9 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avat sendRequest(avatar_id, APT_PROPERTIES, "AvatarPropertiesRequest"); } -void LLAvatarPropertiesProcessor::sendAvatarPicksRequest(const LLUUID& avatar_id) +void LLAvatarPropertiesProcessor::sendAvatarLegacyPropertiesRequest(const LLUUID& avatar_id) { - sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest"); -} - -void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id) -{ - sendGenericRequest(avatar_id, APT_NOTES, "avatarnotesrequest"); -} - -void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_id) -{ - sendGenericRequest(avatar_id, APT_GROUPS, "avatargroupsrequest"); + sendRequest(avatar_id, APT_PROPERTIES_LEGACY, "AvatarPropertiesRequest"); } void LLAvatarPropertiesProcessor::sendAvatarTexturesRequest(const LLUUID& avatar_id) @@ -211,42 +193,6 @@ void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& ava sendGenericRequest(avatar_id, APT_CLASSIFIEDS, "avatarclassifiedsrequest"); } -void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props) -{ - if (!gAgent.isInitialized() || (gAgent.getID().isNull())) - { - LL_WARNS() << "Sending avatarinfo update DENIED - invalid agent" << LL_ENDL; - return; - } - - LL_WARNS() << "Sending avatarinfo update. This trims profile descriptions!!!" << LL_ENDL; - - // This value is required by sendAvatarPropertiesUpdate method. - //A profile should never be mature. (From the original code) - BOOL mature = FALSE; - - LLMessageSystem *msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_AvatarPropertiesUpdate); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - msg->nextBlockFast(_PREHASH_PropertiesData); - - msg->addUUIDFast(_PREHASH_ImageID, avatar_props->image_id); - msg->addUUIDFast(_PREHASH_FLImageID, avatar_props->fl_image_id); - msg->addStringFast(_PREHASH_AboutText, avatar_props->about_text); - msg->addStringFast(_PREHASH_FLAboutText, avatar_props->fl_about_text); - - msg->addBOOLFast(_PREHASH_AllowPublish, avatar_props->allow_publish); - msg->addBOOLFast(_PREHASH_MaturePublish, mature); - msg->addStringFast(_PREHASH_ProfileURL, avatar_props->profile_url); - - gAgent.sendReliableMessage(); -} - - - //static std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_data) { @@ -256,13 +202,13 @@ std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_ { return avatar_data->caption_text; } - static const std::array<const char*, 4> ACCT_TYPE{{ + const char* const ACCT_TYPE[] = { "AcctTypeResident", "AcctTypeTrial", "AcctTypeCharterMember", "AcctTypeEmployee" - }}; - U8 caption_max = (U8)ACCT_TYPE.size() - 1; + }; + U8 caption_max = (U8)LL_ARRAY_SIZE(ACCT_TYPE)-1; U8 caption_index = llclamp(avatar_data->caption_index, (U8)0, caption_max); return LLTrans::getString(ACCT_TYPE[caption_index]); } @@ -271,15 +217,21 @@ std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_ std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_data) { // Special accounts like M Linden don't have payment info revealed. - if (!avatar_data->caption_text.empty()) return ""; + if (!avatar_data->caption_text.empty()) + return ""; + + // Linden employees don't have payment info revealed + constexpr S32 LINDEN_EMPLOYEE_INDEX = 3; + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) + return ""; - BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED); - BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED); + bool transacted = (avatar_data->flags & AVATAR_TRANSACTED); + bool identified = (avatar_data->flags & AVATAR_IDENTIFIED); // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations //BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED); const char* payment_text; - if(transacted) + if (transacted) { payment_text = "PaymentInfoUsed"; } @@ -298,19 +250,22 @@ std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_ bool LLAvatarPropertiesProcessor::hasPaymentInfoOnFile(const LLAvatarData* avatar_data) { // Special accounts like M Linden don't have payment info revealed. - // M Linden? lol Who the fuck wrote this? A dinosaur? - if (!avatar_data->caption_text.empty()) return true; + if (!avatar_data->caption_text.empty()) + return true; // Linden employees don't have payment info revealed - //const S32 LINDEN_EMPLOYEE_INDEX = 3; - //if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return true; + constexpr S32 LINDEN_EMPLOYEE_INDEX = 3; + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) + return true; return ((avatar_data->flags & AVATAR_TRANSACTED) || (avatar_data->flags & AVATAR_IDENTIFIED)); } // static -void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id) +void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_url, LLUUID avatar_id, EAvatarProcessorType type) { + LLAvatarPropertiesProcessor& inst = instance(); + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestAvatarPropertiesCoro", httpPolicy)); @@ -320,105 +275,104 @@ void LLAvatarPropertiesProcessor::requestAvatarPropertiesCoro(std::string cap_ur LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); httpOpts->setFollowRedirects(true); - std::string finalUrl = cap_url + "/" + agent_id.asString(); + std::string finalUrl = cap_url + "/" + avatar_id.asString(); LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders); + // Response is being processed, no longer pending is required + inst.removePendingRequest(avatar_id, type); + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status || !result.has("id") - || agent_id != result["id"].asUUID()) + || avatar_id != result["id"].asUUID()) { - LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL; - LLAvatarPropertiesProcessor* self = getInstance(); - self->removePendingRequest(agent_id, APT_PROPERTIES); - self->removePendingRequest(agent_id, APT_INTERESTS); - self->removePendingRequest(agent_id, APT_PICKS); - self->removePendingRequest(agent_id, APT_GROUPS); - self->removePendingRequest(agent_id, APT_NOTES); + LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << avatar_id + << (!status ? " (no HTTP status)" : !result.has("id") ? " (no result.id)" : + std::string(" (result.id=") + result["id"].asUUID().asString() + ")") + << LL_ENDL; return; } - // Avatar Data - LLAvatarData avatar_data; + std::string birth_date; - avatar_data.agent_id = gAgent.getID(); - avatar_data.avatar_id = agent_id; + avatar_data.agent_id = gAgentID; + avatar_data.avatar_id = avatar_id; avatar_data.image_id = result["sl_image_id"].asUUID(); avatar_data.fl_image_id = result["fl_image_id"].asUUID(); avatar_data.partner_id = result["partner_id"].asUUID(); avatar_data.about_text = result["sl_about_text"].asString(); avatar_data.fl_about_text = result["fl_about_text"].asString(); avatar_data.born_on = result["member_since"].asDate(); - avatar_data.profile_url = result.has("home_page") ? result["home_page"].asString() : getProfileURL(agent_id.asString()); + // TODO: SL-20163 Remove the "has" check when SRV-684 is done + // and the field "hide_age" is included to the http response + inst.mIsHideAgeSupportedByServer = result.has("hide_age"); + avatar_data.hide_age = inst.isHideAgeSupportedByServer() && result["hide_age"].asBoolean(); + avatar_data.profile_url = getProfileURL(avatar_id.asString()); + avatar_data.customer_type = result["customer_type"].asString(); + avatar_data.notes = result["notes"].asString(); avatar_data.flags = 0; - avatar_data.caption_index = 0; - - LLAvatarPropertiesProcessor* self = getInstance(); - // Request processed, no longer pending - self->removePendingRequest(agent_id, APT_PROPERTIES); - self->notifyObservers(agent_id, &avatar_data, APT_PROPERTIES); - - // Picks - - LLSD picks_array = result["picks"]; - LLAvatarPicks avatar_picks; - avatar_picks.agent_id = gAgent.getID(); // Not in use? - avatar_picks.target_id = agent_id; - - for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) + if (result["online"].asBoolean()) { - const LLSD& pick_data = *it; - avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); + avatar_data.flags |= AVATAR_ONLINE; + } + if (result["allow_publish"].asBoolean()) + { + avatar_data.flags |= AVATAR_ALLOW_PUBLISH; + } + if (result["identified"].asBoolean()) + { + avatar_data.flags |= AVATAR_IDENTIFIED; + } + if (result["transacted"].asBoolean()) + { + avatar_data.flags |= AVATAR_TRANSACTED; } - // Request processed, no longer pending - self->removePendingRequest(agent_id, APT_PICKS); - self->notifyObservers(agent_id, &avatar_picks, APT_PICKS); + avatar_data.caption_index = 0; + if (result.has("charter_member")) // won't be present if "caption" is set + { + avatar_data.caption_index = result["charter_member"].asInteger(); + } + else if (result.has("caption")) + { + avatar_data.caption_text = result["caption"].asString(); + } // Groups - LLSD groups_array = result["groups"]; - LLAvatarGroups avatar_groups; - avatar_groups.agent_id = gAgent.getID(); // Not in use? - avatar_groups.avatar_id = agent_id; // target_id - for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it) { const LLSD& group_info = *it; - LLAvatarGroups::LLGroupData group_data; + LLAvatarData::LLGroupData group_data; group_data.group_powers = 0; // Not in use? group_data.group_title = group_info["name"].asString(); // Missing data, not in use? group_data.group_id = group_info["id"].asUUID(); group_data.group_name = group_info["name"].asString(); group_data.group_insignia_id = group_info["image_id"].asUUID(); - avatar_groups.group_list.push_back(group_data); + avatar_data.group_list.push_back(group_data); } - self->removePendingRequest(agent_id, APT_GROUPS); - self->notifyObservers(agent_id, &avatar_groups, APT_GROUPS); - - // Notes - LLAvatarNotes avatar_notes; - - avatar_notes.agent_id = gAgent.getID(); - avatar_notes.target_id = agent_id; - avatar_notes.notes = result["notes"].asString(); + // Picks + LLSD picks_array = result["picks"]; + for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) + { + const LLSD& pick_data = *it; + avatar_data.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); + } - // Request processed, no longer pending - self->removePendingRequest(agent_id, APT_NOTES); - self->notifyObservers(agent_id, &avatar_notes, APT_NOTES); + inst.notifyObservers(avatar_id, &avatar_data, type); } -void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**) +void LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**) { - LLAvatarData avatar_data; + LLAvatarLegacyData avatar_data; std::string birth_date; msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, avatar_data.agent_id); @@ -429,64 +383,57 @@ void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_AboutText, avatar_data.about_text); msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_FLAboutText, avatar_data.fl_about_text); msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_BornOn, birth_date); - msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_ProfileURL, avatar_data.profile_url); + msg->getString( _PREHASH_PropertiesData, _PREHASH_ProfileURL, avatar_data.profile_url); msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_Flags, avatar_data.flags); - LLDateUtil::dateFromPDTString(avatar_data.born_on, birth_date); avatar_data.caption_index = 0; S32 charter_member_size = 0; - charter_member_size = msg->getSizeFast(_PREHASH_PropertiesData, _PREHASH_CharterMember); - if(1 == charter_member_size) + charter_member_size = msg->getSize(_PREHASH_PropertiesData, _PREHASH_CharterMember); + if (1 == charter_member_size) { - msg->getBinaryDataFast(_PREHASH_PropertiesData, _PREHASH_CharterMember, &avatar_data.caption_index, 1); + msg->getBinaryData(_PREHASH_PropertiesData, _PREHASH_CharterMember, &avatar_data.caption_index, 1); } - else if(1 < charter_member_size) + else if (1 < charter_member_size) { - msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text); + msg->getString(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text); } LLAvatarPropertiesProcessor* self = getInstance(); // Request processed, no longer pending - self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES); - self->notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES); + self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES_LEGACY); + self->notifyObservers(avatar_data.avatar_id, &avatar_data, APT_PROPERTIES_LEGACY); } void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* msg, void**) { - LLAvatarInterests interests; - - msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, interests.agent_id); - msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AvatarID, interests.avatar_id); - msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_WantToMask, interests.want_to_mask); - msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_WantToText, interests.want_to_text); - msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_SkillsMask, interests.skills_mask); - msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_SkillsText, interests.skills_text); - msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_LanguagesText, interests.languages_text); - - LLAvatarPropertiesProcessor* self = getInstance(); - // Request processed, no longer pending - self->removePendingRequest(interests.avatar_id, APT_INTERESTS); - self->notifyObservers(interests.avatar_id, &interests, APT_INTERESTS); +/* + AvatarInterestsReply is automatically sent by the server in response to the + AvatarPropertiesRequest (in addition to the AvatarPropertiesReply message). + If the interests panel is no longer part of the design (?) we should just register the message + to a handler function that does nothing. + That will suppress the warnings and be compatible with old server versions. + WARNING: LLTemplateMessageReader::decodeData: Message from 216.82.37.237:13000 with no handler function received: AvatarInterestsReply +*/ } void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**) { LLAvatarClassifieds classifieds; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, classifieds.agent_id); - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TargetID, classifieds.target_id); + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, classifieds.agent_id); + msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, classifieds.target_id); - S32 block_count = msg->getNumberOfBlocksFast(_PREHASH_Data); + S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data); for(int n = 0; n < block_count; ++n) { LLAvatarClassifieds::classified_data data; - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, data.name, n); + msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n); + msg->getString(_PREHASH_Data, _PREHASH_Name, data.name, n); - classifieds.classifieds_list.push_back(data); + classifieds.classifieds_list.emplace_back(data); } LLAvatarPropertiesProcessor* self = getInstance(); @@ -499,66 +446,46 @@ void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* ms { LLAvatarClassifiedInfo c_info; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, c_info.agent_id); - - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ClassifiedID, c_info.classified_id); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_CreatorID, c_info.creator_id); - msg->getU32Fast(_PREHASH_Data, _PREHASH_CreationDate, c_info.creation_date); - msg->getU32Fast(_PREHASH_Data, _PREHASH_ExpirationDate, c_info.expiration_date); - msg->getU32Fast(_PREHASH_Data, _PREHASH_Category, c_info.category); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, c_info.name); - msg->getStringFast(_PREHASH_Data, _PREHASH_Desc, c_info.description); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ParcelID, c_info.parcel_id); - msg->getU32Fast(_PREHASH_Data, _PREHASH_ParentEstate, c_info.parent_estate); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_SnapshotID, c_info.snapshot_id); - msg->getStringFast(_PREHASH_Data, _PREHASH_SimName, c_info.sim_name); - msg->getVector3dFast(_PREHASH_Data, _PREHASH_PosGlobal, c_info.pos_global); - msg->getStringFast(_PREHASH_Data, _PREHASH_ParcelName, c_info.parcel_name); - msg->getU8Fast(_PREHASH_Data, _PREHASH_ClassifiedFlags, c_info.flags); - msg->getS32Fast(_PREHASH_Data, _PREHASH_PriceForListing, c_info.price_for_listing); + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, c_info.agent_id); + + msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, c_info.classified_id); + msg->getUUID(_PREHASH_Data, _PREHASH_CreatorID, c_info.creator_id); + msg->getU32(_PREHASH_Data, _PREHASH_CreationDate, c_info.creation_date); + msg->getU32(_PREHASH_Data, _PREHASH_ExpirationDate, c_info.expiration_date); + msg->getU32(_PREHASH_Data, _PREHASH_Category, c_info.category); + msg->getString(_PREHASH_Data, _PREHASH_Name, c_info.name); + msg->getString(_PREHASH_Data, _PREHASH_Desc, c_info.description); + msg->getUUID(_PREHASH_Data, _PREHASH_ParcelID, c_info.parcel_id); + msg->getU32(_PREHASH_Data, _PREHASH_ParentEstate, c_info.parent_estate); + msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, c_info.snapshot_id); + msg->getString(_PREHASH_Data, _PREHASH_SimName, c_info.sim_name); + msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, c_info.pos_global); + msg->getString(_PREHASH_Data, _PREHASH_ParcelName, c_info.parcel_name); + msg->getU8(_PREHASH_Data, _PREHASH_ClassifiedFlags, c_info.flags); + msg->getS32(_PREHASH_Data, _PREHASH_PriceForListing, c_info.price_for_listing); LLAvatarPropertiesProcessor* self = getInstance(); // Request processed, no longer pending self->removePendingRequest(c_info.creator_id, APT_CLASSIFIED_INFO); self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO); + self->removePendingRequest(c_info.classified_id, APT_CLASSIFIED_INFO); + self->notifyObservers(c_info.classified_id, &c_info, APT_CLASSIFIED_INFO); } void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**) { - LLAvatarNotes avatar_notes; - - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_notes.agent_id); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_TargetID, avatar_notes.target_id); - msg->getStringFast(_PREHASH_Data, _PREHASH_Notes, avatar_notes.notes); - - LLAvatarPropertiesProcessor* self = getInstance(); - // Request processed, no longer pending - self->removePendingRequest(avatar_notes.target_id, APT_NOTES); - self->notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES); + // Deprecated, new "AgentProfile" allows larger notes } void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**) { - LLAvatarPicks avatar_picks; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.agent_id); - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TargetID, avatar_picks.target_id); + LLUUID agent_id; + LLUUID target_id; + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, target_id); - S32 block_count = msg->getNumberOfBlocksFast(_PREHASH_Data); - for (int block = 0; block < block_count; ++block) - { - LLUUID pick_id; - std::string pick_name; - - msg->getUUIDFast(_PREHASH_Data, _PREHASH_PickID, pick_id, block); - msg->getStringFast(_PREHASH_Data, _PREHASH_PickName, pick_name, block); - - avatar_picks.picks_list.push_back(std::make_pair(pick_id,pick_name)); - } - LLAvatarPropertiesProcessor* self = getInstance(); - // Request processed, no longer pending - self->removePendingRequest(avatar_picks.target_id, APT_PICKS); - self->notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS); + LL_DEBUGS("AvatarProperties") << "Received AvatarPicksReply for " << target_id << LL_ENDL; } void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, void**) @@ -567,24 +494,24 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi // Extract the agent id and verify the message is for this // client. - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, pick_data.agent_id ); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_PickID, pick_data.pick_id); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_CreatorID, pick_data.creator_id); + msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, pick_data.agent_id ); + msg->getUUID(_PREHASH_Data, _PREHASH_PickID, pick_data.pick_id); + msg->getUUID(_PREHASH_Data, _PREHASH_CreatorID, pick_data.creator_id); // ** top_pick should be deleted, not being used anymore - angela - msg->getBOOLFast(_PREHASH_Data, _PREHASH_TopPick, pick_data.top_pick); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_ParcelID, pick_data.parcel_id); - msg->getStringFast(_PREHASH_Data, _PREHASH_Name, pick_data.name); - msg->getStringFast(_PREHASH_Data, _PREHASH_Desc, pick_data.desc); - msg->getUUIDFast(_PREHASH_Data, _PREHASH_SnapshotID, pick_data.snapshot_id); + msg->getBOOL(_PREHASH_Data, _PREHASH_TopPick, pick_data.top_pick); + msg->getUUID(_PREHASH_Data, _PREHASH_ParcelID, pick_data.parcel_id); + msg->getString(_PREHASH_Data, _PREHASH_Name, pick_data.name); + msg->getString(_PREHASH_Data, _PREHASH_Desc, pick_data.desc); + msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, pick_data.snapshot_id); - msg->getStringFast(_PREHASH_Data, _PREHASH_User, pick_data.user_name); - msg->getStringFast(_PREHASH_Data, _PREHASH_OriginalName, pick_data.original_name); - msg->getStringFast(_PREHASH_Data, _PREHASH_SimName, pick_data.sim_name); - msg->getVector3dFast(_PREHASH_Data, _PREHASH_PosGlobal, pick_data.pos_global); + msg->getString(_PREHASH_Data, _PREHASH_User, pick_data.user_name); + msg->getString(_PREHASH_Data, _PREHASH_OriginalName, pick_data.original_name); + msg->getString(_PREHASH_Data, _PREHASH_SimName, pick_data.sim_name); + msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, pick_data.pos_global); - msg->getS32Fast(_PREHASH_Data, _PREHASH_SortOrder, pick_data.sort_order); - msg->getBOOLFast(_PREHASH_Data, _PREHASH_Enabled, pick_data.enabled); + msg->getS32(_PREHASH_Data, _PREHASH_SortOrder, pick_data.sort_order); + msg->getBOOL(_PREHASH_Data, _PREHASH_Enabled, pick_data.enabled); LLAvatarPropertiesProcessor* self = getInstance(); // don't need to remove pending request as we don't track pick info @@ -593,44 +520,30 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, void**) { - LLAvatarGroups avatar_groups; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_groups.agent_id ); - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_groups.avatar_id ); - - S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData); - for(S32 i = 0; i < group_count; ++i) - { - LLAvatarGroups::LLGroupData group_data; - - msg->getU64Fast( _PREHASH_GroupData, _PREHASH_GroupPowers, group_data.group_powers, i ); - msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupTitle, group_data.group_title, i ); - msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupID, group_data.group_id, i); - msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group_data.group_name, i ); - msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupInsigniaID, group_data.group_insignia_id, i ); + /* + AvatarGroupsReply is automatically sent by the server in response to the + AvatarPropertiesRequest in addition to the AvatarPropertiesReply message. + */ + LLUUID agent_id; + LLUUID avatar_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id); - avatar_groups.group_list.push_back(group_data); - } - - LLAvatarPropertiesProcessor* self = getInstance(); - self->removePendingRequest(avatar_groups.avatar_id, APT_GROUPS); - self->notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS); + LL_DEBUGS("AvatarProperties") << "Received AvatarGroupsReply for " << avatar_id << LL_ENDL; } -void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type) +void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id, void* data, EAvatarProcessorType type) { // Copy the map (because observers may delete themselves when updated?) LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers; - observer_multimap_t::iterator oi = observers.begin(); - observer_multimap_t::iterator end = observers.end(); - for (; oi != end; ++oi) + for (const auto& [agent_id, observer] : observers) { // only notify observers for the same agent, or if the observer // didn't know the agent ID and passed a NULL id. - const LLUUID &agent_id = oi->first; if (agent_id == id || agent_id.isNull()) { - oi->second->processProperties(data,type); + observer->processProperties(data, type); } } } @@ -644,47 +557,26 @@ void LLAvatarPropertiesProcessor::sendFriendRights(const LLUUID& avatar_id, S32 // setup message header msg->newMessageFast(_PREHASH_GrantUserRights); msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUID(_PREHASH_AgentID, gAgentID); + msg->addUUID(_PREHASH_SessionID, gAgentSessionID); msg->nextBlockFast(_PREHASH_Rights); - msg->addUUIDFast(_PREHASH_AgentRelated, avatar_id); - msg->addS32Fast(_PREHASH_RelatedRights, rights); + msg->addUUID(_PREHASH_AgentRelated, avatar_id); + msg->addS32(_PREHASH_RelatedRights, rights); gAgent.sendReliableMessage(); } } -void LLAvatarPropertiesProcessor::sendNotes(const LLUUID& avatar_id, const std::string& notes) -{ - if(!avatar_id.isNull()) - { - LLMessageSystem* msg = gMessageSystem; - - // setup message header - msg->newMessageFast(_PREHASH_AvatarNotesUpdate); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_Data); - msg->addUUIDFast(_PREHASH_TargetID, avatar_id); - msg->addStringFast(_PREHASH_Notes, notes); - - gAgent.sendReliableMessage(); - } -} - - void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id ) { LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_PickDelete); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Data); - msg->addUUIDFast(_PREHASH_PickID, pick_id); + msg->newMessage(_PREHASH_PickDelete); + msg->nextBlock(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgentID); + msg->addUUID(_PREHASH_SessionID, gAgentSessionID); + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_PickID, pick_id); gAgent.sendReliableMessage(); LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); @@ -695,47 +587,48 @@ void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_ { LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ClassifiedDelete); + msg->newMessage(_PREHASH_ClassifiedDelete); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlock(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgentID); + msg->addUUID(_PREHASH_SessionID, gAgentSessionID); - msg->nextBlockFast(_PREHASH_Data); - msg->addUUIDFast(_PREHASH_ClassifiedID, classified_id); + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_ClassifiedID, classified_id); gAgent.sendReliableMessage(); } void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick) { - if (!new_pick) return; + if (!new_pick) + return; LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_PickInfoUpdate); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->newMessage(_PREHASH_PickInfoUpdate); + msg->nextBlock(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgentID); + msg->addUUID(_PREHASH_SessionID, gAgentSessionID); - msg->nextBlockFast(_PREHASH_Data); - msg->addUUIDFast(_PREHASH_PickID, new_pick->pick_id); - msg->addUUIDFast(_PREHASH_CreatorID, new_pick->creator_id); + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_PickID, new_pick->pick_id); + msg->addUUID(_PREHASH_CreatorID, new_pick->creator_id); //legacy var need to be deleted - msg->addBOOLFast(_PREHASH_TopPick, FALSE); + msg->addBOOL(_PREHASH_TopPick, FALSE); // fills in on simulator if null - msg->addUUIDFast(_PREHASH_ParcelID, new_pick->parcel_id); - msg->addStringFast(_PREHASH_Name, new_pick->name); - msg->addStringFast(_PREHASH_Desc, new_pick->desc); - msg->addUUIDFast(_PREHASH_SnapshotID, new_pick->snapshot_id); - msg->addVector3dFast(_PREHASH_PosGlobal, new_pick->pos_global); + msg->addUUID(_PREHASH_ParcelID, new_pick->parcel_id); + msg->addString(_PREHASH_Name, new_pick->name); + msg->addString(_PREHASH_Desc, new_pick->desc); + msg->addUUID(_PREHASH_SnapshotID, new_pick->snapshot_id); + msg->addVector3d(_PREHASH_PosGlobal, new_pick->pos_global); // Only top picks have a sort order - msg->addS32Fast(_PREHASH_SortOrder, 0); + msg->addS32(_PREHASH_SortOrder, 0); - msg->addBOOLFast(_PREHASH_Enabled, new_pick->enabled); + msg->addBOOL(_PREHASH_Enabled, new_pick->enabled); gAgent.sendReliableMessage(); LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); @@ -750,43 +643,23 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassif LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ClassifiedInfoUpdate); + msg->newMessage(_PREHASH_ClassifiedInfoUpdate); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_Data); - msg->addUUIDFast(_PREHASH_ClassifiedID, c_data->classified_id); - msg->addU32Fast(_PREHASH_Category, c_data->category); - msg->addStringFast(_PREHASH_Name, c_data->name); - msg->addStringFast(_PREHASH_Desc, c_data->description); - msg->addUUIDFast(_PREHASH_ParcelID, c_data->parcel_id); - msg->addU32Fast(_PREHASH_ParentEstate, 0); - msg->addUUIDFast(_PREHASH_SnapshotID, c_data->snapshot_id); - msg->addVector3dFast(_PREHASH_PosGlobal, c_data->pos_global); - msg->addU8Fast(_PREHASH_ClassifiedFlags, c_data->flags); - msg->addS32Fast(_PREHASH_PriceForListing, c_data->price_for_listing); + msg->nextBlock(_PREHASH_AgentData); + msg->addUUID(_PREHASH_AgentID, gAgentID); + msg->addUUID(_PREHASH_SessionID, gAgentSessionID); - gAgent.sendReliableMessage(); -} - -void LLAvatarPropertiesProcessor::sendInterestsUpdate(const LLAvatarInterests* i_data) -{ - if(!i_data) return; - - LLMessageSystem* msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_AvatarInterestsUpdate); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast( _PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast( _PREHASH_PropertiesData); - msg->addU32Fast( _PREHASH_WantToMask, i_data->want_to_mask); - msg->addStringFast( _PREHASH_WantToText, i_data->want_to_text); - msg->addU32Fast( _PREHASH_SkillsMask, i_data->skills_mask); - msg->addStringFast( _PREHASH_SkillsText, i_data->skills_text); - msg->addStringFast( _PREHASH_LanguagesText, i_data->languages_text); + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_ClassifiedID, c_data->classified_id); + msg->addU32(_PREHASH_Category, c_data->category); + msg->addString(_PREHASH_Name, c_data->name); + msg->addString(_PREHASH_Desc, c_data->description); + msg->addUUID(_PREHASH_ParcelID, c_data->parcel_id); + msg->addU32(_PREHASH_ParentEstate, 0); + msg->addUUID(_PREHASH_SnapshotID, c_data->snapshot_id); + msg->addVector3d(_PREHASH_PosGlobal, c_data->pos_global); + msg->addU8(_PREHASH_ClassifiedFlags, c_data->flags); + msg->addS32(_PREHASH_PriceForListing, c_data->price_for_listing); gAgent.sendReliableMessage(); } @@ -795,9 +668,7 @@ void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, { // Must ask for a pick based on the creator id because // the pick database is distributed to the inventory cluster. JC - std::vector<std::string> request_params; - request_params.push_back(creator_id.asString() ); - request_params.push_back(pick_id.asString() ); + std::vector<std::string> request_params{ creator_id.asString(), pick_id.asString() }; send_generic_message("pickinforequest", request_params); } @@ -805,14 +676,14 @@ void LLAvatarPropertiesProcessor::sendClassifiedInfoRequest(const LLUUID& classi { LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ClassifiedInfoRequest); - msg->nextBlockFast(_PREHASH_AgentData); + msg->newMessage(_PREHASH_ClassifiedInfoRequest); + msg->nextBlock(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUID(_PREHASH_AgentID, gAgentID); + msg->addUUID(_PREHASH_SessionID, gAgentSessionID); - msg->nextBlockFast(_PREHASH_Data); - msg->addUUIDFast(_PREHASH_ClassifiedID, classified_id); + msg->nextBlock(_PREHASH_Data); + msg->addUUID(_PREHASH_ClassifiedID, classified_id); gAgent.sendReliableMessage(); } @@ -826,7 +697,7 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva if (it == mRequestTimestamps.end()) return false; // We found a request, check if it has timed out - U32 now = time(NULL); + U32 now = time(nullptr); const U32 REQUEST_EXPIRE_SECS = 5; U32 expires = it->second + REQUEST_EXPIRE_SECS; @@ -840,7 +711,7 @@ bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAva void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type) { timestamp_map_t::key_type key = std::make_pair(avatar_id, type); - U32 now = time(NULL); + U32 now = time(nullptr); // Add or update existing (expired) request mRequestTimestamps[ key ] = now; } diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index e4a0f0588124769f10bbd30a7c22b27680a45b26..c73cc69e624f1921a0039fd3d6b1b0213c1560ca 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -50,18 +50,23 @@ class LLMessageSystem; enum EAvatarProcessorType { - APT_PROPERTIES, + APT_PROPERTIES_LEGACY, // APT_PROPERTIES via udp request (Truncates data!!!) + APT_PROPERTIES, // APT_PROPERTIES via http request APT_NOTES, APT_GROUPS, APT_PICKS, APT_PICK_INFO, APT_TEXTURES, - APT_INTERESTS, APT_CLASSIFIEDS, APT_CLASSIFIED_INFO }; -struct LLAvatarData +// legacy data is supposed to match AvatarPropertiesReply, +// but it is obsolete, fields like about_text will truncate +// data, if you need them, use AgenProfile cap. +// Todo: remove it once once icon ids get moved elsewhere, +// since AgentProfile is too large for bulk icon requests +struct LLAvatarLegacyData { LLUUID agent_id; LLUUID avatar_id; //target id @@ -76,17 +81,61 @@ struct LLAvatarData std::string caption_text; std::string customer_type; U32 flags; - BOOL allow_publish; }; -struct LLAvatarPicks +struct LLAvatarData { - LLUUID agent_id; - LLUUID target_id; //target id + LLUUID agent_id; + LLUUID avatar_id; //target id + LLUUID image_id; + LLUUID fl_image_id; + LLUUID partner_id; + std::string about_text; + std::string fl_about_text; + LLDate born_on; + std::string profile_url; + U8 caption_index; + std::string caption_text; + std::string customer_type; + U32 flags; + bool hide_age; + std::string notes; - typedef std::pair<LLUUID,std::string> pick_data_t; + struct LLGroupData; + typedef std::list<LLGroupData> group_list_t; + group_list_t group_list; + + typedef std::pair<LLUUID, std::string> pick_data_t; typedef std::list< pick_data_t> picks_list_t; picks_list_t picks_list; + BOOL allow_publish; + LLAvatarData() = default; + LLAvatarData(const LLAvatarLegacyData& legacy_data) + { + agent_id = legacy_data.agent_id; + avatar_id = legacy_data.avatar_id; + image_id = legacy_data.image_id; + fl_image_id = legacy_data.fl_image_id; + partner_id = legacy_data.partner_id; + about_text = legacy_data.about_text; + fl_about_text = legacy_data.fl_about_text; + born_on = legacy_data.born_on; + profile_url = legacy_data.profile_url; + caption_index = legacy_data.caption_index; + caption_text = legacy_data.caption_text; + customer_type = legacy_data.customer_type; + flags = legacy_data.flags; + } +}; + +struct LLAvatarData::LLGroupData +{ + U64 group_powers; + BOOL accept_notices; + std::string group_title; + LLUUID group_id; + std::string group_name; + LLUUID group_insignia_id; }; struct LLPickData @@ -110,7 +159,16 @@ struct LLPickData //used only in write (update) requests LLUUID session_id; +}; +struct LLAvatarPicks +{ + LLUUID agent_id; + LLUUID target_id; //target id + + typedef std::pair<LLUUID,std::string> pick_data_t; + typedef std::list< pick_data_t> picks_list_t; + picks_list_t picks_list; }; struct LLAvatarNotes @@ -179,25 +237,14 @@ struct LLAvatarClassifiedInfo S32 price_for_listing; }; -struct LLAvatarInterests -{ - LLUUID agent_id; - LLUUID avatar_id; //target id - U32 want_to_mask; - std::string want_to_text; - U32 skills_mask; - std::string skills_text; - std::string languages_text; -}; - class LLAvatarPropertiesObserver { public: - virtual ~LLAvatarPropertiesObserver() = default; + virtual ~LLAvatarPropertiesObserver() {} virtual void processProperties(void* data, EAvatarProcessorType type) = 0; }; -class LLAvatarPropertiesProcessor final +class LLAvatarPropertiesProcessor : public LLSingleton<LLAvatarPropertiesProcessor> { LLSINGLETON(LLAvatarPropertiesProcessor); @@ -211,9 +258,7 @@ class LLAvatarPropertiesProcessor final // Request various types of avatar data. Duplicate requests will be // suppressed while waiting for a response from the network. void sendAvatarPropertiesRequest(const LLUUID& avatar_id); - void sendAvatarPicksRequest(const LLUUID& avatar_id); - void sendAvatarNotesRequest(const LLUUID& avatar_id); - void sendAvatarGroupsRequest(const LLUUID& avatar_id); + void sendAvatarLegacyPropertiesRequest(const LLUUID& avatar_id); void sendAvatarTexturesRequest(const LLUUID& avatar_id); void sendAvatarClassifiedsRequest(const LLUUID& avatar_id); @@ -222,22 +267,18 @@ class LLAvatarPropertiesProcessor final void sendClassifiedInfoRequest(const LLUUID& classified_id); - void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props); - void sendPickInfoUpdate(const LLPickData* new_pick); void sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data); - void sendInterestsUpdate(const LLAvatarInterests* i_data); - void sendFriendRights(const LLUUID& avatar_id, S32 rights); - void sendNotes(const LLUUID& avatar_id, const std::string& notes); - void sendPickDelete(const LLUUID& pick_id); void sendClassifiedDelete(const LLUUID& classified_id); + bool isHideAgeSupportedByServer() { return mIsHideAgeSupportedByServer; } + // Returns translated, human readable string for account type, such // as "Resident" or "Linden Employee". Used for profiles, inspectors. static std::string accountType(const LLAvatarData* avatar_data); @@ -249,9 +290,10 @@ class LLAvatarPropertiesProcessor final static bool hasPaymentInfoOnFile(const LLAvatarData* avatar_data); - static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID agent_id); + static void requestAvatarPropertiesCoro(std::string cap_url, LLUUID avatar_id, EAvatarProcessorType type); - static void processAvatarPropertiesReply(LLMessageSystem* msg, void**); + // Processing of UDP variant of properties, truncates certain fields! + static void processAvatarLegacyPropertiesReply(LLMessageSystem* msg, void**); static void processAvatarInterestsReply(LLMessageSystem* msg, void**); @@ -272,7 +314,7 @@ class LLAvatarPropertiesProcessor final void sendRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method); void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string &method); void sendAvatarPropertiesRequestMessage(const LLUUID& avatar_id); - void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url); + void initAgentProfileCapRequest(const LLUUID& avatar_id, const std::string& cap_url, EAvatarProcessorType type); void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type); @@ -302,6 +344,9 @@ class LLAvatarPropertiesProcessor final // Map avatar_id+request_type -> U32 timestamp in seconds typedef std::map< std::pair<LLUUID, EAvatarProcessorType>, U32> timestamp_map_t; timestamp_map_t mRequestTimestamps; + + // Is returned by isHideAgeSupportedByServer() + bool mIsHideAgeSupportedByServer { false }; }; #endif // LL_LLAVATARPROPERTIESPROCESSOR_H diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 2921152c1475b973f06f50eb8454fbdf405c035a..af0c8ce7ecd761f3104477c6497ee8fe86202e0f 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -89,7 +89,7 @@ LLScreenChannel* LLChannelManager::createNotificationChannel() { // creating params for a channel LLScreenChannelBase::Params p; - p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID")); + p.id = NOTIFICATION_CHANNEL_UUID; p.channel_align = CA_RIGHT; p.toast_align = NA_TOP; @@ -109,7 +109,7 @@ void LLChannelManager::onLoginCompleted() if (!channel) continue; // don't calc notifications for Nearby Chat - if(channel->getChannelID() == LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))) + if(channel->getChannelID() == NEARBY_CHAT_CHANNEL_UUID) { continue; } @@ -131,7 +131,7 @@ void LLChannelManager::onLoginCompleted() { // create a channel for the StartUp Toast LLScreenChannelBase::Params p; - p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID")); + p.id = STARTUP_CHANNEL_UUID; p.channel_align = CA_RIGHT; mStartUpChannel = createChannel(p); @@ -145,8 +145,7 @@ void LLChannelManager::onLoginCompleted() // init channel's position and size S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound); + mStartUpChannel->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound); if (gSkinSettings.getBool("LegacyNotificationWell")) { mStartUpChannel->setMouseDownCallback(boost::bind(&LLLegacyNotificationWellWindow::onStartUpToastClick, @@ -173,7 +172,7 @@ void LLChannelManager::onStartUpToastClose() { mStartUpChannel->setVisible(FALSE); mStartUpChannel->closeStartUpToast(); - removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID"))); + removeChannelByID(STARTUP_CHANNEL_UUID); mStartUpChannel = NULL; } @@ -267,12 +266,12 @@ LLNotificationsUI::LLScreenChannel* LLChannelManager::getNotificationScreenChann { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + findChannelByID(NOTIFICATION_CHANNEL_UUID)); if (channel == NULL) { - LL_WARNS() << "Can't find screen channel by NotificationChannelUUID" << LL_ENDL; - llassert(!"Can't find screen channel by NotificationChannelUUID"); + LL_WARNS() << "Can't find screen channel by Notification Channel UUID" << LL_ENDL; + llassert(!"Can't find screen channel by Notification Channel UUID"); } return channel; diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 67090772fd2fc7769597a233e89b8ffefb40661c..c43864d85f1528c3867a60a69b12ad80b7683294 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -142,7 +142,7 @@ class CofAttachmentContextMenu : public CofContextMenu registrar.add("Attachment.Touch", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs)); registrar.add("Attachment.Edit", boost::bind(handleMultiple, handle_item_edit, mUUIDs)); - registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); + registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op)); LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; enable_registrar.add("Attachment.OnEnable", boost::bind(&CofAttachmentContextMenu::onEnable, this, _2)); @@ -195,7 +195,7 @@ class CofClothingContextMenu : public CofContextMenu LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; LLUUID selected_id = mUUIDs.back(); - registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); + registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op)); registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id)); registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id)); diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 56be87865ed33e3011ce76ecf7516078475063fd..e1f2fd513733639c4cf5809ef3dfbab46c4ce1f1 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -70,6 +70,7 @@ namespace { const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue"); + const F32 QUEUE_INVENTORY_FETCH_TIMEOUT = 300.f; // ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged // callback mechanism and the LLEventPump coroutine architecture allowing the @@ -376,8 +377,6 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. // which is caught in objectScriptProcessingQueueCoro bool monocompile = floater->mMono; - F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout"); - // Initial test to see if we can (or should) attempt to compile the script. LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory); @@ -403,7 +402,7 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat LLExperienceCache::instance().fetchAssociatedExperience(inventory->getParentUUID(), inventory->getUUID(), boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1)); - result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, + result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true))); } else @@ -467,7 +466,7 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat &LLFloaterCompileQueue::handleScriptRetrieval, &userData); - result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, + result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true))); } @@ -519,7 +518,7 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); } - result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSDMap("timeout", LLSD::Boolean(true))); + result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true))); floater.check(); @@ -823,8 +822,6 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. // This is expected if the dialog closes. LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true); - F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout"); - try { @@ -846,7 +843,7 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L args["[OBJECT_NAME]"] = (*itObj).mObjectName; floater->addStringMessage(floater->getString("LoadingObjInv", args)); - LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout, + LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true))); if (result.has("timeout")) diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 07b8ac9e0f57eaf7131dde77c2ffe95247e14389..d42881bcdd5c7b02dbe81d6ef8a54a0da60e95eb 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -131,9 +131,9 @@ void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_ { LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents); F32 offset_dist = pos_box_offset.length(); - if (offset_dist > max_legal_offset && offset_dist > 0.f) + if (offset_dist > MAX_LEGAL_OFFSET && offset_dist > 0.f) { - F32 target_dist = (offset_dist - max_legal_offset); + F32 target_dist = (offset_dist - MAX_LEGAL_OFFSET); new_pos_fixup = (target_dist/offset_dist)*pos_box_offset; } #ifdef SHOW_DEBUG @@ -148,12 +148,12 @@ void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_ } #endif } - if (box_size/mScaleConstraintFixup > max_legal_size) + if (box_size/mScaleConstraintFixup > MAX_LEGAL_SIZE) { - new_scale_fixup = mScaleConstraintFixup*max_legal_size/box_size; + new_scale_fixup = mScaleConstraintFixup* MAX_LEGAL_SIZE /box_size; #ifdef SHOW_DEBUG LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup " - << mScaleConstraintFixup << " max legal " << max_legal_size + << mScaleConstraintFixup << " max legal " << MAX_LEGAL_SIZE << " -> new scale " << new_scale_fixup << LL_ENDL; #endif } @@ -179,8 +179,6 @@ void LLControlAvatar::matchVolumeTransform() mPositionConstraintFixup = new_pos_fixup; mScaleConstraintFixup = new_scale_fixup; - static const LLCachedControl<F32> global_scale(gSavedSettings, "AnimatedObjectsGlobalScale"); - if (mRootVolp->isAttachment()) { LLVOAvatar *attached_av = getAttachedAvatar(); @@ -201,7 +199,7 @@ void LLControlAvatar::matchVolumeTransform() mRoot->setWorldRotation(obj_rot * joint_rot); setRotation(mRoot->getRotation()); - setGlobalScale(global_scale * mScaleConstraintFixup); + setGlobalScale(mScaleConstraintFixup); } else { @@ -253,7 +251,7 @@ void LLControlAvatar::matchVolumeTransform() } mRoot->setPosition(vol_pos + mPositionConstraintFixup); - setGlobalScale(global_scale * mScaleConstraintFixup); + setGlobalScale(mScaleConstraintFixup); } } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 842788e0cd68a596ac45211c7c630a0f556aea23..43a97381560dfb4d9f109c163c08eac7f769a4ba 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -82,7 +82,7 @@ class LLConversationItem : public LLFolderViewModelItemCommon virtual BOOL isItemRenameable() const { return TRUE; } virtual BOOL renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return TRUE; } virtual BOOL isItemMovable( void ) const { return FALSE; } - virtual BOOL isItemRemovable( void ) const { return FALSE; } + virtual BOOL isItemRemovable(bool check_worn = true) const { return FALSE; } virtual BOOL isItemInTrash( void) const { return FALSE; } virtual BOOL removeItem() { return FALSE; } virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 706f4e20cf4f69d9cd89dd49584a430d11a85df1..4509acf99eb58ab2a90acea85d4b8729c34a0bed 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -106,6 +106,8 @@ LLConversationViewSession::~LLConversationViewSession() } mFlashTimer->unset(); + delete mFlashTimer; + mFlashStateOn = false; } void LLConversationViewSession::destroyView() diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 7081198d89e6ac8c9706629cac97a563399db8f7..dcd414292dc2df036661738c3a6690747a638d06 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -2085,7 +2085,7 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ { LL_WARNS("ENVIRONMENT") << "Couldn't retrieve environment settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; } - else if (LLApp::isExiting()) + else if (LLApp::isExiting() || gDisconnected) { return; } diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 41c81c1730f8a92c0fe364ecf46c3598ff3289fa..394ab9e17c0246575b744cb4f53824d259e7f79f 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -243,6 +243,12 @@ LLExpandableTextBox::LLExpandableTextBox(const Params& p) mTextBox->setCommitCallback(boost::bind(&LLExpandableTextBox::onExpandClicked, this)); } + +LLExpandableTextBox::~LLExpandableTextBox() +{ + gViewerWindow->removePopup(this); +} + void LLExpandableTextBox::draw() { if(mBGVisible && !mExpanded) diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h index bac9d9fe6e49ae55961a384d822fc21bbc9481c6..63283b6fe0093e0ab763effc0f2bb0ab6cf5f207 100644 --- a/indra/newview/llexpandabletextbox.h +++ b/indra/newview/llexpandabletextbox.h @@ -121,7 +121,7 @@ class LLExpandableTextBox final : public LLUICtrl /** * Returns text */ - virtual std::string getText() const { return mText; } + virtual const std::string& getText() const { return mText; } /** * Sets text @@ -154,6 +154,8 @@ class LLExpandableTextBox final : public LLUICtrl */ /*virtual*/ void draw(); + virtual ~LLExpandableTextBox(); + protected: LLExpandableTextBox(const Params& p); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 41e47878871d58877bdd18221c1f99d65cca79bf..36adfac185c9d05ef69368377849d07cb037ca87 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -1070,6 +1070,9 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF switch(filter) { case FFLOAD_ALL: + case FFLOAD_EXE: + allowedv->emplace_back("app"); + allowedv->emplace_back("exe"); allowedv->emplace_back("wav"); allowedv->emplace_back("bvh"); allowedv->emplace_back("anim"); @@ -1091,9 +1094,6 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF allowedv->emplace_back("png"); allowedv->emplace_back("webp"); break; - case FFLOAD_EXE: - allowedv->emplace_back("app"); - allowedv->emplace_back("exe"); break; case FFLOAD_WAV: allowedv->emplace_back("wav"); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index eb0691ebef09dfece25594e7e3c90da40efa65f8..4eaa01f4ec8f29c8e695ea45249b9a771464d0ba 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -111,15 +111,11 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key) mCloseOnSelect(FALSE), mExcludeAgentFromSearchResults(FALSE), mContextConeOpacity (0.f), - mContextConeInAlpha(0.f), - mContextConeOutAlpha(0.f), - mContextConeFadeTime(0.f) + mContextConeInAlpha(CONTEXT_CONE_IN_ALPHA), + mContextConeOutAlpha(CONTEXT_CONE_OUT_ALPHA), + mContextConeFadeTime(CONTEXT_CONE_FADE_TIME) { mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); - - mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); - mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); - mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } BOOL LLFloaterAvatarPicker::postBuild() diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index d720fe9ac7554cddb49d0f85b2b9b3308fea483d..e8274ed31ec1d839f128ab34c6a10f6197afe108 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -105,9 +105,9 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show mActive ( TRUE ), mCanApplyImmediately ( show_apply_immediate ), mContextConeOpacity ( 0.f ), - mContextConeInAlpha ( 0.f ), - mContextConeOutAlpha ( 0.f ), - mContextConeFadeTime ( 0.f ) + mContextConeInAlpha (CONTEXT_CONE_IN_ALPHA), + mContextConeOutAlpha (CONTEXT_CONE_OUT_ALPHA), + mContextConeFadeTime (CONTEXT_CONE_FADE_TIME) { mCommitCallbackRegistrar.add("ColorPicker.menuDoToSelected", boost::bind(&LLFloaterColorPicker::menuDoToSelected, this, _2)); @@ -115,10 +115,6 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show // create user interface for this picker createUI (); - - mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); - mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); - mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } LLFloaterColorPicker::~LLFloaterColorPicker() diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index e1b0190c0330eec55eb91afa7cf01b528d054f0b..812a84a282286b8140f91c8522fcefa32e1e7920 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -37,13 +37,14 @@ const std::string LL_FCP_COMPLETE_NAME("complete_name"); const std::string LL_FCP_ACCOUNT_NAME("user_name"); +const S32 CONVERSATION_HISTORY_PAGE_SIZE = 100; LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_id) : LLFloater(session_id), mChatHistory(NULL), mSessionID(session_id.asUUID()), mCurrentPage(0), - mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")), + mPageSize(CONVERSATION_HISTORY_PAGE_SIZE), mAccountName(session_id[LL_FCP_ACCOUNT_NAME]), mCompleteName(session_id[LL_FCP_COMPLETE_NAME]), mMutex(), diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index e54e233e5d14c062e65c848807c67af1f03d0b35..a2729970cdbb408b3a8f2cd68227b078b519ac9d 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -39,8 +39,9 @@ #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llsdserialize.h" -#include "lltextbox.h" -#include "llviewerchat.h" +#include "lltextbox.h" +#include "lltrans.h" +#include "llviewerchat.h" namespace { // The following variables and constants are used for storing the floater state @@ -128,7 +129,7 @@ class LLEmojiGridIcon : public LLScrollingPanel , const LLEmojiSearchResult& emoji) : LLScrollingPanel(panel_params) , mData(emoji) - , mText(LLWString(1, emoji.Character)) + , mChar(LLWString(1, emoji.Character)) { } @@ -138,8 +139,8 @@ class LLEmojiGridIcon : public LLScrollingPanel F32 x = getRect().getWidth() / 2; F32 y = getRect().getHeight() / 2; - LLFontGL::getFontEmoji()->render( - mText, // wstr + LLFontGL::getFontEmojiLarge()->render( + mChar, // wstr 0, // begin_offset x, // x y, // y @@ -154,11 +155,11 @@ class LLEmojiGridIcon : public LLScrollingPanel virtual void updatePanel(BOOL allow_modify) override {} const LLEmojiSearchResult& getData() const { return mData; } - LLWString getText() const { return mText; } + const LLWString& getChar() const { return mChar; } private: const LLEmojiSearchResult mData; - const LLWString mText; + const LLWString mChar; }; class LLEmojiPreviewPanel : public LLPanel @@ -229,7 +230,7 @@ class LLEmojiPreviewPanel : public LLPanel { F32 x0 = x; F32 x1 = max_pixels; - LLFontGL* font = LLFontGL::getFontEmoji(); + LLFontGL* font = LLFontGL::getFontEmojiLarge(); if (mBegin) { std::string text = mTitle.substr(0, mBegin); @@ -332,6 +333,14 @@ void LLFloaterEmojiPicker::onOpen(const LLSD& key) gFloaterView->adjustToFitScreen(this, FALSE); } +void LLFloaterEmojiPicker::onClose(bool app_quitting) +{ + if (!app_quitting) + { + LLEmojiHelper::instance().hideHelper(nullptr, true); + } +} + void LLFloaterEmojiPicker::dirtyRect() { super::dirtyRect(); @@ -388,9 +397,12 @@ void LLFloaterEmojiPicker::initialize() } else { - const std::string prompt("No emoji found for "); - std::string title(prompt + '"' + mFilterPattern.substr(1) + '"'); - mPreview->setData(EMPTY_LIST_IMAGE_INDEX, title, prompt.size() + 1, title.size() - 1); + std::size_t begin, end; + LLStringUtil::format_map_t args; + args["[FILTER]"] = mFilterPattern.substr(1); + std::string title(getString("text_no_emoji_for_filter", args)); + LLEmojiDictionary::searchInShortCode(begin, end, title, mFilterPattern); + mPreview->setData(EMPTY_LIST_IMAGE_INDEX, title, begin, end); showPreview(true); } return; @@ -424,7 +436,7 @@ void LLFloaterEmojiPicker::fillGroups() mGroupButtons.clear(); LLButton::Params params; - params.font = LLFontGL::getFontEmoji(); + params.font = LLFontGL::getFontEmojiLarge(); LLRect rect; rect.mTop = mGroups->getRect().getHeight(); @@ -489,10 +501,12 @@ void LLFloaterEmojiPicker::fillCategoryRecentlyUsed(std::map<std::string, std::v auto e2d = emoji2descr.find(emoji); if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) { - const std::string shortcode(e2d->second->ShortCodes.front()); - if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) + for (const std::string& shortcode : e2d->second->ShortCodes) { - emojis.emplace_back(emoji, shortcode, begin, end); + if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) + { + emojis.emplace_back(emoji, shortcode, begin, end); + } } } } @@ -521,10 +535,12 @@ void LLFloaterEmojiPicker::fillCategoryFrequentlyUsed(std::map<std::string, std: auto e2d = emoji2descr.find(emoji.first); if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) { - const std::string shortcode(e2d->second->ShortCodes.front()); - if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) + for (const std::string& shortcode : e2d->second->ShortCodes) { - emojis.emplace_back(emoji.first, shortcode, begin, end); + if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) + { + emojis.emplace_back(emoji.first, shortcode, begin, end); + } } } } @@ -557,10 +573,12 @@ void LLFloaterEmojiPicker::fillGroupEmojis(std::map<std::string, std::vector<LLE { if (!descr->ShortCodes.empty()) { - const std::string shortcode(descr->ShortCodes.front()); - if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) + for (const std::string& shortcode : descr->ShortCodes) { - emojis.emplace_back(descr->Character, shortcode, begin, end); + if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) + { + emojis.emplace_back(descr->Character, shortcode, begin, end); + } } } } @@ -928,7 +946,7 @@ void LLFloaterEmojiPicker::onEmojiMouseUp(LLUICtrl* ctrl) if (LLEmojiGridIcon* icon = dynamic_cast<LLEmojiGridIcon*>(ctrl)) { - LLSD value(wstring_to_utf8str(icon->getText())); + LLSD value(wstring_to_utf8str(icon->getChar())); setValue(value); onCommit(); diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h index 82faaf821be7c936dbbdaee6882ead49d9379269..05b4826e372786060cceee1fc037894f6958f36a 100644 --- a/indra/newview/llfloateremojipicker.h +++ b/indra/newview/llfloateremojipicker.h @@ -94,6 +94,7 @@ class LLFloaterEmojiPicker : public LLFloater void unselectGridIcon(LLEmojiGridIcon* icon); void onOpen(const LLSD& key) override; + void onClose(bool app_quitting) override; virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent) override; class LLPanel* mGroups { nullptr }; diff --git a/indra/newview/llfloaterexperiencepicker.cpp b/indra/newview/llfloaterexperiencepicker.cpp index 668143933c7344107d05569831b369b55dcb27d1..93eaa6b64b87eadfb52624772123a4d6773d19a9 100644 --- a/indra/newview/llfloaterexperiencepicker.cpp +++ b/indra/newview/llfloaterexperiencepicker.cpp @@ -88,13 +88,10 @@ LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key ) :LLFloater(key) ,mSearchPanel(NULL) ,mContextConeOpacity(0.f) - ,mContextConeInAlpha(0.f) - ,mContextConeOutAlpha(0.f) - ,mContextConeFadeTime(0.f) + ,mContextConeInAlpha(CONTEXT_CONE_IN_ALPHA) + ,mContextConeOutAlpha(CONTEXT_CONE_OUT_ALPHA) + ,mContextConeFadeTime(CONTEXT_CONE_FADE_TIME) { - mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); - mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); - mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } LLFloaterExperiencePicker::~LLFloaterExperiencePicker() diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index b5c5c102c2d11a83625c4c5c2ac276f7697a68bd..ecd90b961139a7e81f4359376ff7caaf6afdc951 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -332,55 +332,63 @@ void LLFloaterImagePreview::draw() //----------------------------------------------------------------------------- bool LLFloaterImagePreview::loadImage(const std::string& src_filename) { - std::string exten = gDirUtilp->getExtension(src_filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); - - LLImageDimensionsInfo image_info; - if (!image_info.load(src_filename,codec)) + try { - mImageLoadError = image_info.getLastError(); - return false; - } + std::string exten = gDirUtilp->getExtension(src_filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); - S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); - S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); + LLImageDimensionsInfo image_info; + if (!image_info.load(src_filename, codec)) + { + mImageLoadError = image_info.getLastError(); + return false; + } - if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) - { - LLStringUtil::format_map_t args; - args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_height); + S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); + S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); - mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); - return false; - } + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); - // Load the image - LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); - if (image.isNull()) - { - return false; - } - if (!image->load(src_filename)) - { - return false; - } - // Decompress or expand it in a raw image structure - LLPointer<LLImageRaw> raw_image = new LLImageRaw; - if (!image->decode(raw_image, 0.0f)) - { - return false; + mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); + return false; + } + + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return false; + } + if (!image->load(src_filename)) + { + return false; + } + // Decompress or expand it in a raw image structure + LLPointer<LLImageRaw> raw_image = new LLImageRaw; + if (!image->decode(raw_image, 0.0f)) + { + return false; + } + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + + raw_image->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); + mRawImagep = raw_image; } - // Check the image constraints - if ((image->getComponents() != 3) && (image->getComponents() != 4)) + catch (...) { - image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + LOG_UNHANDLED_EXCEPTION(""); return false; } - raw_image->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); - mRawImagep = raw_image; - return true; } diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 6eb59ea6bb0f0575f8c9465cc3b56756283cf1d0..a708782d3887b5c10f47156732aa233823d25c8f 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -306,7 +306,8 @@ void LLFloaterIMNearbyChat::loadHistory() void LLFloaterIMNearbyChat::removeScreenChat() { - LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( + LLNotificationsUI::NEARBY_CHAT_CHANNEL_UUID); if(chat_channel) { chat_channel->removeToastsFromChannel(); diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 7dc1d72a95c73c7bb05fc7b4b7a0407873cd245c..490c5b4b5b395bb30d34fc52dff67ae26ba33ecf 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -620,7 +620,7 @@ LLFloaterIMNearbyChatHandler::LLFloaterIMNearbyChatHandler() { // Getting a Channel for our notifications LLFloaterIMNearbyChatScreenChannel::Params p; - p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); + p.id = NEARBY_CHAT_CHANNEL_UUID; LLFloaterIMNearbyChatScreenChannel* channel = new LLFloaterIMNearbyChatScreenChannel(p); LLFloaterIMNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel; diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 20a7beab26fc58f42ce80b3320489c526c21f525..47bf95bd9100f3acddb9f6d78c55aee5705502a1 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -811,7 +811,7 @@ void LLFloaterIMSession::setDocked(bool docked, bool pop_on_undock) // update notification channel state LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); if(!isChatMultiTab()) { @@ -847,7 +847,7 @@ void LLFloaterIMSession::setVisible(BOOL visible) { LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); LLFloaterIMSessionTab::setVisible(visible); @@ -1025,7 +1025,7 @@ void LLFloaterIMSession::updateMessages() // remove embedded notification from channel LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*> (LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); if (getVisible()) { // toast will be automatically closed since it is not storable toast diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index e7c49c6626e4748e648d95dd163a81d3066918d0..ed5432498bda6c2f3b6a85a167dbef2a2b3f48a9 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -268,9 +268,13 @@ BOOL LLFloaterIMSessionTab::postBuild() mEmojiRecentEmptyText->setToolTip(mEmojiRecentEmptyText->getText()); mEmojiRecentEmptyText->setVisible(false); + mEmojiRecentContainer = getChild<LLPanel>("emoji_recent_container"); + mEmojiRecentContainer->setVisible(false); + mEmojiRecentIconsCtrl = getChild<LLPanelEmojiComplete>("emoji_recent_icons_ctrl"); + mEmojiRecentIconsCtrl->setFocusReceivedCallback([this](LLFocusableElement*) { onEmojiRecentPanelFocusReceived(); }); + mEmojiRecentIconsCtrl->setFocusLostCallback([this](LLFocusableElement*) { onEmojiRecentPanelFocusLost(); }); mEmojiRecentIconsCtrl->setCommitCallback([this](LLUICtrl*, const LLSD& value) { onRecentEmojiPicked(value); }); - mEmojiRecentIconsCtrl->setVisible(false); mEmojiPickerShowBtn = getChild<LLButton>("emoji_picker_show_btn"); mEmojiPickerShowBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnClicked(); }); @@ -477,7 +481,7 @@ void LLFloaterIMSessionTab::initEmojiRecentPanel() if (recentlyUsed.empty()) { mEmojiRecentEmptyText->setVisible(TRUE); - mEmojiRecentIconsCtrl->setVisible(FALSE); + mEmojiRecentContainer->setVisible(FALSE); } else { @@ -488,10 +492,22 @@ void LLFloaterIMSessionTab::initEmojiRecentPanel() } mEmojiRecentIconsCtrl->setEmojis(emojis); mEmojiRecentEmptyText->setVisible(FALSE); - mEmojiRecentIconsCtrl->setVisible(TRUE); + mEmojiRecentContainer->setVisible(TRUE); } } +// static +void LLFloaterIMSessionTab::onEmojiRecentPanelFocusReceived() +{ + mEmojiRecentContainer->addBorder(); +} + +// static +void LLFloaterIMSessionTab::onEmojiRecentPanelFocusLost() +{ + mEmojiRecentContainer->removeBorder(); +} + void LLFloaterIMSessionTab::onRecentEmojiPicked(const LLSD& value) { LLSD::String str = value.asString(); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 61520ac17bb1875dc6adfa964d962ba473d97005..950dcba4adaf0a8beb78368895503afa38489c19 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -184,6 +184,7 @@ class LLFloaterIMSessionTab LLLayoutPanel* mInputButtonPanel; LLLayoutPanel* mEmojiRecentPanel; LLTextBox* mEmojiRecentEmptyText; + LLPanel* mEmojiRecentContainer; LLPanelEmojiComplete* mEmojiRecentIconsCtrl; LLParticipantList* getParticipantList(); conversations_widgets_map mConversationsWidgets; @@ -232,6 +233,8 @@ class LLFloaterIMSessionTab void onEmojiRecentPanelToggleBtnClicked(); void onEmojiPickerShowBtnClicked(); void initEmojiRecentPanel(); + void onEmojiRecentPanelFocusReceived(); + void onEmojiRecentPanelFocusLost(); void onRecentEmojiPicked(const LLSD& value); bool checkIfTornOff(); diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index 0fc99431913e3f8ffd433c4d2989044c7cba64a1..09763b7bb5a2da12a77d03abad37f528c1f3dfd1 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -256,6 +256,13 @@ void LLFloaterJoystick::refresh() initFromSettings(); } +bool LLFloaterJoystick::addDeviceCallback(std::string &name, LLSD& value, void* userdata) +{ + LLFloaterJoystick * floater = (LLFloaterJoystick*)userdata; + floater->mJoysticksCombo->add(name, value, ADD_BOTTOM, 1); + return false; // keep searching +} + void LLFloaterJoystick::addDevice(std::string &name, LLSD& value) { mJoysticksCombo->add(name, value, ADD_BOTTOM, 1); @@ -270,19 +277,21 @@ void LLFloaterJoystick::refreshListOfDevices() mHasDeviceList = false; + void* win_calback = nullptr; // di8_devices_callback callback is immediate and happens in scope of getInputDevices() #if LL_WINDOWS && !LL_MESA_HEADLESS // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib U32 device_type = DI8DEVCLASS_GAMECTRL; - void* callback = &di8_list_devices_callback; + win_calback = di8_list_devices_callback; +#elif LL_DARWIN + U32 device_type = 0; #else - // MAC doesn't support device search yet - // On MAC there is an ndof_idsearch and it is possible to specify product - // and manufacturer in NDOF_Device for ndof_init_first to pick specific one + // On MAC it is possible to specify product + // and manufacturer in NDOF_Device for + // ndof_init_first to pick specific device U32 device_type = 0; - void* callback = NULL; #endif - if (gViewerWindow->getWindow()->getInputDevices(device_type, callback, this)) + if (gViewerWindow->getWindow()->getInputDevices(device_type, addDeviceCallback, win_calback, this)) { mHasDeviceList = true; } @@ -425,9 +434,10 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel) } } - std::string device_id = LLViewerJoystick::getInstance()->getDeviceUUIDString(); - gSavedSettings.setString("JoystickDeviceUUID", device_id); - LL_DEBUGS("Joystick") << "Selected " << device_id << " as joystick." << LL_ENDL; + LLViewerJoystick::getInstance()->saveDeviceIdToSettings(); + + std::string device_string = LLViewerJoystick::getInstance()->getDeviceUUIDString(); + LL_DEBUGS("Joystick") << "Selected " << device_string << " as joystick." << LL_ENDL; self->refreshListOfDevices(); } diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index e6e058de7da80f49d69894bdec13c66940e349d7..6a804239dbf9556acf416c399f05b7b6ba7ea11a 100644 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -47,6 +47,7 @@ class LLFloaterJoystick final : public LLFloater static void setSNDefaults(); static void setXboxDefaults(); + static bool addDeviceCallback(std::string &name, LLSD& value, void* userdata); void addDevice(std::string &name, LLSD& value); protected: diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp index 7f661e96aa3f1749e3acbf7ecaa836ec9ce4a820..5a074e30ed8675c7093a6905e184d7bdc68f5340 100644 --- a/indra/newview/llfloaternotificationstabbed.cpp +++ b/indra/newview/llfloaternotificationstabbed.cpp @@ -155,7 +155,7 @@ LLPanel * LLFloaterNotificationsTabbed::findItemByID(const LLUUID& id, const std void LLFloaterNotificationsTabbed::initChannel() { LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID); mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); if(NULL == mChannel) { diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp index b5bc0f608fc1eefe053ecfa627af037faa25b24d..b2a461d37bc4c344354f8d3e63d99b8ad65d2549 100644 --- a/indra/newview/llfloaterobjectweights.cpp +++ b/indra/newview/llfloaterobjectweights.cpp @@ -203,11 +203,13 @@ void LLFloaterObjectWeights::refresh() LLAccountingCostManager::getInstance()->addObject((*iter)->getObject()->getID()); } + std::string url = region->getCapability("ResourceCostSelected"); + if (!url.empty()) { // Update the transaction id before the new fetch request generateTransactionID(); - LLAccountingCostManager::getInstance()->fetchCosts(Roots, getObserverHandle()); + LLAccountingCostManager::getInstance()->fetchCosts(Roots, url, getObserverHandle()); toggleWeightsLoadingIndicators(true); } } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 3bda5d100cc568a4fcb30903a2a705c5be01da29..86dca9f987b0d2e89869d7e5e18878920bddbd8d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -392,9 +392,9 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) { - if ( APT_PROPERTIES == type ) + if ( APT_PROPERTIES_LEGACY == type ) { - const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData ); + const LLAvatarLegacyData* pAvatarData = static_cast<const LLAvatarLegacyData*>( pData ); if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id.notNull())) { mAllowPublish = (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH); @@ -544,7 +544,7 @@ BOOL LLFloaterPreference::postBuild() void LLFloaterPreference::updateDeleteTranscriptsButton() { - getChild<LLButton>("delete_transcripts")->setEnabled(LLLogChat::anyTranscriptsExist()); + getChild<LLButton>("delete_transcripts")->setEnabled(LLLogChat::transcriptFilesExist()); } void LLFloaterPreference::onDoNotDisturbResponseChanged() @@ -1078,7 +1078,6 @@ void LLFloaterPreference::cancel() void LLFloaterPreference::onOpen(const LLSD& key) { - // this variable and if that follows it are used to properly handle do not disturb mode response message // if user is logged in and we haven't initialized do not disturb mode response yet, do it if (!mDnDInit && LLStartUp::getStartupState() == STATE_STARTED) @@ -1104,7 +1103,7 @@ void LLFloaterPreference::onOpen(const LLSD& key) (gAgent.isMature() || gAgent.isGodlike()); LLComboBox* maturity_combo = getChild<LLComboBox>("maturity_desired_combobox"); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest( gAgent.getID() ); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarLegacyPropertiesRequest( gAgent.getID() ); if (can_choose_maturity) { // if they're not adult or a god, they shouldn't see the adult selection, so delete it diff --git a/indra/newview/llfloaterprofiletexture.cpp b/indra/newview/llfloaterprofiletexture.cpp index d55e48ef7dd5bd44ec1e1c67f454919d8c70ec40..f2ac80657379b44a739b77892444adafa211f588 100644 --- a/indra/newview/llfloaterprofiletexture.cpp +++ b/indra/newview/llfloaterprofiletexture.cpp @@ -33,39 +33,173 @@ #include "llpreview.h" // fors constants #include "lltrans.h" #include "llviewercontrol.h" -#include "lltextureview.h" #include "llviewertexture.h" #include "llviewertexturelist.h" + ////////////////////////////////////////////////////////////////////////// + // LLProfileImageCtrl + ////////////////////////////////////////////////////////////////////////// -LLFloaterProfileTexture::LLFloaterProfileTexture(LLView* owner) - : LLFloater(LLSD()) - , mUpdateDimensions(TRUE) - , mLastHeight(0) - , mLastWidth(0) +static LLDefaultChildRegistry::Register<LLProfileImageCtrl> r("profile_image"); + +LLProfileImageCtrl::LLProfileImageCtrl(const LLProfileImageCtrl::Params& p) + : LLIconCtrl(p) , mImage(NULL) , mImageOldBoostLevel(LLGLTexture::BOOST_NONE) - , mOwnerHandle(owner->getHandle()) + , mWasNoDelete(false) + , mImageLoadedSignal(NULL) { - buildFromFile("floater_profile_texture.xml"); } -LLFloaterProfileTexture::~LLFloaterProfileTexture() +LLProfileImageCtrl::~LLProfileImageCtrl() +{ + LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList); + releaseTexture(); + + delete mImageLoadedSignal; +} + +void LLProfileImageCtrl::releaseTexture() { if (mImage.notNull()) { mImage->setBoostLevel(mImageOldBoostLevel); + if (!mWasNoDelete) + { + // In most cases setBoostLevel marks images as NO_DELETE + mImage->forceActive(); + } mImage = NULL; } +} + +void LLProfileImageCtrl::setValue(const LLSD& value) +{ + LLUUID id = value.asUUID(); + setImageAssetId(id); + if (id.isNull()) + { + LLIconCtrl::setValue("Generic_Person_Large", LLGLTexture::BOOST_UI); + } + else + { + // called second to not change priority before it gets saved to mImageOldBoostLevel + LLIconCtrl::setValue(value, LLGLTexture::BOOST_PREVIEW); + } +} + +void LLProfileImageCtrl::draw() +{ + if (mImage.notNull()) + { + // Pump the texture priority + mImage->addTextureStats(MAX_IMAGE_AREA); + mImage->setKnownDrawSize(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT, LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); + } + LLIconCtrl::draw(); +} - LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList); +boost::signals2::connection LLProfileImageCtrl::setImageLoadedCallback(const image_loaded_signal_t::slot_type& cb) +{ + if (!mImageLoadedSignal) mImageLoadedSignal = new image_loaded_signal_t(); + + return mImageLoadedSignal->connect(cb); +} + +void LLProfileImageCtrl::setImageAssetId(const LLUUID& asset_id) +{ + if (mImageID == asset_id) + { + return; + } + + releaseTexture(); + + mImageID = asset_id; + if (mImageID.notNull()) + { + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mWasNoDelete = mImage->getTextureState() == LLGLTexture::NO_DELETE; + mImageOldBoostLevel = mImage->getBoostLevel(); + mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + mImage->setKnownDrawSize(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT, LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); + mImage->forceToSaveRawImage(0); + + if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) + { + mImage->setLoadedCallback(LLProfileImageCtrl::onImageLoaded, + 0, TRUE, FALSE, new LLHandle<LLUICtrl>(getHandle()), &mCallbackTextureList); + } + else + { + onImageLoaded(true, mImage); + } + } +} + +void LLProfileImageCtrl::onImageLoaded(bool success, LLViewerFetchedTexture* img) +{ + if (mImageLoadedSignal) + { + (*mImageLoadedSignal)(success, img); + } +} + +// static +void LLProfileImageCtrl::onImageLoaded(BOOL success, + LLViewerFetchedTexture* src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata) +{ + if (!userdata) return; + + LLHandle<LLUICtrl>* handle = (LLHandle<LLUICtrl>*)userdata; + + if (!handle->isDead()) + { + LLProfileImageCtrl* caller = static_cast<LLProfileImageCtrl*>(handle->get()); + if (caller && caller->mImageLoadedSignal) + { + (*caller->mImageLoadedSignal)(success, src_vi); + } + } + + if (final || !success) + { + delete handle; + } +} + + +////////////////////////////////////////////////////////////////////////// +// LLFloaterProfileTexture + ////////////////////////////////////////////////////////////////////////// + +LLFloaterProfileTexture::LLFloaterProfileTexture(LLView* owner) + : LLFloater(LLSD()) + , mLastHeight(0) + , mLastWidth(0) + , mOwnerHandle(owner->getHandle()) + , mContextConeOpacity(0.f) + , mCloseButton(NULL) + , mProfileIcon(NULL) +{ + buildFromFile("floater_profile_texture.xml"); +} + +LLFloaterProfileTexture::~LLFloaterProfileTexture() +{ } // virtual BOOL LLFloaterProfileTexture::postBuild() { - mProfileIcon = getChild<LLIconCtrl>("profile_pic"); + mProfileIcon = getChild<LLProfileImageCtrl>("profile_pic"); + mProfileIcon->setImageLoadedCallback([this](BOOL success, LLViewerFetchedTexture* imagep) {onImageLoaded(success, imagep); }); mCloseButton = getChild<LLButton>("close_btn"); mCloseButton->setCommitCallback([this](LLUICtrl*, void*) { closeFloater(); }, nullptr); @@ -83,55 +217,41 @@ void LLFloaterProfileTexture::reshape(S32 width, S32 height, BOOL called_from_pa // When we receive it, reshape the window accordingly. void LLFloaterProfileTexture::updateDimensions() { - if (mImage.isNull()) + LLPointer<LLViewerFetchedTexture> image = mProfileIcon->getImage(); + if (image.isNull()) { return; } - if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) + if ((image->getFullWidth() * image->getFullHeight()) == 0) { return; } - S32 img_width = mImage->getFullWidth(); - S32 img_height = mImage->getFullHeight(); - - if (mAssetStatus != LLPreview::PREVIEW_ASSET_LOADED - || mLastWidth != img_width - || mLastHeight != img_height) - { - mAssetStatus = LLPreview::PREVIEW_ASSET_LOADED; - // Asset has been fully loaded - mUpdateDimensions = TRUE; - } + S32 img_width = image->getFullWidth(); + S32 img_height = image->getFullHeight(); mLastHeight = img_height; mLastWidth = img_width; - // Reshape the floater only when required - if (mUpdateDimensions) - { - mUpdateDimensions = FALSE; - - LLRect old_floater_rect = getRect(); - LLRect old_image_rect = mProfileIcon->getRect(); - S32 width = old_floater_rect.getWidth() - old_image_rect.getWidth() + mLastWidth; - S32 height = old_floater_rect.getHeight() - old_image_rect.getHeight() + mLastHeight; + LLRect old_floater_rect = getRect(); + LLRect old_image_rect = mProfileIcon->getRect(); + S32 width = old_floater_rect.getWidth() - old_image_rect.getWidth() + mLastWidth; + S32 height = old_floater_rect.getHeight() - old_image_rect.getHeight() + mLastHeight; - const F32 MAX_DIMENTIONS = 1024; // most profiles are supposed to be 256x256 + const F32 MAX_DIMENTIONS = 1024; // most profiles are supposed to be 256x256 - S32 biggest_dim = llmax(width, height); - if (biggest_dim > MAX_DIMENTIONS) - { - F32 scale_down = MAX_DIMENTIONS / (F32)biggest_dim; - width *= scale_down; - height *= scale_down; - } + S32 biggest_dim = llmax(width, height); + if (biggest_dim > MAX_DIMENTIONS) + { + F32 scale_down = MAX_DIMENTIONS / (F32)biggest_dim; + width *= scale_down; + height *= scale_down; + } - //reshape floater - reshape(width, height); + //reshape floater + reshape(width, height); - gFloaterView->adjustToFitScreen(this, FALSE); - } + gFloaterView->adjustToFitScreen(this, FALSE); } void LLFloaterProfileTexture::draw() @@ -151,75 +271,18 @@ void LLFloaterProfileTexture::onOpen(const LLSD& key) void LLFloaterProfileTexture::resetAsset() { - mProfileIcon->setValue("Generic_Person_Large"); - mImageID = LLUUID::null; - if (mImage.notNull()) - { - mImage->setBoostLevel(mImageOldBoostLevel); - mImage = NULL; - } + mProfileIcon->setValue(LLUUID::null); } void LLFloaterProfileTexture::loadAsset(const LLUUID &image_id) { - if (mImageID != image_id) - { - if (mImage.notNull()) - { - mImage->setBoostLevel(mImageOldBoostLevel); - mImage = NULL; - } - } - else - { - return; - } - mProfileIcon->setValue(image_id); - mImageID = image_id; - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - mImageOldBoostLevel = mImage->getBoostLevel(); - - if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) - { - mImage->setLoadedCallback(LLFloaterProfileTexture::onTextureLoaded, - 0, TRUE, FALSE, new LLHandle<LLFloater>(getHandle()), &mCallbackTextureList); - - mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); - mAssetStatus = LLPreview::PREVIEW_ASSET_LOADING; - } - else - { - mAssetStatus = LLPreview::PREVIEW_ASSET_LOADED; - } - - mUpdateDimensions = TRUE; updateDimensions(); } -// static -void LLFloaterProfileTexture::onTextureLoaded( - BOOL success, - LLViewerFetchedTexture *src_vi, - LLImageRaw* src, - LLImageRaw* aux_src, - S32 discard_level, - BOOL final, - void* userdata) +void LLFloaterProfileTexture::onImageLoaded(BOOL success, LLViewerFetchedTexture* imagep) { - LLHandle<LLFloater>* handle = (LLHandle<LLFloater>*)userdata; - - if (!handle->isDead()) - { - LLFloaterProfileTexture* floater = static_cast<LLFloaterProfileTexture*>(handle->get()); - if (floater && success) - { - floater->mUpdateDimensions = TRUE; - floater->updateDimensions(); - } - } - - if (final || !success) + if (success) { - delete handle; + updateDimensions(); } } diff --git a/indra/newview/llfloaterprofiletexture.h b/indra/newview/llfloaterprofiletexture.h index e0ec0b16ef470f5241838ca478e29e4cedce346c..12efbab572d2d3d178d1057cdc6043d2a0f8420f 100644 --- a/indra/newview/llfloaterprofiletexture.h +++ b/indra/newview/llfloaterprofiletexture.h @@ -1,25 +1,25 @@ -/** +/** * @file llfloaterprofiletexture.h * @brief LLFloaterProfileTexture class definition * * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2022, 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,11 +28,50 @@ #define LL_LLFLOATERPROFILETEXTURE_H #include "llfloater.h" +#include "lliconctrl.h" #include "llviewertexture.h" class LLButton; class LLImageRaw; -class LLIconCtrl; + +class LLProfileImageCtrl: public LLIconCtrl +{ +public: + struct Params: public LLInitParam::Block<Params, LLIconCtrl::Params> + { + }; + + LLProfileImageCtrl(const Params& p); + virtual ~LLProfileImageCtrl(); + + + virtual void setValue(const LLSD& value) override; + LLUUID getImageAssetId() { return mImageID; } + LLPointer<LLViewerFetchedTexture> getImage() {return mImage;} + void draw() override; + + typedef boost::signals2::signal<void(bool success, LLViewerFetchedTexture* imagep)> image_loaded_signal_t; + boost::signals2::connection setImageLoadedCallback(const image_loaded_signal_t::slot_type& cb); +private: + void onImageLoaded(bool success, LLViewerFetchedTexture* src_vi); + static void onImageLoaded(BOOL success, + LLViewerFetchedTexture* src_vi, + LLImageRaw* src, + LLImageRaw* aux_src, + S32 discard_level, + BOOL final, + void* userdata); + void releaseTexture(); + + void setImageAssetId(const LLUUID& asset_id); +private: + LLPointer<LLViewerFetchedTexture> mImage; + LLUUID mImageID; + S32 mImageOldBoostLevel; + bool mWasNoDelete; + image_loaded_signal_t* mImageLoadedSignal; + LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList; +}; class LLFloaterProfileTexture : public LLFloater { @@ -46,36 +85,23 @@ class LLFloaterProfileTexture : public LLFloater void resetAsset(); void loadAsset(const LLUUID &image_id); - - static void onTextureLoaded( - BOOL success, - LLViewerFetchedTexture *src_vi, - LLImageRaw* src, - LLImageRaw* aux_src, - S32 discard_level, - BOOL final, - void* userdata); + void onImageLoaded(BOOL success, LLViewerFetchedTexture* imagep); void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override; + + LLHandle<LLFloater> getHandle() const { return LLFloater::getHandle(); } protected: BOOL postBuild() override; private: void updateDimensions(); - LLUUID mImageID; - LLPointer<LLViewerFetchedTexture> mImage; - S32 mImageOldBoostLevel; - S32 mAssetStatus; F32 mContextConeOpacity; S32 mLastHeight; S32 mLastWidth; - BOOL mUpdateDimensions; LLHandle<LLView> mOwnerHandle; - LLIconCtrl* mProfileIcon; + LLProfileImageCtrl* mProfileIcon; LLButton* mCloseButton; - - LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList; }; #endif // LL_LLFLOATERPROFILETEXTURE_H diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index b9a31796bdf284d3b3314bbbb003d762ffee15a7..f58b4c041b9701e4335c86a794571613e3555e4e 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -50,12 +50,6 @@ class LLSearchHandler : public LLCommandHandler LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { } bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch")) - { - LLNotificationsUtil::add("NoSearch", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - const size_t parts = tokens.size(); // get the (optional) category for the search diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 5e3cad4928348c3bb5743b64eb5fc931e6f46fa2..78ec8e5b546a4084f18e60cf1daaeb284bfa4504 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -279,9 +279,7 @@ void LLFloaterSellLandUI::refreshUI() getChild<LLUICtrl>("info_size")->setTextArg("[AREA]", llformat("%d", mParcelActualArea)); std::string price_str = getChild<LLUICtrl>("price")->getValue().asString(); - bool valid_price = false; - valid_price = (price_str != "") && LLTextValidate::validateNonNegativeS32(utf8str_to_wstring(price_str)); - + bool valid_price = !price_str.empty() && LLTextValidate::validateNonNegativeS32.validate(price_str); if (valid_price && mParcelActualArea > 0) { F32 per_meter_price = 0; @@ -295,7 +293,7 @@ void LLFloaterSellLandUI::refreshUI() { getChildView("price_per_m")->setVisible(FALSE); - if ("" == price_str) + if (price_str.empty()) { setBadge("step_price", BADGE_NOTE); } @@ -327,9 +325,7 @@ void LLFloaterSellLandUI::refreshUI() // Must select Sell To: Anybody, or User (with a specified username) std::string sell_to = getChild<LLUICtrl>("sell_to")->getValue().asString(); - bool valid_sell_to = "select" != sell_to && - (("user" != sell_to || "self" != sell_to) || mAuthorizedBuyer.notNull()); - + bool valid_sell_to = "select" != sell_to && (("user" != sell_to || "self" != sell_to) || mAuthorizedBuyer.notNull()); if (!valid_sell_to) { setBadge("step_sell_to", BADGE_NOTE); @@ -340,7 +336,6 @@ void LLFloaterSellLandUI::refreshUI() } bool valid_sell_objects = ("none" != getChild<LLUICtrl>("sell_objects")->getValue().asString()); - if (!valid_sell_objects) { setBadge("step_sell_objects", BADGE_NOTE); diff --git a/indra/newview/llfloatersimplesnapshot.cpp b/indra/newview/llfloatersimplesnapshot.cpp index 37f845b3d7b2541ff46015dd206f9b178d7c2423..5d65bf2d0d8d68f552147925526d73add02869c0 100644 --- a/indra/newview/llfloatersimplesnapshot.cpp +++ b/indra/newview/llfloatersimplesnapshot.cpp @@ -370,7 +370,7 @@ void LLFloaterSimpleSnapshot::onSend() else { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); } } @@ -389,7 +389,7 @@ void LLFloaterSimpleSnapshot::uploadThumbnail(const std::string &file_path, cons if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, THUMBNAIL_SNAPSHOT_DIM_MAX, THUMBNAIL_SNAPSHOT_DIM_MIN, true)) { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); LL_WARNS("Thumbnail") << "Failed to upload thumbnail for " << inventory_id << " " << task_id << ", reason: " << notif_args["REASON"].asString() << LL_ENDL; return; @@ -404,7 +404,7 @@ void LLFloaterSimpleSnapshot::uploadThumbnail(LLPointer<LLImageRaw> raw_image, c if (!LLViewerTextureList::createUploadFile(raw_image, temp_file, THUMBNAIL_SNAPSHOT_DIM_MAX, THUMBNAIL_SNAPSHOT_DIM_MIN)) { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); LL_WARNS("Thumbnail") << "Failed to upload thumbnail for " << inventory_id << " " << task_id << ", reason: " << notif_args["REASON"].asString() << LL_ENDL; return; diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 8c325bc79c141407c021e1629ab80b892b705ad4..a36c5139c1b5bf8305b90749e197e8863daa297c 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -153,12 +153,6 @@ class LLWorldMapHandler : public LLCommandHandler const std::string& grid, LLMediaCtrl* web) { - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap")) - { - LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - if (params.size() == 0) { // support the secondlife:///app/worldmap SLapp @@ -214,12 +208,6 @@ class LLMapTrackAvatarHandler : public LLCommandHandler const std::string& grid, LLMediaCtrl* web) { - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap")) - { - LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - //Make sure we have some parameters if (params.size() == 0) { diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index f212b0b14c393fbe95b6bc3310a6d001ca40a066..4681a3817b587598c9898acbe8a8f1e6d087dcf7 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -63,6 +63,9 @@ // Longest time, in seconds, to wait for all animations to stop playing const F32 MAX_WAIT_ANIM_SECS = 60.f; +// Longest time, in seconds, to wait for a key release. +// This should be relatively long, but not too long. 10 minutes is enough +const F32 MAX_WAIT_KEY_SECS = 60.f * 10.f; // Lightweight constructor. // init() does the heavy lifting. @@ -533,7 +536,7 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset LLGestureMgr::instance().replaceGesture(base_item_id, gesture, new_asset_id); } -void LLGestureMgr::playGesture(LLMultiGesture* gesture) +void LLGestureMgr::playGesture(LLMultiGesture* gesture, bool fromKeyPress) { if (!gesture) return; @@ -544,6 +547,7 @@ void LLGestureMgr::playGesture(LLMultiGesture* gesture) // Reset gesture to first step gesture->reset(); + gesture->mTriggeredByKey = fromKeyPress; // Add to list of playing gesture->mPlaying = TRUE; @@ -741,7 +745,8 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) if (!gesture) continue; if (gesture->mKey == key - && gesture->mMask == mask) + && gesture->mMask == mask + && gesture->mWaitingKeyRelease == FALSE) { matching.push_back(gesture); } @@ -754,13 +759,38 @@ BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) LLMultiGesture* gesture = matching[random]; - playGesture(gesture); + playGesture(gesture, TRUE); return TRUE; } return FALSE; } +BOOL LLGestureMgr::triggerGestureRelease(KEY key, MASK mask) +{ + std::vector <LLMultiGesture *> matching; + item_map_t::iterator it; + + // collect matching gestures + for (it = mActive.begin(); it != mActive.end(); ++it) + { + LLMultiGesture* gesture = (*it).second; + + // asset data might not have arrived yet + if (!gesture) continue; + + if (gesture->mKey == key + && gesture->mMask == mask) + { + gesture->mKeyReleased = TRUE; + } + } + + //If we found one, block. Otherwise tell them it's free to go. + return matching.size() > 0; +} + + S32 LLGestureMgr::getPlayingCount() const { return mPlaying.size(); @@ -909,6 +939,32 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture) continue; } + // If we're waiting a fixed amount of time, check for timer + // expiration. + if (gesture->mWaitingKeyRelease) + { + // We're waiting for a certain amount of time to pass + if (gesture->mKeyReleased) + { + // wait is done, continue execution + gesture->mWaitingKeyRelease = FALSE; + gesture->mCurrentStep++; + } + else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_KEY_SECS) + { + LL_INFOS("GestureMgr") << "Waited too long for key release, continuing gesture." + << LL_ENDL; + gesture->mWaitingKeyRelease = FALSE; + gesture->mCurrentStep++; + } + else + { + // we're waiting, so execution is done for now + waiting = TRUE; + } + continue; + } + // If we're waiting on our animations to stop, poll for // completion. if (gesture->mWaitingAnimations) @@ -1027,7 +1083,17 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) case STEP_WAIT: { LLGestureStepWait* wait_step = (LLGestureStepWait*)step; - if (wait_step->mFlags & WAIT_FLAG_TIME) + if (gesture->mTriggeredByKey // Only wait here IF we were triggered by a key! + && gesture->mWaitingKeyRelease == FALSE // We can only do this once! Prevent gestures infinitely running + && wait_step->mFlags & WAIT_FLAG_KEY_RELEASE) + { + // Lets wait for the key release first so we don't hold up re-presses + gesture->mWaitingKeyRelease = TRUE; + gesture->mKeyReleased = FALSE; + // Use the wait timer as a deadlock breaker for key release waits. + gesture->mWaitTimer.reset(); + } + else if (wait_step->mFlags & WAIT_FLAG_TIME) { gesture->mWaitingTimer = TRUE; gesture->mWaitTimer.reset(); @@ -1035,8 +1101,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) else if (wait_step->mFlags & WAIT_FLAG_ALL_ANIM) { gesture->mWaitingAnimations = TRUE; - // Use the wait timer as a deadlock breaker for animation - // waits. + // Use the wait timer as a deadlock breaker for animation waits. gesture->mWaitTimer.reset(); } else diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 14651dcc96fadace05b2171dbb38289e38e75b41..aa09f06bb8b448a5727abed9a016dfbfcd9d18e9 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -102,7 +102,10 @@ class LLGestureMgr final : public LLSingleton<LLGestureMgr>, public LLInventoryF const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being // previewed. - void playGesture(LLMultiGesture* gesture); + void playGesture(LLMultiGesture* gesture, bool fromKeyPress); + void playGesture(LLMultiGesture* gesture) { + playGesture(gesture, FALSE); + } void playGesture(const LLUUID& item_id); // Stop all requested or playing anims for this gesture @@ -118,10 +121,14 @@ class LLGestureMgr final : public LLSingleton<LLGestureMgr>, public LLInventoryF { mCallbackMap[inv_item_id] = cb; } - // Trigger the first gesture that matches this key. + // Trigger a random gesture that matches this key. // Returns TRUE if it finds a gesture bound to that key. BOOL triggerGesture(KEY key, MASK mask); + // Trigger release wait on all gestures that matches this key. + // Returns TRUE if it finds a gesture bound to that key. + BOOL triggerGestureRelease(KEY key, MASK mask); + // Trigger all gestures referenced as substrings in this string BOOL triggerAndReviseString(const std::string &str, std::string *revised_string = NULL); diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 6860427f03c55be3a2af5e0c21021208d5c25879..b6b828bf3cd689ae0f321348b67a5ce95c7e3dba 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -96,12 +96,6 @@ class LLGroupCommandHandler : public LLCommandHandler return true; } - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableGroupInfo")) - { - LLNotificationsUtil::add("NoGroupInfo", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - if (tokens.size() < 1) { return false; @@ -392,7 +386,16 @@ void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id) args["GROUP"] = gdatap->mName; LLSD payload; payload["group_id"] = group_id; - LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup); + if (gdatap->mMembershipFee > 0) + { + args["COST"] = gdatap->mMembershipFee; + LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup); + } + else + { + LLNotificationsUtil::add("GroupLeaveConfirmMemberNoFee", args, payload, onLeaveGroup); + } + } // static @@ -431,13 +434,17 @@ void LLGroupActions::inspect(const LLUUID& group_id) } // static -void LLGroupActions::show(const LLUUID& group_id) +void LLGroupActions::show(const LLUUID &group_id, bool expand_notices_tab) { if (group_id.isNull()) return; LLSD params; params["group_id"] = group_id; + if (expand_notices_tab) + { + params["action"] = "show_notices"; + } if (gSavedSettings.getBool("ShowGroupFloaters")) { diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h index f92894edf5ad296d139accb04029fe41e8738dc5..d906f33a4b21c484bb935a03e92929bd238ac1a6 100644 --- a/indra/newview/llgroupactions.h +++ b/indra/newview/llgroupactions.h @@ -57,7 +57,7 @@ class LLGroupActions /** * Show group information panel. */ - static void show(const LLUUID& group_id); + static void show(const LLUUID& group_id, bool expand_notices_tab = false); // [SL:KB] - Patch: Notification-GroupCreateNotice | Checked: 2012-02-16 (Catznip-3.2) /** diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 9c22e92cefc843674ffbc27b18c7ac9251f85b09..efa068f67f1baf8756fd4973f901631251b75cd7 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -309,6 +309,7 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL item->getChildView("info_btn")->setVisible( false); item->getChildView("profile_btn")->setVisible( false); + item->getChildView("notices_btn")->setVisible(false); item->setGroupIconVisible(mShowIcons); if (!mShowIcons) { @@ -433,6 +434,7 @@ mGroupIcon(NULL), mGroupNameBox(NULL), mInfoBtn(NULL), mProfileBtn(NULL), +mNoticesBtn(NULL), mVisibilityHideBtn(NULL), mVisibilityShowBtn(NULL), mGroupID(LLUUID::null), @@ -465,6 +467,9 @@ BOOL LLGroupListItem::postBuild() mProfileBtn = getChild<LLButton>("profile_btn"); mProfileBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onProfileBtnClick(); }); + mNoticesBtn = getChild<LLButton>("notices_btn"); + mNoticesBtn->setClickedCallback([this](LLUICtrl *, const LLSD &) { onNoticesBtnClick(); }); + mVisibilityHideBtn = findChild<LLButton>("visibility_hide_btn"); if (mVisibilityHideBtn) { @@ -500,13 +505,17 @@ void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask) { mInfoBtn->setVisible(true); mProfileBtn->setVisible(true); - if (mForAgent && mVisibilityHideBtn) + if (mForAgent) { LLGroupData agent_gdatap; if (gAgent.getGroupData(mGroupID, agent_gdatap)) { - mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile); - mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile); + if (mVisibilityHideBtn) + { + mVisibilityHideBtn->setVisible(agent_gdatap.mListInProfile); + mVisibilityShowBtn->setVisible(!agent_gdatap.mListInProfile); + } + mNoticesBtn->setVisible(true); } } } @@ -519,6 +528,7 @@ void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask) getChildView("hovered_icon")->setVisible( false); mInfoBtn->setVisible(false); mProfileBtn->setVisible(false); + mNoticesBtn->setVisible(false); if (mVisibilityHideBtn) { mVisibilityHideBtn->setVisible(false); @@ -613,6 +623,11 @@ void LLGroupListItem::onProfileBtnClick() LLGroupActions::show(mGroupID); } +void LLGroupListItem::onNoticesBtnClick() +{ + LLGroupActions::show(mGroupID, true); +} + void LLGroupListItem::onVisibilityBtnClick(bool new_visibility) { LLGroupData agent_gdatap; diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 4b01d4830be4dfd4546fc2c28c061f162bd0cf08..3fa9ca2f95d4b3c9501640bd09d280f80e67e3b7 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -123,6 +123,7 @@ class LLGroupListItem : public LLPanel void setBold(bool bold); void onInfoBtnClick(); void onProfileBtnClick(); + void onNoticesBtnClick(); void onVisibilityBtnClick(bool new_visibility); LLTextBox* mGroupNameBox; @@ -130,6 +131,7 @@ class LLGroupListItem : public LLPanel LLGroupIconCtrl* mGroupIcon; LLButton* mInfoBtn; LLButton* mProfileBtn; + LLButton* mNoticesBtn; LLButton* mVisibilityHideBtn; LLButton* mVisibilityShowBtn; diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 3554412e188a2573eed0d47c3a58a5365829f68b..bc2d9052f139d28fc4b9b6bd225480ae881bdca6 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -55,8 +55,7 @@ LLIMHandler::~LLIMHandler() void LLIMHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 6af7b980468bef1c2d5d4cb403e5ae74c891c63a..604e7ca03aaff6381d8aff449f9b052e3e968fb1 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -595,6 +595,12 @@ void chatterBoxHistoryCoro(std::string url, LLUUID sessionId, std::string from, return; } + if (LLApp::isExiting() || gDisconnected) + { + LL_DEBUGS("ChatHistory") << "Ignoring chat history response, shutting down" << LL_ENDL; + return; + } + // Add history to IM session LLSD history = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT]; @@ -4027,6 +4033,12 @@ class LLViewerChatterBoxSessionStartReply : public LLHTTPNode const LLSD& context, const LLSD& input) const { + if (LLApp::isExiting() || gDisconnected) + { + LL_DEBUGS("ChatHistory") << "Ignoring ChatterBox session, Shutting down" << LL_ENDL; + return; + } + LLSD body; LLUUID temp_session_id; LLUUID session_id; diff --git a/indra/newview/llinspect.cpp b/indra/newview/llinspect.cpp index eafe140256b7e7d00f4a46aefb07c94d621e1fe5..dbe75f912ef7cedff29bfe8ec1bbceca5ce27cf6 100644 --- a/indra/newview/llinspect.cpp +++ b/indra/newview/llinspect.cpp @@ -45,8 +45,8 @@ LLInspect::~LLInspect() // virtual void LLInspect::draw() { - static LLUICachedControl<F32> FADE_TIME("InspectorFadeTime", 1.f); - static LLUICachedControl<F32> STAY_TIME("InspectorShowTime", 1.f); + const F32 FADE_TIME = 0.5f; + const F32 STAY_TIME = 3.f; if (mOpenTimer.getStarted()) { LLFloater::draw(); @@ -59,7 +59,7 @@ void LLInspect::draw() } else if (mCloseTimer.getStarted()) { - F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_TIME(), 1.f, 0.f); + F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 1.f, 0.f); LLViewDrawContext context(alpha); LLFloater::draw(); if (mCloseTimer.getElapsedTimeF32() > FADE_TIME) diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 61213c1a5d4588f86ff256b60852997f89861185..2bd4796bd0f00f42c137d4c94bc366bf57c18ad3 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -261,12 +261,15 @@ void LLInspectAvatar::requestUpdate() void LLInspectAvatar::processAvatarData(LLAvatarData* data) { LLStringUtil::format_map_t args; - { - std::string birth_date = LLTrans::getString("AvatarBirthDateFormat"); - LLStringUtil::format(birth_date, LLSD().with("datetime", (S32) data->born_on.secondsSinceEpoch())); - args["[BORN_ON]"] = birth_date; - } - args["[AGE]"] = LLDateUtil::ageFromDate(data->born_on, LLDate::now()); + + std::string birth_date = LLTrans::getString(data->hide_age ? + "AvatarBirthDateFormatShort" : + "AvatarBirthDateFormatFull"); + LLStringUtil::format(birth_date, LLSD().with("datetime", (S32)data->born_on.secondsSinceEpoch())); + args["[BORN_ON]"] = birth_date; + args["[AGE]"] = data->hide_age ? + LLStringUtilBase<char>::null : + LLDateUtil::ageFromDate(data->born_on, LLDate::now()); args["[SL_PROFILE]"] = data->about_text; args["[RW_PROFILE"] = data->fl_about_text; args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data); diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index 0104714a163fc3b2f881db333911aabb27cbf606..2e0589348997f8d1590c9590ba3f011204fa6952 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -61,7 +61,7 @@ LLInspectToast::LLInspectToast(const LLSD& notification_id) : LLInspect(LLSD()), mPanel(NULL) { LLScreenChannelBase* channel = LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID); mScreenChannel = dynamic_cast<LLScreenChannel*>(channel); if(NULL == mScreenChannel) { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9f2334943ca5811298dcb04664b548296e4c52c0..d5ad6248679f42659c6cd33f8e9e91311c3a215d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -99,6 +99,7 @@ void copy_slurl_to_clipboard_callback_inv(const std::string& slurl); const F32 SOUND_GAIN = 1.0f; +const F32 FOLDER_LOADING_MESSAGE_DELAY = 0.5f; // Seconds to wait before showing the LOADING... text in folder views using namespace LLOldEvents; @@ -317,9 +318,9 @@ void LLInvFVBridge::setCreationDate(time_t creation_date_utc) // Can be destroyed (or moved to trash) -BOOL LLInvFVBridge::isItemRemovable() const +BOOL LLInvFVBridge::isItemRemovable(bool check_worn) const { - return get_is_item_removable(getInventoryModel(), mUUID); + return get_is_item_removable(getInventoryModel(), mUUID, check_worn); } // Can be moved to another folder @@ -830,9 +831,6 @@ void hide_context_entries(LLMenuGL& menu, bool found = false; - std::string myinput; - std::vector<std::string> mylist{ "a", "b", "c" }; - menuentry_vec_t::const_iterator itor2 = std::find(entries_to_show.begin(), entries_to_show.end(), name); if (itor2 != entries_to_show.end()) { @@ -932,7 +930,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } items.push_back(std::string("Cut")); - if (!isItemMovable() || !isItemRemovable()) + if (!isItemMovable() || !canMenuCut()) { disabled_items.push_back(std::string("Cut")); } @@ -998,7 +996,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, if(!single_folder_root) { // items.push_back(std::string("Cut")); -// if (!isItemMovable() || !isItemRemovable()) +// if (!isItemMovable() || !canMenuCut()) // { // disabled_items.push_back(std::string("Cut")); // } @@ -1183,7 +1181,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, items.push_back(std::string("Delete")); - if (!isItemRemovable() || isPanelActive("Favorite Items")) + if (isPanelActive("Favorite Items") || !canMenuDelete()) { disabled_items.push_back(std::string("Delete")); } @@ -1339,6 +1337,16 @@ void LLInvFVBridge::addLinkReplaceMenuOption(menuentry_vec_t& items, menuentry_v } } +bool LLInvFVBridge::canMenuDelete() +{ + return isItemRemovable(false); +} + +bool LLInvFVBridge::canMenuCut() +{ + return isItemRemovable(true); +} + // *TODO: remove this BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const { @@ -2634,45 +2642,16 @@ void LLFolderBridge::update() } } - -// Iterate through a folder's children to determine if -// all the children are removable. -class LLIsItemRemovable : public LLFolderViewFunctor -{ -public: - LLIsItemRemovable() : mPassed(TRUE) {} - virtual void doFolder(LLFolderViewFolder* folder) - { - mPassed &= folder->getViewModelItem()->isItemRemovable(); - } - virtual void doItem(LLFolderViewItem* item) - { - mPassed &= item->getViewModelItem()->isItemRemovable(); - } - BOOL mPassed; -}; - // Can be destroyed (or moved to trash) -BOOL LLFolderBridge::isItemRemovable() const +BOOL LLFolderBridge::isItemRemovable(bool check_worn) const { - if (!get_is_category_removable(getInventoryModel(), mUUID)) + if (!get_is_category_and_children_removable(getInventoryModel(), mUUID, check_worn)) { return FALSE; } - LLInventoryPanel* panel = mInventoryPanel.get(); - LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL); - if (folderp) - { - LLIsItemRemovable folder_test; - folderp->applyFunctorToChildren(folder_test); - if (!folder_test.mPassed) - { - return FALSE; - } - } - - if (isMarketplaceListingsFolder() && (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID))) + if (isMarketplaceListingsFolder() + && (!LLMarketplaceData::instance().isSLMDataFetched() || LLMarketplaceData::instance().getActivationState(mUUID))) { return FALSE; } @@ -4617,10 +4596,12 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items if (!isInboxFolder() // don't allow creation in inbox && outfits_id != mUUID) { + bool menu_items_added = false; // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) { items.push_back(std::string("New Folder")); + menu_items_added = true; } if (!isMarketplaceListingsFolder()) { @@ -4638,6 +4619,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back("New Settings"); } } + else + { + items.push_back(std::string("New Listing Folder")); + } + if (menu_items_added) + { + items.push_back(std::string("Create Separator")); + } } getClipboardEntries(false, items, disabled_items, flags); } @@ -4779,7 +4768,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& return; } - if (!isItemRemovable()) + if (!canMenuDelete()) { disabled_items.push_back(std::string("Delete")); } @@ -5164,6 +5153,192 @@ void LLFolderBridge::modifyOutfit(BOOL append) } } +//static +void LLFolderBridge::onCanDeleteIdle(void* user_data) +{ + LLFolderBridge* self = (LLFolderBridge*)user_data; + + // we really need proper onidle mechanics that returns available time + const F32 EXPIRY_SECONDS = 0.008f; + LLTimer timer; + timer.setTimerExpirySec(EXPIRY_SECONDS); + + LLInventoryModel* model = self->getInventoryModel(); + if (model) + { + switch (self->mCanDeleteFolderState) + { + case CDS_INIT_FOLDER_CHECK: + // Can still be expensive, split it further? + model->collectDescendents( + self->mUUID, + self->mFoldersToCheck, + self->mItemsToCheck, + LLInventoryModel::EXCLUDE_TRASH); + self->mCanDeleteFolderState = CDS_PROCESSING_ITEMS; + break; + + case CDS_PROCESSING_ITEMS: + while (!timer.hasExpired() && !self->mItemsToCheck.empty()) + { + LLViewerInventoryItem* item = self->mItemsToCheck.back().get(); + if (item) + { + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item)) + { + if (get_is_item_worn(item)) + { + // At the moment we disable 'cut' if category has worn items (do we need to?) + // but allow 'delete' to happen since it will prompt user to detach + self->mCanCut = false; + } + } + + if (!item->getIsLinkType() && get_is_item_worn(item)) + { + self->mCanCut = false; + } + } + self->mItemsToCheck.pop_back(); + } + self->mCanDeleteFolderState = CDS_PROCESSING_FOLDERS; + break; + case CDS_PROCESSING_FOLDERS: + { + const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + LLViewerInventoryCategory* outfit_linked_category = base_outfit_link ? base_outfit_link->getLinkedCategory() : nullptr; + + while (!timer.hasExpired() && !self->mFoldersToCheck.empty()) + { + LLViewerInventoryCategory* cat = self->mFoldersToCheck.back().get(); + if (cat) + { + const LLFolderType::EType folder_type = cat->getPreferredType(); + if (LLFolderType::lookupIsProtectedType(folder_type)) + { + self->mCanCut = false; + self->mCanDelete = false; + self->completeDeleteProcessing(); + break; + } + + // Can't delete the outfit that is currently being worn. + if (folder_type == LLFolderType::FT_OUTFIT) + { + if (cat == outfit_linked_category) + { + self->mCanCut = false; + self->mCanDelete = false; + self->completeDeleteProcessing(); + break; + } + } + } + self->mFoldersToCheck.pop_back(); + } + } + self->mCanDeleteFolderState = CDS_DONE; + break; + case CDS_DONE: + self->completeDeleteProcessing(); + break; + } + } +} + +bool LLFolderBridge::canMenuDelete() +{ + LLInventoryModel* model = getInventoryModel(); + if (!model) return false; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (!category) + { + return false; + } + + S32 version = category->getVersion(); + if (mLastCheckedVersion == version) + { + return mCanDelete; + } + + initCanDeleteProcessing(model, version); + return false; +} + +bool LLFolderBridge::canMenuCut() +{ + LLInventoryModel* model = getInventoryModel(); + if (!model) return false; + LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); + if (!category) + { + return false; + } + + S32 version = category->getVersion(); + if (mLastCheckedVersion == version) + { + return mCanCut; + } + + initCanDeleteProcessing(model, version); + return false; +} + +void LLFolderBridge::initCanDeleteProcessing(LLInventoryModel* model, S32 version) +{ + if (mCanDeleteFolderState == CDS_DONE + || mInProgressVersion != version) + { + if (get_is_category_removable(model, mUUID)) + { + // init recursive check of content + mInProgressVersion = version; + mCanCut = true; + mCanDelete = true; + mCanDeleteFolderState = CDS_INIT_FOLDER_CHECK; + mFoldersToCheck.clear(); + mItemsToCheck.clear(); + gIdleCallbacks.addFunction(onCanDeleteIdle, this); + } + else + { + // no check needed + mCanDelete = false; + mCanCut = false; + mLastCheckedVersion = version; + mCanDeleteFolderState = CDS_DONE; + mFoldersToCheck.clear(); + mItemsToCheck.clear(); + } + } +} + +void LLFolderBridge::completeDeleteProcessing() +{ + LLInventoryModel* model = getInventoryModel(); + LLViewerInventoryCategory* category = model ? (LLViewerInventoryCategory*)model->getCategory(mUUID) : nullptr; + if (model && category && category->getVersion() == mInProgressVersion) + { + mLastCheckedVersion = mInProgressVersion; + mCanDeleteFolderState = CDS_DONE; + gIdleCallbacks.deleteFunction(onCanDeleteIdle, this); + } + else + { + mCanDelete = false; + mCanCut = false; + mLastCheckedVersion = LLViewerInventoryCategory::VERSION_UNKNOWN; + mCanDeleteFolderState = CDS_DONE; + } + + if (mRoot) + { + mRoot->updateMenu(); + } +} + // +=================================================+ // | LLMarketplaceFolderBridge | @@ -5207,9 +5382,7 @@ LLUIImagePtr LLMarketplaceFolderBridge::getMarketplaceFolderIcon(BOOL is_open) c std::string LLMarketplaceFolderBridge::getLabelSuffix() const { - static LLCachedControl<F32> folder_loading_message_delay(gSavedSettings, "FolderLoadingMessageWaitTime", 0.5f); - - if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= folder_loading_message_delay()) + if (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= FOLDER_LOADING_MESSAGE_DELAY) { return llformat(" (%s) ", LLTrans::getString("LoadingData").c_str()); } @@ -5327,6 +5500,27 @@ void drop_to_favorites_cb(const LLUUID& id, LLPointer<LLInventoryCallback> cb1, cb2->fire(id); } +LLFolderBridge::LLFolderBridge(LLInventoryPanel* inventory, + LLFolderView* root, + const LLUUID& uuid) + : LLInvFVBridge(inventory, root, uuid) + , mCallingCards(FALSE) + , mWearables(FALSE) + , mIsLoading(false) + , mShowDescendantsCount(false) + , mCanDeleteFolderState(CDS_DONE) + , mLastCheckedVersion(S32_MIN) + , mInProgressVersion(S32_MIN) + , mCanDelete(false) + , mCanCut(false) +{ +} + +LLFolderBridge::~LLFolderBridge() +{ + gIdleCallbacks.deleteFunction(onCanDeleteIdle, this); +} + void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item, LLPointer<LLInventoryCallback> cb) { // use callback to rearrange favorite landmarks after adding @@ -7011,6 +7205,26 @@ LLInventoryObject* LLObjectBridge::getObject() const return object; } +LLViewerInventoryItem* LLObjectBridge::getItem() const +{ + LLInventoryModel* model = getInventoryModel(); + if (model) + { + return model->getItem(mUUID); + } + return NULL; +} + +LLViewerInventoryCategory* LLObjectBridge::getCategory() const +{ + LLInventoryModel* model = getInventoryModel(); + if (model) + { + return model->getCategory(mUUID); + } + return NULL; +} + // virtual void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 4883bf00cfbf187a2245979316a1cacb89e673c1..6ae5c0c4d7163468c1000f811c4159b745934c72 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -114,7 +114,7 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory virtual BOOL isItemRenameable() const { return TRUE; } virtual BOOL isMultiPreviewAllowed() { return TRUE; } //virtual BOOL renameItem(const std::string& new_name) {} - virtual BOOL isItemRemovable() const; + virtual BOOL isItemRemovable(bool check_worn = true) const; virtual BOOL isItemMovable() const; virtual BOOL isItemInTrash() const; virtual bool isItemInOutfits() const; @@ -166,6 +166,9 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory virtual void addLinkReplaceMenuOption(menuentry_vec_t& items, menuentry_vec_t& disabled_items); + virtual bool canMenuDelete(); + virtual bool canMenuCut(); + protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); @@ -282,13 +285,9 @@ class LLFolderBridge : public LLInvFVBridge public: LLFolderBridge(LLInventoryPanel* inventory, LLFolderView* root, - const LLUUID& uuid) - : LLInvFVBridge(inventory, root, uuid), - mCallingCards(FALSE), - mWearables(FALSE), - mIsLoading(false), - mShowDescendantsCount(false) - {} + const LLUUID& uuid); + + ~LLFolderBridge(); BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE, LLPointer<LLInventoryCallback> cb = NULL); BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE, LLPointer<LLInventoryCallback> cb = NULL); @@ -331,7 +330,7 @@ class LLFolderBridge : public LLInvFVBridge void* cargo_data, std::string& tooltip_msg); - virtual BOOL isItemRemovable() const; + virtual BOOL isItemRemovable(bool check_worn = true) const; virtual BOOL isItemMovable() const ; virtual BOOL isUpToDate() const; virtual bool isItemCopyable(bool can_copy_as_link = true) const; @@ -405,6 +404,31 @@ class LLFolderBridge : public LLInvFVBridge LLTimer mTimeSinceRequestStart; std::string mMessage; LLRootHandle<LLFolderBridge> mHandle; + +private: + // checking if folder is cutable or deletable is expensive, + // cache values and split check over frames + static void onCanDeleteIdle(void* user_data); + void initCanDeleteProcessing(LLInventoryModel* model, S32 version); + void completeDeleteProcessing(); + bool canMenuDelete(); + bool canMenuCut(); + + enum ECanDeleteState + { + CDS_INIT_FOLDER_CHECK, + CDS_PROCESSING_ITEMS, + CDS_PROCESSING_FOLDERS, + CDS_DONE, + }; + + ECanDeleteState mCanDeleteFolderState; + LLInventoryModel::cat_array_t mFoldersToCheck; + LLInventoryModel::item_array_t mItemsToCheck; + S32 mLastCheckedVersion; + S32 mInProgressVersion; + bool mCanDelete; + bool mCanCut; }; class LLTextureBridge : public LLItemBridge @@ -537,6 +561,8 @@ class LLObjectBridge : public LLItemBridge virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL renameItem(const std::string& new_name); LLInventoryObject* getObject() const; + LLViewerInventoryItem* getItem() const; + LLViewerInventoryCategory* getCategory() const; protected: static LLUUID sContextMenuItemID; // Only valid while the context menu is open. U32 mAttachPt; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index cd06cb9452dd6fbe66112a697ff4e951be56e319..0db149da2e13b37e5917d10cca1a04c4f0074ff9 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -606,9 +606,8 @@ BOOL get_is_parent_to_worn_item(const LLUUID& id) return FALSE; } -BOOL get_is_item_worn(const LLUUID& id) +BOOL get_is_item_worn(const LLUUID& id, const LLViewerInventoryItem* item) { - const LLViewerInventoryItem* item = gInventory.getItem(id); if (!item) return FALSE; @@ -647,6 +646,21 @@ BOOL get_is_item_worn(const LLUUID& id) return FALSE; } +BOOL get_is_item_worn(const LLUUID& id) +{ + const LLViewerInventoryItem* item = gInventory.getItem(id); + return get_is_item_worn(id, item); +} + +BOOL get_is_item_worn(const LLViewerInventoryItem* item) +{ + if (!item) + { + return FALSE; + } + return get_is_item_worn(item->getUUID(), item); +} + BOOL get_can_item_be_worn(const LLUUID& id) { const LLViewerInventoryItem* item = gInventory.getItem(id); @@ -740,26 +754,27 @@ BOOL get_is_category_movable(const LLInventoryModel* model, const LLUUID& id) } // [/SL:KB] -BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id) +bool get_is_item_removable(const LLInventoryModel* model, const LLUUID& id, bool check_worn) { if (!model) { - return FALSE; + return false; } // Can't delete an item that's in the library. if (!model->isObjectDescendentOf(id, gInventory.getRootFolderID())) { - return FALSE; + return false; } // Disable delete from COF folder; have users explicitly choose "detach/take off", // unless the item is not worn but in the COF (i.e. is bugged). - if (LLAppearanceMgr::instance().getIsProtectedCOFItem(id)) + const LLViewerInventoryItem* obj = model->getItem(id); + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(obj)) { - if (get_is_item_worn(id)) + if (get_is_item_worn(id, obj)) { - return FALSE; + return false; } } @@ -767,20 +782,19 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id) if ( (RlvActions::isRlvEnabled()) && (RlvFolderLocks::instance().hasLockedFolder(RLV_LOCK_ANY)) && (!RlvFolderLocks::instance().canRemoveItem(id)) ) { - return FALSE; + return false; } // [/RLVa:KB] - const LLInventoryObject *obj = model->getItem(id); if (obj && obj->getIsLinkType()) { - return TRUE; + return true; } - if (get_is_item_worn(id)) + if (check_worn && get_is_item_worn(id, obj)) { - return FALSE; + return false; } - return TRUE; + return true; } bool get_is_item_editable(const LLUUID& inv_item_id) @@ -882,6 +896,74 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id) return TRUE; } +bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUID& folder_id, bool check_worn) +{ + if (!get_is_category_removable(model, folder_id)) + { + return false; + } + + const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) + { + return false; + } + + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + model->collectDescendents( + folder_id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + + if (check_worn) + { + for (LLInventoryModel::item_array_t::value_type& item : item_array) + { + // Disable delete/cut from COF folder; have users explicitly choose "detach/take off", + // unless the item is not worn but in the COF (i.e. is bugged). + if (item) + { + if (LLAppearanceMgr::instance().getIsProtectedCOFItem(item)) + { + if (get_is_item_worn(item)) + { + return false; + } + } + + if (!item->getIsLinkType() && get_is_item_worn(item)) + { + return false; + } + } + } + } + + const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + LLViewerInventoryCategory* outfit_linked_category = base_outfit_link ? base_outfit_link->getLinkedCategory() : nullptr; + for (LLInventoryModel::cat_array_t::value_type& cat : cat_array) + { + const LLFolderType::EType folder_type = cat->getPreferredType(); + if (LLFolderType::lookupIsProtectedType(folder_type)) + { + return false; + } + + // Can't delete the outfit that is currently being worn. + if (folder_type == LLFolderType::FT_OUTFIT) + { + if (cat == outfit_linked_category) + { + return false; + } + } + } + + return true; +} + BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id) { if (!model) @@ -2868,7 +2950,7 @@ bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventory { if (item) { - return !get_is_item_removable(&gInventory, item->getUUID()); + return !get_is_item_removable(&gInventory, item->getUUID(), true); } if (cat) { @@ -3150,6 +3232,8 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root { const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); bool marketplacelistings_item = false; + bool has_worn = false; + bool needs_replacement = false; LLAllDescendentsPassedFilter f; for (std::set<LLFolderViewItem*>::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it) { @@ -3158,14 +3242,69 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root folder->applyFunctorRecursively(f); } LLFolderViewModelItemInventory * viewModel = dynamic_cast<LLFolderViewModelItemInventory *>((*it)->getViewModelItem()); - if (viewModel && gInventory.isObjectDescendentOf(viewModel->getUUID(), marketplacelistings_id)) + LLUUID obj_id = viewModel->getUUID(); + if (viewModel && gInventory.isObjectDescendentOf(obj_id, marketplacelistings_id)) { marketplacelistings_item = true; break; } + + LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id); + if (cat) + { + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + + gInventory.collectDescendents(obj_id, categories, items, FALSE); + + for (LLInventoryModel::item_array_t::value_type& item : items) + { + if (get_is_item_worn(item)) + { + has_worn = true; + LLWearableType::EType type = item->getWearableType(); + if (type == LLWearableType::WT_SHAPE + || type == LLWearableType::WT_SKIN + || type == LLWearableType::WT_HAIR + || type == LLWearableType::WT_EYES) + { + needs_replacement = true; + break; + } + } + } + if (needs_replacement) + { + break; + } + } + LLViewerInventoryItem* item = gInventory.getItem(obj_id); + if (item && get_is_item_worn(item)) + { + has_worn = true; + LLWearableType::EType type = item->getWearableType(); + if (type == LLWearableType::WT_SHAPE + || type == LLWearableType::WT_SKIN + || type == LLWearableType::WT_HAIR + || type == LLWearableType::WT_EYES) + { + needs_replacement = true; + break; + } + } } // Fall through to the generic confirmation if the user choose to ignore the specialized one - if ( (!f.allDescendentsPassedFilter()) && !marketplacelistings_item && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) ) + if (needs_replacement) + { + LLNotificationsUtil::add("CantDeleteRequiredClothing"); + } + else if (has_worn) + { + LLSD payload; + payload["has_worn"] = true; + LLNotificationsUtil::add("DeleteWornItems", LLSD(), payload, boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle())); + } + else if ( (!f.allDescendentsPassedFilter()) && !marketplacelistings_item && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) ) { LLNotificationsUtil::add("DeleteFilteredItems", LLSD(), LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle())); } @@ -3488,12 +3627,82 @@ void LLInventoryAction::onItemsRemovalConfirmation(const LLSD& notification, con S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0 && !root.isDead() && !root.get()->isDead()) { + bool has_worn = notification["payload"]["has_worn"].asBoolean(); LLFolderView* folder_root = root.get(); //Need to remove item from DND before item is removed from root folder view //because once removed from root folder view the item is no longer a selected item removeItemFromDND(folder_root); + + // removeSelectedItems will change selection, collect worn items beforehand + uuid_vec_t worn; + uuid_vec_t item_deletion_list; + uuid_vec_t cat_deletion_list; + if (has_worn) + { + //Get selected items + LLFolderView::selected_items_t selectedItems = folder_root->getSelectedItems(); + + //If user is in DND and deletes item, make sure the notification is not displayed by removing the notification + //from DND history and .xml file. Once this is done, upon exit of DND mode the item deleted will not show a notification. + for (LLFolderView::selected_items_t::iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + LLFolderViewModelItemInventory* viewModel = dynamic_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem()); + + LLUUID obj_id = viewModel->getUUID(); + LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id); + bool cat_has_worn = false; + if (cat) + { + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + + gInventory.collectDescendents(obj_id, categories, items, FALSE); + + for (LLInventoryModel::item_array_t::value_type& item : items) + { + if (get_is_item_worn(item)) + { + worn.push_back(item->getUUID()); + cat_has_worn = true; + } + } + if (cat_has_worn) + { + cat_deletion_list.push_back(obj_id); + } + } + LLViewerInventoryItem* item = gInventory.getItem(obj_id); + if (item && get_is_item_worn(item)) + { + worn.push_back(obj_id); + item_deletion_list.push_back(obj_id); + } + } + } + + // removeSelectedItems will check if items are worn before deletion, + // don't 'unwear' yet to prevent race conditions from unwearing + // and removing simultaneously folder_root->removeSelectedItems(); + // unwear then delete the rest + if (!worn.empty()) + { + // should fire once after every item gets detached + LLAppearanceMgr::instance().removeItemsFromAvatar(worn, + [item_deletion_list, cat_deletion_list]() + { + for (const LLUUID& id : item_deletion_list) + { + remove_inventory_item(id, NULL); + } + for (const LLUUID& id : cat_deletion_list) + { + remove_inventory_category(id, NULL); + } + }); + } + // Update the marketplace listings that have been affected by the operation updateMarketplaceFolders(); } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 3cc2634a901eb9ac18750b1c8127d71e8a16c889..0b449ae681f8213552cb64b6f1e1895c214ed409 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -48,6 +48,7 @@ BOOL get_is_parent_to_worn_item(const LLUUID& id); // Is this item or its baseitem is worn, attached, etc... BOOL get_is_item_worn(const LLUUID& id); +BOOL get_is_item_worn(const LLViewerInventoryItem* item); // Could this item be worn (correct type + not already being worn) BOOL get_can_item_be_worn(const LLUUID& id); @@ -58,13 +59,14 @@ BOOL get_is_item_movable(const LLInventoryModel* model, const LLUUID& id); BOOL get_is_category_movable(const LLInventoryModel* model, const LLUUID& id); // [/SL:KB] -BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id); +bool get_is_item_removable(const LLInventoryModel* model, const LLUUID& id, bool check_worn); // Performs the appropiate edit action (if one exists) for this item bool get_is_item_editable(const LLUUID& inv_item_id); void handle_item_edit(const LLUUID& inv_item_id); BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id); +bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUID& folder_id, bool check_worn); BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id); diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index eff3109876514d47ba3d670e595284f4d4b63142..4dae97088f194dee43ca41865799aad6e4c6f85b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -187,7 +187,7 @@ LLInventoryGallery::~LLInventoryGallery() mHiddenItems.pop_back(); panelp->die(); } - + if (gInventory.containsObserver(mCategoriesObserver)) { @@ -200,7 +200,7 @@ LLInventoryGallery::~LLInventoryGallery() gInventory.removeObserver(mThumbnailsObserver); } delete mThumbnailsObserver; - + LLGestureMgr::instance().removeObserver(mGestureObserver); delete mGestureObserver; } @@ -263,7 +263,7 @@ void LLInventoryGallery::updateRootFolder() updateRemovedItem(mHiddenItems[i]->getUUID()); } mItemBuildQuery.clear(); - + if (gInventory.containsObserver(mCategoriesObserver)) { gInventory.removeObserver(mCategoriesObserver); @@ -284,7 +284,7 @@ void LLInventoryGallery::updateRootFolder() mRootChangedSignal(); gInventory.addObserver(mCategoriesObserver); - + // Start observing changes in selected category. mCategoriesObserver->addCategory(mFolderID, boost::bind(&LLInventoryGallery::refreshList, this, mFolderID)); @@ -294,7 +294,7 @@ void LLInventoryGallery::updateRootFolder() // the observer will refresh the list as soon as the new items // arrive. category->fetch(); - + //refreshList(cat_id); LLInventoryModel::cat_array_t* cat_array; LLInventoryModel::item_array_t* item_array; @@ -308,7 +308,7 @@ void LLInventoryGallery::updateRootFolder() { mItemBuildQuery.insert((*iter)->getUUID()); } - + for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin(); iter != item_array->end(); iter++) @@ -448,7 +448,7 @@ void LLInventoryGallery::reArrangeRows(S32 row_diff) buf_items.push_back(*it); } mHiddenItems.clear(); - + mItemsInRow+= row_diff; updateGalleryWidth(); @@ -458,7 +458,7 @@ void LLInventoryGallery::reArrangeRows(S32 row_diff) { return compareGalleryItem(item1, item2, sort_by_date, sort_folders_by_name); }); - + for (std::vector<LLInventoryGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) { (*it)->setHidden(false); @@ -735,7 +735,7 @@ void LLInventoryGallery::setFilterSubString(const std::string& string) { mFilterSubString = string; mFilter->setFilterSubString(string); - + //reArrangeRows(); } @@ -763,7 +763,7 @@ bool LLInventoryGallery::checkAgainstFilters(LLInventoryGalleryItem* item, const { return false; } - + bool hidden = false; if(mFilter->getFilterCreatorType() == LLInventoryFilter::FILTERCREATOR_SELF) @@ -806,7 +806,7 @@ bool LLInventoryGallery::checkAgainstFilters(LLInventoryGalleryItem* item, const desc = item->getItemName() + item->getItemNameSuffix(); break; } - + LLStringUtil::toUpper(desc); std::string cur_filter = filter_substring; @@ -1668,6 +1668,45 @@ void LLInventoryGallery::cut() mFilterSubString.clear(); } + + +bool is_category_removable(const LLUUID& folder_id, bool check_worn) +{ + if (!get_is_category_removable(&gInventory, folder_id)) + { + return false; + } + + // check children + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(folder_id, cat_array, item_array); + + for (LLInventoryModel::item_array_t::value_type& item : *item_array) + { + if (!get_is_item_removable(&gInventory, item->getUUID(), check_worn)) + { + return false; + } + } + + for (LLInventoryModel::cat_array_t::value_type& cat : *cat_array) + { + if (!is_category_removable(cat->getUUID(), check_worn)) + { + return false; + } + } + + const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) + { + return false; + } + + return true; +} + BOOL LLInventoryGallery::canCut() const { if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty()) @@ -1680,12 +1719,12 @@ BOOL LLInventoryGallery::canCut() const LLViewerInventoryCategory* cat = gInventory.getCategory(id); if (cat) { - if (!get_is_category_removable(&gInventory, id)) + if (!get_is_category_and_children_removable(&gInventory, id, true)) { return FALSE; } } - else if (!get_is_item_removable(&gInventory, id)) + else if (!get_is_item_removable(&gInventory, id, true)) { return FALSE; } @@ -1864,42 +1903,149 @@ void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { - for (const LLUUID& id : selected_ids) + bool has_worn = notification["payload"]["has_worn"].asBoolean(); + uuid_vec_t worn; + uuid_vec_t item_deletion_list; + uuid_vec_t cat_deletion_list; + for (const LLUUID& obj_id : selected_ids) { - LLInventoryObject* obj = gInventory.getObject(id); - if (!obj) + LLViewerInventoryCategory* cat = gInventory.getCategory(obj_id); + if (cat) { - return; - } - if (obj->getType() == LLAssetType::AT_CATEGORY) - { - if (get_is_category_removable(&gInventory, id)) + bool cat_has_worn = false; + if (has_worn) + { + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + + gInventory.collectDescendents(obj_id, categories, items, FALSE); + + for (LLInventoryModel::item_array_t::value_type& item : items) + { + if (get_is_item_worn(item)) + { + worn.push_back(item->getUUID()); + cat_has_worn = true; + } + } + } + if (cat_has_worn) + { + cat_deletion_list.push_back(obj_id); + } + else { - gInventory.removeCategory(id); + gInventory.removeCategory(obj_id); } } - else + LLViewerInventoryItem* item = gInventory.getItem(obj_id); + if (item) { - if (get_is_item_removable(&gInventory, id)) + if (has_worn && get_is_item_worn(item)) { - gInventory.removeItem(id); + worn.push_back(item->getUUID()); + item_deletion_list.push_back(item->getUUID()); + } + else + { + gInventory.removeItem(obj_id); } } } + + if (!worn.empty()) + { + // should fire once after every item gets detached + LLAppearanceMgr::instance().removeItemsFromAvatar(worn, + [item_deletion_list, cat_deletion_list]() + { + for (const LLUUID& id : item_deletion_list) + { + remove_inventory_item(id, NULL); + } + for (const LLUUID& id : cat_deletion_list) + { + remove_inventory_category(id, NULL); + } + }); + } } } void LLInventoryGallery::deleteSelection() { - if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + bool has_worn = false; + bool needs_replacement = false; + for (const LLUUID& id : mSelectedItemIDs) { - LLNotifications::instance().setIgnored("DeleteItems", false); - LLInventoryAction::sDeleteConfirmationDisplayed = true; + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + + gInventory.collectDescendents(id, categories, items, FALSE); + + for (LLInventoryModel::item_array_t::value_type& item : items) + { + if (get_is_item_worn(item)) + { + has_worn = true; + LLWearableType::EType type = item->getWearableType(); + if (type == LLWearableType::WT_SHAPE + || type == LLWearableType::WT_SKIN + || type == LLWearableType::WT_HAIR + || type == LLWearableType::WT_EYES) + { + needs_replacement = true; + break; + } + } + } + if (needs_replacement) + { + break; + } + } + + LLViewerInventoryItem* item = gInventory.getItem(id); + if (item && get_is_item_worn(item)) + { + has_worn = true; + LLWearableType::EType type = item->getWearableType(); + if (type == LLWearableType::WT_SHAPE + || type == LLWearableType::WT_SKIN + || type == LLWearableType::WT_HAIR + || type == LLWearableType::WT_EYES) + { + needs_replacement = true; + break; + } + } + } + + if (needs_replacement) + { + LLNotificationsUtil::add("CantDeleteRequiredClothing"); } + else if (has_worn) + { + LLSD payload; + payload["has_worn"] = true; + LLNotificationsUtil::add("DeleteWornItems", LLSD(), payload, boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); + } + else + { + if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + { + LLNotifications::instance().setIgnored("DeleteItems", false); + LLInventoryAction::sDeleteConfirmationDisplayed = true; + } - LLSD args; - args["QUESTION"] = LLTrans::getString("DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); + LLSD args; + args["QUESTION"] = LLTrans::getString("DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); + } } bool LLInventoryGallery::canDeleteSelection() @@ -1925,7 +2071,7 @@ bool LLInventoryGallery::canDeleteSelection() return false; } } - else if (!get_is_item_removable(&gInventory, id)) + else if (!get_is_item_removable(&gInventory, id, true)) { return false; } @@ -2209,7 +2355,7 @@ void LLInventoryGallery::onCOFChanged() LLCommonUtils::computeDifference(vnew, mCOFLinkedItems, vadded, vremoved); mCOFLinkedItems = vnew; - + for (uuid_vec_t::const_iterator iter = vadded.begin(); iter != vadded.end(); ++iter) @@ -2240,7 +2386,7 @@ void LLInventoryGallery::onGesturesChanged() LLCommonUtils::computeDifference(vnew, mActiveGestures, vadded, vremoved); mActiveGestures = vnew; - + for (uuid_vec_t::const_iterator iter = vadded.begin(); iter != vadded.end(); ++iter) @@ -2419,7 +2565,7 @@ void LLInventoryGallery::startDrag() ids.push_back(selected_id); } - const LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); + const LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); if (cat) { if (gInventory.isObjectDescendentOf(selected_id, gInventory.getLibraryRootFolderID())) @@ -2497,7 +2643,7 @@ bool LLInventoryGallery::checkAgainstFilterType(const LLUUID& object_id) break; } } - + if (filterTypes & LLInventoryFilter::FILTERTYPE_DATE) { const U16 HOURS_TO_SECONDS = 3600; @@ -2941,7 +3087,7 @@ void LLThumbnailsObserver::changed(U32 mask) { const LLUUID& obj_id = (*iter).first; LLItemData& data = (*iter).second; - + LLInventoryObject* obj = gInventory.getObject(obj_id); if (!obj) { @@ -3152,7 +3298,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, // //-------------------------------------------------------------------------------- - + //-------------------------------------------------------------------------------- // Determine if item can be moved & dropped // Note: if user_confirm is false, we already went through those accept logic test and can skip them @@ -3179,7 +3325,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, { //disable dropping in or out of marketplace for now return FALSE; - + /*const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, folder_id); LLViewerInventoryCategory * dest_folder = cat; accept = can_move_item_to_marketplace(master_folder, dest_folder, inv_item, tooltip_msg, LLToolDragAndDrop::instance().getCargoCount() - LLToolDragAndDrop::instance().getCargoIndex());*/ @@ -3191,7 +3337,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, LLViewerInventoryCategory * dest_folder = cat; accept = dest_folder->acceptItem(inv_item); } - + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); if (accept && drop) @@ -3265,7 +3411,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, gInventory.changeItemParent((LLViewerInventoryItem*)inv_item, folder_id, move_is_into_trash); } - + if (move_is_from_marketplacelistings) { // If we move from an active (listed) listing, checks that it's still valid, if not, unlist @@ -3485,7 +3631,7 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); //const LLUUID from_folder_uuid = inv_cat->getParentUUID(); - + const BOOL move_is_into_current_outfit = (dest_id == current_outfit_id); const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(dest_id, marketplacelistings_id); const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id); @@ -3594,7 +3740,7 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, is_movable = FALSE; // tooltip? } - + LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; if (is_movable) @@ -3660,7 +3806,7 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, } } } - + if (is_movable && move_is_into_marketplacelistings) { const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, dest_id); @@ -3733,7 +3879,7 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, { //disable dropping in or out of marketplace for now return FALSE; - + // If we are moving a folder at the listing folder level (i.e. its parent is the marketplace listings folder) /*if (from_folder_uuid == marketplacelistings_id) { diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 6e8694cdaf0c37965221ddbe89393929ff3875b7..3bd0fc098ce9f8b13c125436ddfce3be7ceb801e 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -62,7 +62,7 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu() registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery))); enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2)); - + LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml"); updateMenuItemsVisibility(menu); @@ -321,7 +321,7 @@ void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLS if (!new_name.empty()) { LLUUID id = notification["payload"]["id"].asUUID(); - + LLViewerInventoryCategory* cat = gInventory.getCategory(id); if(cat && (cat->getName() != new_name)) { @@ -330,7 +330,7 @@ void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLS update_inventory_category(cat->getUUID(),updates, NULL); return; } - + LLViewerInventoryItem* item = gInventory.getItem(id); if(item && (item->getName() != new_name)) { @@ -379,12 +379,12 @@ bool LLInventoryGalleryContextMenu::canSetUploadLocation(const LLSD& userdata) bool is_inbox_folder(LLUUID item_id) { const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); - + if (inbox_id.isNull()) { return false; } - + return gInventory.isObjectDescendentOf(item_id, inbox_id); } @@ -495,7 +495,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } } items.push_back(std::string("Purge Item")); - if (is_folder && !get_is_category_removable(&gInventory, selected_id)) + if (is_folder && !get_is_category_and_children_removable(&gInventory, selected_id, true)) { disabled_items.push_back(std::string("Purge Item")); } @@ -542,11 +542,16 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } items.push_back(std::string("Cut")); items.push_back(std::string("Delete")); - if(!get_is_category_removable(&gInventory, selected_id)) + + if(!get_is_category_and_children_removable(&gInventory, selected_id, false)) { disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } + else if (!get_is_category_and_children_removable(&gInventory, selected_id, true)) + { + disabled_items.push_back(std::string("Cut")); + } if(!is_inbox) { @@ -577,11 +582,15 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { items.push_back(std::string("Delete")); } - if(!get_is_item_removable(&gInventory, selected_id)) + if (!get_is_item_removable(&gInventory, selected_id, false)) { disabled_items.push_back(std::string("Delete")); disabled_items.push_back(std::string("Cut")); } + else if(!get_is_item_removable(&gInventory, selected_id, true)) + { + disabled_items.push_back(std::string("Cut")); + } if (selected_item && (selected_item->getInventoryType() != LLInventoryType::IT_CALLINGCARD) && !is_inbox && selected_item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) { @@ -616,7 +625,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("Open")); disabled_items.push_back(std::string("Open Original")); } - + if(LLAssetType::AT_GESTURE == obj->getType()) { items.push_back(std::string("Gesture Separator")); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 2e02e8c14dba485c524e005583b6134b9b835a89..43f904904b72fe34a9886bd1b01e0208329529fe 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1892,12 +1892,10 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, << " from " << make_inventory_info(item->getParentUUID()) << " to " << make_inventory_info(new_parent_id) << LL_ENDL; - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - accountForUpdate(update); + LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(), -1); + accountForUpdate(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1, false); + accountForUpdate(new_folder); LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); new_item->setParent(new_parent_id); @@ -1930,12 +1928,10 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, << " from " << make_inventory_info(cat->getParentUUID()) << " to " << make_inventory_info(new_parent_id) << LL_ENDL; - LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1); - update.push_back(new_folder); - accountForUpdate(update); + accountForUpdate(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1, false); + accountForUpdate(new_folder); LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); new_cat->setParent(new_parent_id); @@ -2707,7 +2703,10 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const { descendents_actual += update.mDescendentDelta; cat->setDescendentCount(descendents_actual); - cat->setVersion(++version); + if (update.mChangeVersion) + { + cat->setVersion(++version); + } LL_DEBUGS(LOG_INV) << "accounted: '" << cat->getName() << "' " << version << " with " << descendents_actual << " descendents." << LL_ENDL; @@ -2735,7 +2734,7 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const } void LLInventoryModel::accountForUpdate( - const LLInventoryModel::update_list_t& update) + const LLInventoryModel::update_list_t& update) const { update_list_t::const_iterator it = update.begin(); update_list_t::const_iterator end = update.end(); @@ -2746,7 +2745,7 @@ void LLInventoryModel::accountForUpdate( } void LLInventoryModel::accountForUpdate( - const LLInventoryModel::update_map_t& update) + const LLInventoryModel::update_map_t& update) const { LLCategoryUpdate up; update_map_t::const_iterator it = update.begin(); @@ -2875,6 +2874,17 @@ bool LLInventoryModel::loadSkeleton( gzip_filename.append(".gz"); LLFILE* fp = LLFile::fopen(gzip_filename, "rb"); bool remove_inventory_file = false; + if (LLAppViewer::instance()->isSecondInstance()) + { + // Safeguard viewer against trying to unpack file twice + // ex: user logs into two accounts simultaneously, so two + // viewers are trying to unpack library into same file + // + // Would be better to do it in gunzip_file, but it doesn't + // have access to llfilesystem + inventory_filename = gDirUtilp->getTempFilename(); + remove_inventory_file = true; + } if(fp) { fclose(fp); @@ -3087,7 +3097,7 @@ bool LLInventoryModel::loadSkeleton( // clean up the gunzipped file. LLFile::remove(inventory_filename); } - if(is_cache_obsolete) + if(is_cache_obsolete && !LLAppViewer::instance()->isSecondInstance()) { // If out of date, remove the gzipped file too. LL_WARNS(LOG_INV) << "Inv cache out of date, removing" << LL_ENDL; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 19b4795c3e4f1f9041cba4867d2c32676dd97adf..610f7b880504121b09e64c84129a797330086695 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -531,12 +531,14 @@ class LLInventoryModel // Represents the number of items added or removed from a category. struct LLCategoryUpdate { - LLCategoryUpdate() : mDescendentDelta(0) {} - LLCategoryUpdate(const LLUUID& category_id, S32 delta) : + LLCategoryUpdate() : mDescendentDelta(0), mChangeVersion(true) {} + LLCategoryUpdate(const LLUUID& category_id, S32 delta, bool change_version = true) : mCategoryID(category_id), - mDescendentDelta(delta) {} + mDescendentDelta(delta), + mChangeVersion(change_version) {} LLUUID mCategoryID; S32 mDescendentDelta; + bool mChangeVersion; }; typedef std::vector<LLCategoryUpdate> update_list_t; @@ -554,8 +556,8 @@ class LLInventoryModel // Call when there are category updates. Call them *before* the // actual update so the method can do descendent accounting correctly. void accountForUpdate(const LLCategoryUpdate& update) const; - void accountForUpdate(const update_list_t& updates); - void accountForUpdate(const update_map_t& updates); + void accountForUpdate(const update_list_t& updates) const; + void accountForUpdate(const update_map_t& updates) const; // Return (yes/no/maybe) child status of category children. EHasChildren categoryHasChildren(const LLUUID& cat_id) const; diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 9859b769ea2b7c41435dcf2c64df68a673fd3374..a57b049a390f4e20aee83fee3533e9244ff1522f 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -237,10 +237,9 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) // Can't access old mTextEntry fields as they are protected, so lets build new params // That is C&P from LLComboBox::createLineEditor function - static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0); S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0; LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button; + text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * BTN_DROP_SHADOW; LLLineEditor::Params params = p.combo_editor; params.rect(text_entry_rect); @@ -729,7 +728,7 @@ void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data) value["item_type"] = LANDMARK; value["AssetUUID"] = landmark_items[i]->getAssetUUID(); - add(landmark_items[i]->getName(), value); + addLocationHistoryEntry(landmark_items[i]->getName(), value); } //Let's add teleport history items @@ -756,7 +755,7 @@ void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data) value["region"] = result->mRegion; value["tooltip"] = LLSLURL(result->mGrid, result->mRegion, result->mLocalPos).getSLURLString(); - add(result->getTitle(), value); + addLocationHistoryEntry(result->getTitle(), value); } result = std::find_if(result + 1, th_items.end(), boost::bind( &LLLocationInputCtrl::findTeleportItemsByTitle, this, @@ -1018,6 +1017,17 @@ void LLLocationInputCtrl::positionMaturityButton() mMaturityButton->setVisible(rect.mRight < mTextEntry->getRect().getWidth() - right_pad); } +void LLLocationInputCtrl::addLocationHistoryEntry(const std::string& title, const LLSD& value) +{ + // SL-20286 : Duplication of autocomplete results occurs when entering some search queries in the navigation bar + // Exclude visual duplicates (items with the same titles) in the dropdown list + LLScrollListItem* item = mList->getItemByLabel(title); + if (!item) + { + add(title, value); + } +} + void LLLocationInputCtrl::rebuildLocationHistory(const std::string& filter) { LLLocationHistory::location_list_t filtered_items; @@ -1046,7 +1056,7 @@ void LLLocationInputCtrl::rebuildLocationHistory(const std::string& filter) value["grid"] = it->mGrid; value["region"] = it->mRegion; value["tooltip"] = LLSLURL(it->mGrid, it->mRegion, it->mLocalPos).getSLURLString(); - add(it->getLocation(), value); + addLocationHistoryEntry(it->getLocation(), value); } } diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 627bd3b3eb053c5aadb1bed7081d5a6bb62018f2..c2f9fa2229c0ae7f7251661fd87cec8ac3422821 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -149,6 +149,7 @@ class LLLocationInputCtrl void refreshMaturityButton(); void positionMaturityButton(); + void addLocationHistoryEntry(const std::string& title, const LLSD& value); void rebuildLocationHistory(const std::string& filter = LLStringUtil::null); bool findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter); void setText(const LLStringExplicit& text); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index cdc929d29606de92889aed4428d527cb352cb607..0dcd89f194c5b9babddbd16333183351d5255133 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -635,6 +635,27 @@ std::string LLLogChat::oldLogFileName(std::string filename) return scanResult; } +bool LLLogChat::transcriptFilesExist() +{ + std::string pattern = "*." + LL_TRANSCRIPT_FILE_EXTENSION; + // get Users log directory + std::string dirname = gDirUtilp->getPerAccountChatLogsDir(); + + // add final OS dependent delimiter + dirname += gDirUtilp->getDirDelimiter(); + + LLDirIterator iter(dirname, pattern); + std::string filename; + while (iter.next(filename)) + { + std::string fullname = gDirUtilp->add(dirname, filename); + if (isTranscriptFileFound(fullname)) + { + return true; + } + } + return false; +} // static void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions) { diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index 009a528f44403ab8c82e6cadbd5c4305edafdcc0..fb51c250704a81b3129beb7b29d0ac2ea451fcd7 100644 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -103,6 +103,7 @@ class LLLogChat final : public LLSingleton<LLLogChat> const std::string& from, const LLUUID& from_id, const std::string& line); + static bool transcriptFilesExist(); static void findTranscriptFiles(std::string pattern, std::vector<std::string>& list_of_transcriptions); static void getListOfTranscriptFiles(std::vector<std::string>& list); static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions); diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 8d87136e0ada0d6215ad9b473a294c947ba4cae0..4ca123e0cad9dc4dbab91b4e5ec570e460fa7815 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -451,13 +451,13 @@ void LLModelPreview::rebuildUploadData() // That's ok, but might not what they wanted. Use default_physics_shape if found. std::ostringstream out; out << "No physics model specified for " << instance.mLabel; - if (mDefaultPhysicsShapeP) + if (mDefaultPhysicsShapeP.notNull()) { out << " - using: " << DEFAULT_PHYSICS_MESH_NAME; lod_model = mDefaultPhysicsShapeP; } LL_WARNS() << out.str() << LL_ENDL; - LLFloaterModelPreview::addStringToLog(out, !mDefaultPhysicsShapeP); // Flash log tab if no default. + LLFloaterModelPreview::addStringToLog(out, mDefaultPhysicsShapeP.isNull()); // Flash log tab if no default. } if (lod_model) @@ -1090,8 +1090,9 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) if (loaded_lod == LLModel::LOD_PHYSICS) { // Explicitly loading physics. See if there is a default mesh. LLMatrix4 ignored_transform; // Each mesh that uses this will supply their own. - mDefaultPhysicsShapeP = nullptr; - FindModel(mScene[loaded_lod], DEFAULT_PHYSICS_MESH_NAME + getLodSuffix(loaded_lod), mDefaultPhysicsShapeP, ignored_transform); + LLModel* out_model = nullptr; + FindModel(mScene[loaded_lod], DEFAULT_PHYSICS_MESH_NAME + getLodSuffix(loaded_lod), out_model, ignored_transform); + mDefaultPhysicsShapeP = out_model; mWarnOfUnmatchedPhyicsMeshes = true; } BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 46bc9fd8ecfa3042259b94cdfb19c3464226e4aa..213b8fdc023c5e17376e5e8072576039d6df97e3 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -240,7 +240,7 @@ class LLModelPreview final : public LLViewerDynamicTexture, public LLMutex /// It is set only when the user chooses a physics shape file that contains a mesh with a name that matches DEFAULT_PHYSICS_MESH_NAME. /// It is reset when such a name is not found, and when resetting the modelpreview. /// Not read unless mWarnOfUnmatchedPhyicsMeshes is true. - LLModel* mDefaultPhysicsShapeP{}; + LLPointer<LLModel> mDefaultPhysicsShapeP; typedef enum { diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index a24b249f70231b7de66a258586452dab0bb9c7e7..1a4d57f17927bda123d6be8d1870b9f52f36b6d8 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -355,10 +355,9 @@ void LLNavigationBar::draw() { if (isBackgroundVisible()) { - static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0); static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow"); gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - color_drop_shadow, drop_shadow_floater ); + color_drop_shadow, DROP_SHADOW_FLOATER); } LLPanel::draw(); diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index fdf90a704a29dcc7fa148919f95defcdcbbccb61..9936cd937b24887fc0130ef039931116ca4e3cd2 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -50,7 +50,7 @@ LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notif mIsModal(is_modal) { LLScreenChannelBase::Params p; - p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID")); + p.id = ALERT_CHANNEL_UUID; p.display_toasts_always = true; p.toast_align = NA_CENTRE; p.channel_align = CA_CENTRE; diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 26824895a8cfb73285391393aa3594eb128c6e83..b3db6d5a63b438da2995e88026a7e3174ccebdc7 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -57,8 +57,7 @@ LLGroupHandler::~LLGroupHandler() void LLGroupHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 4f39725fa29fd34deb401963ef82586f60003d8e..31628a4137ead67ce3b69149a86e9acc1a3edc9a 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -66,8 +66,7 @@ LLOfferHandler::~LLOfferHandler() void LLOfferHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index c8e69b566266c10bd28a42e29bd79bb06b012131..4db4f977953929f64831af6fb66e1d6a2d9d4c4e 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -66,8 +66,7 @@ LLScriptHandler::~LLScriptHandler() void LLScriptHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index d2e1d69319e33034f73a89cec2f84a6792105fa0..7bb3e33a7b11944a271929cfe4eb3361ff51df3e 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -61,8 +61,7 @@ LLTipHandler::~LLTipHandler() void LLTipHandler::initChannel() { S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mChannel.get()->init(channel_right_bound - channel_width, channel_right_bound); + mChannel.get()->init(channel_right_bound - NOTIFY_BOX_WIDTH, channel_right_bound); } //-------------------------------------------------------------------------- diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 3d4561b2252b1fc9df429d8599e94f567b071fff..ee9ecab55e405c81554dacff6830c0836e1225ec 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -780,7 +780,7 @@ void LLOutfitListBase::onOpen(const LLSD& info) // Start observing changes in "My Outfits" category. mCategoriesObserver->addCategory(outfits, - boost::bind(&LLOutfitListBase::refreshList, this, outfits)); + boost::bind(&LLOutfitListBase::observerCallback, this, outfits)); // Start observing changes in Current Outfit category. //const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); @@ -800,6 +800,13 @@ void LLOutfitListBase::onOpen(const LLSD& info) } } +void LLOutfitListBase::observerCallback(const LLUUID& category_id) +{ + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + mChangedItems.insert(changed_items.begin(), changed_items.end()); + refreshList(category_id); +} + void LLOutfitListBase::refreshList(const LLUUID& category_id) { bool wasNull = mRefreshListState.CategoryUUID.isNull(); @@ -904,24 +911,22 @@ void LLOutfitListBase::onIdleRefreshList() // Get changed items from inventory model and update outfit tabs // which might have been renamed. - const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); - for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); - items_iter != changed_items.end(); - ++items_iter) + while (!mChangedItems.empty()) { + std::set<LLUUID>::const_iterator items_iter = mChangedItems.begin(); LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter); - if (!cat) + mChangedItems.erase(items_iter); + + // Links aren't supposed to be allowed here, check only cats + if (cat) { - LLInventoryObject* obj = gInventory.getObject(*items_iter); - if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) - { - break; - } - cat = (LLViewerInventoryCategory*)obj; + std::string name = cat->getName(); + updateChangedCategoryName(cat, name); } - std::string name = cat->getName(); - updateChangedCategoryName(cat, name); + curent_time = LLTimer::getTotalSeconds(); + if (curent_time >= end_time) + return; } sortOutfits(); diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 527ce3e3a8e6a595ed3cd2790b6993058cba5555..5f4d073ed32f68a4b7d3d31ffd09bc0d2bd494fa 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -113,6 +113,7 @@ class LLOutfitListBase : public LLPanelAppearanceTab void updateAvatarComplexity(U32 complexity); protected: + void observerCallback(const LLUUID& category_id); virtual LLOutfitListGearMenuBase* createGearMenu() = 0; virtual void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id) = 0; virtual void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) = 0; @@ -131,6 +132,7 @@ class LLOutfitListBase : public LLPanelAppearanceTab uuid_vec_t::const_iterator AddedIterator; uuid_vec_t::const_iterator RemovedIterator; } mRefreshListState; + std::set<LLUUID> mChangedItems; bool mIsInitialized; LLInventoryCategoriesObserver* mCategoriesObserver; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 4c097bb0451d005e1f0e94024ab9535b72cb59bb..ab3661ffcd185930750af8ff19e1e1b9dbc635a2 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -128,6 +128,54 @@ void LLPanelProfileTab::setApplyProgress(bool started) } } +static void put_avatar_properties_coro(std::string cap_url, LLUUID agent_id, LLSD data, std::function<void(bool)> callback) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("put_avatar_properties_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + std::string finalUrl = cap_url + "/" + agent_id.asString(); + + LLSD result = httpAdapter->putAndSuspend(httpRequest, finalUrl, data, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("AvatarProperties") << "Failed to put agent information " << data << " for id " << agent_id << LL_ENDL; + } + else + { + LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Data: " << data << " Result: " << httpResults << LL_ENDL; + } + + if (callback) + { + callback(status); + } +} + +bool LLPanelProfileTab::saveAgentUserInfoCoro(std::string name, LLSD value, std::function<void(bool)> callback) const +{ + std::string cap_url = gAgent.getRegionCapability("AgentProfile"); + if (cap_url.empty()) + { + LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; + return false; + } + + LLCoros::instance().launch("putAgentUserInfoCoro", + boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with(name, value), callback)); + + return true; +} + LLPanelProfilePropertiesProcessorTab::LLPanelProfilePropertiesProcessorTab() : LLPanelProfileTab() { @@ -153,3 +201,13 @@ void LLPanelProfilePropertiesProcessorTab::setAvatarId(const LLUUID & avatar_id) LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this); } } + +void LLPanelProfilePropertiesProcessorTab::updateData() +{ + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); + } +} diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index f182660c8ea68cbe09626c5d2f4e042e9f317695..ec620b39e1620a10b6f09a184e4cb047a73c1876 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -92,17 +92,17 @@ class LLPanelProfileTab /** * Returns avatar ID. */ - virtual const LLUUID& getAvatarId() { return mAvatarId; } + virtual const LLUUID& getAvatarId() const { return mAvatarId; } /** * Sends update data request to server. */ - virtual void updateData() {}; + virtual void updateData(){}; /** * Clears panel data if viewing avatar info for first time and sends update data request. */ - virtual void onOpen(const LLSD& key); + virtual void onOpen(const LLSD& key) override; /** * Clears all data received from server. @@ -133,6 +133,8 @@ class LLPanelProfileTab const bool getSelfProfile() const { return mSelfProfile; } + bool saveAgentUserInfoCoro(std::string name, LLSD value, std::function<void(bool)> callback = nullptr) const; + public: void setIsLoading() { mLoadingState = PROFILE_LOADING; } void resetLoading() { mLoadingState = PROFILE_INIT; } @@ -158,12 +160,14 @@ class LLPanelProfilePropertiesProcessorTab LLPanelProfilePropertiesProcessorTab(); ~LLPanelProfilePropertiesProcessorTab(); - /*virtual*/ void setAvatarId(const LLUUID& avatar_id); + void setAvatarId(const LLUUID& avatar_id) override; + + void updateData() override; /** * Processes data received from server via LLAvatarPropertiesObserver. */ - virtual void processProperties(void* data, EAvatarProcessorType type) = 0; + virtual void processProperties(void* data, EAvatarProcessorType type) override = 0; }; #endif // LL_LLPANELAVATAR_H diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 53c7a899e949d2a3c3163e724f7c44b35c058609..b8b95fc711a8e3692df07413770a14e96d4958e0 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -121,6 +121,11 @@ LLPanelClassifiedInfo::~LLPanelClassifiedInfo() LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); } sAllPanels.remove(this); + + if (getAvatarId().notNull()) + { + LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this); + } } // static diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 82dea0222efed15c9066ae35ff901c4623809350..e34cfd0b2607a2f56c516289f37d3e1a001616f5 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -138,6 +138,15 @@ void LLPanelGroup::onOpen(const LLSD& key) if(panel_notices) panel_notices->refreshNotices(); } + else if (str_action == "show_notices") + { + setGroupID(group_id); + + LLAccordionCtrl *tab_ctrl = getChild<LLAccordionCtrl>("groups_accordion"); + tab_ctrl->collapseAllTabs(); + getChild<LLAccordionCtrlTab>("group_notices_tab")->setDisplayChildren(true); + tab_ctrl->arrange(); + } // [SL:KB] - Patch: Notification-GroupCreateNotice | Checked: 2012-02-16 (Catznip-3.2) else if(str_action == "view_notices") { @@ -283,8 +292,15 @@ void LLPanelGroup::onBtnGroupChatClicked(void* user_data) void LLPanelGroup::onBtnJoin() { - LL_DEBUGS() << "joining group: " << mID << LL_ENDL; - LLGroupActions::join(mID); + if (LLGroupActions::isInGroup(mID)) + { + LLGroupActions::leave(mID); + } + else + { + LL_DEBUGS() << "joining group: " << mID << LL_ENDL; + LLGroupActions::join(mID); + } } void LLPanelGroup::changed(LLGroupChange gc) @@ -334,12 +350,17 @@ void LLPanelGroup::update(LLGroupChange gc) LLGroupData agent_gdatap; bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery(); - bool join_btn_visible = !is_member && gdatap->mOpenEnrollment; + bool join_btn_visible = is_member || gdatap->mOpenEnrollment; mButtonJoin->setVisible(join_btn_visible); mJoinText->setVisible(join_btn_visible); - if(join_btn_visible) + if (is_member) + { + mJoinText->setValue(getString("group_member")); + mButtonJoin->setLabel(getString("leave_txt")); + } + else if(join_btn_visible) { LLStringUtil::format_map_t string_args; std::string fee_buff; @@ -354,6 +375,7 @@ void LLPanelGroup::update(LLGroupChange gc) fee_buff = getString("group_join_free", string_args); } mJoinText->setValue(fee_buff); + mButtonJoin->setLabel(getString("join_txt")); } } } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index b71a63267f261c1aad641d2270179ce61917d251..41ca5d8d20cf29d8735eda5b363036b527e8a864 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -250,6 +250,7 @@ BOOL LLPanelGroupNotices::postBuild() mNoticesList = getChild<LLScrollListCtrl>("notice_list",recurse); mNoticesList->setCommitOnSelectionChange(TRUE); mNoticesList->setCommitCallback(onSelectNotice, this); + mNoticesList->sortByColumn("date", false); mBtnNewMessage = getChild<LLButton>("create_new_notice",recurse); mBtnNewMessage->setClickedCallback(onClickNewMessage, this); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index e3faefcb98a69a072e6cb076dde0709544912832..6a17cf04e2e53cda5968989146843cd3c1826f0d 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -287,7 +287,7 @@ BOOL LLPanelObject::postBuild() mCtrlSculptTexture = getChild<LLTextureCtrl>("sculpt texture control"); if (mCtrlSculptTexture) { - mCtrlSculptTexture->setDefaultImageAssetID(LLUUID(SCULPT_DEFAULT_TEXTURE)); + mCtrlSculptTexture->setDefaultImageAssetID(SCULPT_DEFAULT_TEXTURE); mCtrlSculptTexture->setCommitCallback( boost::bind(&LLPanelObject::onCommitSculpt, this, _2 )); mCtrlSculptTexture->setOnCancelCallback( boost::bind(&LLPanelObject::onCancelSculpt, this, _2 )); mCtrlSculptTexture->setOnSelectCallback( boost::bind(&LLPanelObject::onSelectSculpt, this, _2 )); @@ -2297,7 +2297,7 @@ void LLPanelObject::onCancelSculpt(const LLSD& data) { if(mSculptTextureRevert.isNull()) { - mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE); + mSculptTextureRevert = SCULPT_DEFAULT_TEXTURE; } mCtrlSculptTexture->setImageAssetID(mSculptTextureRevert); @@ -2562,7 +2562,7 @@ void LLPanelObject::onCopyParams() } else { - mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); + mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; } mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index f54ec59eca5c0da0eee7fbf3a1f927563596b01a..ed2ca6395f4d87de7ee3c8c872ef1a1e11887339 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -135,7 +135,7 @@ class LLTaskInvFVBridge : public LLFolderViewModelItemInventory virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); virtual BOOL isItemMovable() const; - virtual BOOL isItemRemovable() const; + virtual BOOL isItemRemovable(bool check_worn = true) const; virtual BOOL removeItem(); virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); virtual void move(LLFolderViewModelItem* parent_listener); @@ -379,7 +379,7 @@ BOOL LLTaskInvFVBridge::isItemMovable() const return TRUE; } -BOOL LLTaskInvFVBridge::isItemRemovable() const +BOOL LLTaskInvFVBridge::isItemRemovable(bool check_worn) const { const LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID()); // [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-1.0.5a @@ -684,7 +684,7 @@ class LLTaskCategoryBridge : public LLTaskInvFVBridge virtual BOOL isItemRenameable() const; // virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL renameItem(const std::string& new_name); - virtual BOOL isItemRemovable() const; + virtual BOOL isItemRemovable(bool check_worn = true) const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual bool hasChildren() const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; @@ -744,7 +744,7 @@ BOOL LLTaskCategoryBridge::renameItem(const std::string& new_name) return FALSE; } -BOOL LLTaskCategoryBridge::isItemRemovable() const +BOOL LLTaskCategoryBridge::isItemRemovable(bool check_worn) const { return FALSE; } diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 701d0ab42261c4f2ee7ff78c1ad6de036d4fa9e2..f5088e007b6b9fa8b59825a687ef9e033d4364c7 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -72,7 +72,6 @@ //#include "llpanelblockedlist.h" #include "llpanelprofileclassifieds.h" #include "llpanelprofilepicks.h" -#include "llthumbnailctrl.h" #include "lltrans.h" #include "llviewercontrol.h" #include "llviewermenu.h" //is_agent_mappable @@ -104,216 +103,6 @@ static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; ////////////////////////////////////////////////////////////////////////// -void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("request_avatar_properties_coro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t httpHeaders; - - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); - httpOpts->setFollowRedirects(true); - - std::string finalUrl = cap_url + "/" + agent_id.asString(); - - LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl, httpOpts, httpHeaders); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Result: " << httpResults << LL_ENDL; - - if (!status - || !result.has("id") - || agent_id != result["id"].asUUID()) - { - LL_WARNS("AvatarProperties") << "Failed to get agent information for id " << agent_id << LL_ENDL; - return; - } - - LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", agent_id)); - if (!floater_profile) - { - // floater is dead, so panels are dead as well - return; - } - - LLPanel *panel = floater_profile->findChild<LLPanel>(PANEL_PROFILE_VIEW, TRUE); - LLPanelProfile *panel_profile = dynamic_cast<LLPanelProfile*>(panel); - if (!panel_profile) - { - LL_WARNS() << PANEL_PROFILE_VIEW << " not found" << LL_ENDL; - return; - } - - - // Avatar Data - - LLAvatarData *avatar_data = &panel_profile->mAvatarData; - std::string birth_date; - - avatar_data->agent_id = agent_id; - avatar_data->avatar_id = agent_id; - avatar_data->image_id = result["sl_image_id"].asUUID(); - avatar_data->fl_image_id = result["fl_image_id"].asUUID(); - avatar_data->partner_id = result["partner_id"].asUUID(); - avatar_data->about_text = result["sl_about_text"].asString(); - avatar_data->fl_about_text = result["fl_about_text"].asString(); - avatar_data->born_on = result["member_since"].asDate(); - avatar_data->profile_url = getProfileURL(agent_id.asString()); - avatar_data->customer_type = result["customer_type"].asString(); - - avatar_data->flags = 0; - - if (result["online"].asBoolean()) - { - avatar_data->flags |= AVATAR_ONLINE; - } - if (result["allow_publish"].asBoolean()) - { - avatar_data->flags |= AVATAR_ALLOW_PUBLISH; - } - if (result["identified"].asBoolean()) - { - avatar_data->flags |= AVATAR_IDENTIFIED; - } - if (result["transacted"].asBoolean()) - { - avatar_data->flags |= AVATAR_TRANSACTED; - } - - avatar_data->caption_index = 0; - if (result.has("charter_member")) // won't be present if "caption" is set - { - avatar_data->caption_index = result["charter_member"].asInteger(); - } - else if (result.has("caption")) - { - avatar_data->caption_text = result["caption"].asString(); - } - - panel = floater_profile->findChild<LLPanel>(PANEL_SECONDLIFE, TRUE); - LLPanelProfileSecondLife *panel_sl = dynamic_cast<LLPanelProfileSecondLife*>(panel); - if (panel_sl) - { - panel_sl->processProfileProperties(avatar_data); - } - - panel = floater_profile->findChild<LLPanel>(PANEL_WEB, TRUE); - LLPanelProfileWeb *panel_web = dynamic_cast<LLPanelProfileWeb*>(panel); - if (panel_web) - { - panel_web->setLoaded(); - } - - panel = floater_profile->findChild<LLPanel>(PANEL_FIRSTLIFE, TRUE); - LLPanelProfileFirstLife *panel_first = dynamic_cast<LLPanelProfileFirstLife*>(panel); - if (panel_first) - { - panel_first->processProperties(avatar_data); - } - - // Picks - - LLSD picks_array = result["picks"]; - LLAvatarPicks avatar_picks; - avatar_picks.agent_id = agent_id; // Not in use? - avatar_picks.target_id = agent_id; - - for (LLSD::array_const_iterator it = picks_array.beginArray(); it != picks_array.endArray(); ++it) - { - const LLSD& pick_data = *it; - avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); - } - - panel = floater_profile->findChild<LLPanel>(PANEL_PICKS, TRUE); - LLPanelProfilePicks *panel_picks = dynamic_cast<LLPanelProfilePicks*>(panel); - if (panel_picks) - { - // Refresh pick limit before processing - LLAgentPicksInfo::getInstance()->onServerRespond(&avatar_picks); - panel_picks->processProperties(&avatar_picks); - } - - // Groups - - LLSD groups_array = result["groups"]; - LLAvatarGroups avatar_groups; - avatar_groups.agent_id = agent_id; // Not in use? - avatar_groups.avatar_id = agent_id; // target_id - - for (LLSD::array_const_iterator it = groups_array.beginArray(); it != groups_array.endArray(); ++it) - { - const LLSD& group_info = *it; - LLAvatarGroups::LLGroupData group_data; - group_data.group_powers = 0; // Not in use? - group_data.group_title = group_info["name"].asString(); // Missing data, not in use? - group_data.group_id = group_info["id"].asUUID(); - group_data.group_name = group_info["name"].asString(); - group_data.group_insignia_id = group_info["image_id"].asUUID(); - - avatar_groups.group_list.push_back(group_data); - } - - if (panel_sl) - { - panel_sl->processGroupProperties(&avatar_groups); - } - - // Notes - LLAvatarNotes avatar_notes; - - avatar_notes.agent_id = agent_id; - avatar_notes.target_id = agent_id; - avatar_notes.notes = result["notes"].asString(); - - panel = floater_profile->findChild<LLPanel>(PANEL_NOTES, TRUE); - LLPanelProfileNotes *panel_notes = dynamic_cast<LLPanelProfileNotes*>(panel); - if (panel_notes) - { - panel_notes->processProperties(&avatar_notes); - } -} - -//TODO: changes take two minutes to propagate! -// Add some storage that holds updated data for two minutes -// for new instances to reuse the data -// Profile data is only relevant to own avatar, but notes -// are for everybody (no onger an issue?) -void put_avatar_properties_coro(std::string cap_url, LLUUID agent_id, LLSD data, std::function<void(bool)> callback) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("put_avatar_properties_coro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t httpHeaders; - - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); - httpOpts->setFollowRedirects(true); - - std::string finalUrl = cap_url + "/" + agent_id.asString(); - - LLSD result = httpAdapter->putAndSuspend(httpRequest, finalUrl, data, httpOpts, httpHeaders); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status) - { - LL_WARNS("AvatarProperties") << "Failed to put agent information " << data << " for id " << agent_id << LL_ENDL; - } - else - { - LL_DEBUGS("AvatarProperties") << "Agent id: " << agent_id << " Data: " << data << " Result: " << httpResults << LL_ENDL; - } - - if (callback) - { - callback(status); - } -} - ////////////////////////////////////////////////////////////////////////// // LLWebProfileHandler @@ -748,11 +537,12 @@ void LLFloaterProfilePermissions::onCancel() // LLPanelProfileSecondLife LLPanelProfileSecondLife::LLPanelProfileSecondLife() - : LLPanelProfileTab() + : LLPanelProfilePropertiesProcessorTab() , mAvatarNameCacheConnection() , mHasUnsavedDescriptionChanges(false) , mWaitingForImageUpload(false) , mAllowPublish(false) + , mHideAge(false) { mCommitCallbackRegistrar.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); mEnableCallbackRegistrar.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); @@ -786,7 +576,8 @@ BOOL LLPanelProfileSecondLife::postBuild() { mGroupList = getChild<LLGroupList>("group_list"); mShowInSearchCombo = getChild<LLComboBox>("show_in_search"); - mSecondLifePic = getChild<LLThumbnailCtrl>("2nd_life_pic"); + mHideAgeCombo = getChild<LLComboBox>("hide_age"); + mSecondLifePic = getChild<LLProfileImageCtrl>("2nd_life_pic"); mSecondLifePicLayout = getChild<LLPanel>("image_panel"); mDescriptionEdit = getChild<LLTextEditor>("sl_description_edit"); mAgentActionMenuButton = getChild<LLMenuButton>("agent_actions_menu"); @@ -800,6 +591,7 @@ BOOL LLPanelProfileSecondLife::postBuild() mCantEditObjectsIcon = getChild<LLIconCtrl>("cant_edit_objects"); mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); + mHideAgeCombo->setCommitCallback([this](LLUICtrl*, void*) { onHideAgeCallback(); }, nullptr); mGroupList->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { LLPanelProfileSecondLife::openGroupProfile(); }); mGroupList->setReturnCallback([this](LLUICtrl*, const LLSD&) { LLPanelProfileSecondLife::openGroupProfile(); }); mSaveDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); @@ -874,26 +666,6 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); } -void LLPanelProfileSecondLife::updateData() -{ - LLUUID avatar_id = getAvatarId(); - if (!getStarted() && avatar_id.notNull()) - { - setIsLoading(); - - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLCoros::instance().launch("requestAgentUserInfoCoro", - boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); - } - else - { - LL_WARNS() << "Failed to update profile data, no cap found" << LL_ENDL; - } - } -} - void LLPanelProfileSecondLife::refreshName() { if (!mAvatarNameCacheConnection.connected()) @@ -908,10 +680,9 @@ void LLPanelProfileSecondLife::resetData() // Set default image and 1:1 dimensions for it mSecondLifePic->setValue("Generic_Person_Large"); - mImageId = LLUUID::null; LLRect imageRect = mSecondLifePicLayout->getRect(); - mSecondLifePicLayout->reshape(imageRect.getHeight(), imageRect.getHeight()); + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); setDescriptionText(LLStringUtil::null); mGroups.clear(); @@ -937,6 +708,18 @@ void LLPanelProfileSecondLife::resetData() childSetVisible("partner_spacer_layout", TRUE); } +void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProfileProperties(avatar_data); + } + } +} + void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) { const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); @@ -956,22 +739,18 @@ void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avat fillAccountStatus(avatar_data); - setLoaded(); -} - -void LLPanelProfileSecondLife::processGroupProperties(const LLAvatarGroups* avatar_groups) -{ - - LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); - const LLAvatarGroups::group_list_t::const_iterator it_end = avatar_groups->group_list.end(); + LLAvatarData::group_list_t::const_iterator it = avatar_data->group_list.begin(); + const LLAvatarData::group_list_t::const_iterator it_end = avatar_data->group_list.end(); for (; it_end != it; ++it) { - LLAvatarGroups::LLGroupData group_data = *it; + LLAvatarData::LLGroupData group_data = *it; mGroups[group_data.group_name] = group_data.group_id; } mGroupList->setGroups(mGroups); + + setLoaded(); } void LLPanelProfileSecondLife::openGroupProfile() @@ -1005,36 +784,12 @@ void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) { mSecondLifePic->setValue(image_asset_id); - mImageId = image_asset_id; - - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(image_asset_id); - if (imagep->getFullHeight()) - { - onImageLoaded(true, imagep); - } - else - { - imagep->setLoadedCallback(onImageLoaded, - MAX_DISCARD_LEVEL, - FALSE, - FALSE, - new LLHandle<LLPanel>(getHandle()), - NULL, - FALSE); - } LLFloater *floater = mFloaterProfileTextureHandle.get(); if (floater) { LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); - if (mImageId.notNull()) - { - texture_view->loadAsset(mImageId); - } - else - { - texture_view->resetAsset(); - } + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); } setProfileImageUploading(false); @@ -1078,42 +833,16 @@ void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) // and to make sure icons in text will be up to date LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); - fillAgeData(avatar_data->born_on); + fillAgeData(avatar_data); setDescriptionText(avatar_data->about_text); - if (avatar_data->image_id.notNull()) - { - mSecondLifePic->setValue(avatar_data->image_id); - mImageId = avatar_data->image_id; - } - else - { - mSecondLifePic->setValue("Generic_Person_Large"); - mImageId = LLUUID::null; - } - - // Will be loaded as a LLViewerFetchedTexture::BOOST_UI due to mSecondLifePic - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(avatar_data->image_id); - if (imagep->getFullHeight()) - { - onImageLoaded(true, imagep); - } - else - { - imagep->setLoadedCallback(onImageLoaded, - MAX_DISCARD_LEVEL, - FALSE, - FALSE, - new LLHandle<LLPanel>(getHandle()), - NULL, - FALSE); - } + mSecondLifePic->setValue(avatar_data->image_id); if (getSelfProfile()) { mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; - mShowInSearchCombo->setValue((BOOL)mAllowPublish); + mShowInSearchCombo->setValue(mAllowPublish ? TRUE : FALSE); } } @@ -1252,21 +981,47 @@ void LLPanelProfileSecondLife::fillRightsData() } } -void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) +void LLPanelProfileSecondLife::fillAgeData(const LLAvatarData* avatar_data) { // Date from server comes already converted to stl timezone, // so display it as an UTC + 0 - std::string name_and_date = getString("date_format"); + bool hide_age = avatar_data->hide_age && !getSelfProfile(); + std::string name_and_date = getString(hide_age ? "date_format_short" : "date_format_full"); LLSD args_name; - args_name["datetime"] = (S32)born_on.secondsSinceEpoch(); + args_name["datetime"] = (S32)avatar_data->born_on.secondsSinceEpoch(); LLStringUtil::format(name_and_date, args_name); getChild<LLUICtrl>("sl_birth_date")->setValue(name_and_date); - std::string register_date = getString("age_format"); - LLSD args_age; - args_age["[AGE]"] = LLDateUtil::ageFromDate(born_on, LLDate::now()); - LLStringUtil::format(register_date, args_age); - getChild<LLUICtrl>("user_age")->setValue(register_date); + LLUICtrl* userAgeCtrl = getChild<LLUICtrl>("user_age"); + if (hide_age) + { + userAgeCtrl->setVisible(FALSE); + } + else + { + std::string register_date = getString("age_format"); + LLSD args_age; + args_age["[AGE]"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); + LLStringUtil::format(register_date, args_age); + userAgeCtrl->setValue(register_date); + } + + BOOL showHideAgeCombo = FALSE; + if (getSelfProfile()) + { + if (LLAvatarPropertiesProcessor::getInstance()->isHideAgeSupportedByServer()) + { + F64 birth = avatar_data->born_on.secondsSinceEpoch(); + F64 now = LLDate::now().secondsSinceEpoch(); + if (now - birth > 365 * 24 * 60 * 60) + { + mHideAge = avatar_data->hide_age; + mHideAgeCombo->setValue(mHideAge ? TRUE : FALSE); + showHideAgeCombo = TRUE; + } + } + } + mHideAgeCombo->setVisible(showHideAgeCombo); } void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep) @@ -1283,34 +1038,6 @@ void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTextur } } -//static -void LLPanelProfileSecondLife::onImageLoaded(BOOL success, - LLViewerFetchedTexture *src_vi, - LLImageRaw* src, - LLImageRaw* aux_src, - S32 discard_level, - BOOL final, - void* userdata) -{ - if (!userdata) return; - - LLHandle<LLPanel>* handle = (LLHandle<LLPanel>*)userdata; - - if (!handle->isDead()) - { - LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(handle->get()); - if (panel) - { - panel->onImageLoaded(success, src_vi); - } - } - - if (final || !success) - { - delete handle; - } -} - // virtual, called by LLAvatarTracker void LLPanelProfileSecondLife::changed(U32 mask) { @@ -1341,7 +1068,7 @@ void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); } - LLPanelProfileTab::setAvatarId(avatar_id); + LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); if (LLAvatarActions::isFriend(getAvatarId())) { @@ -1383,6 +1110,10 @@ void LLPanelProfileSecondLife::setLoaded() if (getSelfProfile()) { mShowInSearchCombo->setEnabled(TRUE); + if (mHideAgeCombo->getVisible()) + { + mHideAgeCombo->setEnabled(TRUE); + } mDescriptionEdit->setEnabled(TRUE); } } @@ -1495,7 +1226,7 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) } else if (item_name == "upload_photo") { - (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle<LLPanel>(getHandle()), + (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle<LLPanel>(LLPanel::getHandle()), [this] (LLUUID const& id) { setProfileImageUploaded(id); }))->getFile(); LLFloater* floaterp = mFloaterTexturePickerHandle.get(); @@ -1572,7 +1303,7 @@ bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) else if (item_name == "remove_photo") { std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - return mImageId.notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + return mSecondLifePic->getImageAssetId().notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); } return false; @@ -1636,39 +1367,28 @@ void LLPanelProfileSecondLife::onSetDescriptionDirty() void LLPanelProfileSecondLife::onShowInSearchCallback() { - S32 value = mShowInSearchCombo->getValue().asInteger(); - if (mAllowPublish == (bool)value) - { + bool value = mShowInSearchCombo->getValue().asInteger(); + if (value == mAllowPublish) return; - } - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - mAllowPublish = value; - LLSD data; - data["allow_publish"] = mAllowPublish; - LLCoros::instance().launch("putAgentUserInfoCoro", - boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), data, nullptr)); - } - else - { - LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; - } + + mAllowPublish = value; + saveAgentUserInfoCoro("allow_publish", value); +} + +void LLPanelProfileSecondLife::onHideAgeCallback() +{ + bool value = mHideAgeCombo->getValue().asInteger(); + if (value == mHideAge) + return; + + mHideAge = value; + saveAgentUserInfoCoro("hide_age", value); } void LLPanelProfileSecondLife::onSaveDescriptionChanges() { mDescriptionText = mDescriptionEdit->getValue().asString(); - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLCoros::instance().launch("putAgentUserInfoCoro", - boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("sl_about_text", mDescriptionText), nullptr)); - } - else - { - LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; - } + saveAgentUserInfoCoro("sl_about_text", mDescriptionText); mSaveDescriptionChanges->setEnabled(FALSE); mDiscardDescriptionChanges->setEnabled(FALSE); @@ -1718,9 +1438,9 @@ void LLPanelProfileSecondLife::onShowAgentProfileTexture() { LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); mFloaterProfileTextureHandle = texture_view->getHandle(); - if (mImageId.notNull()) + if (mSecondLifePic->getImageAssetId().notNull()) { - texture_view->loadAsset(mImageId); + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); } else { @@ -1737,9 +1457,9 @@ void LLPanelProfileSecondLife::onShowAgentProfileTexture() LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); texture_view->setMinimized(FALSE); texture_view->setVisibleAndFrontmost(TRUE); - if (mImageId.notNull()) + if (mSecondLifePic->getImageAssetId().notNull()) { - texture_view->loadAsset(mImageId); + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); } else { @@ -1762,10 +1482,10 @@ void LLPanelProfileSecondLife::onShowTexturePicker() getWindow()->setCursor(UI_CURSOR_WAIT); LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( this, - mImageId, + mSecondLifePic->getImageAssetId(), LLUUID::null, LLUUID::null, - mImageId, + mSecondLifePic->getImageAssetId(), FALSE, FALSE, "SELECT PHOTO", @@ -1803,56 +1523,37 @@ void LLPanelProfileSecondLife::onShowTexturePicker() void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) { - if (mImageId == id) - { + if (mSecondLifePic->getImageAssetId() == id) return; - } - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) + std::function<void(bool)> callback = [id](bool result) { - std::function<void(bool)> callback = [id](bool result) - { - if (result) - { - LLAvatarIconIDCache::getInstance()->add(gAgentID, id); - // Should trigger callbacks in icon controls - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); - } - }; - LLSD params; - params["sl_image_id"] = id; - LLCoros::instance().launch("putAgentUserInfoCoro", - boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params, callback)); - - mImageId = id; - if (mImageId == LLUUID::null) + if (result) { - mSecondLifePic->setValue("Generic_Person_Large"); + LLAvatarIconIDCache::getInstance()->add(gAgentID, id); + // Should trigger callbacks in icon controls (or request Legacy) + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); } - else + }; + + if (!saveAgentUserInfoCoro("sl_image_id", id, callback)) + return; + + mSecondLifePic->setValue(id); + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); + if (id == LLUUID::null) { - mSecondLifePic->setValue(mImageId); + texture_view->resetAsset(); } - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (floater) + else { - LLFloaterProfileTexture * texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); - if (mImageId == LLUUID::null) - { - texture_view->resetAsset(); - } - else - { - texture_view->loadAsset(mImageId); - } + texture_view->loadAsset(id); } } - else - { - LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; - } } ////////////////////////////////////////////////////////////////////////// @@ -1981,6 +1682,8 @@ void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e LLStringUtil::format_map_t args; args["[TIME]"] = llformat("%.2f", mPerformanceTimer.getElapsedTimeF32()); childSetValue("status_text", LLSD( getString("LoadTime", args)) ); + + setLoaded(); } break; @@ -1996,7 +1699,7 @@ void LLPanelProfileWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e ////////////////////////////////////////////////////////////////////////// LLPanelProfileFirstLife::LLPanelProfileFirstLife() - : LLPanelProfileTab() + : LLPanelProfilePropertiesProcessorTab() , mHasUnsavedChanges(false) { } @@ -2008,7 +1711,7 @@ LLPanelProfileFirstLife::~LLPanelProfileFirstLife() BOOL LLPanelProfileFirstLife::postBuild() { mDescriptionEdit = getChild<LLTextEditor>("fl_description_edit"); - mPicture = getChild<LLThumbnailCtrl>("real_world_pic"); + mPicture = getChild<LLProfileImageCtrl>("real_world_pic"); mUploadPhoto = getChild<LLButton>("fl_upload_image"); mChangePhoto = getChild<LLButton>("fl_change_image"); @@ -2044,7 +1747,7 @@ void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) { mUploadPhoto->setEnabled(!loading); mChangePhoto->setEnabled(!loading); - mRemovePhoto->setEnabled(!loading && mImageId.notNull()); + mRemovePhoto->setEnabled(!loading && mPicture->getImageAssetId().notNull()); LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("image_upload_indicator"); indicator->setVisible(loading); @@ -2061,7 +1764,6 @@ void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) { mPicture->setValue(image_asset_id); - mImageId = image_asset_id; setProfileImageUploading(false); } @@ -2075,7 +1777,7 @@ void LLPanelProfileFirstLife::commitUnsavedChanges() void LLPanelProfileFirstLife::onUploadPhoto() { - (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle<LLPanel>(getHandle()), + (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle<LLPanel>(LLPanel::getHandle()), [this](LLUUID const& id) { setProfileImageUploaded(id); }))->getFile(); LLFloater* floaterp = mFloaterTexturePickerHandle.get(); @@ -2099,10 +1801,10 @@ void LLPanelProfileFirstLife::onChangePhoto() getWindow()->setCursor(UI_CURSOR_WAIT); LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( this, - mImageId, + mPicture->getImageAssetId(), LLUUID::null, LLUUID::null, - mImageId, + mPicture->getImageAssetId(), FALSE, FALSE, "SELECT PHOTO", @@ -2150,35 +1852,15 @@ void LLPanelProfileFirstLife::onRemovePhoto() void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) { - if (mImageId == id) - { + if (mPicture->getImageAssetId() == id) return; - } - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLSD params; - params["fl_image_id"] = id; - LLCoros::instance().launch("putAgentUserInfoCoro", - boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), params, nullptr)); + if (!saveAgentUserInfoCoro("fl_image_id", id)) + return; - mImageId = id; - if (mImageId.notNull()) - { - mPicture->setValue(mImageId); - } - else - { - mPicture->setValue("Generic_Person_Large"); - } + mPicture->setValue(id); - mRemovePhoto->setEnabled(mImageId.notNull()); - } - else - { - LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; - } + mRemovePhoto->setEnabled(id.notNull()); } void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) @@ -2201,16 +1883,7 @@ void LLPanelProfileFirstLife::onSetDescriptionDirty() void LLPanelProfileFirstLife::onSaveDescriptionChanges() { mCurrentDescription = mDescriptionEdit->getValue().asString(); - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLCoros::instance().launch("putAgentUserInfoCoro", - boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("fl_about_text", mCurrentDescription), nullptr)); - } - else - { - LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; - } + saveAgentUserInfoCoro("fl_about_text", mCurrentDescription); mSaveChanges->setEnabled(FALSE); mDiscardChanges->setEnabled(FALSE); @@ -2222,20 +1895,23 @@ void LLPanelProfileFirstLife::onDiscardDescriptionChanges() setDescriptionText(mCurrentDescription); } +void LLPanelProfileFirstLife::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProperties(avatar_data); + } + } +} + void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) { setDescriptionText(avatar_data->fl_about_text); - mImageId = avatar_data->fl_image_id; - - if (mImageId.notNull()) - { - mPicture->setValue(mImageId); - } - else - { - mPicture->setValue("Generic_Person_Large"); - } + mPicture->setValue(avatar_data->fl_image_id); setLoaded(); } @@ -2243,8 +1919,7 @@ void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) void LLPanelProfileFirstLife::resetData() { setDescriptionText(std::string()); - mPicture->setValue("Generic_Person_Large"); - mImageId = LLUUID::null; + mPicture->setValue(LLUUID::null); mUploadPhoto->setVisible(getSelfProfile()); mChangePhoto->setVisible(getSelfProfile()); @@ -2261,7 +1936,7 @@ void LLPanelProfileFirstLife::setLoaded() { mDescriptionEdit->setEnabled(TRUE); mPicture->setEnabled(TRUE); - mRemovePhoto->setEnabled(mImageId.notNull()); + mRemovePhoto->setEnabled(mPicture->getImageAssetId().notNull()); } } @@ -2280,9 +1955,9 @@ void LLPanelProfileFirstLife::onShowAgentFirstlifeTexture() { LLFloaterProfileTexture* texture_view = new LLFloaterProfileTexture(parent_floater); mFloaterProfileTextureHandle = texture_view->getHandle(); - if (mImageId.notNull()) + if (mPicture->getImageAssetId().notNull()) { - texture_view->loadAsset(mImageId); + texture_view->loadAsset(mPicture->getImageAssetId()); } else { @@ -2299,9 +1974,9 @@ void LLPanelProfileFirstLife::onShowAgentFirstlifeTexture() LLFloaterProfileTexture* texture_view = dynamic_cast<LLFloaterProfileTexture*>(floater); texture_view->setMinimized(FALSE); texture_view->setVisibleAndFrontmost(TRUE); - if (mImageId.notNull()) + if (mPicture->getImageAssetId().notNull()) { - texture_view->loadAsset(mImageId); + texture_view->loadAsset(mPicture->getImageAssetId()); } else { @@ -2315,7 +1990,7 @@ void LLPanelProfileFirstLife::onShowAgentFirstlifeTexture() ////////////////////////////////////////////////////////////////////////// LLPanelProfileNotes::LLPanelProfileNotes() -: LLPanelProfileTab() +: LLPanelProfilePropertiesProcessorTab() , mHasUnsavedChanges(false) { @@ -2325,22 +2000,6 @@ LLPanelProfileNotes::~LLPanelProfileNotes() { } -void LLPanelProfileNotes::updateData() -{ - LLUUID avatar_id = getAvatarId(); - if (!getStarted() && avatar_id.notNull()) - { - setIsLoading(); - - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLCoros::instance().launch("requestAgentUserInfoCoro", - boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); - } - } -} - void LLPanelProfileNotes::commitUnsavedChanges() { if (mHasUnsavedChanges) @@ -2389,16 +2048,7 @@ void LLPanelProfileNotes::onSetNotesDirty() void LLPanelProfileNotes::onSaveNotesChanges() { mCurrentNotes = mNotesEditor->getValue().asString(); - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLCoros::instance().launch("putAgentUserInfoCoro", - boost::bind(put_avatar_properties_coro, cap_url, getAvatarId(), LLSD().with("notes", mCurrentNotes), nullptr)); - } - else - { - LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; - } + saveAgentUserInfoCoro("notes", mCurrentNotes); mSaveChanges->setEnabled(FALSE); mDiscardChanges->setEnabled(FALSE); @@ -2410,9 +2060,21 @@ void LLPanelProfileNotes::onDiscardNotesChanges() setNotesText(mCurrentNotes); } -void LLPanelProfileNotes::processProperties(LLAvatarNotes* avatar_notes) +void LLPanelProfileNotes::processProperties(void* data, EAvatarProcessorType type) { - setNotesText(avatar_notes->notes); + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProperties(avatar_data); + } + } +} + +void LLPanelProfileNotes::processProperties(const LLAvatarData* avatar_data) +{ + setNotesText(avatar_data->notes); mNotesEditor->setEnabled(TRUE); setLoaded(); } @@ -2423,14 +2085,6 @@ void LLPanelProfileNotes::resetData() setNotesText(std::string()); } -void LLPanelProfileNotes::setAvatarId(const LLUUID& avatar_id) -{ - if (avatar_id.notNull()) - { - LLPanelProfileTab::setAvatarId(avatar_id); - } -} - ////////////////////////////////////////////////////////////////////////// // LLPanelProfile @@ -2507,12 +2161,7 @@ void LLPanelProfile::updateData() mPanelFirstlife->setIsLoading(); mPanelNotes->setIsLoading(); - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - if (!cap_url.empty()) - { - LLCoros::instance().launch("requestAgentUserInfoCoro", - boost::bind(request_avatar_properties_coro, cap_url, avatar_id)); - } + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); } } diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index 34fcc4ae796118bb2c3099c356f2f85c94f43e2d..248fefb4fdd6e3e9e2f53ef1cf890007b7f87ea9 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -59,9 +59,9 @@ class LLTextBase; class LLMenuButton; class LLLineEditor; class LLTextEditor; -class LLThumbnailCtrl; class LLPanelProfileClassifieds; class LLPanelProfilePicks; +class LLProfileImageCtrl; class LLViewerFetchedTexture; @@ -69,7 +69,7 @@ class LLViewerFetchedTexture; * Panel for displaying Avatar's second life related info. */ class LLPanelProfileSecondLife - : public LLPanelProfileTab + : public LLPanelProfilePropertiesProcessorTab , public LLFriendObserver , public LLVoiceClientStatusObserver { @@ -94,10 +94,6 @@ class LLPanelProfileSecondLife void resetData() override; - /** - * Sends update data request to server. - */ - void updateData() override; void refreshName(); void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); @@ -108,7 +104,7 @@ class LLPanelProfileSecondLife bool hasUnsavedChanges() override; void commitUnsavedChanges() override; - friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); + void processProperties(void* data, EAvatarProcessorType type) override; protected: /** @@ -116,11 +112,6 @@ class LLPanelProfileSecondLife */ void processProfileProperties(const LLAvatarData* avatar_data); - /** - * Processes group related data received from server. - */ - void processGroupProperties(const LLAvatarGroups* avatar_groups); - /** * Fills common for Avatar profile and My Profile fields. */ @@ -144,16 +135,9 @@ class LLPanelProfileSecondLife /** * Fills user name, display name, age. */ - void fillAgeData(const LLDate &born_on); + void fillAgeData(const LLAvatarData* avatar_data); void onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep); - static void onImageLoaded(BOOL success, - LLViewerFetchedTexture *src_vi, - LLImageRaw* src, - LLImageRaw* aux_src, - S32 discard_level, - BOOL final, - void* userdata); /** * Displays avatar's online status if possible. @@ -180,6 +164,7 @@ class LLPanelProfileSecondLife void setDescriptionText(const std::string &text); void onSetDescriptionDirty(); void onShowInSearchCallback(); + void onHideAgeCallback(); void onSaveDescriptionChanges(); void onDiscardDescriptionChanges(); void onShowAgentPermissionsDialog(); @@ -194,7 +179,8 @@ class LLPanelProfileSecondLife LLGroupList* mGroupList; LLComboBox* mShowInSearchCombo; - LLThumbnailCtrl* mSecondLifePic; + LLComboBox* mHideAgeCombo; + LLProfileImageCtrl* mSecondLifePic; LLPanel* mSecondLifePicLayout; LLTextEditor* mDescriptionEdit; LLMenuButton* mAgentActionMenuButton; @@ -215,9 +201,8 @@ class LLPanelProfileSecondLife bool mVoiceStatus; bool mWaitingForImageUpload; bool mAllowPublish; + bool mHideAge; std::string mDescriptionText; - LLUUID mImageId; - boost::signals2::connection mAvatarNameCacheConnection; boost::signals2::connection mRlvBehaviorConn; }; @@ -249,8 +234,6 @@ class LLPanelProfileWeb void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); - protected: void onCommitLoad(LLUICtrl* ctrl); @@ -269,7 +252,7 @@ class LLPanelProfileWeb * Panel for displaying Avatar's first life related info. */ class LLPanelProfileFirstLife - : public LLPanelProfileTab + : public LLPanelProfilePropertiesProcessorTab { public: LLPanelProfileFirstLife(); @@ -279,6 +262,7 @@ class LLPanelProfileFirstLife BOOL postBuild() override; + void processProperties(void* data, EAvatarProcessorType type) override; void processProperties(const LLAvatarData* avatar_data); void resetData() override; @@ -289,8 +273,6 @@ class LLPanelProfileFirstLife bool hasUnsavedChanges() override { return mHasUnsavedChanges; } void commitUnsavedChanges() override; - friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); - protected: void setLoaded() override; @@ -305,7 +287,7 @@ class LLPanelProfileFirstLife void onShowAgentFirstlifeTexture(); LLTextEditor* mDescriptionEdit; - LLThumbnailCtrl* mPicture; + LLProfileImageCtrl* mPicture; LLButton* mUploadPhoto; LLButton* mChangePhoto; LLButton* mRemovePhoto; @@ -316,7 +298,6 @@ class LLPanelProfileFirstLife LLHandle<LLFloater> mFloaterTexturePickerHandle; std::string mCurrentDescription; - LLUUID mImageId; bool mHasUnsavedChanges; }; @@ -324,24 +305,21 @@ class LLPanelProfileFirstLife * Panel for displaying Avatar's notes and modifying friend's rights. */ class LLPanelProfileNotes - : public LLPanelProfileTab + : public LLPanelProfilePropertiesProcessorTab { public: LLPanelProfileNotes(); /*virtual*/ ~LLPanelProfileNotes(); - void setAvatarId(const LLUUID& avatar_id) override; - void onOpen(const LLSD& key) override; BOOL postBuild() override; - void processProperties(LLAvatarNotes* avatar_notes); + void processProperties(void* data, EAvatarProcessorType type) override; + void processProperties(const LLAvatarData* avatar_data); void resetData() override; - void updateData() override; - bool hasUnsavedChanges() override { return mHasUnsavedChanges; } void commitUnsavedChanges() override; @@ -388,10 +366,6 @@ class LLPanelProfile void showClassified(const LLUUID& classified_id = LLUUID::null, bool edit = false); void createClassified(); - LLAvatarData getAvatarData() { return mAvatarData; }; - - friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); - private: void onTabChange(); @@ -402,13 +376,6 @@ class LLPanelProfile LLPanelProfileFirstLife* mPanelFirstlife; LLPanelProfileNotes* mPanelNotes; LLTabContainer* mTabContainer; - - // Todo: due to server taking minutes to update this needs a more long term storage - // to reuse recently saved values if user opens floater again - // Storage implementation depends onto how a cap will be implemented, if cap will be - // enought to fully update LLAvatarPropertiesProcessor, then this storage can be - // implemented there. - LLAvatarData mAvatarData; }; #endif //LL_LLPANELPROFILE_H diff --git a/indra/newview/llpanelprofilelegacy.cpp b/indra/newview/llpanelprofilelegacy.cpp index 45ce189ffdde34c8a699555a7763e69909f131bc..e6b9428bffe59c30957c8016f22d6ddc83ba4cf4 100644 --- a/indra/newview/llpanelprofilelegacy.cpp +++ b/indra/newview/llpanelprofilelegacy.cpp @@ -85,7 +85,7 @@ LLPanelProfileLegacy::LLPanelProfileLegacy() , mPanelGroups(nullptr) { mChildStack.setParent(this); - mCommitCallbackRegistrar.add("Profile.CommitInterest", boost::bind(&LLPanelProfileLegacy::onCommitInterest, this)); + //mCommitCallbackRegistrar.add("Profile.CommitInterest", boost::bind(&LLPanelProfileLegacy::onCommitInterest, this)); mCommitCallbackRegistrar.add("Profile.CommitProperties", boost::bind(&LLPanelProfileLegacy::onCommitAvatarProperties, this)); mCommitCallbackRegistrar.add("Profile.CommitRights", boost::bind(&LLPanelProfileLegacy::onCommitRights, this)); mCommitCallbackRegistrar.add("Profile.CommitModifyObjectRights", boost::bind(&LLPanelProfileLegacy::onCommitModifyObjectsRights, this, _1)); @@ -164,9 +164,9 @@ void LLPanelProfileLegacy::onOpen(const LLSD& key) getChild<LLView>("www")->setVisible(!is_self); getChild<LLView>("www_edit")->setVisible(is_self); getChild<LLView>("allow_publish")->setVisible(is_self); - childSetEnabled("wanna_something", is_self); - childSetEnabled("can_something", is_self); - childSetEnabled("languages", is_self); + //childSetEnabled("wanna_something", is_self); + //childSetEnabled("can_something", is_self); + //childSetEnabled("languages", is_self); for (const std::string& checkbox: sWantCheckboxes) childSetEnabled(checkbox, is_self); for (const std::string& checkbox: sSkillsCheckboxes) @@ -174,7 +174,7 @@ void LLPanelProfileLegacy::onOpen(const LLSD& key) childSetEnabled("drop_target", !is_self); getChild<LLLayoutPanel>("avatar_in_search", is_self); getChild<LLDropTarget>("drop_target")->setAgentID(av_id); - resetInterestsControlValues(); + //resetInterestsControlValues(); updateData(); resetControls(); @@ -197,21 +197,21 @@ void LLPanelProfileLegacy::resetControls() : "MuteAvatar")); } -void LLPanelProfileLegacy::resetInterestsControlValues() -{ - for (U32 i = 0; i < sWantCheckboxes.size(); ++i) - { - getChild<LLCheckBoxCtrl>(sWantCheckboxes.at(i))->setValue(FALSE); - } - - for (U32 i = 0; i < sSkillsCheckboxes.size(); ++i) - { - getChild<LLCheckBoxCtrl>(sSkillsCheckboxes.at(i))->setValue(FALSE); - } - getChild<LLLineEditor>("wanna_something")->setText(LLStringUtil::null); - getChild<LLLineEditor>("can_something")->setText(LLStringUtil::null); - getChild<LLLineEditor>("languages")->setText(LLStringUtil::null); -} +//void LLPanelProfileLegacy::resetInterestsControlValues() +//{ +// for (U32 i = 0; i < sWantCheckboxes.size(); ++i) +// { +// getChild<LLCheckBoxCtrl>(sWantCheckboxes.at(i))->setValue(FALSE); +// } +// +// for (U32 i = 0; i < sSkillsCheckboxes.size(); ++i) +// { +// getChild<LLCheckBoxCtrl>(sSkillsCheckboxes.at(i))->setValue(FALSE); +// } +// getChild<LLLineEditor>("wanna_something")->setText(LLStringUtil::null); +// getChild<LLLineEditor>("can_something")->setText(LLStringUtil::null); +// getChild<LLLineEditor>("languages")->setText(LLStringUtil::null); +//} void LLPanelProfileLegacy::updateData() { @@ -385,11 +385,6 @@ void LLPanelProfileLegacy::updateData() }); } - else - { - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarNotesRequest(getAvatarId()); - } mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileLegacy::onAvatarNameCache, this, _1, _2)); @@ -491,25 +486,25 @@ void LLPanelProfileLegacy::processProperties(void* data, EAvatarProcessorType ty getChild<LLTextEditor>("notes")->setValue(pData->notes); break; } - case APT_INTERESTS: - { - const LLAvatarInterests* pData = static_cast<const LLAvatarInterests*>(data); - if (!pData || pData->avatar_id != getAvatarId()) return; - - for (U32 i = 0; i < sWantCheckboxes.size(); ++i) - { - getChild<LLCheckBoxCtrl>(sWantCheckboxes.at(i))->setValue(pData->want_to_mask & (1<<i) ? TRUE : FALSE); - } - - for (U32 i = 0; i < sSkillsCheckboxes.size(); ++i) - { - getChild<LLCheckBoxCtrl>(sSkillsCheckboxes.at(i))->setValue(pData->skills_mask & (1<<i) ? TRUE : FALSE); - } - getChild<LLLineEditor>("wanna_something")->setText(pData->want_to_text); - getChild<LLLineEditor>("can_something")->setText(pData->skills_text); - getChild<LLLineEditor>("languages")->setText(pData->languages_text); - break; - } + //case APT_INTERESTS: + //{ + // const LLAvatarInterests* pData = static_cast<const LLAvatarInterests*>(data); + // if (!pData || pData->avatar_id != getAvatarId()) return; + + // for (U32 i = 0; i < sWantCheckboxes.size(); ++i) + // { + // getChild<LLCheckBoxCtrl>(sWantCheckboxes.at(i))->setValue(pData->want_to_mask & (1<<i) ? TRUE : FALSE); + // } + + // for (U32 i = 0; i < sSkillsCheckboxes.size(); ++i) + // { + // getChild<LLCheckBoxCtrl>(sSkillsCheckboxes.at(i))->setValue(pData->skills_mask & (1<<i) ? TRUE : FALSE); + // } + // getChild<LLLineEditor>("wanna_something")->setText(pData->want_to_text); + // getChild<LLLineEditor>("can_something")->setText(pData->skills_text); + // getChild<LLLineEditor>("languages")->setText(pData->languages_text); + // break; + //} case APT_GROUPS: { const LLAvatarGroups* pData = static_cast<LLAvatarGroups*>(data); @@ -653,43 +648,6 @@ void LLPanelProfileLegacy::onCommitAvatarProperties() "sendAvatarProfileCoro", boost::bind(&LLPanelProfileLegacy::sendAvatarProfileCoro, this, cap, data)); } - else - { - LLAvatarData data = LLAvatarData(); - data.avatar_id = gAgentID; - data.image_id = getChild<LLTextureCtrl>("sl_profile_pic")->getImageAssetID(); - data.fl_image_id = getChild<LLTextureCtrl>("fl_profile_pic")->getImageAssetID(); - data.about_text = getChild<LLTextEditor>("sl_about")->getText(); - data.fl_about_text = getChild<LLTextEditor>("fl_about")->getText(); - data.profile_url = getChild<LLLineEditor>("www_edit")->getText(); - data.allow_publish = getChild<LLCheckBoxCtrl>("allow_publish")->getValue().asBoolean(); - - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&data); - } -} - -void LLPanelProfileLegacy::onCommitInterest() -{ - if (getAvatarId() != gAgentID) return; - LLAvatarInterests data = LLAvatarInterests(); - - data.want_to_mask = 0x0; - data.skills_mask = 0x0; - data.want_to_text = getChild<LLLineEditor>("wanna_something")->getText(); - data.skills_text = getChild<LLLineEditor>("can_something")->getText(); - data.languages_text = getChild<LLLineEditor>("languages")->getText(); - for (U32 i = 0; i < sWantCheckboxes.size(); ++i) - { - if(getChild<LLCheckBoxCtrl>(sWantCheckboxes.at(i))->getValue().asBoolean()) - data.want_to_mask |= 1<<i; - } - for (U32 i = 0; i < sSkillsCheckboxes.size(); ++i) - { - if(getChild<LLCheckBoxCtrl>(sSkillsCheckboxes.at(i))->getValue().asBoolean()) - data.skills_mask |= 1<<i; - } - - LLAvatarPropertiesProcessor::getInstance()->sendInterestsUpdate(&data); } void LLPanelProfileLegacy::onCommitNotes(LLUICtrl* ctrl) @@ -701,11 +659,6 @@ void LLPanelProfileLegacy::onCommitNotes(LLUICtrl* ctrl) boost::bind(&LLPanelProfileLegacy::sendAvatarProfileCoro, this, cap, LLSD().with("notes", ctrl->getValue().asString()))); } - else - { - const std::string& notes = ctrl->getValue().asString(); - LLAvatarPropertiesProcessor::getInstance()->sendNotes(getAvatarId(), notes); - } } void LLPanelProfileLegacy::onDoubleClickName() @@ -916,7 +869,6 @@ void LLPanelProfileLegacy::LLPanelProfilePicks::updateData() { mPicksList->clear(); mClassifiedsList->clear(); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId()); LLAvatarPropertiesProcessor::getInstance()->sendAvatarClassifiedsRequest(getAvatarId()); } @@ -1493,10 +1445,6 @@ void LLPanelProfileLegacy::LLPanelProfileGroups::updateData() { mGroupsText->setVisible(TRUE); mGroupsList->clear(); - if (gAgent.getRegionCapability(AGENT_PROFILE_CAP).empty()) - { - LLAvatarPropertiesProcessor::getInstance()->sendAvatarGroupsRequest(getAvatarId()); - } } void LLPanelProfileLegacy::LLPanelProfileGroups::processProperties(void* data, EAvatarProcessorType type) diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 1779ea7ab087d9b20d40dffe30e666fd3e9018b4..aa3439ece3223fb8de6bb35bd753c5478faa81fc 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -101,12 +101,6 @@ class LLPickHandler : public LLCommandHandler return true; } - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnablePicks")) - { - LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - // handle app/pick/create urls first if (params.size() == 1 && params[0].asString() == "create") { @@ -305,17 +299,21 @@ void LLPanelProfilePicks::callbackDeletePick(const LLSD& notification, const LLS void LLPanelProfilePicks::processProperties(void* data, EAvatarProcessorType type) { - if (APT_PICKS == type) + if (APT_PROPERTIES == type) { - LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data); - if (avatar_picks && getAvatarId() == avatar_picks->target_id) + LLAvatarData* avatar_picks = static_cast<LLAvatarData*>(data); + if (avatar_picks && getAvatarId() == avatar_picks->avatar_id) { + if (getSelfProfile()) + { + LLAgentPicksInfo::getInstance()->onServerRespond(avatar_picks); + } processProperties(avatar_picks); } } } -void LLPanelProfilePicks::processProperties(const LLAvatarPicks* avatar_picks) +void LLPanelProfilePicks::processProperties(const LLAvatarData* avatar_picks) { LLUUID selected_id = mPickToSelectOnLoad; bool has_selection = false; @@ -333,7 +331,7 @@ void LLPanelProfilePicks::processProperties(const LLAvatarPicks* avatar_picks) mTabContainer->deleteAllTabs(); - LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); + LLAvatarData::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); for (; avatar_picks->picks_list.end() != it; ++it) { LLUUID pick_id = it->first; @@ -437,7 +435,7 @@ void LLPanelProfilePicks::updateData() { setIsLoading(); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(avatar_id); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(avatar_id); } if (!getIsLoaded()) { diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h index 4472c3bcd2a935748aeefe135aa04b5fe9cd542e..aa3dadd1b6b5f11512c0bf5d39dfbafc67df971c 100644 --- a/indra/newview/llpanelprofilepicks.h +++ b/indra/newview/llpanelprofilepicks.h @@ -58,7 +58,7 @@ class LLPanelProfilePicks void selectPick(const LLUUID& pick_id); void processProperties(void* data, EAvatarProcessorType type) override; - void processProperties(const LLAvatarPicks* avatar_picks); + void processProperties(const LLAvatarData* avatar_picks); void resetData() override; @@ -77,8 +77,6 @@ class LLPanelProfilePicks bool hasUnsavedChanges() override; void commitUnsavedChanges() override; - friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id); - private: void onClickNewBtn(); void onClickDelete(); diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index ddc50f1296fb946261c4ad505177b4c86edfacbe..cf27cd3e7dce6f57d5b5694d613e862b4ab251e3 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -117,9 +117,9 @@ class LLWearingContextMenu : public LLListContextMenu registrar.add("Wearing.EditOutfit", boost::bind(&edit_outfit)); registrar.add("Wearing.ShowOriginal", boost::bind(show_item_original, mUUIDs.front())); registrar.add("Wearing.TakeOff", - boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op)); registrar.add("Wearing.Detach", - boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs, no_op)); LLContextMenu* menu = createFromFile("menu_wearing_tab.xml"); updateMenuItemsVisibility(menu); diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 4aca704a277e09bddbe00b558dcb34465162a84c..e06d025f5920dec407db197620fbd4c3bc97cb11 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -115,7 +115,7 @@ void LLPersistentNotificationStorage::loadNotifications() using namespace LLNotificationsUI; LLScreenChannel* notification_channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + findChannelByID(LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); LLNotifications& instance = LLNotifications::instance(); S32 processed_notifications = 0; diff --git a/indra/newview/llpopupview.cpp b/indra/newview/llpopupview.cpp index 353d261ad188ecd39129efa679b55d3cf3162d27..0b13fc37b96ed92d47809afee7c2dd4d8c5d933e 100644 --- a/indra/newview/llpopupview.cpp +++ b/indra/newview/llpopupview.cpp @@ -256,16 +256,16 @@ void LLPopupView::removePopup(LLView* popup) void LLPopupView::clearPopups() { - for (popup_list_t::iterator popup_it = mPopups.begin(); - popup_it != mPopups.end();) + while (!mPopups.empty()) { + popup_list_t::iterator popup_it = mPopups.begin(); LLView* popup = popup_it->get(); - - popup_list_t::iterator cur_popup_it = popup_it; - ++popup_it; - - mPopups.erase(cur_popup_it); - popup->onTopLost(); + // Remove before notifying in case it will cause removePopup + mPopups.erase(popup_it); + if (popup) + { + popup->onTopLost(); + } } } diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index fab4ac5b22acb35eb5393d8c8fd9132958169f73..cc1a16653f5fec31c5088616975d3c3461f78ac2 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -556,6 +556,9 @@ void LLPresetsManager::loadPreset(const std::string& subdirectory, std::string n LL_DEBUGS() << "attempting to load preset '"<<name<<"' from '"<<full_path<<"'" << LL_ENDL; + bool appearance_camera_movement = gSavedSettings.getBOOL("AppearanceCameraMovement"); + bool edit_camera_movement = gSavedSettings.getBOOL("EditCameraMovement"); + mIgnoreChangedSignal = true; if(gSavedSettings.loadFromFile(full_path, false, true) > 0) { @@ -575,6 +578,16 @@ void LLPresetsManager::loadPreset(const std::string& subdirectory, std::string n { gSavedSettings.setString("PresetCameraActive", name); triggerChangeCameraSignal(); + + //SL-20277 old preset files may contain settings that should be ignored when loading camera presets + if (appearance_camera_movement != (bool)gSavedSettings.getBOOL("AppearanceCameraMovement")) + { + gSavedSettings.setBOOL("AppearanceCameraMovement", appearance_camera_movement); + } + if (edit_camera_movement != (bool)gSavedSettings.getBOOL("EditCameraMovement")) + { + gSavedSettings.setBOOL("EditCameraMovement", edit_camera_movement); + } } } else diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 1577dc64c88fb5ad42acf92ffc2275c3f0d4eb52..872c699035bb3730aeec39ed913ef3180b460b49 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -433,6 +433,11 @@ BOOL LLPreviewGesture::postBuild() edit->setIgnoreTab(TRUE); mChatEditor = edit; + check = getChild<LLCheckBoxCtrl>( "wait_key_release_check"); + check->setVisible(FALSE); + check->setCommitCallback(onCommitWait, this); + mWaitKeyReleaseCheck = check; + check = getChild<LLCheckBoxCtrl>( "wait_anim_check"); check->setVisible(FALSE); check->setCommitCallback(onCommitWait, this); @@ -646,6 +651,7 @@ void LLPreviewGesture::refresh() mAnimationRadio->setEnabled(FALSE); mSoundCombo->setEnabled(FALSE); mChatEditor->setEnabled(FALSE); + mWaitKeyReleaseCheck->setEnabled(FALSE); mWaitAnimCheck->setEnabled(FALSE); mWaitTimeCheck->setEnabled(FALSE); mWaitTimeEditor->setEnabled(FALSE); @@ -668,6 +674,7 @@ void LLPreviewGesture::refresh() mAnimationRadio->setEnabled(modifiable); mSoundCombo->setEnabled(modifiable); mChatEditor->setEnabled(modifiable); + mWaitKeyReleaseCheck->setEnabled(modifiable); mWaitAnimCheck->setEnabled(modifiable); mWaitTimeCheck->setEnabled(modifiable); mWaitTimeEditor->setEnabled(modifiable); @@ -703,6 +710,7 @@ void LLPreviewGesture::refresh() mAnimationRadio->setVisible(FALSE); mSoundCombo->setVisible(FALSE); mChatEditor->setVisible(FALSE); + mWaitKeyReleaseCheck->setVisible(FALSE); mWaitAnimCheck->setVisible(FALSE); mWaitTimeCheck->setVisible(FALSE); mWaitTimeEditor->setVisible(FALSE); @@ -747,6 +755,8 @@ void LLPreviewGesture::refresh() { LLGestureStepWait* wait_step = (LLGestureStepWait*)step; optionstext = getString("step_wait"); + mWaitKeyReleaseCheck->setVisible(TRUE); + mWaitKeyReleaseCheck->set(wait_step->mFlags & WAIT_FLAG_KEY_RELEASE); mWaitAnimCheck->setVisible(TRUE); mWaitAnimCheck->set(wait_step->mFlags & WAIT_FLAG_ALL_ANIM); mWaitTimeCheck->setVisible(TRUE); @@ -1528,6 +1538,7 @@ void LLPreviewGesture::onCommitWait(LLUICtrl* ctrl, void* data) LLGestureStepWait* wait_step = (LLGestureStepWait*)step; U32 flags = 0x0; + if (self->mWaitKeyReleaseCheck->get()) flags |= WAIT_FLAG_KEY_RELEASE; if (self->mWaitAnimCheck->get()) flags |= WAIT_FLAG_ALL_ANIM; if (self->mWaitTimeCheck->get()) flags |= WAIT_FLAG_TIME; wait_step->mFlags = flags; diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index a18c6c7f186ca9214f86e4eab4eb2d10f3dc8997..09e73946b5ab7502b775a2679b8bae128b7e0e7a 100644 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -154,6 +154,7 @@ class LLPreviewGesture final : public LLPreview LLComboBox* mAnimationCombo; LLComboBox* mSoundCombo; LLLineEditor* mChatEditor; + LLCheckBoxCtrl* mWaitKeyReleaseCheck; LLCheckBoxCtrl* mWaitAnimCheck; LLCheckBoxCtrl* mWaitTimeCheck; LLLineEditor* mWaitTimeEditor; diff --git a/indra/newview/llprofileimagepicker.cpp b/indra/newview/llprofileimagepicker.cpp index 7588c528dab24630fd4a2791d4e00d371fbb6e4c..9930b6eea7818ef444207f8cac038dd888bcf372 100644 --- a/indra/newview/llprofileimagepicker.cpp +++ b/indra/newview/llprofileimagepicker.cpp @@ -77,7 +77,7 @@ void LLProfileImagePicker::notify(const std::vector<std::string>& filenames) if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", failed to open image" << LL_ENDL; return; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 79a1e7e0761ad4e142179f798e99bf7c63e5f661..ab44085eb755906430615e89ee677d656a569a75 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -56,7 +56,7 @@ void LLReflectionMap::update(U32 resolution, U32 face) llassert(mCubeArray.notNull()); llassert(mCubeIndex != -1); //llassert(LLPipeline::sRenderDeferred); - + // make sure we don't walk off the edge of the render target while (resolution > gPipeline.mRT->deferredScreen.getWidth() || resolution > gPipeline.mRT->deferredScreen.getHeight()) @@ -70,11 +70,12 @@ void LLReflectionMap::autoAdjustOrigin() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mGroup && !mComplete) + + if (mGroup && !mComplete && !mGroup->hasState(LLViewerOctreeGroup::DEAD)) { const LLVector4a* bounds = mGroup->getBounds(); auto* node = mGroup->getOctreeNode(); - auto* part = mGroup->getSpatialPartition(); + LLSpatialPartition* part = mGroup->getSpatialPartition(); if (part && part->mPartitionType == LLViewerRegion::PARTITION_VOLUME) { @@ -141,7 +142,7 @@ void LLReflectionMap::autoAdjustOrigin() LLVector3 origin(fp); F32 height = LLWorld::instance().resolveLandHeightAgent(origin) + 2.f; fp[2] = llmax(fp[2], height); - + // make sure radius encompasses all objects LLSimdScalar r2 = 0.0; for (int i = 0; i < 8; ++i) @@ -161,7 +162,7 @@ void LLReflectionMap::autoAdjustOrigin() // make sure near clip doesn't poke through ground fp[2] = llmax(fp[2], height+mRadius*0.5f); - + } } else if (mViewerObject) @@ -234,7 +235,7 @@ bool LLReflectionMap::getIsDynamic() { static LLCachedControl<S32> sProbeDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); if (sProbeDetail > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY && - mViewerObject && + mViewerObject && mViewerObject->getVolume()) { return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic(); @@ -244,7 +245,7 @@ bool LLReflectionMap::getIsDynamic() } bool LLReflectionMap::getBox(LLMatrix4& box) -{ +{ if (mViewerObject) { LLVolume* volume = mViewerObject->getVolume(); @@ -269,7 +270,7 @@ bool LLReflectionMap::getBox(LLMatrix4& box) mv.mul(vobjp->mDrawable->getWorldMatrix()); mv.mul(scale); - // inverse is camera space to object unit cube + // inverse is camera space to object unit cube mv.invert(); box = LLMatrix4(mv); return true; @@ -334,7 +335,7 @@ void LLReflectionMap::doOcclusion(const LLVector4a& eye) mOccluded = false; return; } - + if (mOcclusionQuery == 0) { // no query was previously issued, allocate one and issue LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - glGenQueries"); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 80c0252a8eec061e07fcb8e4bbaf88eebe871ac2..bcdd337c079e955a4a276a9cfbce616321b81c70 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -172,9 +172,9 @@ void LLScreenChannelBase::init(S32 channel_left, S32 channel_right) void LLScreenChannelBase::updateRect() { - static const LLCachedControl<S32> channel_bottom_margin(gSavedSettings, "ChannelBottomPanelMargin"); + const S32 CHANNEL_BOTTOM_PANEL_MARGIN = 35; S32 channel_top = getChannelRect().mTop; - S32 channel_bottom = getChannelRect().mBottom + channel_bottom_margin; + S32 channel_bottom = getChannelRect().mBottom + CHANNEL_BOTTOM_PANEL_MARGIN; S32 channel_left = getRect().mLeft; S32 channel_right = getRect().mRight; setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index e2c4ffd66cfdcf45149b06f4cb5a6e7054a69cba..748d4b507e7a90d63a78e749d64ee452435b46ad 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -34,6 +34,12 @@ namespace LLNotificationsUI { + const LLUUID ALERT_CHANNEL_UUID("F3E07BC8-A973-476D-8C7F-F3B7293975D1"); + const LLUUID NOTIFICATION_CHANNEL_UUID("AEED3193-8709-4693-8558-7452CCA97AE5"); + const LLUUID NEARBY_CHAT_CHANNEL_UUID("E1158BD6-661C-4981-9DAD-4DCBFF062502"); + const LLUUID STARTUP_CHANNEL_UUID("B56AF90D-6684-48E4-B1E4-722D3DEB2CB6"); + + const S32 NOTIFY_BOX_WIDTH = 305; typedef enum e_notification_toast_alignment { diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index fafe5c0f571e8622992747b1fb45440577173c1d..3f863311efa304cbbbed9e192e4717a5ae05134a 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -335,7 +335,7 @@ void LLScriptFloater::hideToastsIfNeeded() // find channel LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID)); // update notification channel state if(channel) { diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp index dfb26b47fcf7d51bdbe058189cf32134879d715c..dbab7e53b62d8d1060f9c52a8d1c498fe73889df 100644 --- a/indra/newview/llsetkeybinddialog.cpp +++ b/indra/newview/llsetkeybinddialog.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llsetkeybinddialog.cpp * @brief LLSetKeyBindDialog class implementation. * * $LicenseInfo:firstyear=2019&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2019, 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$ */ @@ -74,13 +74,10 @@ LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key) pUpdater(NULL), mLastMaskKey(0), mContextConeOpacity(0.f), - mContextConeInAlpha(0.f), - mContextConeOutAlpha(0.f), - mContextConeFadeTime(0.f) + mContextConeInAlpha(CONTEXT_CONE_IN_ALPHA), + mContextConeOutAlpha(CONTEXT_CONE_OUT_ALPHA), + mContextConeFadeTime(CONTEXT_CONE_FADE_TIME) { - mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); - mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); - mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); } LLSetKeyBindDialog::~LLSetKeyBindDialog() diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 3368c93036b87bec7adf74e1bd5feb6466cdd321..035780268ac7e60bb20c147ccf8fe2334158bdfa 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -79,6 +79,32 @@ LLSidepanelTaskInfo* LLSidepanelTaskInfo::sActivePanel = NULL; static LLPanelInjector<LLSidepanelTaskInfo> t_task_info("sidepanel_task_info"); +static std::string click_action_to_string_value(U8 click_action) +{ + switch (click_action) + { + case CLICK_ACTION_TOUCH: + return "Touch"; + case CLICK_ACTION_SIT: + return "Sit"; + case CLICK_ACTION_BUY: + return "Buy"; + case CLICK_ACTION_PAY: + return "Pay"; + case CLICK_ACTION_OPEN: + return "Open"; + case CLICK_ACTION_ZOOM: + return "Zoom"; + case CLICK_ACTION_DISABLED: + return "None"; + case CLICK_ACTION_IGNORE: + return "Ignore"; + default: + return "Touch"; + } + return "Touch"; +} + // Default constructor LLSidepanelTaskInfo::LLSidepanelTaskInfo() : mVisibleDebugPermissions(true) // space was allocated by default @@ -908,11 +934,7 @@ void LLSidepanelTaskInfo::refresh() U8 click_action = 0; if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action)) { - LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction"); - if (ComboClickAction) - { - ComboClickAction->setCurrentByIndex((S32)click_action); - } + getChild<LLComboBox>("clickaction")->setValue(click_action_to_string_value(click_action)); } getChildView("label click action")->setEnabled(is_perm_modify && is_nonpermanent_enforced && all_volume); getChildView("clickaction")->setEnabled(is_perm_modify && is_nonpermanent_enforced && all_volume); @@ -1167,6 +1189,8 @@ static U8 string_value_to_click_action(std::string p_value) return CLICK_ACTION_ZOOM; if (p_value == "None") return CLICK_ACTION_DISABLED; + if (p_value == "Ignore") + return CLICK_ACTION_IGNORE; return CLICK_ACTION_TOUCH; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 0653b4a96e8eb9284990800105f1741e07dc72aa..c63f8151e3e00c4ef22329e80b8bc6f0f7f705d6 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1599,6 +1599,8 @@ bool check_rigged_group(LLDrawable* drawable) if (root->isState(LLDrawable::RIGGED) && root->getSpatialGroup() != group) { + LL_WARNS() << "[root->isState(LLDrawable::RIGGED) and root->getSpatialGroup() != group] is true" + " (" << root->getSpatialGroup() << " != " << group << ")" << LL_ENDL; llassert(false); return false; } @@ -1608,8 +1610,10 @@ bool check_rigged_group(LLDrawable* drawable) { for (auto& face : root->getFaces()) { - if ((S32) face->getDrawOrderIndex() <= last_draw_index) + if ((S32)face->getDrawOrderIndex() <= last_draw_index) { + LL_WARNS() << "[(S32)face->getDrawOrderIndex() <= last_draw_index] is true" + " (" << (S32)face->getDrawOrderIndex() << " <= " << last_draw_index << ")" << LL_ENDL; llassert(false); return false; } @@ -1623,8 +1627,10 @@ bool check_rigged_group(LLDrawable* drawable) { for (auto& face : child->mDrawable->getFaces()) { - if ((S32) face->getDrawOrderIndex() <= last_draw_index) + if ((S32)face->getDrawOrderIndex() <= last_draw_index) { + LL_WARNS() << "[(S32)face->getDrawOrderIndex() <= last_draw_index] is true" + " (" << (S32)face->getDrawOrderIndex() << " <= " << last_draw_index << ")" << LL_ENDL; llassert(false); return false; } @@ -1634,6 +1640,8 @@ bool check_rigged_group(LLDrawable* drawable) if (child->mDrawable->getSpatialGroup() != group) { + LL_WARNS() << "[child->mDrawable->getSpatialGroup() != group] is true" + " (" << child->mDrawable->getSpatialGroup() << " != " << group << ")" << LL_ENDL; llassert(false); return false; } diff --git a/indra/newview/llsplitbutton.cpp b/indra/newview/llsplitbutton.cpp index 60c0272a8b546a81a774d1bd5f655211760a59f0..5e363b358a7f22fe5928d4324b33e9cf08278a90 100644 --- a/indra/newview/llsplitbutton.cpp +++ b/indra/newview/llsplitbutton.cpp @@ -243,7 +243,14 @@ LLSplitButton::LLSplitButton(const LLSplitButton::Params& p) item_top -= (rc.getHeight() + BUTTON_PAD); } - setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this)); + mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this)); +} + +LLSplitButton::~LLSplitButton() +{ + // explicitly disconect to avoid hideButtons with + // dead pointers being called on destruction + mTopLostSignalConnection.disconnect(); } diff --git a/indra/newview/llsplitbutton.h b/indra/newview/llsplitbutton.h index 427ed7ba769bc9e185b17663f26620449d379255..4571a233fe309aaa62c06041bda7e8bf6c9c0157 100644 --- a/indra/newview/llsplitbutton.h +++ b/indra/newview/llsplitbutton.h @@ -67,7 +67,7 @@ class LLSplitButton }; - virtual ~LLSplitButton() {}; + virtual ~LLSplitButton(); //Overridden virtual void onFocusLost(); @@ -99,6 +99,8 @@ class LLSplitButton LLButton* mShownItem; EArrowPosition mArrowPosition; + boost::signals2::connection mTopLostSignalConnection; + commit_callback_t mSelectionCallback; }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1613fb8f868e65aa6d441882d0a524975f56ee10..a2b431b890bede1f1f2169771d1e4b2987e3418e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2062,8 +2062,10 @@ bool idle_startup() display_startup(); return FALSE; } + LLInventoryModelBackgroundFetch::instance().start(); - LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::instance().initCOFID(); + LLUUID cof_id = LLAppearanceMgr::instance().getCOF(); LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); if (cof && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) @@ -2385,7 +2387,7 @@ bool idle_startup() static LLFrameTimer wearables_timer; const F32 wearables_time = wearables_timer.getElapsedTimeF32(); - static LLCachedControl<F32> max_wearables_time(gSavedSettings, "ClothingLoadingDelay"); + const F32 MAX_WEARABLES_TIME = 10.f; if (!gAgent.isOutfitChosen() && isAgentAvatarValid()) { @@ -2404,7 +2406,7 @@ bool idle_startup() display_startup(); - if (gAgent.isOutfitChosen() && (wearables_time > max_wearables_time)) + if (gAgent.isOutfitChosen() && (wearables_time > MAX_WEARABLES_TIME)) { if (gInventory.isInventoryUsable()) { @@ -2824,14 +2826,11 @@ void register_viewer_callbacks(LLMessageSystem* msg) LLViewerParcelMgr::processParcelDwellReply); msg->setHandlerFuncFast(_PREHASH_AvatarPropertiesReply, - &LLAvatarPropertiesProcessor::processAvatarPropertiesReply); + &LLAvatarPropertiesProcessor::processAvatarLegacyPropertiesReply); msg->setHandlerFuncFast(_PREHASH_AvatarInterestsReply, &LLAvatarPropertiesProcessor::processAvatarInterestsReply); msg->setHandlerFuncFast(_PREHASH_AvatarGroupsReply, &LLAvatarPropertiesProcessor::processAvatarGroupsReply); - // ratings deprecated - //msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply, - // LLPanelAvatar::processAvatarStatisticsReply); msg->setHandlerFuncFast(_PREHASH_AvatarNotesReply, &LLAvatarPropertiesProcessor::processAvatarNotesReply); msg->setHandlerFuncFast(_PREHASH_AvatarPicksReply, @@ -3001,6 +3000,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); // Initiate creation of COF, since we're also bypassing that. gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); + LLAppearanceMgr::getInstance()->initCOFID(); ESex gender; if (gender_name == "male") @@ -3113,7 +3113,9 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_AGENT_SEND ); RTNENUM( STATE_AGENT_WAIT ); RTNENUM( STATE_INVENTORY_SEND ); - RTNENUM(STATE_INVENTORY_CALLBACKS ); + RTNENUM( STATE_INVENTORY_CALLBACKS ); + RTNENUM( STATE_INVENTORY_SKEL ); + RTNENUM( STATE_INVENTORY_SEND2 ); RTNENUM( STATE_MISC ); RTNENUM( STATE_PRECACHE ); RTNENUM( STATE_WEARABLES_WAIT ); @@ -3156,6 +3158,7 @@ void reset_login() gAgent.cleanup(); gSky.cleanup(); // mVOSkyp is an inworld object. LLWorld::getInstance()->resetClass(); + LLAppearanceMgr::getInstance()->cleanup(); if ( gViewerWindow ) { // Hide menus and normal buttons diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index a59e33b6ba7de595a0a356fb79e8b93d56469a2f..5c31ad4feb6a7aaa34ee2e9261fd646535a2b0b4 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -128,7 +128,7 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) void LLSysWellWindow::initChannel() { LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( - LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID); mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); if(NULL == mChannel) { diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 847bb7a739440539e125e397f00880e0dbd0aa2e..835fab8d17f35f8e5b0aa377620dc0ddb4ebed0a 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -348,13 +348,13 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler } // Threads: Tid - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { - worker->callbackDecoded(success, raw, aux, request_id); + worker->callbackDecoded(success, error_message, raw, aux, request_id); } } private: @@ -398,7 +398,7 @@ class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler void callbackCacheWrite(bool success); // Threads: Tid - void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id); + void callbackDecoded(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id); // Threads: T* void setGetStatus(LLCore::HttpStatus status, const std::string& reason) @@ -2357,7 +2357,7 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) ////////////////////////////////////////////////////////////////////////////// // Threads: Tid -void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id) +void LLTextureFetchWorker::callbackDecoded(bool success, const std::string &error_message, LLImageRaw* raw, LLImageRaw* aux, S32 decode_id) { LLMutexLock lock(&mWorkMutex); // +Mw if (mDecodeHandle == 0) @@ -2394,7 +2394,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag } else { - LL_WARNS(LOG_TXT) << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; + LL_WARNS(LOG_TXT) << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << ", reason: " << error_message << LL_ENDL; removeFromCache(); mDecodedDiscard = -1; // Redundant, here for clarity and paranoia } diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 2805c676b28aaa24ecb7c09cbde3968129945351..9f522665fe27e63e24b55e8794e52cb999e669a5 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -424,14 +424,12 @@ void LLAvatarTexBar::draw() text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT); line_num++; } - const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout"); const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); LLColor4 header_color(1.f, 1.f, 1.f, 0.9f); - const std::string texture_timeout_str = texture_timeout ? llformat("%d",texture_timeout) : "Disabled"; const std::string override_tex_discard_level_str = override_tex_discard_level ? llformat("%d",override_tex_discard_level) : "Disabled"; - std::string header_text = llformat("[ Timeout('AvatarBakedTextureUploadTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str()); + std::string header_text = llformat("[ Timeout:60 ] [ LOD_Override('TextureDiscardLevel'):%s ]", override_tex_discard_level_str.c_str()); LLFontGL::getFontMonospace()->renderUTF8(header_text, 0, l_offset, v_offset + line_height*line_num, header_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT); line_num++; diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index c873167729048bcd9fe4dc926cf6dc976d4cf277..a3b2c79015f128f73f4835b93d22722d65733677 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -90,6 +90,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal std::string edit_text_contents; S32 edit_text_max_chars = 0; bool is_password = false; + bool allow_emoji = false; LLToastPanel::setBackgroundVisible(FALSE); LLToastPanel::setBackgroundOpaque(TRUE); @@ -134,6 +135,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal edit_text_contents = (*it)["value"].asString(); edit_text_name = (*it)["name"].asString(); edit_text_max_chars = (*it)["max_length_chars"].asInteger(); + allow_emoji = (*it)["allow_emoji"].asBoolean(); } else if (type == "password") { @@ -292,6 +294,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight()); mLineEditor->setRect(leditor_rect); mLineEditor->setMaxTextChars(edit_text_max_chars); + mLineEditor->setAllowEmoji(allow_emoji); mLineEditor->setText(edit_text_contents); std::string notif_name = mNotification->getName(); @@ -497,10 +500,9 @@ void LLToastAlertPanel::draw() } static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow"); - static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 5); gl_drop_shadow( 0, LLToastPanel::getRect().getHeight(), LLToastPanel::getRect().getWidth(), 0, - shadow_color, shadow_lines); + shadow_color, DROP_SHADOW_FLOATER); LLToastPanel::draw(); } diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index dc5d9c9e1f66c5abf7a236f7c2282b0f85927486..a091370ee872c0bbadc56935082f477ff8667c7a 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -50,14 +50,15 @@ S32 BUTTON_WIDTH = 90; //static -const LLFontGL* LLToastNotifyPanel::sFont = NULL; -const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; +const std::string LLToastNotifyPanel::sFontDefault("Emoji"); +const std::string LLToastNotifyPanel::sFontScript("SansSerif"); LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) -: LLCheckBoxToastPanel(notification), - LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID()) +: LLCheckBoxToastPanel(notification) +, LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID()) +, mTextBox(NULL) { init(rect, show_images); } @@ -85,11 +86,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt mBtnCallbackData.push_back(userdata); LLButton::Params p; - bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2; - const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog - p.name = form_element["name"].asString(); - p.label = form_element["text"].asString(); - p.tool_tip = form_element["text"].asString(); + S32 index = form_element["index"].asInteger(); + std::string name = form_element["name"].asString(); + std::string text = form_element["text"].asString(); + bool make_small_btn = index == -1 || index == -2; // for block and ignore buttons in script dialog + const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor( + mIsScriptDialog ? sFontScript : sFontDefault, make_small_btn ? "Small" : "Medium", 0)); + p.name = name; + p.label = text; + p.tool_tip = text; p.font = font; p.rect.height = BTN_HEIGHT; p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); @@ -256,19 +261,12 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) { deleteAllChildren(); - mTextBox = NULL; - mInfoPanel = NULL; - mControlPanel = NULL; - mNumOptions = 0; - mNumButtons = 0; - mAddedDefaultBtn = false; - LLRect current_rect = getRect(); setXMLFilename(""); buildFromFile("panel_notification.xml"); - if(rect != LLRect::null) + if (rect != LLRect::null) { this->setShape(rect); } @@ -295,12 +293,6 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) // setup parameters // get a notification message mMessage = mNotification->getMessage(); - // init font variables - if (!sFont) - { - sFont = LLFontGL::getFontSansSerif(); - sFontSmall = LLFontGL::getFontSansSerifSmall(); - } // initialize setFocusRoot(!mIsTip); // get a form for the notification @@ -318,15 +310,18 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) if (mIsCaution && !mIsTip) { mTextBox = getChild<LLTextBox>("caution_text_box"); + mTextBox->setFont(LLFontGL::getFont(LLFontDescriptor(mIsScriptDialog ? sFontScript : sFontDefault, "Medium", LLFontGL::BOLD))); } else { mTextBox = getChild<LLTextEditor>("text_editor_box"); + mTextBox->setFont(LLFontGL::getFont(LLFontDescriptor(mIsScriptDialog ? sFontScript : sFontDefault, "Medium", 0))); } mTextBox->setMaxTextLength(LLToastPanel::MAX_TEXT_LENGTH); mTextBox->setVisible(TRUE); mTextBox->setPlainText(!show_images); + mTextBox->setUseEmoji(!mIsScriptDialog); mTextBox->setContentTrusted(is_content_trusted); mTextBox->setValue(mNotification->getMessage()); mTextBox->setIsFriendCallback(LLAvatarActions::isFriend); @@ -438,6 +433,21 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) } } +void LLToastNotifyPanel::deleteAllChildren() +{ + // some visibility changes, re-init and reshape will attempt to + // use mTextBox or other variables. Reset to avoid crashes + // and other issues. + mTextBox = NULL; + mInfoPanel = NULL; + mControlPanel = NULL; + mNumOptions = 0; + mNumButtons = 0; + mAddedDefaultBtn = false; + + LLCheckBoxToastPanel::deleteAllChildren(); +} + bool LLToastNotifyPanel::isControlPanelEnabled() const { bool cp_enabled = mControlPanel->getEnabled(); diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 2d15a98df351807dff5049655253a7fe2f768a2a..162999dae7f7a5c252123a02fd0d28625e7c54f9 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -63,6 +63,7 @@ class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker< LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); virtual void init( LLRect rect, bool show_images ); + virtual void deleteAllChildren(); virtual ~LLToastNotifyPanel(); LLPanel * getControlPanel() { return mControlPanel; } @@ -102,9 +103,9 @@ class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker< //std::vector<index_button_pair_t> mButtons; // panel elements - LLTextBase* mTextBox; - LLPanel* mInfoPanel; // a panel, that contains an information - LLPanel* mControlPanel; // a panel, that contains buttons (if present) + LLTextBase* mTextBox { nullptr }; + LLPanel* mInfoPanel { nullptr }; // panel for text information + LLPanel* mControlPanel { nullptr }; // panel for buttons (if present) // internal handler for button being clicked static void onClickButton(void* data); @@ -124,17 +125,17 @@ class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker< */ //void disableRespondedOptions(const LLNotificationPtr& notification); - bool mIsTip; - bool mAddedDefaultBtn; - bool mIsScriptDialog; - bool mIsCaution; + bool mIsTip { false }; + bool mAddedDefaultBtn { false }; + bool mIsScriptDialog { false }; + bool mIsCaution { false }; std::string mMessage; - S32 mNumOptions; - S32 mNumButtons; + S32 mNumOptions { 0 }; + S32 mNumButtons { 0 }; - static const LLFontGL* sFont; - static const LLFontGL* sFontSmall; + static const std::string sFontDefault; + static const std::string sFontScript; }; class LLIMToastNotifyPanel final : public LLToastNotifyPanel diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 826c6ea8b106c3f9efdb63121509d3b1811688e6..ee52eda48287c8600e46654a06c8cb753afd3bd4 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -305,12 +305,10 @@ void LLToolDragAndDrop::setDragStart(S32 x, S32 y) BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y) { - static LLCachedControl<S32> drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold", 3); - S32 mouse_delta_x = x - mDragStartX; S32 mouse_delta_y = y - mDragStartY; - return (mouse_delta_x * mouse_delta_x) + (mouse_delta_y * mouse_delta_y) > drag_and_drop_threshold * drag_and_drop_threshold; + return (mouse_delta_x * mouse_delta_x) + (mouse_delta_y * mouse_delta_y) > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD; } void LLToolDragAndDrop::beginDrag(EDragAndDropType type, @@ -575,12 +573,13 @@ BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask) BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask) { + const F32 DRAG_N_DROP_TOOLTIP_DELAY = 0.10000000149f; if (!mToolTipMsg.empty()) { LLToolTipMgr::instance().unblockToolTips(); LLToolTipMgr::instance().show(LLToolTip::Params() .message(mToolTipMsg) - .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" ))); + .delay_time(DRAG_N_DROP_TOOLTIP_DELAY)); return TRUE; } return FALSE; diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 232595e4fbdf93279584e455badac2144ce864fd..c3332c36776b5446f97ec06d477d01ef0573f147 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -223,6 +223,13 @@ BOOL LLVisualParamHint::render() LLVector3 target_pos = target_joint_pos + (target_offset * avatar_rotation); F32 cam_angle_radians = mVisualParam->getCameraAngle() * DEG_TO_RAD; + + static LLCachedControl<bool> auto_camera_position(gSavedSettings, "AppearanceCameraMovement"); + if (!auto_camera_position) + { + cam_angle_radians += F_PI; + } + LLVector3 camera_snapshot_offset( mVisualParam->getCameraDistance() * cosf( cam_angle_radians ), mVisualParam->getCameraDistance() * sinf( cam_angle_radians ), diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 4d614d765e9490d1a17a3a3aeda458c1991487d6..f69e2c8165577f9c3b4d12e2bf07c6007e55d5b5 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -90,8 +90,8 @@ LLToolPie::LLToolPie() mMouseSteerX(-1), mMouseSteerY(-1), mClickAction(0), - mClickActionBuyEnabled( gSavedSettings.getBOOL("ClickActionBuyEnabled") ), - mClickActionPayEnabled( gSavedSettings.getBOOL("ClickActionPayEnabled") ), + mClickActionBuyEnabled( TRUE ), + mClickActionPayEnabled( TRUE ), mDoubleClickTimer() { } @@ -855,9 +855,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) { S32 delta_x = x - mMouseDownX; S32 delta_y = y - mMouseDownY; - - static const LLCachedControl<S32> threshold(gSavedSettings, "DragAndDropDistanceThreshold"); - if (delta_x * delta_x + delta_y * delta_y > threshold * threshold) + if (delta_x * delta_x + delta_y * delta_y > DRAG_N_DROP_DISTANCE_THRESHOLD * DRAG_N_DROP_DISTANCE_THRESHOLD) { startCameraSteering(); steerCameraWithMouse(x, y); @@ -1207,12 +1205,11 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l final_name = LLTrans::getString("TooltipPerson");; } -// [RLVa:KB] - Checked: RLVa-1.2.0 + const F32 INSPECTOR_TOOLTIP_DELAY = 0.35f; if ( (!RlvActions::isRlvEnabled()) || ( (RlvActions::canInteract(hover_object, mHoverPick.mObjectOffset)) && (RlvActions::canShowName(RlvActions::SNC_DEFAULT, hover_object->getID())) ) ) { // [/RLVa:KB] - static const LLCachedControl<F32> av_inspector_tooltip_delay(gSavedSettings, "AvatarInspectorTooltipDelay"); LLInspector::Params p; p.fillFrom(LLUICtrlFactory::getDefaultParams<LLInspector>()); p.message(final_name); @@ -1220,7 +1217,7 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l p.click_callback(boost::bind(showAvatarInspector, hover_object->getID())); p.visible_time_near(6.f); p.visible_time_far(3.f); - p.delay_time(av_inspector_tooltip_delay); + p.delay_time(INSPECTOR_TOOLTIP_DELAY); p.wrap(false); LLToolTipMgr::instance().show(p); diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp index fc90b4fbed140c6922099c289211db8bf14a0bd3..e019af2fe8a455ee39ac62a44341f0bdf584d564 100644 --- a/indra/newview/lluploaddialog.cpp +++ b/indra/newview/lluploaddialog.cpp @@ -149,6 +149,7 @@ void LLUploadDialog::setMessage( const std::string& msg) LLUploadDialog::~LLUploadDialog() { + gViewerWindow->removePopup(this); gFocusMgr.releaseFocusIfNeeded( this ); // LLFilePicker::instance().reset(); diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp index c3e05a56200f21fc29963dfb184d687dc1b63eb4..058b6e6862015a9b36dbe5b797ea5d54fc277854 100644 --- a/indra/newview/llurllineeditorctrl.cpp +++ b/indra/newview/llurllineeditorctrl.cpp @@ -62,7 +62,7 @@ void LLURLLineEditor::cut() deleteSelection(); // Validate new string and rollback the if needed. - BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) ); + bool need_to_rollback = mPrevalidator && !mPrevalidator.validate(mText.getWString()); if( need_to_rollback ) { rollback.doRollback( this ); diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index f2410179181a75d685f425a060cddfcb4f7973cd..0e1fe058b524027802c7ba35123933654e7985cd 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -421,7 +421,7 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() if (!LLViewerTextureList::createUploadFile(getFileName(), filename, codec)) { errorMessage = llformat("Problem with file %s:\n\n%s\n", - getFileName().c_str(), LLImage::getLastError().c_str()); + getFileName().c_str(), LLImage::getLastThreadError().c_str()); errorLabel = "ProblemWithFile"; error = true; } diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 5846b3af5bffdd2ecb9823557f6030cb55dcdfd7..d76bd3547f1d9ee03a9e32db014997affa0e8f2b 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -48,6 +48,8 @@ #include "llstreamingaudio.h" ///////////////////////////////////////////////////////// +const U32 FMODEX_DECODE_BUFFER_SIZE = 1000; // in milliseconds +const U32 FMODEX_STREAM_BUFFER_SIZE = 7000; // in milliseconds LLViewerAudio::LLViewerAudio() : mDone(true), @@ -420,15 +422,19 @@ void audio_update_volume(bool force_update) gAudiop->setMasterGain ( master_volume ); - static const LLCachedControl<F32> doppler_volume(gSavedSettings, "AudioLevelDoppler"); - gAudiop->setDopplerFactor(doppler_volume); + const F32 AUDIO_LEVEL_DOPPLER = 1.f; + gAudiop->setDopplerFactor(AUDIO_LEVEL_DOPPLER); - static const LLCachedControl<F32> rolloff_volume(gSavedSettings, "AudioLevelRolloff"); - static const LLCachedControl<F32> underwater_rolloff_volume(gSavedSettings, "AudioLevelUnderwaterRolloff"); if(!LLViewerCamera::getInstance()->cameraUnderWater()) - gAudiop->setRolloffFactor(rolloff_volume); + { + const F32 AUDIO_LEVEL_ROLLOFF = 1.f; + gAudiop->setRolloffFactor(AUDIO_LEVEL_ROLLOFF); + } else - gAudiop->setRolloffFactor(underwater_rolloff_volume); + { + const F32 AUDIO_LEVEL_UNDERWATER_ROLLOFF = 5.f; + gAudiop->setRolloffFactor(AUDIO_LEVEL_UNDERWATER_ROLLOFF); + } gAudiop->setMuted(mute_audio || progress_view_visible); @@ -541,8 +547,8 @@ void audio_update_wind(bool force_update) // whereas steady-state avatar walk velocity is only 3.2 m/s. // Without this the world feels desolate on first login when you are // standing still. - static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); - LLVector3 scaled_wind_vec = gWindVec * wind_level; + const F32 WIND_LEVEL = 0.5f; + LLVector3 scaled_wind_vec = gWindVec * WIND_LEVEL; // Mix in the avatar's motion, subtract because when you walk north, // the apparent wind moves south. diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index ee97eefab4bec075ba74abf45065658ace743c47..8ef8ffcd652dc4f0aeec8d5baf3bbe070e8e1917 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -368,15 +368,6 @@ static bool handleChatFontSizeChanged(const LLSD& newvalue) return true; } -static bool handleChatPersistTimeChanged(const LLSD& newvalue) -{ - if(gConsole) - { - gConsole->setLinePersistTime((F32) newvalue.asReal()); - } - return true; -} - static bool handleConsoleMaxLinesChanged(const LLSD& newvalue) { if(gConsole) @@ -653,6 +644,18 @@ void handleUserTargetDrawDistanceChanged(const LLSD& newValue) LLPerfStats::tunables.userTargetDrawDistance = newval; } +void handleUserMinDrawDistanceChanged(const LLSD &newValue) +{ + const auto newval = gSavedSettings.getF32("AutoTuneRenderFarClipMin"); + LLPerfStats::tunables.userMinDrawDistance = newval; +} + +void handleUserTargetReflectionsChanged(const LLSD& newValue) +{ + const auto newval = gSavedSettings.getS32("UserTargetReflections"); + LLPerfStats::tunables.userTargetReflections = newval; +} + void handlePerformanceStatsEnabledChanged(const LLSD& newValue) { const auto newval = gSavedSettings.getBOOL("PerfStatsCaptureEnabled"); @@ -784,7 +787,6 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); setting_setup_signal_listener(gSavedSettings, "ChatFontName", handleChatFontSizeChanged); setting_setup_signal_listener(gSavedSettings, "ChatFontSize", handleChatFontSizeChanged); - setting_setup_signal_listener(gSavedSettings, "ChatPersistTime", handleChatPersistTimeChanged); setting_setup_signal_listener(gSavedSettings, "ConsoleMaxLines", handleConsoleMaxLinesChanged); setting_setup_signal_listener(gSavedSettings, "UploadBakedTexOld", handleUploadBakedTexOldChanged); setting_setup_signal_listener(gSavedSettings, "UseOcclusion", handleUseOcclusionChanged); @@ -795,9 +797,6 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "AudioLevelMusic", handleAudioVolumeChanged); setting_setup_signal_listener(gSavedSettings, "AudioLevelMedia", handleAudioVolumeChanged); setting_setup_signal_listener(gSavedSettings, "AudioLevelVoice", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelDoppler", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelRolloff", handleAudioVolumeChanged); - setting_setup_signal_listener(gSavedSettings, "AudioLevelUnderwaterRolloff", handleAudioVolumeChanged); setting_setup_signal_listener(gSavedSettings, "MuteAudio", handleAudioVolumeChanged); setting_setup_signal_listener(gSavedSettings, "MuteMusic", handleAudioVolumeChanged); setting_setup_signal_listener(gSavedSettings, "MuteMedia", handleAudioVolumeChanged); @@ -883,6 +882,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderAvatarMaxART", handleRenderAvatarMaxARTChanged); setting_setup_signal_listener(gSavedSettings, "PerfStatsCaptureEnabled", handlePerformanceStatsEnabledChanged); setting_setup_signal_listener(gSavedSettings, "AutoTuneRenderFarClipTarget", handleUserTargetDrawDistanceChanged); + setting_setup_signal_listener(gSavedSettings, "AutoTuneRenderFarClipMin", handleUserMinDrawDistanceChanged); setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorFarAwayDistance", handleUserImpostorDistanceChanged); setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorByDistEnabled", handleUserImpostorByDistEnabledChanged); setting_setup_signal_listener(gSavedSettings, "TuningFPSStrategy", handleFPSTuningStrategyChanged); @@ -922,8 +922,6 @@ DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255)); LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"]; DECL_LLCC(LLSD, test_llsd); -static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment"); - void test_cached_control() { #define do { TEST_LLCC(T, V) if((T)mySetting_##T != V) LL_ERRS() << "Fail "#T << LL_ENDL; } while(0) @@ -940,8 +938,6 @@ void test_cached_control() TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f)); TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255)); //There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd); - - if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL; } #endif // TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 01a496cc4c5b78e61a99d74d9eed4150af3d9f8c..414461fcfb9188b53eae46114720440e2b338370 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -223,11 +223,11 @@ void display_update_camera() void display_stats() { LL_PROFILE_ZONE_SCOPED - static const LLCachedControl<F32> fps_log_freq(gSavedSettings, "FPSLogFrequency"); - if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq) + const F32 FPS_LOG_FREQUENCY = 10.f; + if (gRecentFPSTime.getElapsedTimeF32() >= FPS_LOG_FREQUENCY) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - FPS"); - F32 fps = gRecentFrameCount / fps_log_freq; + F32 fps = gRecentFrameCount / FPS_LOG_FREQUENCY; LL_INFOS() << llformat("FPS: %.02f", fps) << LL_ENDL; gRecentFrameCount = 0; gRecentFPSTime.reset(); @@ -242,8 +242,8 @@ void display_stats() LLMemory::logMemoryInfo(TRUE) ; gRecentMemoryTime.reset(); } - static const LLCachedControl<F32> asset_storage_log_freq(gSavedSettings, "AssetStorageLogFrequency"); - if (asset_storage_log_freq > 0.f && gAssetStorageLogTime.getElapsedTimeF32() >= asset_storage_log_freq) + const F32 ASSET_STORAGE_LOG_FREQUENCY = 60.f; + if (gAssetStorageLogTime.getElapsedTimeF32() >= ASSET_STORAGE_LOG_FREQUENCY) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Asset Storage"); gAssetStorageLogTime.reset(); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index d9caff9d6092f622e7e83dde8fc0312460bec3af..739234534a912cf52824469210becdb1e2ddc9ce 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -228,8 +228,18 @@ std::string string_from_guid(const GUID &guid) return res; } +#elif LL_DARWIN + +bool macos_devices_callback(std::string &product_name, LLSD &data, void* userdata) +{ + std::string product = data["product"].asString(); + + return LLViewerJoystick::getInstance()->initDevice(nullptr, product, data); +} + #endif + // ----------------------------------------------------------------------------- void LLViewerJoystick::updateEnabled(bool autoenable) { @@ -436,25 +446,48 @@ void LLViewerJoystick::init(bool autoenable) { if (mNdofDev) { + U32 device_type = 0; + void* win_callback = nullptr; + std::function<bool(std::string&, LLSD&, void*)> osx_callback; // di8_devices_callback callback is immediate and happens in scope of getInputDevices() #if LL_WINDOWS && !LL_MESA_HEADLESS // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib - U32 device_type = DI8DEVCLASS_GAMECTRL; - void* callback = &di8_devices_callback; -#else - // MAC doesn't support device search yet - // On MAC there is an ndof_idsearch and it is possible to specify product - // and manufacturer in NDOF_Device for ndof_init_first to pick specific one - U32 device_type = 0; - void* callback = NULL; + device_type = DI8DEVCLASS_GAMECTRL; + win_callback = &di8_devices_callback; +#elif LL_DARWIN + osx_callback = macos_devices_callback; + + if (mLastDeviceUUID.isMap()) + { + std::string manufacturer = mLastDeviceUUID["manufacturer"].asString(); + std::string product = mLastDeviceUUID["product"].asString(); + + strncpy(mNdofDev->manufacturer, manufacturer.c_str(), sizeof(mNdofDev->manufacturer)); + strncpy(mNdofDev->product, product.c_str(), sizeof(mNdofDev->product)); + + if (ndof_init_first(mNdofDev, nullptr)) + { + mDriverState = JDS_INITIALIZING; + // Saved device no longer exist + // No device found + LL_WARNS() << "ndof_init_first FAILED" << LL_ENDL; + } + else + { + mDriverState = JDS_INITIALIZED; + } + } #endif - if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL)) + if (mDriverState != JDS_INITIALIZED) { - LL_INFOS("Joystick") << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL; - // Failed to gather devices from windows, init first suitable one - mLastDeviceUUID = LLSD(); - void *preffered_device = NULL; - initDevice(preffered_device); + if (!gViewerWindow->getWindow()->getInputDevices(device_type, osx_callback, win_callback, NULL)) + { + LL_INFOS("Joystick") << "Failed to gather input devices. Falling back to ndof's init" << LL_ENDL; + // Failed to gather devices, init first suitable one + mLastDeviceUUID = LLSD(); + void *preffered_device = NULL; + initDevice(preffered_device); + } } if (mDriverState == JDS_INITIALIZING) @@ -580,27 +613,49 @@ void LLViewerJoystick::initDevice(LLSD &guid) { #if LIB_NDOF mLastDeviceUUID = guid; + U32 device_type = 0; + void* win_callback = nullptr; + std::function<bool(std::string&, LLSD&, void*)> osx_callback; + mDriverState = JDS_INITIALIZING; #if LL_WINDOWS && !LL_MESA_HEADLESS // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib - U32 device_type = DI8DEVCLASS_GAMECTRL; - void* callback = &di8_devices_callback; -#else - // MAC doesn't support device search yet - // On MAC there is an ndof_idsearch and it is possible to specify product - // and manufacturer in NDOF_Device for ndof_init_first to pick specific one - U32 device_type = 0; - void* callback = NULL; + device_type = DI8DEVCLASS_GAMECTRL; + win_callback = &di8_devices_callback; +#elif LL_DARWIN + osx_callback = macos_devices_callback; + if (mLastDeviceUUID.isMap()) + { + std::string manufacturer = mLastDeviceUUID["manufacturer"].asString(); + std::string product = mLastDeviceUUID["product"].asString(); + + strncpy(mNdofDev->manufacturer, manufacturer.c_str(), sizeof(mNdofDev->manufacturer)); + strncpy(mNdofDev->product, product.c_str(), sizeof(mNdofDev->product)); + + if (ndof_init_first(mNdofDev, nullptr)) + { + mDriverState = JDS_INITIALIZING; + // Saved device no longer exist + // Np other device present + LL_WARNS() << "ndof_init_first FAILED" << LL_ENDL; + } + else + { + mDriverState = JDS_INITIALIZED; + } + } #endif - mDriverState = JDS_INITIALIZING; - if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL)) + if (mDriverState != JDS_INITIALIZED) { - LL_INFOS("Joystick") << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL; - // Failed to gather devices from windows, init first suitable one - void *preffered_device = NULL; - mLastDeviceUUID = LLSD(); - initDevice(preffered_device); + if (!gViewerWindow->getWindow()->getInputDevices(device_type, osx_callback, win_callback, NULL)) + { + LL_INFOS("Joystick") << "Failed to gather input devices. Falling back to ndof's init" << LL_ENDL; + // Failed to gather devices from window, init first suitable one + void *preffered_device = NULL; + mLastDeviceUUID = LLSD(); + initDevice(preffered_device); + } } if (mDriverState == JDS_INITIALIZING) @@ -611,22 +666,40 @@ void LLViewerJoystick::initDevice(LLSD &guid) #endif } -void LLViewerJoystick::initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid) +bool LLViewerJoystick::initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid) { #if LIB_NDOF mLastDeviceUUID = guid; +#if LL_DARWIN + if (guid.isMap()) + { + std::string manufacturer = mLastDeviceUUID["manufacturer"].asString(); + std::string product = mLastDeviceUUID["product"].asString(); + + strncpy(mNdofDev->manufacturer, manufacturer.c_str(), sizeof(mNdofDev->manufacturer)); + strncpy(mNdofDev->product, product.c_str(), sizeof(mNdofDev->product)); + } + else + { + mNdofDev->product[0] = '\0'; + mNdofDev->manufacturer[0] = '\0'; + } +#else size_t dest_size = sizeof(mNdofDev->product); strncpy(mNdofDev->product, name.c_str(), dest_size); mNdofDev->product[dest_size-1] = '\0'; mNdofDev->manufacturer[0] = '\0'; +#endif - initDevice(preffered_device); + return initDevice(preffered_device); +#else + return false; #endif } -void LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE8* */) +bool LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE8* */) { #if LIB_NDOF // Different joysticks will return different ranges of raw values. @@ -656,8 +729,10 @@ void LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE else { mDriverState = JDS_INITIALIZED; + return true; } #endif + return false; } // ----------------------------------------------------------------------------- @@ -1394,6 +1469,8 @@ bool LLViewerJoystick::isDeviceUUIDSet() #if LL_WINDOWS && !LL_MESA_HEADLESS // for ease of comparison and to dial less with platform specific variables, we store id as LLSD binary return mLastDeviceUUID.isBinary(); +#elif LL_DARWIN + return mLastDeviceUUID.isMap(); #else return false; #endif @@ -1420,19 +1497,48 @@ std::string LLViewerJoystick::getDeviceUUIDString() { return std::string(); } +#elif LL_DARWIN + if (mLastDeviceUUID.isMap()) + { + std::string manufacturer = mLastDeviceUUID["manufacturer"].asString(); + std::string product = mLastDeviceUUID["product"].asString(); + return manufacturer + ":" + product; + } + else + { + return std::string(); + } #else return std::string(); - // return mLastDeviceUUID; +#endif +} + +void LLViewerJoystick::saveDeviceIdToSettings() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // can't save as binary directly, + // someone editing the xml will corrupt it + // so convert to string first + std::string device_string = getDeviceUUIDString(); + gSavedSettings.setLLSD("JoystickDeviceUUID", LLSD(device_string)); +#else + LLSD device_id = getDeviceUUID(); + gSavedSettings.setLLSD("JoystickDeviceUUID", device_id); #endif } void LLViewerJoystick::loadDeviceIdFromSettings() { + LLSD dev_id = gSavedSettings.getLLSD("JoystickDeviceUUID"); #if LL_WINDOWS && !LL_MESA_HEADLESS // We can't save binary data to gSavedSettings, somebody editing the file will corrupt it, // so _GUID data gets converted to string (we probably can convert it to LLUUID with memcpy) // and here we need to convert it back to binary from string - std::string device_string = gSavedSettings.getString("JoystickDeviceUUID"); + std::string device_string; + if (dev_id.isString()) + { + device_string = dev_id.asString(); + } if (device_string.empty()) { mLastDeviceUUID = LLSD(); @@ -1446,10 +1552,22 @@ void LLViewerJoystick::loadDeviceIdFromSettings() LLSD::Binary data; //just an std::vector data.resize(size); memcpy(&data[0], &guid /*POD _GUID*/, size); - // We store this data in LLSD since LLSD is versatile and will be able to handle both GUID2 - // and any data MAC will need for device selection + // We store this data in LLSD since it can handle both GUID2 and long mLastDeviceUUID = LLSD(data); } +#elif LL_DARWIN + if (!dev_id.isMap()) + { + mLastDeviceUUID = LLSD(); + } + else + { + std::string manufacturer = mLastDeviceUUID["manufacturer"].asString(); + std::string product = mLastDeviceUUID["product"].asString(); + LL_DEBUGS("Joystick") << "Looking for device by manufacturer: " << manufacturer << " and product: " << product << LL_ENDL; + // We store this data in LLSD since it can handle both GUID2 and long + mLastDeviceUUID = dev_id; + } #else mLastDeviceUUID = LLSD(); //mLastDeviceUUID = gSavedSettings.getLLSD("JoystickDeviceUUID"); diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index aba3bf18c6e179027becddfc9330bcaac584f92d..51a1c26d8b112f9851c82489518665feac61d0d9 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -30,6 +30,9 @@ #include "stdtypes.h" #if LIB_NDOF +#if LL_DARWIN +#define TARGET_OS_MAC 1 +#endif #include "ndofdev_external.h" #else #define NDOF_Device void @@ -52,8 +55,8 @@ class LLViewerJoystick final : public LLSingleton<LLViewerJoystick> public: void init(bool autoenable); void initDevice(LLSD &guid); - void initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/); - void initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid); + bool initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/); + bool initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid); void terminate(); void updateStatus(); @@ -77,6 +80,7 @@ class LLViewerJoystick final : public LLSingleton<LLViewerJoystick> LLSD getDeviceUUID(); //unconverted, OS dependent value wrapped into LLSD, for comparison/search std::string getDeviceUUIDString(); // converted readable value for settings std::string getDescription(); + void saveDeviceIdToSettings(); protected: void updateEnabled(bool autoenable); @@ -105,7 +109,11 @@ class LLViewerJoystick final : public LLSingleton<LLViewerJoystick> bool mCameraUpdated; bool mOverrideCamera; U32 mJoystickRun; - LLSD mLastDeviceUUID; // _GUID as U8 binary map, integer 1 for no device/ndof's device + + // Windows: _GUID as U8 binary map + // MacOS: long as an U8 binary map + // Else: integer 1 for no device/ndof's default device + LLSD mLastDeviceUUID; // SETTINGS diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 39171c9605630a9c77c570022c8f9cca7b9d1109..dccc9cda6be450ade50e1e5694d1b8e5f670af14 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7599,33 +7599,65 @@ class LLAttachmentDetach : public view_listener_t { // Called when the user clicked on an object attached to them // and selected "Detach". - LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject *object = selection->getPrimaryObject(); if (!object) { LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; return true; } - LLViewerObject *parent = (LLViewerObject*)object->getParent(); - while (parent) + struct f: public LLSelectedObjectFunctor { - if(parent->isAvatar()) + f() : mAvatarsInSelection(false) {} + virtual bool apply(LLViewerObject* objectp) { - break; + if (!objectp) + { + return false; + } + + if (objectp->isAvatar()) + { + mAvatarsInSelection = true; + return false; + } + + LLViewerObject* parent = (LLViewerObject*)objectp->getParent(); + while (parent) + { + if (parent->isAvatar()) + { + break; + } + objectp = parent; + parent = (LLViewerObject*)parent->getParent(); + } + + // std::set to avoid dupplicate 'roots' from linksets + mRemoveSet.insert(objectp->getAttachmentItemID()); + + return true; } - object = parent; - parent = (LLViewerObject*)parent->getParent(); - } + bool mAvatarsInSelection; + uuid_set_t mRemoveSet; + } func; + // Probbly can run applyToRootObjects instead, + // but previous version of this code worked for any selected object + selection->applyToObjects(&func); - if (!object) + if (func.mAvatarsInSelection) { - LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; + // Not possible under normal circumstances + // Either avatar selection is ON or has to do with animeshes + // Better stop this than mess something + LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; return true; } - if (object->isAvatar()) + if (func.mRemoveSet.empty()) { - LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; + LL_WARNS() << "handle_detach() - no valid attachments in selection to detach" << LL_ENDL; return true; } @@ -7640,7 +7672,8 @@ class LLAttachmentDetach : public view_listener_t } // [/RLVa:KB] - LLAppearanceMgr::instance().removeItemFromAvatar(object->getAttachmentItemID()); + uuid_vec_t detach_list(func.mRemoveSet.begin(), func.mRemoveSet.end()); + LLAppearanceMgr::instance().removeItemsFromAvatar(detach_list); return true; } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 49ff7492893ed419c6e2fc0537a6b32c4ba453b3..8aeaa40d4e166804df3e85770cdf3c510c55224e 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -965,7 +965,7 @@ void handle_compress_image(void*) } else { - LL_INFOS() << "Compression failed: " << LLImage::getLastError() << LL_ENDL; + LL_INFOS() << "Compression failed: " << LLImage::getLastThreadError() << LL_ENDL; } infile = picker.getNextFile(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 053c3bc5e2d1f013d8279d756df106083b1a3f39..44fd59d5b57134dbaab2eb78d1487b8febdd2bc7 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1677,8 +1677,9 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, const LLUUID& blocked_id; }; - LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID( - gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id)); + LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel( + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID, + OfferMatcher(blocked_id)); } @@ -6224,8 +6225,9 @@ void script_question_mute(const LLUUID& task_id, const std::string& object_name) const LLUUID& blocked_id; }; - LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID( - gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(task_id)); + LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel( + LLNotificationsUI::NOTIFICATION_CHANNEL_UUID, + OfferMatcher(task_id)); } static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 4e0e43217f094a6e5a62b22299adbd22fce0244f..5d67931accf309107a482936f602f370a381c7ea 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4026,21 +4026,13 @@ F32 LLViewerObject::recursiveGetEstTrianglesMax() const S32 LLViewerObject::getAnimatedObjectMaxTris() const { S32 max_tris = 0; - static LLCachedControl<bool> anim_obj_ignore_limits(gSavedSettings, "AnimatedObjectsIgnoreLimits"); - if (anim_obj_ignore_limits) + if (gAgent.getRegion()) { - max_tris = S32_MAX; - } - else - { - if (gAgent.getRegion()) + LLSD features; + gAgent.getRegion()->getSimulatorFeatures(features); + if (features.has("AnimatedObjects")) { - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (features.has("AnimatedObjects")) - { - max_tris = features["AnimatedObjects"]["AnimatedObjectMaxTris"].asInteger(); - } + max_tris = features["AnimatedObjects"]["AnimatedObjectMaxTris"].asInteger(); } } return max_tris; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 29d0ee261403e92f6c4ed2608faa4b265eae85b8..1870a72ae2244c5ca78b3e25b08b6e8f0f97eceb 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1547,6 +1547,12 @@ void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user) // static void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **user) { + if (LLApp::isExiting() || gDisconnected) + { + LL_DEBUGS("ParcelMgr") << "Ignoring parcel properties, shutting down" << LL_ENDL; + return; + } + S32 request_result; S32 sequence_id; BOOL snap_selection = FALSE; diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index bf34b947d46e6a0e02a25bdb851617ecd6ce8107..5741404ed01cf2d87b368d85d83c0f1437b5eeb1 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -50,7 +50,8 @@ #include "pipeline.h" -const U8 OVERLAY_IMG_COMPONENTS = 4; +static const U8 OVERLAY_IMG_COMPONENTS = 4; +static const F32 LINE_WIDTH = 0.0625f; LLViewerParcelOverlay::update_signal_t* LLViewerParcelOverlay::mUpdateSignal = NULL; @@ -60,11 +61,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ mRegionSize(S32(region_width_meters)), mDirty( FALSE ), mTimeSinceLastUpdate(), - mOverlayTextureIdx(-1), - mVertexCount(0), - mVertexArray(nullptr), - mColorArray(nullptr) -// mTexCoordArray(NULL), + mOverlayTextureIdx(-1) { // Create a texture to hold color information. // 4 components @@ -109,17 +106,6 @@ LLViewerParcelOverlay::~LLViewerParcelOverlay() delete[] mOwnership; mOwnership = NULL; - - delete[] mVertexArray; - mVertexArray = NULL; - - delete[] mColorArray; - mColorArray = NULL; - -// JC No textures. -// delete mTexCoordArray; -// mTexCoordArray = NULL; - mImageRaw = NULL; } @@ -322,7 +308,6 @@ F32 LLViewerParcelOverlay::getOwnedRatio() const } return (F32)total / (F32)size; - } //--------------------------------------------------------------------------- @@ -339,14 +324,13 @@ F32 LLViewerParcelOverlay::getOwnedRatio() const // Note: Assumes that the ownership array and void LLViewerParcelOverlay::updateOverlayTexture() { - if (mOverlayTextureIdx < 0 && mDirty) - { - mOverlayTextureIdx = 0; - } if (mOverlayTextureIdx < 0) { - return; + if (!mDirty) + return; + mOverlayTextureIdx = 0; } + static const LLUIColor avail_color = LLUIColorTable::instance().getColor("PropertyColorAvail"); static const LLUIColor owned_color = LLUIColorTable::instance().getColor("PropertyColorOther"); static const LLUIColor group_color = LLUIColorTable::instance().getColor("PropertyColorGroup"); @@ -460,39 +444,44 @@ void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay) setDirty(); } - void LLViewerParcelOverlay::updatePropertyLines() { - static LLCachedControl<bool> show_property_lines(gSavedSettings, "ShowPropertyLines"); - if (!show_property_lines) - return; + static LLCachedControl<bool> show(gSavedSettings, "ShowPropertyLines"); - S32 row, col; + if (!show) + return; - const LLColor4U self_coloru = LLUIColorTable::instance().getColor("PropertyColorSelf").get(); - const LLColor4U other_coloru = LLUIColorTable::instance().getColor("PropertyColorOther").get(); - const LLColor4U group_coloru = LLUIColorTable::instance().getColor("PropertyColorGroup").get(); - const LLColor4U for_sale_coloru = LLUIColorTable::instance().getColor("PropertyColorForSale").get(); - const LLColor4U auction_coloru = LLUIColorTable::instance().getColor("PropertyColorAuction").get(); + LLColor4U colors[PARCEL_COLOR_MASK + 1]; + colors[PARCEL_SELF] = LLUIColorTable::instance().getColor("PropertyColorSelf").get(); + colors[PARCEL_OWNED] = LLUIColorTable::instance().getColor("PropertyColorOther").get(); + colors[PARCEL_GROUP] = LLUIColorTable::instance().getColor("PropertyColorGroup").get(); + colors[PARCEL_FOR_SALE] = LLUIColorTable::instance().getColor("PropertyColorForSale").get(); + colors[PARCEL_AUCTION] = LLUIColorTable::instance().getColor("PropertyColorAuction").get(); - // Build into dynamic arrays, then copy into static arrays. - std::vector<LLVector3> new_vertex_array; - new_vertex_array.reserve(256); - std::vector<LLColor4U> new_color_array; - new_color_array.reserve(256); - std::vector<LLVector2> new_coord_array; - new_coord_array.reserve(256); + mEdges.clear(); - U8 overlay = 0; - BOOL add_edge = FALSE; const F32 GRID_STEP = PARCEL_GRID_STEP_METERS; const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge; - for (row = 0; row < GRIDS_PER_EDGE; row++) + for (S32 row = 0; row < GRIDS_PER_EDGE; row++) { - for (col = 0; col < GRIDS_PER_EDGE; col++) + for (S32 col = 0; col < GRIDS_PER_EDGE; col++) { - overlay = mOwnership[row*GRIDS_PER_EDGE+col]; + U8 overlay = mOwnership[row*GRIDS_PER_EDGE+col]; + S32 colorIndex = overlay & PARCEL_COLOR_MASK; + switch(colorIndex) + { + case PARCEL_SELF: + case PARCEL_GROUP: + case PARCEL_OWNED: + case PARCEL_FOR_SALE: + case PARCEL_AUCTION: + break; + default: + continue; + } + + const LLColor4U& color = colors[colorIndex]; F32 left = col*GRID_STEP; F32 right = left+GRID_STEP; @@ -503,259 +492,41 @@ void LLViewerParcelOverlay::updatePropertyLines() // West edge if (overlay & PARCEL_WEST_LINE) { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, WEST, auction_coloru); - break; - default: - break; - } + addPropertyLine(left, bottom, 0, 1, LINE_WIDTH, 0, color); } // East edge - if (col < GRIDS_PER_EDGE-1) + if (col == GRIDS_PER_EDGE - 1 || mOwnership[row * GRIDS_PER_EDGE + col + 1] & PARCEL_WEST_LINE) { - U8 east_overlay = mOwnership[row*GRIDS_PER_EDGE+col+1]; - add_edge = east_overlay & PARCEL_WEST_LINE; - } - else - { - add_edge = TRUE; - } - - if (add_edge) - { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - right, bottom, EAST, auction_coloru); - break; - default: - break; - } + addPropertyLine(right, bottom, 0, 1, -LINE_WIDTH, 0, color); } // South edge if (overlay & PARCEL_SOUTH_LINE) { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, bottom, SOUTH, auction_coloru); - break; - default: - break; - } + addPropertyLine(left, bottom, 1, 0, 0, LINE_WIDTH, color); } - // North edge - if (row < GRIDS_PER_EDGE-1) - { - U8 north_overlay = mOwnership[(row+1)*GRIDS_PER_EDGE+col]; - add_edge = north_overlay & PARCEL_SOUTH_LINE; - } - else - { - add_edge = TRUE; - } - - if (add_edge) + if (row == GRIDS_PER_EDGE - 1 || mOwnership[(row + 1) * GRIDS_PER_EDGE + col] & PARCEL_SOUTH_LINE) { - switch(overlay & PARCEL_COLOR_MASK) - { - case PARCEL_SELF: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, self_coloru); - break; - case PARCEL_GROUP: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, group_coloru); - break; - case PARCEL_OWNED: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, other_coloru); - break; - case PARCEL_FOR_SALE: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, for_sale_coloru); - break; - case PARCEL_AUCTION: - addPropertyLine(new_vertex_array, new_color_array, new_coord_array, - left, top, NORTH, auction_coloru); - break; - default: - break; - } + addPropertyLine(left, top, 1, 0, 0, -LINE_WIDTH, color); } } } - // Now copy into static arrays for faster rendering. - // Attempt to recycle old arrays if possible to avoid memory - // shuffling. - S32 new_vertex_count = new_vertex_array.size(); - - if (!(mVertexArray && mColorArray && new_vertex_count == mVertexCount)) - { - // ...need new arrays - delete[] mVertexArray; - mVertexArray = NULL; - delete[] mColorArray; - mColorArray = NULL; - - mVertexCount = new_vertex_count; - - if (new_vertex_count > 0) - { - mVertexArray = new F32[3 * mVertexCount]; - mColorArray = new U8 [4 * mVertexCount]; - } - } - - // Copy the new data into the arrays - S32 i; - F32* vertex = mVertexArray; - for (i = 0; i < mVertexCount; i++) - { - const LLVector3& point = new_vertex_array.at(i); - *vertex = point.mV[VX]; - vertex++; - *vertex = point.mV[VY]; - vertex++; - *vertex = point.mV[VZ]; - vertex++; - } - - U8* colorp = mColorArray; - for (i = 0; i < mVertexCount; i++) - { - const LLColor4U& color = new_color_array.at(i); - *colorp = color.mV[VRED]; - colorp++; - *colorp = color.mV[VGREEN]; - colorp++; - *colorp = color.mV[VBLUE]; - colorp++; - *colorp = color.mV[VALPHA]; - colorp++; - } - // Everything's clean now mDirty = FALSE; } - -void LLViewerParcelOverlay::addPropertyLine( - std::vector<LLVector3>& vertex_array, - std::vector<LLColor4U>& color_array, - std::vector<LLVector2>& coord_array, - const F32 start_x, const F32 start_y, - const U32 edge, - const LLColor4U& color) +void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F32 dy, F32 tick_dx, F32 tick_dy, const LLColor4U& color) { - LLColor4U underwater( color ); - underwater.mV[VALPHA] /= 2; - - vertex_array.reserve(16); - color_array.reserve(16); - coord_array.reserve(16); - LLSurface& land = mRegion->getLand(); + F32 water_z = land.getWaterHeight(); - F32 dx; - F32 dy; - F32 tick_dx; - F32 tick_dy; - //const F32 LINE_WIDTH = 0.125f; - const F32 LINE_WIDTH = 0.0625f; - - switch(edge) - { - case WEST: - dx = 0.f; - dy = 1.f; - tick_dx = LINE_WIDTH; - tick_dy = 0.f; - break; - - case EAST: - dx = 0.f; - dy = 1.f; - tick_dx = -LINE_WIDTH; - tick_dy = 0.f; - break; - - case NORTH: - dx = 1.f; - dy = 0.f; - tick_dx = 0.f; - tick_dy = -LINE_WIDTH; - break; - - case SOUTH: - dx = 1.f; - dy = 0.f; - tick_dx = 0.f; - tick_dy = LINE_WIDTH; - break; - - default: - LL_ERRS() << "Invalid edge in addPropertyLine" << LL_ENDL; - return; - } + mEdges.resize(mEdges.size() + 1); + Edge& edge = mEdges.back(); + edge.color = color; F32 outside_x = start_x; F32 outside_y = start_y; @@ -764,14 +535,31 @@ void LLViewerParcelOverlay::addPropertyLine( F32 inside_y = start_y + tick_dy; F32 inside_z = 0.f; + auto split = [&](const LLVector3& start, F32 x, F32 y, F32 z, F32 part) + { + F32 new_x = start.mV[0] + (x - start.mV[0]) * part; + F32 new_y = start.mV[1] + (y - start.mV[1]) * part; + F32 new_z = start.mV[2] + (z - start.mV[2]) * part; + edge.vertices.emplace_back(new_x, new_y, new_z); + }; + + auto checkForSplit = [&]() + { + const LLVector3& last_outside = edge.vertices.back(); + F32 z0 = last_outside.mV[2]; + F32 z1 = outside_z; + if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z)) + return; + F32 part = (water_z - z0) / (z1 - z0); + const LLVector3& last_inside = edge.vertices[edge.vertices.size() - 2]; + split(last_inside, inside_x, inside_y, inside_z, part); + split(last_outside, outside_x, outside_y, outside_z, part); + }; + // First part, only one vertex outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); inside_x += dx * LINE_WIDTH; inside_y += dy * LINE_WIDTH; @@ -783,17 +571,8 @@ void LLViewerParcelOverlay::addPropertyLine( inside_z = land.resolveHeightRegion( inside_x, inside_y ); outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (inside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(inside_x, inside_y, inside_z) ); - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - - coord_array.push_back( LLVector2(outside_x - start_x, 1.f) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); inside_x += dx * (dx - LINE_WIDTH); inside_y += dy * (dy - LINE_WIDTH); @@ -802,24 +581,16 @@ void LLViewerParcelOverlay::addPropertyLine( outside_y += dy * (dy - LINE_WIDTH); // Middle part, full width - S32 i; const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); - for (i = 1; i < GRID_STEP; i++) + for (S32 i = 1; i < GRID_STEP; i++) { inside_z = land.resolveHeightRegion( inside_x, inside_y ); outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (inside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); + checkForSplit(); - vertex_array.push_back( LLVector3(inside_x, inside_y, inside_z) ); - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - - coord_array.push_back( LLVector2(outside_x - start_x, 1.f) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); inside_x += dx; inside_y += dy; @@ -838,20 +609,10 @@ void LLViewerParcelOverlay::addPropertyLine( inside_z = land.resolveHeightRegion( inside_x, inside_y ); outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (inside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); + checkForSplit(); - vertex_array.push_back( LLVector3(inside_x, inside_y, inside_z) ); - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - - coord_array.push_back( LLVector2(outside_x - start_x, 1.f) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); - - inside_x += dx * LINE_WIDTH; - inside_y += dy * LINE_WIDTH; + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); outside_x += dx * LINE_WIDTH; outside_y += dy * LINE_WIDTH; @@ -859,14 +620,9 @@ void LLViewerParcelOverlay::addPropertyLine( // Last edge is not drawn to the edge outside_z = land.resolveHeightRegion( outside_x, outside_y ); - if (outside_z > 20.f) color_array.push_back( color ); - else color_array.push_back( underwater ); - - vertex_array.push_back( LLVector3(outside_x, outside_y, outside_z) ); - coord_array.push_back( LLVector2(outside_x - start_x, 0.f) ); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); } - void LLViewerParcelOverlay::setDirty() { mDirty = TRUE; @@ -904,19 +660,15 @@ void LLViewerParcelOverlay::idleUpdate(bool force_update) } } -S32 LLViewerParcelOverlay::renderPropertyLines () +void LLViewerParcelOverlay::renderPropertyLines() { - static LLCachedControl<bool> show_property_lines(gSavedSettings, "ShowPropertyLines"); - if (!show_property_lines) - { - return 0; - } - if (!mVertexArray || !mColorArray) - { - return 0; - } + static LLCachedControl<bool> show(gSavedSettings, "ShowPropertyLines"); + + if (!show) + return; LLSurface& land = mRegion->getLand(); + F32 water_z = land.getWaterHeight() + 0.01f; LLGLSUIDefault gls_ui; // called from pipeline gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -943,16 +695,11 @@ S32 LLViewerParcelOverlay::renderPropertyLines () // Move to appropriate region coords LLVector3 origin = mRegion->getOriginAgent(); - gGL.translatef( origin.mV[VX], origin.mV[VY], origin.mV[VZ] ); + gGL.translatef(origin.mV[VX], origin.mV[VY], origin.mV[VZ]); gGL.translatef(pull_toward_camera.mV[VX], pull_toward_camera.mV[VY], pull_toward_camera.mV[VZ]); - // Include +1 because vertices are fenceposts. - // *2 because it's a quad strip - const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); - const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3; - // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgentCamera.getCameraPositionGlobal() ); @@ -962,91 +709,68 @@ S32 LLViewerParcelOverlay::renderPropertyLines () cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS; cull_plane_point += camera_region; - LLVector3 vertex; - - const S32 BYTES_PER_COLOR = 4; - const S32 FLOATS_PER_VERTEX = 3; - //const S32 FLOATS_PER_TEX_COORD = 2; - S32 i, j; - S32 drawn = 0; - F32* vertexp; - U8* colorp; bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); const F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; - for (i = 0; i < mVertexCount; i += vertex_per_edge) + for (const Edge& edge : mEdges) { - colorp = mColorArray + BYTES_PER_COLOR * i; - vertexp = mVertexArray + FLOATS_PER_VERTEX * i; - - vertex.mV[VX] = *(vertexp); - vertex.mV[VY] = *(vertexp+1); - vertex.mV[VZ] = *(vertexp+2); + LLVector3 center = edge.vertices[edge.vertices.size() >> 1]; - if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) + if (dist_vec_squared2D(center, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } // Destroy vertex, transform to plane-local. - vertex -= cull_plane_point; + center -= cull_plane_point; - // negative dot product means it is in back of the plane - if ( vertex * CAMERA_AT < 0.f ) + // Negative dot product means it is in back of the plane + if (center * CAMERA_AT < 0.f) { continue; } gGL.begin(LLRender::TRIANGLE_STRIP); - for (j = 0; j < vertex_per_edge; j++) - { - gGL.color4ubv(colorp); - gGL.vertex3fv(vertexp); + gGL.color4ubv(edge.color.mV); - colorp += BYTES_PER_COLOR; - vertexp += FLOATS_PER_VERTEX; + for (const LLVector3& vertex : edge.vertices) + { + if (render_hidden || camera_z < water_z || vertex.mV[2] >= water_z) + { + gGL.vertex3fv(vertex.mV); + } + else + { + LLVector3 visible = vertex; + visible.mV[2] = water_z; + gGL.vertex3fv(visible.mV); + } } - drawn += vertex_per_edge; - gGL.end(); if (render_hidden) { LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - colorp = mColorArray + BYTES_PER_COLOR * i; - vertexp = mVertexArray + FLOATS_PER_VERTEX * i; - gGL.begin(LLRender::TRIANGLE_STRIP); - for (j = 0; j < vertex_per_edge; j++) - { - U8 color[4]; - color[0] = colorp[0]; - color[1] = colorp[1]; - color[2] = colorp[2]; - color[3] = colorp[3]/4; + LLColor4U color = edge.color; + color.mV[3] /= 4; + gGL.color4ubv(color.mV); - gGL.color4ubv(color); - gGL.vertex3fv(vertexp); - - colorp += BYTES_PER_COLOR; - vertexp += FLOATS_PER_VERTEX; + for (const LLVector3& vertex : edge.vertices) + { + gGL.vertex3fv(vertex.mV); } - drawn += vertex_per_edge; - gGL.end(); } - } gGL.popMatrix(); - - return drawn; } // Draw half of a single cell (no fill) in a grid drawn from left to right and from bottom to top @@ -1070,11 +794,9 @@ void grid_2d_part_lines(const F32 left, const F32 top, const F32 right, const F3 void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) { - if (!mOwnership) - { - return; - } - if (!gSavedSettings.getBOOL("MiniMapShowPropertyLines")) + static LLCachedControl<bool> show(gSavedSettings, "MiniMapShowPropertyLines"); + + if (!mOwnership || !show) { return; } @@ -1089,11 +811,11 @@ void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_me gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glLineWidth(1.0f); gGL.color4fv(parcel_outline_color); - for (S32 i = 0; i < GRIDS_PER_EDGE + 1; i++) + for (S32 i = 0; i <= GRIDS_PER_EDGE; i++) { const F32 bottom = region_bottom + (i * map_parcel_width); const F32 top = bottom + map_parcel_width; - for (S32 j = 0; j < GRIDS_PER_EDGE + 1; j++) + for (S32 j = 0; j <= GRIDS_PER_EDGE; j++) { const F32 left = region_left + (j * map_parcel_width); const F32 right = left + map_parcel_width; diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 7ea2a48d5dd02b5b3ac2246c3286bc8f06ec93de..8e8427451ecafbb6397483be58f880a0f1437867 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -69,7 +69,7 @@ class LLViewerParcelOverlay final : public LLGLUpdate const U8* getOwnership() const { return mOwnership; } // Returns the number of vertices drawn - S32 renderPropertyLines(); + void renderPropertyLines(); void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); U8 ownership( const LLVector3& pos) const; @@ -96,12 +96,7 @@ class LLViewerParcelOverlay final : public LLGLUpdate U8 parcelFlags(S32 row, S32 col, U8 flags) const; - void addPropertyLine(std::vector<LLVector3>& vertex_array, - std::vector<LLColor4U>& color_array, - std::vector<LLVector2>& coord_array, - const F32 start_x, const F32 start_y, - const U32 edge, - const LLColor4U& color); + void addPropertyLine(F32 start_x, F32 start_y, F32 dx, F32 dy, F32 tick_dx, F32 tick_dy, const LLColor4U& color); void updateOverlayTexture(); void updatePropertyLines(); @@ -126,9 +121,13 @@ class LLViewerParcelOverlay final : public LLGLUpdate LLFrameTimer mTimeSinceLastUpdate; S32 mOverlayTextureIdx; - S32 mVertexCount; - F32* mVertexArray; - U8* mColorArray; + struct Edge + { + std::vector<LLVector3> vertices; + LLColor4U color; + }; + + std::vector<Edge> mEdges; static update_signal_t* mUpdateSignal; }; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 6738ec6bf47fd71af952b125d3300285dfb621b8..4fde7a13707a8b2eeba27af2134232726eb04cd1 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1116,15 +1116,11 @@ void LLViewerRegion::setCacheID(const LLUUID& id) mImpl->mCacheID = id; } -S32 LLViewerRegion::renderPropertyLines() +void LLViewerRegion::renderPropertyLines() { if (mParcelOverlay) { - return mParcelOverlay->renderPropertyLines(); - } - else - { - return 0; + mParcelOverlay->renderPropertyLines(); } } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 4762588226074f203e7ba2a089aeb6d46e39f80b..6f8af41c79024bdd94612532d967e4b40157eda4 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -160,7 +160,7 @@ class LLViewerRegion final : public LLCapabilityProvider // implements this inte // Draw lines in the dirt showing ownership. Return number of // vertices drawn. - S32 renderPropertyLines(); + void renderPropertyLines(); void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index 365d0b7b7b9b4a6350c8eb8c450ebd472867f23f..c8c9284668cebab6cefa2c05cc333717837d1b9d 100644 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -186,11 +186,11 @@ BOOL LLViewerTexLayerSetBuffer::isReadyToUpdate() const // Update if we've hit a timeout. Unlike for uploads, we can make this timeout fairly small // since render unnecessarily doesn't cost much. - static const LLCachedControl<U32> texture_timeout(gSavedSettings, "AvatarBakedLocalTextureUpdateTimeout"); - if (texture_timeout != 0) + const U32 TEXTURE_TIMEOUT = 10; + if (TEXTURE_TIMEOUT != 0) { // If we hit our timeout and have textures available at even lower resolution, then update. - const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= texture_timeout; + const BOOL is_update_textures_timeout = mNeedsUpdateTimer.getElapsedTimeF32() >= TEXTURE_TIMEOUT; const BOOL has_lower_lod = getViewerTexLayerSet()->isLocalTextureDataAvailable(); if (has_lower_lod && is_update_textures_timeout) return TRUE; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7c5d58bc97d266e5baa17af933429178e2f24384..ab5d9c3a8cca57e2fcab9e29430915b200201493 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -602,7 +602,6 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, LLHost request_from_host) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - static LLCachedControl<bool> fast_cache_fetching_enabled(gSavedSettings, "FastCacheFetchEnabled", true); LLPointer<LLViewerFetchedTexture> imagep ; switch(texture_type) @@ -648,11 +647,9 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, imagep->forceActive() ; } - if(fast_cache_fetching_enabled) - { - mFastCacheList.insert(imagep); - imagep->setInFastCacheList(true); - } + mFastCacheList.insert(imagep); + imagep->setInFastCacheList(true); + return imagep ; } @@ -1313,7 +1310,7 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image, return true; } -BOOL LLViewerTextureList::createUploadFile(const std::string& filename, +bool LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec, const S32 max_image_dimentions, @@ -1321,64 +1318,72 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename, bool force_square) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - // Load the image - LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); - if (image.isNull()) - { - LL_WARNS() << "Couldn't open the image to be uploaded." << LL_ENDL; - return FALSE; - } - if (!image->load(filename)) - { - image->setLastError("Couldn't load the image to be uploaded."); - return FALSE; - } - // Decompress or expand it in a raw image structure - LLPointer<LLImageRaw> raw_image = new LLImageRaw; - if (!image->decode(raw_image, 0.0f)) - { - image->setLastError("Couldn't decode the image to be uploaded."); - return FALSE; - } - // Check the image constraints - if ((image->getComponents() != 3) && (image->getComponents() != 4)) + try { - image->setLastError("Image files with less than 3 or more than 4 components are not supported."); - return FALSE; - } - if (image->getWidth() < min_image_dimentions || image->getHeight() < min_image_dimentions) - { - std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx", - min_image_dimentions, - min_image_dimentions, - image->getWidth(), - image->getHeight()); - image->setLastError(reason); - return FALSE; - } - // Convert to j2c (JPEG2000) and save the file locally - LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions, force_square); - if (compressedImage.isNull()) - { - image->setLastError("Couldn't convert the image to jpeg2000."); - LL_INFOS() << "Couldn't convert to j2c, file : " << filename << LL_ENDL; - return FALSE; - } - if (!compressedImage->save(out_filename)) - { - image->setLastError("Couldn't create the jpeg2000 image for upload."); - LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL; - return FALSE; + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + LL_WARNS() << "Couldn't open the image to be uploaded." << LL_ENDL; + return false; + } + if (!image->load(filename)) + { + image->setLastError("Couldn't load the image to be uploaded."); + return false; + } + // Decompress or expand it in a raw image structure + LLPointer<LLImageRaw> raw_image = new LLImageRaw; + if (!image->decode(raw_image, 0.0f)) + { + image->setLastError("Couldn't decode the image to be uploaded."); + return false; + } + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + if (image->getWidth() < min_image_dimentions || image->getHeight() < min_image_dimentions) + { + std::string reason = llformat("Images below %d x %d pixels are not allowed. Actual size: %d x %dpx", + min_image_dimentions, + min_image_dimentions, + image->getWidth(), + image->getHeight()); + image->setLastError(reason); + return false; + } + // Convert to j2c (JPEG2000) and save the file locally + LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image, max_image_dimentions, force_square); + if (compressedImage.isNull()) + { + image->setLastError("Couldn't convert the image to jpeg2000."); + LL_INFOS() << "Couldn't convert to j2c, file : " << filename << LL_ENDL; + return false; + } + if (!compressedImage->save(out_filename)) + { + image->setLastError("Couldn't create the jpeg2000 image for upload."); + LL_INFOS() << "Couldn't create output file : " << out_filename << LL_ENDL; + return false; + } + // Test to see if the encode and save worked + LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; + if (!integrity_test->loadAndValidate(out_filename)) + { + image->setLastError("The created jpeg2000 image is corrupt."); + LL_INFOS() << "Image file : " << out_filename << " is corrupt" << LL_ENDL; + return false; + } } - // Test to see if the encode and save worked - LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; - if (!integrity_test->loadAndValidate( out_filename )) + catch (...) { - image->setLastError("The created jpeg2000 image is corrupt."); - LL_INFOS() << "Image file : " << out_filename << " is corrupt" << LL_ENDL; - return FALSE; + LOG_UNHANDLED_EXCEPTION(""); + return false; } - return TRUE; + return true; } // note: modifies the argument raw_image!!!! diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index cd733ca2a6df6d84e1291827d8772f64d3734ac4..f9173aee2c50ce13710d2229c3f2017236a46f28 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -109,7 +109,7 @@ class LLViewerTextureList const std::string& out_filename, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT, const S32 min_image_dimentions = 0); - static BOOL createUploadFile(const std::string& filename, + static bool createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT, diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 59bff73451bb16cfc33c07e5d187a928fca677aa..ad893c086d9ecf343928cdc55ebf0209a1b66261 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2373,13 +2373,15 @@ void LLViewerWindow::initBase() gFloaterView->setFloaterSnapView(mFloaterSnapRegion->getHandle()); gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); + const F32 CHAT_PERSIST_TIME = 20.f; + // Console llassert( !gConsole ); LLConsole::Params cp; cp.name("console"); cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize")); cp.rect(getChatConsoleRect()); - cp.persist_time(gSavedSettings.getF32("ChatPersistTime")); + cp.persist_time(CHAT_PERSIST_TIME); cp.font_size_index(gSavedSettings.getS32("ChatFontSize")); cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); gConsole = LLUICtrlFactory::create<LLConsole>(cp); @@ -3043,6 +3045,15 @@ BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) } } + // Try for a new-format gesture + if (LLGestureMgr::instance().triggerGestureRelease(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey new gesture release feature" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + //Old format gestures do not support this, so no need to implement it. + // don't pass keys on to world when something in ui has focus return gFocusMgr.childHasKeyboardFocus(mRootView) || LLMenuGL::getKeyboardMode() @@ -3590,13 +3601,13 @@ void LLViewerWindow::updateUI() if (gLoggedInTime.getStarted()) { - static const LLCachedControl<F32> dest_hint_timeout(gSavedSettings, "DestinationGuideHintTimeout"); - if (gLoggedInTime.getElapsedTimeF32() > dest_hint_timeout) + const F32 DESTINATION_GUIDE_HINT_TIMEOUT = 1200.f; + const F32 SIDE_PANEL_HINT_TIMEOUT = 300.f; + if (gLoggedInTime.getElapsedTimeF32() > DESTINATION_GUIDE_HINT_TIMEOUT) { LLFirstUse::notUsingDestinationGuide(); } - static const LLCachedControl<F32> sidepanel_hint_timeout(gSavedSettings, "SidePanelHintTimeout"); - if (gLoggedInTime.getElapsedTimeF32() > sidepanel_hint_timeout) + if (gLoggedInTime.getElapsedTimeF32() > SIDE_PANEL_HINT_TIMEOUT) { LLFirstUse::notUsingSidePanel(); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c3122bb994a164f1ac410d80dc5d58c2636cb390..bda5089c2d3bd773b53351b5f8bef913407cab57 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1381,8 +1381,8 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - static LLCachedControl<S32> box_detail_cache(gSavedSettings, "AvatarBoundingBoxComplexity"); - S32 box_detail = box_detail_cache; + const S32 BOX_DETAIL_DEFAULT = 3; + S32 box_detail = BOX_DETAIL_DEFAULT; if (getOverallAppearance() != AOA_NORMAL) { if (isControlAvatar()) @@ -4470,10 +4470,10 @@ void LLVOAvatar::updateOrientation(LLAgent& agent, F32 speed, F32 delta_time) LLVector3 pelvisDir( mRoot->getWorldMatrix().getRow<LLMatrix4a::ROW_FWD>().getF32ptr() ); - static LLCachedControl<F32> s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow", 60.0); - static LLCachedControl<F32> s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast", 2.0); + const F32 AVATAR_PELVIS_ROTATE_THRESHOLD_SLOW = 60.0f; + const F32 AVATAR_PELVIS_ROTATE_THRESHOLD_FAST = 2.0f; - F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); + F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, AVATAR_PELVIS_ROTATE_THRESHOLD_SLOW, AVATAR_PELVIS_ROTATE_THRESHOLD_FAST); if (self_in_mouselook) { @@ -9557,9 +9557,7 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe // Parse visual params, if any. S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); - static LLCachedControl<bool> block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams"); - bool drop_visual_params_debug = block_some_avatars && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing - if( num_blocks > 1 && !drop_visual_params_debug) + if( num_blocks > 1) { //LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; @@ -9604,14 +9602,7 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe } else { - if (drop_visual_params_debug) - { - LL_INFOS() << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << LL_ENDL; - } - else - { - LL_DEBUGS("Avatar") << "AvatarAppearance msg received without any parameters, object: " << getID() << LL_ENDL; - } + LL_DEBUGS("Avatar") << "AvatarAppearance msg received without any parameters, object: " << getID() << LL_ENDL; } LLVisualParam* appearance_version_param = getVisualParam(11000); diff --git a/indra/newview/llvoicecallhandler.cpp b/indra/newview/llvoicecallhandler.cpp index 43c6952d9ca9e05d249e17aa38d6780a3f38e017..92f3543517b5577e42b5ccbb3ab59b229c217935 100644 --- a/indra/newview/llvoicecallhandler.cpp +++ b/indra/newview/llvoicecallhandler.cpp @@ -40,12 +40,6 @@ class LLVoiceCallAvatarHandler : public LLCommandHandler bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableVoiceCall")) - { - LLNotificationsUtil::add("NoVoiceCall", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - //Make sure we have some parameters if (params.size() == 0) { diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 51c411dc65fd81f9ce6ea077954d244d2fb2dc80..ec2eadd1d66565ea8a037736723337c6802c08c7 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -929,17 +929,17 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() registrar.add("Wearable.CreateNew", boost::bind(createNewWearable, selected_id)); registrar.add("Wearable.ShowOriginal", boost::bind(show_item_original, selected_id)); registrar.add("Wearable.TakeOffDetach", - boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids, no_op)); // Register handlers for clothing. registrar.add("Clothing.TakeOff", - boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids, no_op)); // Register handlers for body parts. // Register handlers for attachments. registrar.add("Attachment.Detach", - boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids)); + boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids, no_op)); registrar.add("Attachment.Touch", boost::bind(handle_attachment_touch, selected_id)); registrar.add("Attachment.Profile", boost::bind(show_item_profile, selected_id)); registrar.add("Object.Attach", boost::bind(LLViewerAttachMenu::attachObjects, ids, _2)); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 458b08d08c03b3855bcda3f9cef4824db4ad0da2..e2a9c9809998edc6ea58f7be2e86e0d009b7df26 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5275,7 +5275,7 @@ void LLPipeline::setupAvatarLights(bool for_edit) light->setSpotExponent(0.f); light->setSpotCutoff(180.f); } - else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) + else if (gAvatarBacklight) { LLVector3 light_dir = sun_up ? LLVector3(mSunDir) : LLVector3(mMoonDir); LLVector3 opposite_pos = -light_dir; diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 41dc8fc7c49ba3ac1f02ae3596cea5f1fb9856dd..def7f11f414247415cfd2f3e2c6188ef1e7dd024 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -1797,7 +1797,7 @@ void RlvForceWear::done() if (!remItems.empty()) { - LLAppearanceMgr::instance().removeItemsFromAvatar(remItems, cb, true); + LLAppearanceMgr::instance().removeItemsFromAvatar(remItems, no_op,cb, true); } if ( (addBodyParts.empty()) && (!addClothing.empty()) && (m_addGestures.empty()) ) diff --git a/indra/newview/skins/default/textures/icons/Group_Notices.png b/indra/newview/skins/default/textures/icons/Group_Notices.png new file mode 100644 index 0000000000000000000000000000000000000000..601502d374fef0744e3f9110f55f3631e8cde7ce Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Group_Notices.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 233d158d1aa5b2cd267547bcacb0bfff50a49bc5..eab371f8b27a740bd8c67aa9855e71df686b737a 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -259,6 +259,8 @@ with the same filename but different name <texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" /> <texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" /> + <texture name="Group_Notices" file_name="icons/Group_Notices.png" preload="false" /> + <texture name="Hand" file_name="icons/hand.png" preload="false" /> <texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/da/emoji_categories.xml b/indra/newview/skins/default/xui/da/emoji_categories.xml index 456b18e4e216be0941190f1938fb1a1199b95a38..f2a7f7a3aa72d101be95156469a6863b394b7e99 100644 --- a/indra/newview/skins/default/xui/da/emoji_categories.xml +++ b/indra/newview/skins/default/xui/da/emoji_categories.xml @@ -5,13 +5,13 @@ <key>Name</key> <string>smileys and emotion</string> <key>Category</key> - <string>smileys and følelser</string> + <string>smileys & følelser</string> </map> <map> <key>Name</key> <string>people and body</string> <key>Category</key> - <string>mennesker and krop</string> + <string>mennesker & krop</string> </map> <map> <key>Name</key> @@ -23,19 +23,19 @@ <key>Name</key> <string>animals and nature</string> <key>Category</key> - <string>dyr and natur</string> + <string>dyr & natur</string> </map> <map> <key>Name</key> <string>food and drink</string> <key>Category</key> - <string>mad and drikke</string> + <string>mad & drikke</string> </map> <map> <key>Name</key> <string>travel and places</string> <key>Category</key> - <string>rejser and steder</string> + <string>rejser & steder</string> </map> <map> <key>Name</key> diff --git a/indra/newview/skins/default/xui/de/emoji_categories.xml b/indra/newview/skins/default/xui/de/emoji_categories.xml index ed63d0bac9d3bfb15529d5b395f4f0d7d3424961..ff9e4aec6363f5cac4888becdefd390c0fda7f5a 100644 --- a/indra/newview/skins/default/xui/de/emoji_categories.xml +++ b/indra/newview/skins/default/xui/de/emoji_categories.xml @@ -5,13 +5,13 @@ <key>Name</key> <string>smileys and emotion</string> <key>Category</key> - <string>Smileys and Emotionen</string> + <string>Smileys & Emotionen</string> </map> <map> <key>Name</key> <string>people and body</string> <key>Category</key> - <string>Menschen and Körper</string> + <string>Menschen & Körper</string> </map> <map> <key>Name</key> @@ -23,19 +23,19 @@ <key>Name</key> <string>animals and nature</string> <key>Category</key> - <string>Tiere and Natur</string> + <string>Tiere & Natur</string> </map> <map> <key>Name</key> <string>food and drink</string> <key>Category</key> - <string>Essen and Trinken</string> + <string>Essen & Trinken</string> </map> <map> <key>Name</key> <string>travel and places</string> <key>Category</key> - <string>Reisen and Orte</string> + <string>Reisen & Orte</string> </map> <map> <key>Name</key> diff --git a/indra/newview/skins/default/xui/en/emoji_categories.xml b/indra/newview/skins/default/xui/en/emoji_categories.xml index 9ccffc5b84d2c6658f62497d74a0c3242f2178a5..bffb0ca181af46640b46be8ddd1054ddf6b58294 100644 --- a/indra/newview/skins/default/xui/en/emoji_categories.xml +++ b/indra/newview/skins/default/xui/en/emoji_categories.xml @@ -1,17 +1,21 @@ <?xml version="1.0" ?> <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="llsd.xsd"> + <!-- WARNING: This file isn't directly localizable at the moment, + translated variants Must match values provided by + 3p_emoji_shortcodes via emoji_characters for categories + to work correctly--> <array> <map> <key>Name</key> <string>smileys and emotion</string> <key>Category</key> - <string>smileys and emotion</string> + <string>smileys & emotion</string> </map> <map> <key>Name</key> <string>people and body</string> <key>Category</key> - <string>people and body</string> + <string>people & body</string> </map> <map> <key>Name</key> @@ -23,19 +27,19 @@ <key>Name</key> <string>animals and nature</string> <key>Category</key> - <string>animals and nature</string> + <string>animals & nature</string> </map> <map> <key>Name</key> <string>food and drink</string> <key>Category</key> - <string>food and drink</string> + <string>food & drink</string> </map> <map> <key>Name</key> <string>travel and places</string> <key>Category</key> - <string>travel and places</string> + <string>travel & places</string> </map> <map> <key>Name</key> diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml index ba2527e55012fb82b525f8977153ff6a523e0136..abe8344097ce80fa40d80cf0a745defd3f0f4dfa 100644 --- a/indra/newview/skins/default/xui/en/floater_create_landmark.xml +++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml @@ -39,7 +39,7 @@ layout="topleft" max_length_bytes="63" name="title_editor" - prevalidate_callback="ascii" + prevalidator="ascii" text_readonly_color="white" top_pad="5" width="290" /> @@ -87,7 +87,7 @@ name="notes_editor" spellcheck="true" text_readonly_color="white" - text_type="ascii_with_newline" + prevalidator="ascii_with_newline" commit_on_focus_lost="true" top_pad="5" width="290" diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml index 2eacc8150eaef65c835b9c099193c11ef22db218..1500c96b8d3f43a37b38bb65940e5e6f096bb347 100644 --- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml +++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml @@ -60,7 +60,7 @@ left_pad="10" max_length_bytes="100" name="day_cycle_name" - prevalidate_callback="ascii" + prevalidator="ascii" top="5" width="200" height="21" /> diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml index d21f8c82bc5cb8bfc0d2dcd72c4d168eece9d254..e4b8f13df7144324366243b05c24cc88902f5527 100644 --- a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -15,6 +15,7 @@ width="304"> <floater.string name="title_for_recently_used" value="Recently used"/> <floater.string name="title_for_frequently_used" value="Frequently used"/> + <floater.string name="text_no_emoji_for_filter" value="No emoji found for '[FILTER]'"/> <scroll_container name="EmojiGridContainer" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml index f424f67df0c1249b430968abc2f10821f82fc9c3..5c31bf8ba0c40746f35802174437642bb16ac691 100644 --- a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml +++ b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml @@ -44,7 +44,7 @@ left_delta="45" width="250" name="settings_name" - prevalidate_callback="ascii" + prevalidator="ascii" max_length_chars="63" height="20"/> <button diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 475485c9d8ff3ba74534561dc50a774ade537f16..5cfddd9ac5636b5548606770c375e55f31805331 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -544,7 +544,7 @@ </layout_panel> <layout_panel name="emoji_recent_layout_panel" - height="30" + height="36" auto_resize="false"> <text name="emoji_recent_empty_text" @@ -554,19 +554,28 @@ h_pad="20" v_pad="10" top="0" - left="1" + left="2" right="-65" - height="30" + height="34" >Recently used emojis will appear here</text> - <emoji_complete - name="emoji_recent_icons_ctrl" + <panel + name="emoji_recent_container" follows="top|left|right" layout="topleft" - max_visible="20" top="0" - left="1" + left="2" right="-65" - height="30"/> + height="34"> + <emoji_complete + name="emoji_recent_icons_ctrl" + follows="top|left|right" + layout="topleft" + max_visible="20" + top="2" + left="2" + right="-2" + height="30"/> + </panel> <button name="emoji_picker_show_btn" label="More" diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml index 5ea751dc7c037aeecd181752494963d947566a37..e5ec9cc97d6da372e4aeddd46b01ffd6adba835f 100644 --- a/indra/newview/skins/default/xui/en/floater_media_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml @@ -211,22 +211,12 @@ <button.commit_callback function="MediaBrowser.OpenWebBrowser" /> </button> - <check_box - control_name="UseExternalBrowser" - follows="bottom|left" - height="20" - label="Always open in my web browser" - layout="topleft" - left_pad="5" - name="open_always" - top_delta="0" - width="200" /> <button follows="bottom|right" height="20" label="Close" layout="topleft" - left_pad="80" + left_pad="285" name="close" top_delta="0" width="70"> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index 5dcac85b4ff2ac42a1eed64f387b0bc0f8925f91..90223fcda8c08e59d4a50ed8c26510721a658370 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -93,7 +93,7 @@ height="19" max_length_bytes="63" name="description_form" - prevalidate_callback="ascii" + prevalidator="ascii" top_pad="5" width="290" /> </panel> diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml index 1abf35e3e5c81939c9efe0fcd9386adfe1aff086..412fe957ee4fd4d9faa1dcf3be794016a7c1c2b3 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml @@ -3,8 +3,8 @@ positioning="centered" save_rect="true" legacy_header_height="18" - height="460" - min_height="460" + height="475" + min_height="475" layout="topleft" name="gesture_preview" help_topic="gesture_preview" @@ -296,6 +296,15 @@ top_pad="3" width="80" /> </radio_group> + <check_box + follows="top|left" + height="20" + label="until key is released" + layout="topleft" + left="28" + name="wait_key_release_check" + top="330" + width="100" /> <check_box follows="top|left" height="20" @@ -303,7 +312,7 @@ layout="topleft" left="28" name="wait_anim_check" - top="330" + top_delta="20" width="100" /> <check_box follows="top|left" diff --git a/indra/newview/skins/default/xui/en/floater_profile_texture.xml b/indra/newview/skins/default/xui/en/floater_profile_texture.xml index da74b7f78e5b842318a35c716d7ef05d802c5cd8..157f012d42e9b7bb916645fe76b44c2487c00995 100644 --- a/indra/newview/skins/default/xui/en/floater_profile_texture.xml +++ b/indra/newview/skins/default/xui/en/floater_profile_texture.xml @@ -27,7 +27,7 @@ follows="left|top" auto_resize="true" layout="topleft"> - <icon + <profile_image name="profile_pic" image_name="Generic_Person_Large" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_region_info.xml b/indra/newview/skins/default/xui/en/floater_region_info.xml index ef506923ca5c92550523f16a716c1ae990c347ec..38f3c89d335023508883f220140a438ab3a48446 100644 --- a/indra/newview/skins/default/xui/en/floater_region_info.xml +++ b/indra/newview/skins/default/xui/en/floater_region_info.xml @@ -6,16 +6,16 @@ name="regioninfo" save_rect="true" title="REGION/ESTATE" - width="633"> + width="637"> <tab_container - follows="all" - halign="left" bottom="555" + follows="left|right|top|bottom" layout="topleft" left="0" name="region_panels" + tab_padding_right="3" tab_position="left" - tab_width="100" - tab_padding_right="0" - top="0" /> + halign="left" + tab_width="110" + top="20"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml index 2eea5c361f32e805cbaf56a82ebc874a1f2ce283..226cb671f8d7191adcd9117131a3056129af6dd5 100644 --- a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml @@ -23,7 +23,7 @@ layout="topleft" left_delta="0" name="ascii_line_editor" - prevalidate_callback="ascii" + prevalidator="ascii" tool_tip="ascii line editor" top_pad="10" width="200"> diff --git a/indra/newview/skins/default/xui/en/floater_test_text_editor.xml b/indra/newview/skins/default/xui/en/floater_test_text_editor.xml index ab3b819e34bd270651ebf09fe5ed7f44ced92278..1cf89a8f94706b8370426aa25f9b81857565201b 100644 --- a/indra/newview/skins/default/xui/en/floater_test_text_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_test_text_editor.xml @@ -38,7 +38,7 @@ name="numeric_text_editor" tool_tip="text editor for numeric text entry only" top_pad="10" - text_type="int" + prevalidator="int" width="200"> This is text that is NOT a number, so shouldn't appear </text_editor> diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 6cc173e47b3c63b20b2fe1efac501059474cdbe0..866384fa1256293f5aa60e5fcca2f4510382a0f1 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -143,6 +143,14 @@ function="Inventory.EmptyLostAndFound" parameter="rename" /> </menu_item_call> + <menu_item_call + label="New Folder" + layout="topleft" + name="New Listing Folder"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="category" /> + </menu_item_call> <menu_item_call label="New Outfit" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 63617b0bd6bb39cf17d3081facce78ea6ffd8f1f..562813f0037db2011e2b68e13e798e6ed44a8b63 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -426,6 +426,16 @@ function="Self.EnableRemoveAllAttachments" /> </menu_item_call> </menu> + <menu_item_call + label="Remove selected attachments" + layout="topleft" + name="Remove Selected Attachments" + shortcut="alt|shift|R"> + <menu_item_call.on_click + function="Attachment.Detach" /> + <menu_item_call.on_enable + function="Attachment.EnableDetach" /> + </menu_item_call> <menu_item_separator/> <menu_item_call label="Complete avatars..." @@ -849,6 +859,33 @@ function="Floater.Show" parameter="360capture" /> </menu_item_call> + <menu + create_jump_keys="true" + label="Zoom level" + name="Zoom menu" + tear_off="true"> + <menu_item_call + label="Zoom out" + name="Zoom Out" + shortcut="control|8"> + <menu_item_call.on_click + function="View.ZoomOut" /> + </menu_item_call> + <menu_item_call + label="Default" + name="Zoom Default" + shortcut="control|9"> + <menu_item_call.on_click + function="View.ZoomDefault" /> + </menu_item_call> + <menu_item_call + label="Zoom in" + name="Zoom In" + shortcut="control|0"> + <menu_item_call.on_click + function="View.ZoomIn" /> + </menu_item_call> + </menu> <menu_item_separator/> <menu_item_call label="Place profile" @@ -2894,29 +2931,6 @@ function="World.EnvPreset" function="View.EnableLastChatter" /> </menu_item_call> - <menu_item_separator/> - - <menu_item_call - label="Zoom In" - name="Zoom In" - shortcut="control|0"> - <menu_item_call.on_click - function="View.ZoomIn" /> - </menu_item_call> - <menu_item_call - label="Zoom Default" - name="Zoom Default" - shortcut="control|9"> - <menu_item_call.on_click - function="View.ZoomDefault" /> - </menu_item_call> - <menu_item_call - label="Zoom Out" - name="Zoom Out" - shortcut="control|8"> - <menu_item_call.on_click - function="View.ZoomOut" /> - </menu_item_call> </menu> <!--Shortcuts--> <menu_item_separator/> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index d4044b978fc36d32d57f8762350bf35bb39beaf5..e330f841f464b9fba428aa6035d49d7d56336552 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -414,6 +414,15 @@ Initialization with the Marketplace failed because of a system or network error. yestext="OK"/> </notification> + <notification + icon="notifytip.tga" + name="InvalidKeystroke" + type="notifytip"> +There was an invalid keystroke entered. +[REASON]. +Please input a valid text. + </notification> + <notification icon="alertmodal.tga" name="MerchantForceValidateListing" @@ -4536,14 +4545,28 @@ Are you sure you want to return the selected objects to their owners? Transferab icon="alert.tga" name="GroupLeaveConfirmMember" type="alert"> -You are currently a member of the group <nolink>[GROUP]</nolink>. -Leave Group? +Leave the group '<nolink>[GROUP]</nolink>'? +Currently, the fee to join this "group" is L$ [COST]. <tag>group</tag> <tag>confirm</tag> <usetemplate name="okcancelbuttons" notext="Cancel" - yestext="OK"/> + yestext="Leave"/> + </notification> + + <notification + icon="alert.tga" + name="GroupLeaveConfirmMemberNoFee" + type="alert"> +Leave the group '<nolink>[GROUP]</nolink>'? +There is currently no fee to join this group. + <tag>group</tag> + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="Leave"/> </notification> @@ -6306,6 +6329,33 @@ Are you sure you want to delete them? notext="Cancel" yestext="OK"/> </notification> + + <notification + icon="alertmodal.tga" + name="DeleteWornItems" + type="alertmodal"> + <unique/> +Some item(s) you wish to delete are being worn on your avatar. +Remove these items from your avatar? + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="Remove item(s) and delete"/> + </notification> + + <notification + icon="alertmodal.tga" + name="CantDeleteRequiredClothing" + type="alertmodal"> + <unique/> +Some item(s) you wish to delete are required clothing layers (skin, shape, hair, eyes). +You must replace those layers before deleting them. + <tag>confirm</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> <notification icon="alertmodal.tga" @@ -6595,14 +6645,6 @@ Your trash is overflowing. This may cause problems logging in. yestext="Check trash folder"/> </notification> - <notification - icon="notifytip.tga" - name="InventoryLimitReachedAIS" - type="notifytip"> -Your inventory is experiencing issues. Please, contact support. - <tag>fail</tag> - </notification> - <notification icon="alertmodal.tga" name="InventoryLimitReachedAISAlert" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 12dc96ba2a55b07595ab764728d573e8d5c602cb..2153da166de002ef90f1651ad695c07416f690ea 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -259,7 +259,7 @@ left="10" max_length_bytes="63" name="description" - prevalidate_callback="ascii" + prevalidator="ascii" select_on_focus="true" top_pad="3" width="290" /> diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 203e07d6caf1567fb914b207ac541977e4d51f40..344cfd26b3c0f83f6e02a01fdd87aafb8c18e5dd 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -65,7 +65,7 @@ Hover your mouse over the options for more help. width="168" /> <text font="SansSerifMedium" - text_color="EmphasisColor" + text_color="white" type="string" follows="left|top" height="16" @@ -75,14 +75,14 @@ Hover your mouse over the options for more help. top_pad="10" visible="true" width="190"> - Free + No charge to join </text> <button follows="left|top" left_delta="0" top_pad="6" height="23" - label="JOIN NOW!" + label="Join group" name="btn_join" visible="true" width="120" /> diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index f4b7db4e234ab674b9803955f937cd8456b27467..aed94ab103a01b327714c6ff7cd9f49f80f3fea1 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -22,10 +22,10 @@ background_visible="true" name="group_join_btn"> Join (L$[AMOUNT]) </panel.string> - <panel.string - name="group_join_free"> - Free - </panel.string> + <panel.string name="group_join_free">No charge to join</panel.string> + <panel.string name="group_member">You are a member</panel.string> + <panel.string name="join_txt">Join group</panel.string> + <panel.string name="leave_txt">Leave</panel.string> <panel name="group_info_top" follows="top|left|right" diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 9e31ff604a7a3e32c68a189ca9f9c69710547afe..ff6af88707a97eab6ae920e62a0567f732678b62 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -48,6 +48,18 @@ use_ellipses="true" value="Unknown" width="242" /> + <button + name="notices_btn" + tool_tip="Group Notices" + top_delta="-4" + left_pad="3" + right="-53" + height="20" + width="20" + follows="right" + image_pressed="Group_Notices" + image_unselected="Group_Notices" + tab_stop="false"/> <button follows="right" height="16" @@ -58,7 +70,7 @@ name="info_btn" tool_tip="More info" tab_stop="false" - top_delta="-2" + top_delta="2" width="16" /> <!--*TODO: Should only appear on rollover--> <button @@ -71,6 +83,6 @@ name="profile_btn" tab_stop="false" tool_tip="View profile" - top_delta="-2" + top_delta="0" width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml index 6a1466867d81c625b88c19cff29bbea3e9fed8c4..c33c9659cfd13f96f5cce03f17d698a95439809f 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml @@ -53,10 +53,23 @@ text_color="ScrollUnselectedColor" use_ellipses="true" /> + <button + name="notices_btn" + tool_tip="Group Notices" + top_delta="-4" + left_pad="3" + right="-80" + height="20" + width="20" + follows="right" + image_pressed="Group_Notices" + image_unselected="Group_Notices" + tab_stop="false" + visible="false"/> <button name="visibility_hide_btn" tool_tip="Hide group on my profile" - top_delta="-3" + top_delta="0" left_pad="3" right="-53" height="20" diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index e2c29fc01953cdebf034c598bc7d594e33bf66a1..40efb7d0aa7105201a78682ae0891db49dc89b33 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -141,7 +141,7 @@ Maximum 200 per group daily left_pad="3" max_length_bytes="63" name="create_subject" - prevalidate_callback="ascii" + prevalidator="ascii" spellcheck="true" width="218" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index 3c62b8a02ef2059fa3eeaa2bbe777df492cc3879..3f76341dbff4fe642a33c432f53094c2e24d5e37 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -308,7 +308,7 @@ left="0" max_length_bytes="63" name="title_editor" - prevalidate_callback="ascii" + prevalidator="ascii" text_readonly_color="white" top_delta="1" width="290"/> @@ -332,7 +332,7 @@ read_only="true" spellcheck="true" text_readonly_color="white" - text_type="ascii_with_newline" + prevalidator="ascii_with_newline" top_pad="5" width="290" wrap="true" /> diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index c03c45551e1001e721fc9a149abdac13ba0222b6..454d00de418460c76442999e05ca9e91bb8b0376 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -69,7 +69,7 @@ left="15" max_chars="128" combo_editor.commit_on_focus_lost="false" - combo_editor.prevalidate_callback="ascii" + combo_editor.prevalidator="ascii" tool_tip="The account name you chose when you registered, like bobsmith12 or Steller Sunshine" top_pad="0" name="username_combo" @@ -167,7 +167,7 @@ max_chars="256" top_pad="0" combo_editor.commit_on_focus_lost="false" - combo_editor.prevalidate_callback="ascii" + combo_editor.prevalidator="ascii" name="server_combo" width="135" combo_button.scale_image="true" > diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 6b8fdcf1e9b4eb57b21bc385a9032691bceaf110..ac7c8b32a2b3e9d94d96a48192c8fba3e00d4075 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -219,6 +219,7 @@ tab_height="30" tab_position="top" tab_min_width="100" + use_tab_offset="true" top="0"> <inventory_panel bg_opaque_color="PanelDefaultBackgroundColor" diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 56d871406464ab072c9b7d306693f3be7919a132..bfe738f47296ba6b1bb730665d94179f9f8cfe00 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -32,21 +32,6 @@ <text border_visible="false" follows="left|right|top|bottom" - font="SansSerif" - height="85" - layout="topleft" - left="10" - name="text_box" - read_only="true" - text_color="White" - top="10" - visible="false" - width="285" - wrap="true"/> - <text - border_visible="false" - follows="left|right|top|bottom" - font="SansSerifBold" height="85" layout="topleft" left="10" @@ -57,14 +42,13 @@ width="285" wrap="true"/> <text_editor - h_pad="0" - v_pad="0" + h_pad="0" + v_pad="0" bg_readonly_color="Transparent" border_visible="false" embedded_items="false" enabled="false" follows="left|right|top|bottom" - font="SansSerif" height="85" layout="topleft" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_profile_classified.xml b/indra/newview/skins/default/xui/en/panel_profile_classified.xml index 9567b1f4ab82e1f2a1501b37e534023c419a3ad4..3f22d210f4d12d8bc8f862ef832855dc06156dbe 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_classified.xml @@ -483,7 +483,7 @@ layout="topleft" font="SansSerif" max_length_bytes="30" - prevalidate_callback="ascii" + prevalidator="ascii" commit_on_focus_lost="false" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml index e0297a9200ed12874e378623cc28e330aa705b2d..dc072824d00a4e5f155be330eb67db8b1c5d6108 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_firstlife.xml @@ -19,9 +19,10 @@ layout="topleft" visible="false" /> - <thumbnail + <profile_image name="real_world_pic" image_name="Generic_Person_Large" + show_loading="false" follows="top|left" interactable="true" for_profile="true" diff --git a/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml b/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml index 8cc230ab0def90fbd44508f511ae42ef0fc25bc2..8d4a3a2e504acf80ff2ace8a320d6f6e3e3db52f 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_legacy_sidetray.xml @@ -147,21 +147,6 @@ Remove Friend name="avatar_groups_tab_panel" top="0" /> </accordion_tab> - <accordion_tab - expanded="false" - layout="topleft" - name="avatar_interest_tab" - title="Interests" - fit_panel="false"> - <panel - border="false" - filename="panel_profile_legacy_interests.xml" - follows="left|top|right" - layout="topleft" - left="0" - name="avatar_interest_tab_panel" - top="0" /> - </accordion_tab> <accordion_tab expanded="false" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml index 29846b58fe24f5381868e747e7b38caa8719eac9..c74d495a9466d35483df184d82b4ebd633199827 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -14,8 +14,11 @@ so display it as an UTC+0 --> <string - name="date_format" + name="date_format_full" value="SL birthdate: [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]" /> + <string + name="date_format_short" + value="SL birthdate: [mth,datetime,utc] [day,datetime,utc]" /> <string name="age_format" value="[AGE]" /> @@ -59,7 +62,7 @@ Account: [ACCTTYPE] top="8" left="6" bottom="-1" - width="160" + width="180" border_size="0" follows="left|top|bottom" layout="topleft" @@ -74,9 +77,10 @@ Account: [ACCTTYPE] auto_resize="false" user_resize="false"> - <thumbnail + <profile_image name="2nd_life_pic" image_name="Generic_Person_Large" + show_loading="false" layout="topleft" follows="all" interactable="true" @@ -328,75 +332,82 @@ Account: [ACCTTYPE] layout="topleft" visible="true"/> </layout_panel> + <layout_panel + name="menu_panel" + follows="all" + layout="topleft" + height="55" + auto_resize="false" + user_resize="false"> + <menu_button + layout="topleft" + follows="left|top" + left="1" + top="25" + height="25" + width="176" + label="Actions" + halign="left" + image_unselected="DropDown_Off" + image_selected="DropDown_On" + image_pressed="DropDown_Press" + image_pressed_selected="DropDown_Press" + image_disabled="DropDown_Disabled" + name="agent_actions_menu"/> + </layout_panel> <layout_panel name="settings_panel" follows="all" layout="topleft" - height="50" + height="70" auto_resize="false" user_resize="false"> <!-- only for self --> - <text - name="search_label" - value="Show my profile in search:" - top="1" - left="6" - right="-1" - height="16" - follows="left|top|right" - layout="topleft"/> <combo_box name="show_in_search" tool_tip="Let people see you in search results" left="1" - top="18" - height="23" - width="140" + top="5" + height="25" + width="176" follows="left|top" layout="topleft" - visible="true" enabled="false"> - <combo_box.item - name="Hide" - label="Hide" - value="0" /> <combo_box.item name="Show" - label="Show" + label="Show me in search" value="1" /> + <combo_box.item + name="Hide" + label="Don't show me in search" + value="0" /> </combo_box> - </layout_panel> - - <layout_panel - name="menu_panel" - follows="all" - layout="topleft" - height="55" - auto_resize="false" - user_resize="false" - > - <menu_button - layout="topleft" - follows="left|top" + <combo_box + name="hide_age" + tool_tip="Let people see your SL age" left="1" - top="25" + top="40" height="25" - width="140" - label="Actions" - halign="left" - image_unselected="DropDown_Off" - image_selected="DropDown_On" - image_pressed="DropDown_Press" - image_pressed_selected="DropDown_Press" - image_disabled="DropDown_Disabled" - name="agent_actions_menu" /> + width="176" + follows="left|top" + layout="topleft" + enabled="false"> + <combo_box.item + name="Show" + label="Show birthdate + SL age" + value="0"/> + <combo_box.item + name="Hide" + label="Show month + day only" + value="1"/> + </combo_box> </layout_panel> </layout_stack> <layout_stack name="main_stack" top="8" - left="168" + left="188" bottom="-1" right="-1" follows="all" diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index bdb4b545c159aba02541ea69d57cbe3a344353e1..1cb3eca2eba230c6d97513ee1f002f3b1b129f7d 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -208,7 +208,7 @@ TestString PleaseIgnore Description: </text> <text_editor - text_type="ascii_printable_no_pipe" + prevalidator="ascii_printable_no_pipe" commit_on_focus_lost="true" border_style="line" border_thickness="1" diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 5e9902f750f9a4be926a8ac195e7fd5435815616..e19fdf5356aa86587522183020676251583ef0f4 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -286,14 +286,14 @@ label="Zoom" name="Zoom" value="Zoom" /> - <combo_box.item - label="Ignore object" - name="Ignoreobject" - value="Ignore" /> <combo_box.item label="None" name="None" value="None" /> + <combo_box.item + label="Ignore object" + name="Ignoreobject" + value="Ignore" /> </combo_box> <panel border="false" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 70a58eaa89d792b575007fe1168f4ce1be2aecdf..771481b9a3e2e17b4056ad15d3220f2158be571f 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -614,7 +614,21 @@ http://secondlife.com/support for help fixing this problem. <string name="zip_files">Zip files</string> <string name="recompile_script_verb">Recompile</string> - <!-- LSL Usage Hover Tips --> + <!-- Text validator error messages --> + <string name="Validator_InvalidNumericString">Invalid numeric string: "[STR]"</string> + <string name="Validator_ShouldNotBeMinus">Invalid initial character: '[CH]' (shouldn't be a minus)</string> + <string name="Validator_ShouldNotBeMinusOrZero">Invalid initial character: '[CH]' (shouldn't be either a minus or a zero)</string> + <string name="Validator_ShouldBeDigit">Invalid character [NR]: '[CH]' (should only be a digit)</string> + <string name="Validator_ShouldBeDigitOrDot">Invalid character [NR]: '[CH]' (should only be a digit or a decimal point)</string> + <string name="Validator_ShouldBeDigitOrAlpha">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character)</string> + <string name="Validator_ShouldBeDigitOrAlphaOrSpace">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character or a space)</string> + <string name="Validator_ShouldBeDigitOrAlphaOrPunct">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character or a punctuation)</string> + <string name="Validator_ShouldBeDigitOrAlphaOrPunctNotSpace">Invalid character [NR]: '[CH]' (should only be a digit or an alpha-numeric ASCII character or a punctuation with no space)</string> + <string name="Validator_ShouldBeDigitNotSpace">Invalid character [NR]: '[CH]' (should only be a digit with no space)</string> + <string name="Validator_ShouldBeASCII">Invalid character [NR]: '[CH]' (should only be an ASCII character)</string> + <string name="Validator_ShouldBeNewLineOrASCII">Invalid character [NR]: '[CH]' (should only be an ASCII character or a new line)</string> + + <!-- LSL Usage Hover Tips --> <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window). This has no effect on viewer code, but prevents Linden Lab internal localization tool from scraping these strings. --> <string name="LSLTipSleepTime" translate="false"> @@ -4000,7 +4014,8 @@ Abuse Report</string> <string name="dance8">dance8</string> <!-- birth date format shared by avatar inspector and profile panels --> - <string name="AvatarBirthDateFormat">[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]</string> + <string name="AvatarBirthDateFormatFull">[mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]</string> + <string name="AvatarBirthDateFormatShort">[mthnum,datetime,slt]/[day,datetime,slt]</string> <string name="DefaultMimeType">none/none</string> <string name="texture_load_dimensions_error">Can't load images larger than [WIDTH]*[HEIGHT]</string> @@ -4067,7 +4082,8 @@ Please check http://status.secondlifegrid.net to see if there is a known problem <string name="EmptyOutfitText">There are no items in this outfit</string> <!-- External editor status codes --> - <string name="ExternalEditorNotSet">Select an editor by setting the environment variable LL_SCRIPT_EDITOR or the ExternalEditor setting.</string> + <string name="ExternalEditorNotSet">Select an editor by setting the environment variable LL_SCRIPT_EDITOR or the ExternalEditor setting. +See https://wiki.secondlife.com/wiki/LSL_Alternate_Editors</string> <string name="ExternalEditorNotFound">Cannot find the external editor you specified. Try enclosing path to the editor with double quotes. (e.g. "/path to my/editor" "%s")</string> diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml index 570e500252679d15543b947ac169e459d0572eb1..036572d67feddd33f995e75eaca714e8163fd158 100644 --- a/indra/newview/skins/default/xui/en/widgets/line_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml @@ -13,5 +13,5 @@ highlight_color="EmphasisColor" mouse_opaque="true" name="line_editor" - font="SansSerifSmall"> + font="EmojiSmall"> </line_editor> diff --git a/indra/newview/skins/default/xui/it/emoji_categories.xml b/indra/newview/skins/default/xui/it/emoji_categories.xml index a4782e60a69a652232229115ad25ea2c0164e93c..b447a5b78b695088d05589c5560f5a605bd00736 100644 --- a/indra/newview/skins/default/xui/it/emoji_categories.xml +++ b/indra/newview/skins/default/xui/it/emoji_categories.xml @@ -5,7 +5,7 @@ <key>Name</key> <string>smileys and emotion</string> <key>Category</key> - <string>smileys and emozione</string> + <string>smileys & emozione</string> </map> <map> <key>Name</key> @@ -23,7 +23,7 @@ <key>Name</key> <string>animals and nature</string> <key>Category</key> - <string>animali and natura</string> + <string>animali & natura</string> </map> <map> <key>Name</key> @@ -35,7 +35,7 @@ <key>Name</key> <string>travel and places</string> <key>Category</key> - <string>viaggi and luoghi</string> + <string>viaggi & luoghi</string> </map> <map> <key>Name</key> diff --git a/indra/newview/skins/default/xui/ja/panel_profile_legacy_sidetray.xml b/indra/newview/skins/default/xui/ja/panel_profile_legacy_sidetray.xml index 614b6f31e73e2ce05f2ba404ec9b59b977bda5b9..7ff419486b0a4f5c83e624b01cfdcb6f150eac33 100644 --- a/indra/newview/skins/default/xui/ja/panel_profile_legacy_sidetray.xml +++ b/indra/newview/skins/default/xui/ja/panel_profile_legacy_sidetray.xml @@ -31,9 +31,6 @@ <accordion_tab name="avatar_groups_tab" title="グループ"> <panel name="avatar_groups_tab_panel"/> </accordion_tab> - <accordion_tab name="avatar_interest_tab" title="関心"> - <panel name="avatar_interest_tab_panel"/> - </accordion_tab> <accordion_tab name="avatar_picks_tab" title="ピック"> <panel name="avatar_picks_tab_panel"/> </accordion_tab> diff --git a/indra/newview/skins/default/xui/pl/emoji_categories.xml b/indra/newview/skins/default/xui/pl/emoji_categories.xml index 9aad7af794f2155cf458fb491b100499131ed565..42f8e2eb4a21f305e27ac4eb595687d952993d34 100644 --- a/indra/newview/skins/default/xui/pl/emoji_categories.xml +++ b/indra/newview/skins/default/xui/pl/emoji_categories.xml @@ -5,13 +5,13 @@ <key>Name</key> <string>smileys and emotion</string> <key>Category</key> - <string>buźki and emocje</string> + <string>buźki & emocje</string> </map> <map> <key>Name</key> <string>people and body</string> <key>Category</key> - <string>ludzie and ciaÅ‚o</string> + <string>ludzie & ciaÅ‚o</string> </map> <map> <key>Name</key> @@ -23,7 +23,7 @@ <key>Name</key> <string>animals and nature</string> <key>Category</key> - <string>zwierzÄ™ta and przyroda</string> + <string>zwierzÄ™ta & przyroda</string> </map> <map> <key>Name</key> @@ -35,7 +35,7 @@ <key>Name</key> <string>travel and places</string> <key>Category</key> - <string>podróże and miejsca</string> + <string>podróże & miejsca</string> </map> <map> <key>Name</key> diff --git a/indra/newview/skins/heretic/xui/en/panel_login.xml b/indra/newview/skins/heretic/xui/en/panel_login.xml index b854c5de8cefaacda3c13436d9de3d31d24df2e0..75c5303f2806bc723545045e7e8b8d60dbedc11f 100644 --- a/indra/newview/skins/heretic/xui/en/panel_login.xml +++ b/indra/newview/skins/heretic/xui/en/panel_login.xml @@ -70,7 +70,7 @@ left="15" max_chars="128" combo_editor.commit_on_focus_lost="false" - combo_editor.prevalidate_callback="ascii" + combo_editor.prevalidator="ascii" tool_tip="The account name you chose when you registered, like bobsmith12 or Steller Sunshine" top_pad="0" name="username_combo" @@ -168,7 +168,7 @@ max_chars="256" top_pad="0" combo_editor.commit_on_focus_lost="false" - combo_editor.prevalidate_callback="ascii" + combo_editor.prevalidator="ascii" name="server_combo" width="135" combo_button.scale_image="true" > diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 6aedfe5479cd62aa020fa10373f0dfec74f44aaa..aa505ed9db27cb82b2cc9d7a819234451c2f9fea 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -100,7 +100,7 @@ def construct(self): # ... and the entire image filters directory self.path("filters") - + # ... and the entire color lut texture directory self.path("colorlut") @@ -468,7 +468,6 @@ def construct(self): # For ICU4C self.path("icudt75.dll") self.path("icuuc75.dll") - # Get fmodstudio dll for audio engine, continue if missing if self.args['fmodstudio'] == 'ON' or self.args['fmodstudio'] == 'TRUE': if self.args['buildtype'].lower() == 'debug': @@ -506,12 +505,8 @@ def construct(self): self.path("SLVoice.exe") # Vivox libraries - if (self.address_size == 64): - self.path("vivoxsdk_x64.dll") - self.path("ortp_x64.dll") - else: - self.path("vivoxsdk.dll") - self.path("ortp.dll") + self.path("vivoxsdk_x64.dll") + self.path("ortp_x64.dll") # Sentry if self.args['sentry'] == 'ON' or self.args['sentry'] == 'TRUE': diff --git a/scripts/code_tools/fix_whitespace.py b/scripts/code_tools/fix_whitespace.py index 1c2ba00bb31f88a15529b380c4253bc726439962..91e82f26f464dbe9d5b56a2b0c018690093b9eef 100644 --- a/scripts/code_tools/fix_whitespace.py +++ b/scripts/code_tools/fix_whitespace.py @@ -33,6 +33,10 @@ def convert_tabs_to_spaces(file_path, tab_stop): with open(file_path, 'r') as file: lines = file.readlines() + # Skip files with no tabs + if not any('\t' in line for line in lines): + return + new_lines = [] for line in lines: # Remove trailing spaces @@ -66,7 +70,7 @@ def process_directory(directory, extensions, tab_stop): def main(): parser = argparse.ArgumentParser(description='Convert tabs to spaces in files, considering tab stops.') - parser.add_argument('-e', '--extensions', type=str, default='cpp,h,hpp,inl,cmake', help='Comma-separated list of file extensions to process (default: "cpp,h,hpp,inl,cmake")') + parser.add_argument('-e', '--extensions', type=str, default='c,cpp,h,hpp,inl,py,glsl,cmake', help='Comma-separated list of file extensions to process (default: "c,cpp,h,hpp,inl,py,glsl,cmake")') parser.add_argument('-t', '--tabstop', type=int, default=4, help='Tab stop size (default: 4)') parser.add_argument('-d', '--directory', type=str, required=True, help='Directory to process') diff --git a/scripts/code_tools/fix_xml_indentations.py b/scripts/code_tools/fix_xml_indentations.py new file mode 100644 index 0000000000000000000000000000000000000000..9c8a1fc04bd76fbbb86b5092532d6a81cbc31e1f --- /dev/null +++ b/scripts/code_tools/fix_xml_indentations.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +"""\ + +This script formats XML files in a given directory with options for indentation and space removal. + +$LicenseInfo:firstyear=2023&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2023, 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$ +""" + +import os +import sys +import glob +import io +import xml.etree.ElementTree as ET + +def get_xml_declaration(file_path): + with open(file_path, 'r', encoding='utf-8') as file: + first_line = file.readline().strip() + if first_line.startswith('<?xml'): + return first_line + return None + +def parse_xml_file(file_path): + try: + tree = ET.parse(file_path) + return tree + except ET.ParseError as e: + print(f"Error parsing XML file {file_path}: {e}") + return None + +def indent(elem, level=0, indent_text=False, indent_tab=False): + indent_string = "\t" if indent_tab else " " + i = "\n" + level * indent_string + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + indent_string + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + indent(elem, level + 1, indent_text, indent_tab) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + if indent_text and elem.text and not elem.text.isspace(): + elem.text = "\n" + (level + 1) * indent_string + elem.text.strip() + "\n" + level * indent_string + +def save_xml(tree, file_path, xml_decl, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False): + if tree is not None: + root = tree.getroot() + indent(root, indent_text=indent_text, indent_tab=indent_tab) + xml_string = ET.tostring(root, encoding='unicode') + if rm_space: + xml_string = xml_string.replace(' />', '/>') + + xml_decl = (xml_decl if (xml_decl and not rewrite_decl) + else '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>') + + try: + with io.open(file_path, 'wb') as file: + file.write(xml_decl.encode('utf-8')) + file.write('\n'.encode('utf-8')) + if xml_string: + file.write(xml_string.encode('utf-8')) + if not xml_string.endswith('\n'): + file.write('\n'.encode('utf-8')) + except IOError as e: + print(f"Error saving file {file_path}: {e}") + +def process_directory(directory_path, indent_text=False, indent_tab=False, rm_space=False, rewrite_decl=False): + if not os.path.isdir(directory_path): + print(f"Directory not found: {directory_path}") + return + + xml_files = glob.glob(os.path.join(directory_path, "*.xml")) + if not xml_files: + print(f"No XML files found in directory: {directory_path}") + return + + for file_path in xml_files: + xml_decl = get_xml_declaration(file_path) + tree = parse_xml_file(file_path) + if tree is not None: + save_xml(tree, file_path, xml_decl, indent_text, indent_tab, rm_space, rewrite_decl) + +if __name__ == "__main__": + if len(sys.argv) < 2 or '--help' in sys.argv: + print("This script formats XML files in a given directory. Useful to fix XUI XMLs after processing by other tools.") + print("\nUsage:") + print(" python fix_xml_indentations.py <path/to/directory> [options]") + print("\nOptions:") + print(" --indent-text Indents text within XML tags.") + print(" --indent-tab Uses tabs instead of spaces for indentation.") + print(" --rm-space Removes spaces in self-closing tags.") + print(" --rewrite_decl Replaces the XML declaration line.") + print("\nCommon Usage:") + print(" To format XML files with text indentation, tab indentation, and removal of spaces in self-closing tags:") + print(" python fix_xml_indentations.py /path/to/xmls --indent-text --indent-tab --rm-space") + sys.exit(1) + + directory_path = sys.argv[1] + indent_text = '--indent-text' in sys.argv + indent_tab = '--indent-tab' in sys.argv + rm_space = '--rm-space' in sys.argv + rewrite_decl = '--rewrite_decl' in sys.argv + process_directory(directory_path, indent_text, indent_tab, rm_space, rewrite_decl)