diff --git a/.gitattributes b/.gitattributes index 3a4c44aedc..baf02f46e3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -30,6 +30,7 @@ indra/tools/vstool/* -text # Files with Windows line endings VivoxAUP.txt text eol=crlf FILES_ARE_UNICODE_UTF-16LE.txt text eol=crlf +*.nsi text eol=crlf # Windows Manifest files *.manifest text eol=crlf diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000000..a110c018ec --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,93 @@ +name: Build + +on: + workflow_dispatch: + pull_request: + push: + branches: [main, contribute] + tags: ["*"] + +jobs: + build: + strategy: + matrix: + runner: [windows-large] + configuration: [ReleaseOS] + addrsize: [64] + include: + - runner: windows-large + configuration: ReleaseOS + addrsize: 32 + runs-on: ${{ matrix.runner }} + env: + AUTOBUILD_CONFIGURATION: ${{ matrix.configuration }} + AUTOBUILD_ADDRSIZE: ${{ matrix.addrsize }} + AUTOBUILD_INSTALLABLE_CACHE: ${{ github.workspace }}/.autobuild-installables + AUTOBUILD_VARIABLES_FILE: ${{ github.workspace }}/.build-variables/variables + AUTOBUILD_VSVER: "170" # vs2k22 + LOGFAIL: debug # Show details when tests fail + GIT_REF: ${{ github.head_ref || github.ref }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Checkout build variables + uses: actions/checkout@v3 + with: + repository: secondlife/build-variables + ref: viewer + path: .build-variables + + - name: Install autobuild and python dependencies + run: pip3 install autobuild llbase + + - name: Cache autobuild packages + uses: actions/cache@v3 + id: cache-installables + with: + path: .autobuild-installables + key: ${{ runner.os }}-${{ matrix.addrsize }}-${{ matrix.configuration }}-${{ hashFiles('autobuild.xml') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.addrsize }}-${{ matrix.configuration }}- + ${{ runner.os }}-${{ matrix.addrsize }}- + + - name: Install windows dependencies + if: runner.os == 'Windows' + run: choco install nsis-unicode + + - name: Build + id: build + shell: bash + env: + RUNNER_OS: ${{ runner.os }} + run: | + # 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. + if [[ "$RUNNER_OS" == "Windows" ]]; then + export PYTHON="$(cygpath -m "$(which python)")" + echo "Python location: $PYTHON" + fi + + autobuild configure -- -DVIEWER_CHANNEL="Second Life Test ${GIT_REF##*/}" + autobuild build --no-configure + + # Find artifacts + if [[ "$RUNNER_OS" == "Windows" ]]; then + installer_path=$(find ./build-*/newview/ | grep '_Setup\.exe') + installer_name="$(basename $installer_path)" + elif [[ "$RUNNER_OS" == "macOS" ]]; then + installer_path=$(find ./build-*/newview/ | grep '\.dmg') + installer_name="$(basename $installer_path)" + fi + + echo "installer_path=$installer_path" >> $GITHUB_OUTPUT + echo "installer_name=$installer_name" >> $GITHUB_OUTPUT + + - name: Upload installer + uses: actions/upload-artifact@v3 + with: + name: ${{ steps.build.outputs.installer_name }} + path: ${{ steps.build.outputs.installer_path }} diff --git a/.github/workflows/build_viewer.yml b/.github/workflows/build_viewer.yml index 8adc9171c1..d85167e867 100644 --- a/.github/workflows/build_viewer.yml +++ b/.github/workflows/build_viewer.yml @@ -2,8 +2,9 @@ name: Build viewer on: push: branches: - - "*release" - - master + - "Firestorm*.*.*" + tags: + - "preview" schedule: - cron: '00 03 * * *' # Run every day at 3am UTC env: @@ -74,14 +75,14 @@ jobs: - name: find channel from Branch name run: | - if [[ "${{ github.ref_name }}" == *Release* ]]; then + if [[ "${{ github.ref_name }}" == Firestorm* ]]; then FS_RELEASE_TYPE=Release + elif [[ "${{ github.ref_name }}" == *review* ]]; then + FS_RELEASE_TYPE=Beta + elif [[ "${{ github.event_name }}" == 'schedule' ]]; then + FS_RELEASE_TYPE=Nightly else - if [[ "${{github.event_name}}" == 'schedule' ]]; then - FS_RELEASE_TYPE=Nightly - else - FS_RELEASE_TYPE=Beta - fi + FS_RELEASE_TYPE=Unknown fi if [[ "${{ matrix.addrsize }}" == "64" ]]; then FS_RELEASE_CHAN="${FS_RELEASE_TYPE}x64" @@ -118,7 +119,11 @@ jobs: shell: bash - name: rclone the private 3p packages for this platform (both 64 & 32) - run: 'rclone copy fs_bundles: --include "*${{ env.fallback_platform }}*bz2" .' + run: 'rclone copy fs_bundles: --filter "- Alpha/*" --filter "+ *${{ env.fallback_platform }}*bz2" .' + + - name: rclone any extra private 3p packages for Alpha (allows library updates not in the main repo) + if: env.FS_BUILD_TYPE == 'Alpha' + run: 'rclone copy fs_bundles:Alpha --include "*${{ env.fallback_platform }}*bz2" .' - name: set VSVER for Windows builds if: runner.os == 'Windows' @@ -255,17 +260,17 @@ jobs: - name: find channel and webhook from Branch name run: | - if [[ "${{ github.ref_name }}" == *Release* ]]; then + if [[ "${{ github.ref_name }}" == Firestorm* ]]; then FS_RELEASE_FOLDER=release FS_BUILD_WEBHOOK_URL=${{ secrets.RELEASE_WEBHOOK_URL }} - else - if [[ "${{github.event_name}}" == 'schedule' ]]; then - FS_RELEASE_FOLDER=nightly - FS_BUILD_WEBHOOK_URL=${{ secrets.NIGHTLY_WEBHOOK_URL }} - else + elif [[ "${{ github.ref_name }}" == *review* ]]; then FS_RELEASE_FOLDER=preview FS_BUILD_WEBHOOK_URL=${{ secrets.BETA_WEBHOOK_URL }} - fi + elif [[ "${{ github.event_name }}" == 'schedule' ]]; then + FS_RELEASE_FOLDER=nightly + FS_BUILD_WEBHOOK_URL=${{ secrets.NIGHTLY_WEBHOOK_URL }} + else + FS_RELEASE_TYPE=Unknown fi echo "FS_RELEASE_FOLDER=${FS_RELEASE_FOLDER}" >> $GITHUB_ENV echo "FS_BUILD_WEBHOOK_URL=${FS_BUILD_WEBHOOK_URL}" >> $GITHUB_ENV diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000000..17c0ace02f --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,18 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main, contribute] + tags: [v*] + + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 82a9a968b9..35ac41420c 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -15,8 +15,8 @@ jobs: - uses: actions/stale@v6 id: stale with: - stale-pr-message: This pull request is stale because it has been open 60 days with no activity. Remove stale label or comment or it will be closed in 7 days - days-before-stale: 60 + stale-pr-message: This pull request is stale because it has been open 30 days with no activity. Remove stale label or comment or it will be closed in 7 days + days-before-stale: 30 days-before-close: 7 exempt-pr-labels: blocked,must,should,keep stale-pr-label: stale diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d296d7a24..fe7dfbac7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,8 @@ repos: - - repo: https://bitbucket.org/lindenlab/git-hooks.git - rev: v1.0.0-beta2 + - repo: https://github.com/secondlife/git-hooks.git + rev: v1.0.0 hooks: - id: opensource-license - - id: jira-issue - id: llsd - id: no-trigraphs - id: copyright @@ -11,7 +10,7 @@ repos: files: \.(cpp|c|h|py|glsl|cmake|txt)$ exclude: language.txt - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.5.0 + rev: v4.4.0 hooks: - id: check-xml - id: mixed-line-ending diff --git a/autobuild.xml b/autobuild.xml index bcb8f8f17e..f7a237b31b 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3430,9 +3430,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 9e1b5515ab59b4e9cfeef6626d65d03d + 6ba629ff34c4b14a1f851de707bc35041df8b6a9 + hash_algorithm + sha1 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/108609/945996/viewer_manager-3.0.577252-darwin64-577252.tar.bz2 + https://github.com/secondlife/viewer-manager/releases/download/v3.0-bd3aec2/viewer_manager-3.0-bd3aec2-darwin64-bd3aec2.tar.zst name darwin64 @@ -3442,24 +3444,28 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 129b80dd47b53bfa02fc21ab1eb1901c + 7e086a28db17b0c086a5460e9d62f0c6584560b3 + hash_algorithm + sha1 url - http://3p.firestormviewer.org/viewer_manager-1.0.180861311-linux64-180861311.tar.bz2 + https://github.com/secondlife/viewer-manager/releases/download/v3.0-bd3aec2/viewer_manager-3.0-bd3aec2-linux64-bd3aec2.tar.zst name linux64 - windows + windows64 archive hash - a3c599595ecc8fb987a5499fca42520a + 1eab994c0c1df5b2c057878a4071a88320cec978 + hash_algorithm + sha1 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/108610/946003/viewer_manager-3.0.577252-windows-577252.tar.bz2 + https://github.com/secondlife/viewer-manager/releases/download/v3.0-bd3aec2/viewer_manager-3.0-bd3aec2-windows64-bd3aec2.tar.zst name - windows + windows64 source @@ -3467,7 +3473,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 3.0.577252 + 3.0-bd3aec2 vlc-bin @@ -4404,7 +4410,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors /t:Build /p:useenv=true /verbosity:minimal - /toolsversion:4.0 /p:VCBuildAdditionalOptions= /incremental @@ -4478,7 +4483,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors /t:Build /p:useenv=true /verbosity:minimal - /toolsversion:4.0 /p:VCBuildAdditionalOptions= /incremental diff --git a/doc/contributions.txt b/doc/contributions.txt index e304bb6cef..a419cda3e0 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -600,6 +600,7 @@ Henri Beauchamp VWR-4157 SL-15175 SL-19110 + SL-19159 herina Bode Hikkoshi Sakai VWR-429 @@ -940,6 +941,8 @@ Lexi Frua Lillie Cordeaux Lilly Zenovka Lizzy Macarthur +Logue Takacs + INTL-490 Luban Yiyuan Luc Starsider Luminous Luminos @@ -1196,6 +1199,7 @@ PanteraPolnocy SL-18891 SL-18904 SL-18937 + SL-19207 SL-19681 Parvati Silverweb Patric Mills diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index ad3aca25fc..f32c941b18 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -77,11 +77,9 @@ if (WINDOWS) # CP changed to only append the flag for 32bit builds - on 64bit builds, # locally at least, the build output is spammed with 1000s of 'D9002' # warnings about this switch being ignored. - # Remove this, it's no option to cl.exe and causes a massive amount of warnings. - #if( ADDRESS_SIZE EQUAL 32 ) - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64") - #endif() - + if(ADDRESS_SIZE EQUAL 32 AND DEFINED ENV{"TEAMCITY_PROJECT_NAME"}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64") + endif() # zlib has assembly-language object files incompatible with SAFESEH add_link_options(/LARGEADDRESSAWARE /SAFESEH:NO @@ -216,6 +214,10 @@ if (DARWIN) set(ENABLE_SIGNING TRUE) set(SIGNING_IDENTITY "Developer ID Application: The Phoenix Firestorm Project, Inc." ) + + # required for clang-15/xcode-15 since our boost package still uses deprecated std::unary_function/binary_function + # see https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#C++-Standard-Library + add_compile_definitions(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) endif (DARWIN) if (LINUX OR DARWIN) diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 8431c04066..1f954c8f65 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -2,7 +2,11 @@ set(PYTHONINTERP_FOUND) -if (WINDOWS) +if (DEFINED ENV{PYTHON}) + # Allow python executable to be explicitly set + set(python "$ENV{PYTHON}") + set(PYTHONINTERP_FOUND ON) +elseif (WINDOWS) # On Windows, explicitly avoid Cygwin Python. if (DEFINED ENV{VIRTUAL_ENV}) @@ -53,7 +57,7 @@ else() if (python) set(PYTHONINTERP_FOUND ON) endif (python) -endif (WINDOWS) +endif (DEFINED ENV{PYTHON}) if (NOT python) message(FATAL_ERROR "No Python interpreter found") diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index a63b38361b..e2b8a7068c 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -32,7 +32,7 @@ #include "llsaleinfo.h" #include "llwearabletype.h" -class LLMD5; +class LLMD5; // [Legacy Bake] class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; @@ -131,6 +131,7 @@ public: // Something happened that requires the wearable to be updated (e.g. worn/unworn). virtual void setUpdated() const = 0; + // [Legacy Bake] // Update the baked texture hash. virtual void addToBakedTextureHash(LLMD5& hash) const = 0; diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 5d23d3a876..bc3d83ee1e 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -31,7 +31,7 @@ #include "llavatarappearance.h" #include "llavatarappearancedefines.h" #include "lldriverparam.h" -#include "llmd5.h" +#include "llmd5.h" // [Legacy Bake] LLWearableData::LLWearableData() : mAvatarAppearance(NULL) @@ -355,6 +355,7 @@ U32 LLWearableData::getWearableCount(const U32 tex_index) const return getWearableCount(wearable_type); } +// [Legacy Bake] LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index, BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache { @@ -391,5 +392,6 @@ LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBaked return hash_id; } +// [Legacy Bake] diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h index cb274ca524..8ecf29a7a0 100644 --- a/indra/llappearance/llwearabledata.h +++ b/indra/llappearance/llwearabledata.h @@ -85,6 +85,7 @@ protected: private: void pullCrossWearableValues(const LLWearableType::EType type); +// [Legacy Bake] //-------------------------------------------------------------------- // Server Communication //-------------------------------------------------------------------- @@ -93,6 +94,7 @@ public: BOOL generate_valid_hash = TRUE); protected: virtual void invalidateBakedTextureHash(LLMD5& hash) const {} +// [Legacy Bake] //-------------------------------------------------------------------- // Member variables diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 8f61654de6..2c4a57675e 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -217,7 +217,8 @@ std::string LLAudioEngine::getInternetStreamURL() { if (mStreamingAudioImpl) return mStreamingAudioImpl->getURL(); - else return std::string(); + + return std::string(); } @@ -358,42 +359,43 @@ void LLAudioEngine::idle() } continue; } - else + + // Check to see if the current sound is done playing. + if (!channelp->isPlaying()) { - // Check to see if the current sound is done playing, or looped. - if (!channelp->isPlaying()) + sourcep->mCurrentDatap = sourcep->mQueuedDatap; + sourcep->mQueuedDatap = NULL; + + // Reset the timer so the source doesn't die. + sourcep->mAgeTimer.reset(); + + // Make sure we have the buffer set up if we just decoded the data + if (sourcep->mCurrentDatap) + { + updateBufferForData(sourcep->mCurrentDatap); + } + + // Actually play the associated data. + sourcep->setupChannel(); + channelp->updateBuffer(); + sourcep->getChannel()->play(); + continue; + } + + // Check to see if the current sound is looped. + if (sourcep->isLoop()) + { + // It's a loop, we need to check and see if we're done with it. + if (channelp->mLoopedThisFrame) { sourcep->mCurrentDatap = sourcep->mQueuedDatap; sourcep->mQueuedDatap = NULL; - // Reset the timer so the source doesn't die. - sourcep->mAgeTimer.reset(); - - // Make sure we have the buffer set up if we just decoded the data - if (sourcep->mCurrentDatap) - { - updateBufferForData(sourcep->mCurrentDatap); - } - - // Actually play the associated data. + // Actually, should do a time sync so if we're a loop master/slave + // we don't drift away. sourcep->setupChannel(); - channelp->updateBuffer(); sourcep->getChannel()->play(); } - else if (sourcep->isLoop()) - { - // It's a loop, we need to check and see if we're done with it. - if (channelp->mLoopedThisFrame) - { - sourcep->mCurrentDatap = sourcep->mQueuedDatap; - sourcep->mQueuedDatap = NULL; - - // Actually, should do a time sync so if we're a loop master/slave - // we don't drift away. - sourcep->setupChannel(); - sourcep->getChannel()->play(); - } - } } } @@ -409,18 +411,11 @@ void LLAudioEngine::idle() for (source_map::value_type& src_pair : mAllSources) { LLAudioSource *sourcep = src_pair.second; - if (sourcep->isMuted()) + if (sourcep->isMuted() && sourcep->isSyncMaster() && sourcep->getPriority() > max_sm_priority) { - continue; - } - if (sourcep->isSyncMaster()) - { - if (sourcep->getPriority() > max_sm_priority) - { - sync_masterp = sourcep; - master_channelp = sync_masterp->getChannel(); - max_sm_priority = sourcep->getPriority(); - } + sync_masterp = sourcep; + master_channelp = sync_masterp->getChannel(); + max_sm_priority = sourcep->getPriority(); } } @@ -755,7 +750,7 @@ F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec) } return (gain); -} +} F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec) @@ -996,11 +991,10 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp) else { LL_DEBUGS("AudioEngine") << "Cleaning up audio sources for "<< asp->getID() <getID() << ")" << LL_ENDL; - if (sourcep == mCurrentSourcep) - { - // Don't reallocate the channel, this will make FMOD goofy. - //LL_INFOS() << "Calling setSource with same source!" << LL_ENDL; + if (sourcep == mCurrentSourcep) + { + // Don't reallocate the channel, this will make FMOD goofy. + //LL_INFOS() << "Calling setSource with same source!" << LL_ENDL; + } + + mCurrentSourcep = sourcep; + + updateBuffer(); + update3DPosition(); } - - mCurrentSourcep = sourcep; - - updateBuffer(); - update3DPosition(); } -} - bool LLAudioChannel::updateBuffer() { diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 74e264377e..ba3a7f32e3 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -95,6 +95,7 @@ public: // initialization/startup/shutdown virtual bool init(void *userdata, const std::string &app_title); virtual std::string getDriverName(bool verbose) = 0; + virtual LLStreamingAudioInterface *createDefaultStreamingAudioImpl() const = 0; virtual void shutdown(); // Used by the mechanics of the engine @@ -526,13 +527,13 @@ struct SoundData const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, - const LLVector3d &pos_global = LLVector3d::zero) + const LLVector3d &pos_global = LLVector3d::zero) : + audio_uuid(audio_uuid), + owner_id(owner_id), + gain(gain), + type(type), + pos_global(pos_global) { - this->audio_uuid = audio_uuid; - this->owner_id = owner_id; - this->gain = gain; - this->type = type; - this->pos_global = pos_global; } }; diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp index 9b215337e9..838b91c66f 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.cpp +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -308,10 +308,6 @@ bool LLAudioEngine_FMODSTUDIO::init(void* userdata, const std::string &app_title Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup"); } - // set up our favourite FMOD-native streaming audio implementation if none has already been added - if (!getStreamingAudioImpl()) // no existing implementation added - setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem)); - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL; FMOD_ADVANCEDSETTINGS settings_dump = { }; @@ -395,6 +391,13 @@ std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose) } +// create our favourite FMOD-native streaming audio implementation +LLStreamingAudioInterface *LLAudioEngine_FMODSTUDIO::createDefaultStreamingAudioImpl() const +{ + return new LLStreamingAudio_FMODSTUDIO(mSystem); +} + + void LLAudioEngine_FMODSTUDIO::allocateListener(void) { try diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h index 0c9b4d186f..e8cc03083b 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -59,6 +59,7 @@ public: // initialization/startup/shutdown virtual bool init(void *user_data, const std::string &app_title); virtual std::string getDriverName(bool verbose); + virtual LLStreamingAudioInterface* createDefaultStreamingAudioImpl() const; virtual void allocateListener(); virtual void shutdown(); diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index d09310a3c4..84df81e048 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -500,13 +500,20 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact // request asset mAssetStatus = ASSET_FETCHED; - LL_DEBUGS("Animation") << "Requesting data fetch for: " << mID << LL_ENDL; - character_id = new LLUUID(mCharacter->getID()); - gAssetStorage->getAssetData(mID, - LLAssetType::AT_ANIMATION, - onLoadComplete, - (void *)character_id, - FALSE); + if (mID.notNull()) + { + LL_DEBUGS("Animation") << "Requesting data fetch for: " << mID << LL_ENDL; + character_id = new LLUUID(mCharacter->getID()); + gAssetStorage->getAssetData(mID, + LLAssetType::AT_ANIMATION, + onLoadComplete, + (void*)character_id, + FALSE); + } + else + { + LL_INFOS("Animation") << "Attempted to fetch animation " << mName << " with null id for character " << mCharacter->getID() << LL_ENDL; + } return STATUS_HOLD; case ASSET_FETCHED: diff --git a/indra/llcommon/hbxxh.h b/indra/llcommon/hbxxh.h index 236716722a..9c0e9cf172 100644 --- a/indra/llcommon/hbxxh.h +++ b/indra/llcommon/hbxxh.h @@ -96,6 +96,15 @@ public: } } + // Make this class no-copy (it would be possible, with custom copy + // operators, but it is not trivially copyable, because of the mState + // pointer): it does not really make sense to allow copying it anyway, + // since all we care about is the resulting digest (so you should only + // need and care about storing/copying the digest and not a class + // instance). + HBXXH64(const HBXXH64&) noexcept = delete; + HBXXH64& operator=(const HBXXH64&) noexcept = delete; + ~HBXXH64(); void update(const void* buffer, size_t len); @@ -199,6 +208,15 @@ public: } } + // Make this class no-copy (it would be possible, with custom copy + // operators, but it is not trivially copyable, because of the mState + // pointer): it does not really make sense to allow copying it anyway, + // since all we care about is the resulting digest (so you should only + // need and care about storing/copying the digest and not a class + // instance). + HBXXH128(const HBXXH128&) noexcept = delete; + HBXXH128& operator=(const HBXXH128&) noexcept = delete; + ~HBXXH128(); void update(const void* buffer, size_t len); diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 937f1a5501..ead46bfa5f 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -349,6 +349,7 @@ const U8 CLICK_ACTION_PLAY = 5; const U8 CLICK_ACTION_OPEN_MEDIA = 6; const U8 CLICK_ACTION_ZOOM = 7; const U8 CLICK_ACTION_DISABLED = 8; +const U8 CLICK_ACTION_IGNORE = 9; // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 284bfb2afa..e3bb661c63 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -828,11 +828,11 @@ bool unix_post_minidump_callback(const char *dump_dir, auto dirPathLength = strlen(dump_dir); auto idLength = strlen(minidump_id); - // The path must not be truncated. - llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); + // The path must not be truncated, and we need to have room left for a terminating zero. + llassert((dirPathLength + idLength + 5) < LLApp::MAX_MINDUMP_PATH_LENGTH); // Buffer overrun avoidance (from Aleric Inglewood) char * path = LLApp::instance()->getMiniDumpFilename(); - auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + auto remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - 1; // Buffer overrun avoidance (from Aleric Inglewood strncpy(path, dump_dir, remaining); remaining -= dirPathLength; path += dirPathLength; diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index 5c46f6a796..4e25001fff 100644 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -167,48 +167,34 @@ const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luc // // defined for U16, U32, U64, S16, S32, S64, : // llclampb(a) // clamps a to [0 .. 255] -// +// -template -inline auto llmax(T1 d1, T2 d2) +// recursion tail +template +inline auto llmax(T data) { - return (d1 > d2) ? d1 : d2; + return data; } -template -inline auto llmax(T1 d1, T2 d2, T3 d3) +template +inline auto llmax(T0 d0, T1 d1, Ts... rest) { - auto r = llmax(d1,d2); - return llmax(r, d3); + auto maxrest = llmax(d1, rest...); + return (d0 > maxrest)? d0 : maxrest; } -template -inline auto llmax(T1 d1, T2 d2, T3 d3, T4 d4) +// recursion tail +template +inline auto llmin(T data) { - auto r1 = llmax(d1,d2); - auto r2 = llmax(d3,d4); - return llmax(r1, r2); + return data; } -template -inline auto llmin(T1 d1, T2 d2) +template +inline auto llmin(T0 d0, T1 d1, Ts... rest) { - return (d1 < d2) ? d1 : d2; -} - -template -inline auto llmin(T1 d1, T2 d2, T3 d3) -{ - auto r = llmin(d1,d2); - return (r < d3 ? r : d3); -} - -template -inline auto llmin(T1 d1, T2 d2, T3 d3, T4 d4) -{ - auto r1 = llmin(d1,d2); - auto r2 = llmin(d3,d4); - return llmin(r1, r2); + auto minrest = llmin(d1, rest...); + return (d0 < minrest) ? d0 : minrest; } template diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index c87c0758fe..259f5bc505 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -204,30 +204,35 @@ public: LLSD packet(LLSDMap("pump", pump)("data", data)); std::ostringstream buffer; - buffer << LLSDNotationStreamer(packet); + // SL-18330: for large data blocks, it's much faster to parse binary + // LLSD than notation LLSD. Use serialize(LLSD_BINARY) rather than + // directly calling LLSDBinaryFormatter because, unlike the latter, + // serialize() prepends the relevant header, needed by a general- + // purpose LLSD parser to distinguish binary from notation. + LLSDSerialize::serialize(packet, buffer, LLSDSerialize::LLSD_BINARY, + LLSDFormatter::OPTIONS_NONE); /*==========================================================================*| // DEBUGGING ONLY: don't copy str() if we can avoid it. std::string strdata(buffer.str()); if (std::size_t(buffer.tellp()) != strdata.length()) { - LL_ERRS("LLLeap") << "tellp() -> " << buffer.tellp() << " != " + LL_ERRS("LLLeap") << "tellp() -> " << static_cast(buffer.tellp()) << " != " << "str().length() -> " << strdata.length() << LL_ENDL; } // DEBUGGING ONLY: reading back is terribly inefficient. std::istringstream readback(strdata); LLSD echo; - LLPointer parser(new LLSDNotationParser()); - S32 parse_status(parser->parse(readback, echo, strdata.length())); - if (parse_status == LLSDParser::PARSE_FAILURE) + bool parse_status(LLSDSerialize::deserialize(echo, readback, strdata.length())); + if (! parse_status) { - LL_ERRS("LLLeap") << "LLSDNotationParser() cannot parse output of " - << "LLSDNotationStreamer()" << LL_ENDL; + LL_ERRS("LLLeap") << "LLSDSerialize::deserialize() cannot parse output of " + << "LLSDSerialize::serialize(LLSD_BINARY)" << LL_ENDL; } if (! llsd_equals(echo, packet)) { - LL_ERRS("LLLeap") << "LLSDNotationParser() produced different LLSD " - << "than passed to LLSDNotationStreamer()" << LL_ENDL; + LL_ERRS("LLLeap") << "LLSDSerialize::deserialize() returned different LLSD " + << "than passed to LLSDSerialize::serialize()" << LL_ENDL; } |*==========================================================================*/ @@ -314,9 +319,17 @@ public: LL_DEBUGS("LLLeap") << "needed " << mExpect << " bytes, got " << childout.size() << ", parsing LLSD" << LL_ENDL; LLSD data; +#if 1 + // specifically require notation LLSD from child LLPointer parser(new LLSDNotationParser()); S32 parse_status(parser->parse(childout.get_istream(), data, mExpect)); if (parse_status == LLSDParser::PARSE_FAILURE) +#else + // SL-18330: accept any valid LLSD serialization format from child + // Unfortunately this runs into trouble we have not yet debugged. + bool parse_status(LLSDSerialize::deserialize(data, childout.get_istream(), mExpect)); + if (! parse_status) +#endif { bad_protocol("unparseable LLSD data"); } diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 9b2a2bab60..0abe817f1d 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -96,7 +96,7 @@ LLMD5::LLMD5() // operation, processing another message block, and updating the // context. -void LLMD5::update (const uint1 *input, const size_t input_length) { +void LLMD5::update (const uint8_t *input, const size_t input_length) { size_t input_index, buffer_index; size_t buffer_space; // how much space is left in buffer @@ -189,7 +189,7 @@ void LLMD5::finalize (){ unsigned char bits[8]; /* Flawfinder: ignore */ size_t index, padLen; - static uint1 PADDING[64]={ + static uint8_t PADDING[64]={ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 @@ -201,8 +201,8 @@ void LLMD5::finalize (){ } // Save number of bits. - // Treat count, a uint64_t, as uint4[2]. - encode (bits, reinterpret_cast(&count), 8); + // Treat count, a uint64_t, as uint32_t[2]. + encode (bits, reinterpret_cast(&count), 8); // Pad out to 56 mod 64. index = size_t((count >> 3) & 0x3f); @@ -412,7 +412,7 @@ Rotation is separate from addition to prevent recomputation. // LLMD5 basic transformation. Transforms state based on block. void LLMD5::transform (const U8 block[64]){ - uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; decode (x, block, 64); @@ -496,38 +496,38 @@ void LLMD5::transform (const U8 block[64]){ state[3] += d; // Zeroize sensitive information. - memset ( (uint1 *) x, 0, sizeof(x)); + memset ( (uint8_t *) x, 0, sizeof(x)); } -// Encodes input (UINT4) into output (unsigned char). Assumes len is +// Encodes input (uint32_t) into output (unsigned char). Assumes len is // a multiple of 4. -void LLMD5::encode (uint1 *output, const uint4 *input, const size_t len) { +void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) { size_t i, j; for (i = 0, j = 0; j < len; i++, j += 4) { - output[j] = (uint1) (input[i] & 0xff); - output[j+1] = (uint1) ((input[i] >> 8) & 0xff); - output[j+2] = (uint1) ((input[i] >> 16) & 0xff); - output[j+3] = (uint1) ((input[i] >> 24) & 0xff); + output[j] = (uint8_t) (input[i] & 0xff); + output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff); + output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff); + output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff); } } -// Decodes input (unsigned char) into output (UINT4). Assumes len is +// Decodes input (unsigned char) into output (uint32_t). Assumes len is // a multiple of 4. -void LLMD5::decode (uint4 *output, const uint1 *input, const size_t len){ +void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){ size_t i, j; for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | - (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); + output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | + (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); } diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 8530dc0389..7d6373c20c 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -67,6 +67,8 @@ documentation and/or software. */ +#include // uint32_t et al. + // use for the raw digest output const int MD5RAW_BYTES = 16; @@ -75,18 +77,13 @@ const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null const int MD5HEX_STR_BYTES = 32; // message system fixed size class LL_COMMON_API LLMD5 { -// first, some types: - typedef unsigned int uint4; // assumes integer is 4 words long - typedef unsigned short int uint2; // assumes short integer is 2 words long - typedef unsigned char uint1; // assumes char is 1 word long - // how many bytes to grab at a time when checking files static const int BLOCK_LEN; public: // methods for controlled operation: LLMD5 (); // simple initializer - void update (const uint1 *input, const size_t input_length); + void update (const uint8_t *input, const size_t input_length); void update (std::istream& stream); void update (FILE *file); void update (const std::string& str); @@ -109,19 +106,19 @@ private: // next, the private data: - uint4 state[4]; + uint32_t state[4]; uint64_t count; // number of *bits*, mod 2^64 - uint1 buffer[64]; // input buffer - uint1 digest[16]; - uint1 finalized; + uint8_t buffer[64]; // input buffer + uint8_t digest[16]; + uint8_t finalized; // last, the private methods, mostly static: void init (); // called by all constructors - void transform (const uint1 *buffer); // does the real update work. Note + void transform (const uint8_t *buffer); // does the real update work. Note // that length is implied to be 64. - static void encode (uint1 *dest, const uint4 *src, const size_t length); - static void decode (uint4 *dest, const uint1 *src, const size_t length); + static void encode (uint8_t *dest, const uint32_t *src, const size_t length); + static void decode (uint32_t *dest, const uint8_t *src, const size_t length); }; diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index bdbb9e85b1..3810aa676c 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -48,6 +48,7 @@ #endif #include "lldate.h" +#include "llmemorystream.h" #include "llsd.h" #include "llstring.h" #include "lluri.h" @@ -64,6 +65,23 @@ const std::string LLSD_NOTATION_HEADER("llsd/notation"); #define windowBits 15 #define ENABLE_ZLIB_GZIP 32 +// If we published this in llsdserialize.h, we could use it in the +// implementation of LLSDOStreamer's operator<<(). +template +void format_using(const LLSD& data, std::ostream& ostr, + LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY) +{ + LLPointer f{ new Formatter }; + f->format(data, ostr, options); +} + +template +S32 parse_using(std::istream& istr, LLSD& data, size_t max_bytes, S32 max_depth=-1) +{ + LLPointer p{ new Parser }; + return p->parse(istr, data, max_bytes, max_depth); +} + /** * LLSDSerialize */ @@ -86,10 +104,10 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize f = new LLSDXMLFormatter; break; - case LLSD_NOTATION: - str << "\n"; - f = new LLSDNotationFormatter; - break; + case LLSD_NOTATION: + str << "\n"; + f = new LLSDNotationFormatter; + break; default: LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL; @@ -104,18 +122,37 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize // static bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes) { - LLPointer p = NULL; char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ - int i; - int inbuf = 0; - bool legacy_no_header = false; bool fail_if_not_legacy = false; - std::string header; - /* - * Get the first line before anything. - */ - str.get(hdr_buf, MAX_HDR_LEN, '\n'); + /* + * Get the first line before anything. Don't read more than max_bytes: + * this get() overload reads no more than (count-1) bytes into the + * specified buffer. In the usual case when max_bytes exceeds + * sizeof(hdr_buf), get() will read no more than sizeof(hdr_buf)-2. + */ + llssize max_hdr_read = MAX_HDR_LEN; + if (max_bytes != LLSDSerialize::SIZE_UNLIMITED) + { + max_hdr_read = llmin(max_bytes + 1, max_hdr_read); + } + str.get(hdr_buf, max_hdr_read, '\n'); + auto inbuf = str.gcount(); + + // https://en.cppreference.com/w/cpp/io/basic_istream/get + // When the get() above sees the specified delimiter '\n', it stops there + // without pulling it from the stream. If it turns out that the stream + // does NOT contain a header, and the content includes meaningful '\n', + // it's important to pull that into hdr_buf too. + if (inbuf < max_bytes && str.get(hdr_buf[inbuf])) + { + // got the delimiting '\n' + ++inbuf; + // None of the following requires that hdr_buf contain a final '\0' + // byte. We could store one if needed, since even the incremented + // inbuf won't exceed sizeof(hdr_buf)-1, but there's no need. + } + std::string header{ hdr_buf, static_cast(inbuf) }; if (str.fail()) { str.clear(); @@ -123,79 +160,97 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes) } if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ - { - legacy_no_header = true; - inbuf = (int)str.gcount(); + { // Create a LLSD XML parser, and parse the first chunk read above. + LLSDXMLParser x; + x.parsePart(hdr_buf, inbuf); // Parse the first part that was already read + auto parsed = x.parse(str, sd, max_bytes - inbuf); // Parse the rest of it + // Formally we should probably check (parsed != PARSE_FAILURE && + // parsed > 0), but since PARSE_FAILURE is -1, this suffices. + return (parsed > 0); } - else + + if (fail_if_not_legacy) { - if (fail_if_not_legacy) - goto fail; - /* - * Remove the newline chars - */ - for (i = 0; i < MAX_HDR_LEN; i++) - { - if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' || - hdr_buf[i] == '\n') - { - hdr_buf[i] = 0; - break; - } - } - header = hdr_buf; + LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL; + return false; + } - std::string::size_type start = std::string::npos; - std::string::size_type end = std::string::npos; - start = header.find_first_not_of(" header syntax + auto start = header.find_first_not_of("parsePart(hdr_buf, inbuf); // Parse the first part that was already read - x->parseLines(str, sd); // Parse the rest of it - delete x; - return true; - } - - if (header == LLSD_BINARY_HEADER) + if (0 == LLStringUtil::compareInsensitive(header, LLSD_BINARY_HEADER)) { - p = new LLSDBinaryParser; + return (parse_using(str, sd, max_bytes-inbuf) > 0); } - else if (header == LLSD_XML_HEADER) + else if (0 == LLStringUtil::compareInsensitive(header, LLSD_XML_HEADER)) { - p = new LLSDXMLParser; + return (parse_using(str, sd, max_bytes-inbuf) > 0); } - else if (header == LLSD_NOTATION_HEADER) + else if (0 == LLStringUtil::compareInsensitive(header, LLSD_NOTATION_HEADER)) { - p = new LLSDNotationParser; + return (parse_using(str, sd, max_bytes-inbuf) > 0); } - else + else // no header we recognize { - LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL; + LLPointer p; + if (inbuf && hdr_buf[0] == '<') + { + // looks like XML + LL_DEBUGS() << "deserialize request with no header, assuming XML" << LL_ENDL; + p = new LLSDXMLParser; + } + else + { + // assume notation + LL_DEBUGS() << "deserialize request with no header, assuming notation" << LL_ENDL; + p = new LLSDNotationParser; + } + // Since we've already read 'inbuf' bytes into 'hdr_buf', prepend that + // data to whatever remains in 'str'. + LLMemoryStreamBuf already(reinterpret_cast(hdr_buf), inbuf); + cat_streambuf prebuff(&already, str.rdbuf()); + std::istream prepend(&prebuff); +#if 1 + return (p->parse(prepend, sd, max_bytes) > 0); +#else + // debugging the reconstituted 'prepend' stream + // allocate a buffer that we hope is big enough for the whole thing + std::vector wholemsg((max_bytes == size_t(SIZE_UNLIMITED))? 1024 : max_bytes); + prepend.read(wholemsg.data(), std::min(max_bytes, wholemsg.size())); + LLMemoryStream replay(reinterpret_cast(wholemsg.data()), prepend.gcount()); + auto success{ p->parse(replay, sd, prepend.gcount()) > 0 }; + { + LL_DEBUGS() << (success? "parsed: $$" : "failed: '") + << std::string(wholemsg.data(), llmin(prepend.gcount(), 100)) << "$$" + << LL_ENDL; + } + return success; +#endif } - - if (p.notNull()) - { - p->parse(str, sd, max_bytes); - return true; - } - -fail: - LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL; - return false; } /** @@ -2195,7 +2250,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 U8* result = NULL; llssize cur_size = 0; z_stream strm; - + constexpr U32 CHUNK = 1024 * 512; static thread_local std::unique_ptr out; @@ -2399,7 +2454,7 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size return result; } -char* strip_deprecated_header(char* in, llssize& cur_size, U32* header_size) +char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size) { const char* deprecated_header = ""; constexpr size_t deprecated_header_size = 17; diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 5ddf0ff552..676b7bfd6a 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -873,5 +873,5 @@ LL_COMMON_API std::string zip_llsd(LLSD& data); LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, size_t& outsize,std::istream& is, S32 size); // returns a pointer to the array or past the array if the deprecated header exists -LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, U32* header_size = nullptr); +LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size = nullptr); #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index 1ff15fcf89..bc32b6fd9e 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -513,3 +513,29 @@ std::istream& operator>>(std::istream& str, const char *tocheck) } return str; } + +int cat_streambuf::underflow() +{ + if (gptr() == egptr()) + { + // here because our buffer is empty + std::streamsize size = 0; + // Until we've run out of mInputs, try reading the first of them + // into mBuffer. If that fetches some characters, break the loop. + while (! mInputs.empty() + && ! (size = mInputs.front()->sgetn(mBuffer.data(), mBuffer.size()))) + { + // We tried to read mInputs.front() but got zero characters. + // Discard the first streambuf and try the next one. + mInputs.pop_front(); + } + // Either we ran out of mInputs or we succeeded in reading some + // characters, that is, size != 0. Tell base class what we have. + setg(mBuffer.data(), mBuffer.data(), mBuffer.data() + size); + } + // If we fell out of the above loop with mBuffer still empty, return + // eof(), otherwise return the next character. + return (gptr() == egptr()) + ? std::char_traits::eof() + : std::char_traits::to_int_type(*gptr()); +} diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h index 1b04bf91d7..bb7bc20327 100644 --- a/indra/llcommon/llstreamtools.h +++ b/indra/llcommon/llstreamtools.h @@ -27,8 +27,10 @@ #ifndef LL_STREAM_TOOLS_H #define LL_STREAM_TOOLS_H +#include #include #include +#include // unless specifed otherwise these all return input_stream.good() @@ -113,6 +115,27 @@ LL_COMMON_API std::streamsize fullread( LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck); +/** + * cat_streambuf is a std::streambuf subclass that accepts a variadic number + * of std::streambuf* (e.g. some_istream.rdbuf()) and virtually concatenates + * their contents. + */ +// derived from https://stackoverflow.com/a/49441066/5533635 +class cat_streambuf: public std::streambuf +{ +private: + std::deque mInputs; + std::vector mBuffer; + +public: + // only valid for std::streambuf* arguments + template + cat_streambuf(Inputs... inputs): + mInputs{inputs...}, + mBuffer(1024) + {} + + int underflow() override; +}; + #endif - - diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index a8dcc5226a..bb3d667a42 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -577,10 +577,12 @@ S32 Recording::getSampleCount( const StatType& stat ) // PeriodicRecording /////////////////////////////////////////////////////////////////////// -PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) +PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state) : mAutoResize(num_periods == 0), mCurPeriod(0), mNumRecordedPeriods(0), + // This guarantee that mRecordingPeriods cannot be empty is essential for + // code in several methods. mRecordingPeriods(num_periods ? num_periods : 1) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; @@ -596,18 +598,19 @@ PeriodicRecording::~PeriodicRecording() void PeriodicRecording::nextPeriod() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; if (mAutoResize) { mRecordingPeriods.push_back(Recording()); } Recording& old_recording = getCurRecording(); - mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size(); + inci(mCurPeriod); old_recording.splitTo(getCurRecording()); - mNumRecordedPeriods = mRecordingPeriods.empty()? 0 : - llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1); + // Since mRecordingPeriods always has at least one entry, we can always + // safely subtract 1 from its size(). + mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1); } void PeriodicRecording::appendRecording(Recording& recording) @@ -620,31 +623,29 @@ void PeriodicRecording::appendRecording(Recording& recording) void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; if (other.mRecordingPeriods.empty()) return; getCurRecording().update(); other.getCurRecording().update(); - - const auto other_recording_slots = other.mRecordingPeriods.size(); + const auto other_num_recordings = other.getNumRecordedPeriods(); const auto other_current_recording_index = other.mCurPeriod; - const auto other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots; + const auto other_oldest_recording_index = other.previ(other_current_recording_index, other_num_recordings); // append first recording into our current slot getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]); // from now on, add new recordings for everything after the first - auto other_index = (other_oldest_recording_index + 1) % other_recording_slots; + auto other_index = other.nexti(other_oldest_recording_index); if (mAutoResize) { // push back recordings for everything in the middle - auto other_index = (other_oldest_recording_index + 1) % other_recording_slots; while (other_index != other_current_recording_index) { mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]); - other_index = (other_index + 1) % other_recording_slots; + other.inci(other_index); } // add final recording, if it wasn't already added as the first @@ -653,36 +654,25 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]); } - mCurPeriod = mRecordingPeriods.empty()? 0 : mRecordingPeriods.size() - 1; + // mRecordingPeriods is never empty() + mCurPeriod = mRecordingPeriods.size() - 1; mNumRecordedPeriods = mCurPeriod; } else { - S32 num_to_copy = llmin((S32)mRecordingPeriods.size(), (S32)other_num_recordings); - - std::vector::iterator src_it = other.mRecordingPeriods.begin() + other_index ; - std::vector::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod; - + auto num_to_copy = llmin(mRecordingPeriods.size(), other_num_recordings); // already consumed the first recording from other, so start counting at 1 - for(S32 i = 1; i < num_to_copy; i++) + for (size_t n = 1, srci = other_index, dsti = mCurPeriod; + n < num_to_copy; + ++n, other.inci(srci), inci(dsti)) { - *dest_it = *src_it; - - if (++src_it == other.mRecordingPeriods.end()) - { - src_it = other.mRecordingPeriods.begin(); - } - - if (++dest_it == mRecordingPeriods.end()) - { - dest_it = mRecordingPeriods.begin(); - } + mRecordingPeriods[dsti] = other.mRecordingPeriods[srci]; } - + // want argument to % to be positive, otherwise result could be negative and thus out of bounds llassert(num_to_copy >= 1); // advance to last recording period copied, and make that our current period - mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size(); + inci(mCurPeriod, num_to_copy - 1); mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1); } @@ -694,13 +684,11 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) F64Seconds PeriodicRecording::getDuration() const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; F64Seconds duration; - auto num_periods = mRecordingPeriods.size(); - for (size_t i = 1; i <= num_periods; i++) + for (size_t n = 0; n < mRecordingPeriods.size(); ++n) { - auto index = (mCurPeriod + num_periods - i) % num_periods; - duration += mRecordingPeriods[index].getDuration(); + duration += mRecordingPeriods[nexti(mCurPeriod, n)].getDuration(); } return duration; } @@ -737,16 +725,14 @@ const Recording& PeriodicRecording::getCurRecording() const Recording& PeriodicRecording::getPrevRecording( size_t offset ) { - auto num_periods = mRecordingPeriods.size(); - offset = llclamp(offset, 0, num_periods - 1); - return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods]; + // reuse const implementation, but return non-const reference + return const_cast( + const_cast(this)->getPrevRecording(offset)); } const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const { - auto num_periods = mRecordingPeriods.size(); - offset = llclamp(offset, 0, num_periods - 1); - return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods]; + return mRecordingPeriods[previ(mCurPeriod, offset)]; } void PeriodicRecording::handleStart() @@ -789,14 +775,14 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other) getCurRecording().splitTo(other.getCurRecording()); } -F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; F64 min_val = std::numeric_limits::max(); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -811,14 +797,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType& stat, siz : NaN; } -F64 PeriodicRecording::getPeriodMax( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodMax( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; F64 max_val = std::numeric_limits::min(); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -834,7 +820,7 @@ F64 PeriodicRecording::getPeriodMax( const StatType& stat, siz } // calculates means using aggregates per period -F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); @@ -842,7 +828,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, si F64 mean = 0; S32 valid_period_count = 0; - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -857,7 +843,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, si : NaN; } -F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); @@ -866,7 +852,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; F64 min_val = std::numeric_limits::max(); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -904,14 +890,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType& stat, si : NaN; } -F64 PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= S32_MAX*/) +F64 PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; F64 max_val = std::numeric_limits::min(); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -927,7 +913,7 @@ F64 PeriodicRecording::getPeriodMax(const StatType& stat, siz } -F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); @@ -935,7 +921,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, s S32 valid_period_count = 0; F64 mean = 0; - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -950,13 +936,13 @@ F64 PeriodicRecording::getPeriodMean( const StatType& stat, s : NaN; } -F64 PeriodicRecording::getPeriodMedian( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodMedian( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); std::vector buf; - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.getDuration() > (F32Seconds)0.f) @@ -976,7 +962,7 @@ F64 PeriodicRecording::getPeriodMedian( const StatType& stat, return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); } -F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); @@ -985,7 +971,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64Kilobytes PeriodicRecording::getPeriodMin( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes min_val(std::numeric_limits::max()); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); min_val = llmin(min_val, recording.getMin(stat)); @@ -1022,13 +1008,13 @@ F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t n return getPeriodMin(static_cast&>(stat), num_periods); } -F64Kilobytes PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= S32_MAX*/) +F64Kilobytes PeriodicRecording::getPeriodMax(const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes max_val(0.0); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); max_val = llmax(max_val, recording.getMax(stat)); @@ -1042,14 +1028,14 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t n return getPeriodMax(static_cast&>(stat), num_periods); } -F64Kilobytes PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64Kilobytes PeriodicRecording::getPeriodMean( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64Kilobytes mean(0); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); mean += recording.getMean(stat); @@ -1063,7 +1049,7 @@ F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t return getPeriodMean(static_cast&>(stat), num_periods); } -F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= S32_MAX*/ ) +F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType& stat, size_t num_periods /*= std::numeric_limits::max()*/ ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); @@ -1072,7 +1058,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType class LLStopWatchControlsMixinCommon { @@ -330,7 +331,7 @@ namespace LLTrace : public LLStopWatchControlsMixin { public: - PeriodicRecording(S32 num_periods, EPlayState state = STOPPED); + PeriodicRecording(size_t num_periods, EPlayState state = STOPPED); ~PeriodicRecording(); void nextPeriod(); @@ -353,7 +354,7 @@ namespace LLTrace Recording snapshotCurRecording() const; template - auto getSampleCount(const StatType& stat, size_t num_periods = S32_MAX) + auto getSampleCount(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); @@ -373,14 +374,14 @@ namespace LLTrace // catch all for stats that have a defined sum template - typename T::value_t getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX) + typename T::value_t getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; typename T::value_t min_val(std::numeric_limits::max()); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -396,39 +397,39 @@ namespace LLTrace } template - T getPeriodMin(const CountStatHandle& stat, size_t num_periods = S32_MAX) + T getPeriodMin(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMin(static_cast&>(stat), num_periods)); } - F64 getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - T getPeriodMin(const SampleStatHandle& stat, size_t num_periods = S32_MAX) + T getPeriodMin(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMin(static_cast&>(stat), num_periods)); } - F64 getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - T getPeriodMin(const EventStatHandle& stat, size_t num_periods = S32_MAX) + T getPeriodMin(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMin(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodMin(const StatType& stat, size_t num_periods = S32_MAX); - F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = S32_MAX); + F64Kilobytes getPeriodMin(const StatType& stat, size_t num_periods = std::numeric_limits::max()); + F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodMinPerSec(const StatType& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMinPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes::fractional_t min_val(std::numeric_limits::max()); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); min_val = llmin(min_val, recording.getPerSec(stat)); @@ -437,7 +438,7 @@ namespace LLTrace } template - typename RelatedTypes::fractional_t getPeriodMinPerSec(const CountStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMinPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMinPerSec(static_cast&>(stat), num_periods)); @@ -449,14 +450,14 @@ namespace LLTrace // catch all for stats that have a defined sum template - typename T::value_t getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX) + typename T::value_t getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); bool has_value = false; typename T::value_t max_val(std::numeric_limits::min()); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) @@ -472,39 +473,39 @@ namespace LLTrace } template - T getPeriodMax(const CountStatHandle& stat, size_t num_periods = S32_MAX) + T getPeriodMax(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMax(static_cast&>(stat), num_periods)); } - F64 getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - T getPeriodMax(const SampleStatHandle& stat, size_t num_periods = S32_MAX) + T getPeriodMax(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMax(static_cast&>(stat), num_periods)); } - F64 getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - T getPeriodMax(const EventStatHandle& stat, size_t num_periods = S32_MAX) + T getPeriodMax(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return T(getPeriodMax(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodMax(const StatType& stat, size_t num_periods = S32_MAX); - F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = S32_MAX); + F64Kilobytes getPeriodMax(const StatType& stat, size_t num_periods = std::numeric_limits::max()); + F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodMaxPerSec(const StatType& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMaxPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); F64 max_val = std::numeric_limits::min(); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); max_val = llmax(max_val, recording.getPerSec(stat)); @@ -513,7 +514,7 @@ namespace LLTrace } template - typename RelatedTypes::fractional_t getPeriodMaxPerSec(const CountStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMaxPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMaxPerSec(static_cast&>(stat), num_periods)); @@ -525,14 +526,14 @@ namespace LLTrace // catch all for stats that have a defined sum template - typename RelatedTypes::fractional_t getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes::fractional_t mean(0); - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.getDuration() > (F32Seconds)0.f) @@ -546,39 +547,39 @@ namespace LLTrace } template - typename RelatedTypes::fractional_t getPeriodMean(const CountStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMean(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods)); } - F64 getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodMean(const SampleStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMean(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods)); } - F64 getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodMean(const EventStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMean(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMean(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodMean(const StatType& stat, size_t num_periods = S32_MAX); - F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = S32_MAX); + F64Kilobytes getPeriodMean(const StatType& stat, size_t num_periods = std::numeric_limits::max()); + F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodMeanPerSec(const StatType& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMeanPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; num_periods = llmin(num_periods, getNumRecordedPeriods()); typename RelatedTypes::fractional_t mean = 0; - for (S32 i = 1; i <= num_periods; i++) + for (size_t i = 1; i <= num_periods; i++) { Recording& recording = getPrevRecording(i); if (recording.getDuration() > (F32Seconds)0.f) @@ -593,64 +594,64 @@ namespace LLTrace } template - typename RelatedTypes::fractional_t getPeriodMeanPerSec(const CountStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodMeanPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodMeanPerSec(static_cast&>(stat), num_periods)); } - F64 getPeriodMedian( const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodMedian( const StatType& stat, size_t num_periods = std::numeric_limits::max()); - template - typename RelatedTypes::fractional_t getPeriodMedianPerSec(const StatType& stat, size_t num_periods = S32_MAX) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); + template + typename RelatedTypes::fractional_t getPeriodMedianPerSec(const StatType& stat, size_t num_periods = std::numeric_limits::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); - std::vector ::fractional_t> buf; - for (S32 i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.getDuration() > (F32Seconds)0.f) - { - buf.push_back(recording.getPerSec(stat)); - } - } - std::sort(buf.begin(), buf.end()); + std::vector ::fractional_t> buf; + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > (F32Seconds)0.f) + { + buf.push_back(recording.getPerSec(stat)); + } + } + std::sort(buf.begin(), buf.end()); - return typename RelatedTypes::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); - } + return typename RelatedTypes::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); + } - template - typename RelatedTypes::fractional_t getPeriodMedianPerSec(const CountStatHandle& stat, size_t num_periods = S32_MAX) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes::fractional_t(getPeriodMedianPerSec(static_cast&>(stat), num_periods)); - } + template + typename RelatedTypes::fractional_t getPeriodMedianPerSec(const CountStatHandle& stat, size_t num_periods = std::numeric_limits::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes::fractional_t(getPeriodMedianPerSec(static_cast&>(stat), num_periods)); + } // // PERIODIC STANDARD DEVIATION // - F64 getPeriodStandardDeviation(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodStandardDeviation(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodStandardDeviation(const SampleStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodStandardDeviation(const SampleStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodStandardDeviation(static_cast&>(stat), num_periods)); } - F64 getPeriodStandardDeviation(const StatType& stat, size_t num_periods = S32_MAX); + F64 getPeriodStandardDeviation(const StatType& stat, size_t num_periods = std::numeric_limits::max()); template - typename RelatedTypes::fractional_t getPeriodStandardDeviation(const EventStatHandle& stat, size_t num_periods = S32_MAX) + typename RelatedTypes::fractional_t getPeriodStandardDeviation(const EventStatHandle& stat, size_t num_periods = std::numeric_limits::max()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; return typename RelatedTypes::fractional_t(getPeriodStandardDeviation(static_cast&>(stat), num_periods)); } - F64Kilobytes getPeriodStandardDeviation(const StatType& stat, size_t num_periods = S32_MAX); - F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = S32_MAX); + F64Kilobytes getPeriodStandardDeviation(const StatType& stat, size_t num_periods = std::numeric_limits::max()); + F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = std::numeric_limits::max()); private: // implementation for LLStopWatchControlsMixin @@ -659,6 +660,35 @@ namespace LLTrace /*virtual*/ void handleReset(); /*virtual*/ void handleSplitTo(PeriodicRecording& other); + // helper methods for wraparound ring-buffer arithmetic + inline + size_t wrapi(size_t i) const + { + return i % mRecordingPeriods.size(); + } + + inline + size_t nexti(size_t i, size_t offset=1) const + { + return wrapi(i + offset); + } + + inline + size_t previ(size_t i, size_t offset=1) const + { + auto num_periods = mRecordingPeriods.size(); + // constrain offset + offset = llclamp(offset, 0, num_periods - 1); + // add size() so expression can't go (unsigned) "negative" + return wrapi(i + num_periods - offset); + } + + inline + void inci(size_t& i, size_t offset=1) const + { + i = nexti(i, offset); + } + private: std::vector mRecordingPeriods; const bool mAutoResize; diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index a40bb0a238..8511d1bc08 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -888,7 +888,7 @@ U32 LLUUID::getRandomSeed() seed[7]=(unsigned char)(pid); getSystemTime((uuid_time_t *)(&seed[8])); - U64 seed64 = HBXXH64((const void*)seed, 16).digest(); + U64 seed64 = HBXXH64::digest((const void*)seed, 16); return U32(seed64) ^ U32(seed64 >> 32); } diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 5f0d7579f2..3962c348ae 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -171,6 +171,14 @@ public: U16 getCRC16() const; U32 getCRC32() const; + // Returns a 64 bits digest of the UUID, by XORing its two 64 bits long + // words. HB + inline U64 getDigest64() const + { + U64* tmp = (U64*)mData; + return tmp[0] ^ tmp[1]; + } + static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal. static const LLUUID null; @@ -222,29 +230,23 @@ public: LLAssetID makeAssetID(const LLUUID& session) const; }; -// Generate a hash of an LLUUID object using the boost hash templates. - -// GCC 4.9 does not like the specialization in form of boost::hash but rather wants a namespace -// template <> -// struct boost::hash -namespace boost { template <> struct hash -// +// std::hash implementation for LLUUID +namespace std { - typedef LLUUID argument_type; - typedef std::size_t result_type; - result_type operator()(argument_type const& s) const - { - result_type seed(0); + template<> struct hash + { + inline size_t operator()(const LLUUID& id) const noexcept + { + return (size_t)id.getDigest64(); + } + }; +} - for (S32 i = 0; i < UUID_BYTES; ++i) - { - boost::hash_combine(seed, s.mData[i]); - } - - return seed; - } -}; -} // close namespace +// For use with boost containers. +inline size_t hash_value(const LLUUID& id) noexcept +{ + return (size_t)id.getDigest64(); +} // UUID hash calculation struct FSUUIDHash @@ -256,17 +258,4 @@ struct FSUUIDHash }; // UUID hash calculation -// Adapt boost hash to std hash -namespace std -{ - template<> struct hash - { - std::size_t operator()(LLUUID const& s) const noexcept - { - return boost::hash()(s); - } - }; -} -#endif - - +#endif // LL_LLUUID_H diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index 18615ba95f..0b43d7ad4b 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -41,7 +41,7 @@ typedef unsigned int U32; // to express an index that might go negative // (ssize_t is provided by SOME compilers, don't collide) -typedef typename std::make_signed::type llssize; // Stop Linux complaining +typedef typename std::make_signed::type llssize; #if LL_WINDOWS // https://docs.microsoft.com/en-us/cpp/build/reference/zc-wchar-t-wchar-t-is-native-type diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 7ee36a9ea6..3ae48a2532 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -109,7 +109,12 @@ namespace tut "import os\n" "import sys\n" "\n" - "from llbase import llsd\n" + "try:\n" + // new freestanding llsd package + " import llsd\n" + "except ImportError:\n" + // older llbase.llsd module + " from llbase import llsd\n" "\n" "class ProtocolError(Exception):\n" " def __init__(self, msg, data):\n" @@ -120,26 +125,26 @@ namespace tut " pass\n" "\n" "def get():\n" - " hdr = ''\n" - " while ':' not in hdr and len(hdr) < 20:\n" - " hdr += sys.stdin.read(1)\n" + " hdr = []\n" + " while b':' not in hdr and len(hdr) < 20:\n" + " hdr.append(sys.stdin.buffer.read(1))\n" " if not hdr:\n" " sys.exit(0)\n" - " if not hdr.endswith(':'):\n" + " if not hdr[-1] == b':':\n" " raise ProtocolError('Expected len:data, got %r' % hdr, hdr)\n" " try:\n" - " length = int(hdr[:-1])\n" + " length = int(b''.join(hdr[:-1]))\n" " except ValueError:\n" " raise ProtocolError('Non-numeric len %r' % hdr[:-1], hdr[:-1])\n" " parts = []\n" " received = 0\n" " while received < length:\n" - " parts.append(sys.stdin.read(length - received))\n" + " parts.append(sys.stdin.buffer.read(length - received))\n" " received += len(parts[-1])\n" - " data = ''.join(parts)\n" + " data = b''.join(parts)\n" " assert len(data) == length\n" " try:\n" - " return llsd.parse(data.encode())\n" + " return llsd.parse(data)\n" // Seems the old indra.base.llsd module didn't properly // convert IndexError (from running off end of string) to // LLSDParseError. @@ -179,11 +184,11 @@ namespace tut " return _reply\n" "\n" "def put(req):\n" - " sys.stdout.write(':'.join((str(len(req)), req)))\n" + " sys.stdout.buffer.write(b'%d:%b' % (len(req), req))\n" " sys.stdout.flush()\n" "\n" "def send(pump, data):\n" - " put(llsd.format_notation(dict(pump=pump, data=data)).decode())\n" + " put(llsd.format_notation(dict(pump=pump, data=data)))\n" "\n" "def request(pump, data):\n" " # we expect 'data' is a dict\n" diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 5dbcf4c9b8..acb2953b5b 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -46,20 +46,24 @@ typedef U32 uint32_t; #include "boost/range.hpp" #include "boost/foreach.hpp" -#include "boost/function.hpp" #include "boost/bind.hpp" #include "boost/phoenix/bind/bind_function.hpp" #include "boost/phoenix/core/argument.hpp" using namespace boost::phoenix; -#include "../llsd.h" -#include "../llsdserialize.h" +#include "llsd.h" +#include "llsdserialize.h" #include "llsdutil.h" -#include "../llformat.h" +#include "llformat.h" +#include "llmemorystream.h" #include "../test/lltut.h" #include "../test/namedtempfile.h" #include "stringize.h" +#include + +typedef std::function FormatterFunction; +typedef std::function ParserFunction; std::vector string_to_vector(const std::string& str) { @@ -112,7 +116,7 @@ namespace tut mSD = LLUUID::null; expected = "\n"; xml_test("null uuid", expected); - + mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed"); expected = "c96f9b1e-f589-4100-9774-d98643ce0bed\n"; xml_test("uuid", expected); @@ -136,7 +140,7 @@ namespace tut expected = "aGVsbG8=\n"; xml_test("binary", expected); } - + template<> template<> void sd_xml_object::test<2>() { @@ -225,7 +229,7 @@ namespace tut expected = "bazfoobar\n"; xml_test("2 element map", expected); } - + template<> template<> void sd_xml_object::test<6>() { @@ -241,7 +245,7 @@ namespace tut expected = "Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==\n"; xml_test("binary", expected); } - + class TestLLSDSerializeData { public: @@ -250,9 +254,34 @@ namespace tut void doRoundTripTests(const std::string&); void checkRoundTrip(const std::string&, const LLSD& v); - - LLPointer mFormatter; - LLPointer mParser; + + void setFormatterParser(LLPointer formatter, LLPointer parser) + { + mFormatter = [formatter](const LLSD& data, std::ostream& str) + { + formatter->format(data, str); + }; + // this lambda must be mutable since otherwise the bound 'parser' + // is assumed to point to a const LLSDParser + mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable + { + // reset() call is needed since test code re-uses parser object + parser->reset(); + return (parser->parse(istr, data, max_bytes) > 0); + }; + } + + void setParser(bool (*parser)(LLSD&, std::istream&, llssize)) + { + // why does LLSDSerialize::deserialize() reverse the parse() params?? + mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) + { + return parser(data, istr, max_bytes); + }; + } + + FormatterFunction mFormatter; + ParserFunction mParser; }; TestLLSDSerializeData::TestLLSDSerializeData() @@ -265,12 +294,11 @@ namespace tut void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v) { - std::stringstream stream; - mFormatter->format(v, stream); + std::stringstream stream; + mFormatter(v, stream); //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL; LLSD w; - mParser->reset(); // reset() call is needed since test code re-uses mParser - mParser->parse(stream, w, stream.str().size()); + mParser(stream, w, stream.str().size()); try { @@ -299,52 +327,52 @@ namespace tut fillmap(root[key], width, depth - 1); } } - + void TestLLSDSerializeData::doRoundTripTests(const std::string& msg) { LLSD v; checkRoundTrip(msg + " undefined", v); - + v = true; checkRoundTrip(msg + " true bool", v); - + v = false; checkRoundTrip(msg + " false bool", v); - + v = 1; checkRoundTrip(msg + " positive int", v); - + v = 0; checkRoundTrip(msg + " zero int", v); - + v = -1; checkRoundTrip(msg + " negative int", v); - + v = 1234.5f; checkRoundTrip(msg + " positive float", v); - + v = 0.0f; checkRoundTrip(msg + " zero float", v); - + v = -1234.5f; checkRoundTrip(msg + " negative float", v); - + // FIXME: need a NaN test - + v = LLUUID::null; checkRoundTrip(msg + " null uuid", v); - + LLUUID newUUID; newUUID.generate(); v = newUUID; checkRoundTrip(msg + " new uuid", v); - + v = ""; checkRoundTrip(msg + " empty string", v); - + v = "some string"; checkRoundTrip(msg + " non-empty string", v); - + v = "Second Life is a 3-D virtual world entirely built and owned by its residents. " "Since opening to the public in 2003, it has grown explosively and today is " @@ -372,7 +400,7 @@ namespace tut for (U32 block = 0x000000; block <= 0x10ffff; block += block_size) { std::ostringstream out; - + for (U32 c = block; c < block + block_size; ++c) { if (c <= 0x000001f @@ -386,7 +414,7 @@ namespace tut if (0x00fdd0 <= c && c <= 0x00fdef) { continue; } if ((c & 0x00fffe) == 0x00fffe) { continue; } // see Unicode standard, section 15.8 - + if (c <= 0x00007f) { out << (char)(c & 0x7f); @@ -410,55 +438,55 @@ namespace tut out << (char)(0x80 | ((c >> 0) & 0x3f)); } } - + v = out.str(); std::ostringstream blockmsg; blockmsg << msg << " unicode string block 0x" << std::hex << block; checkRoundTrip(blockmsg.str(), v); } - + LLDate epoch; v = epoch; checkRoundTrip(msg + " epoch date", v); - + LLDate aDay("2002-12-07T05:07:15.00Z"); v = aDay; checkRoundTrip(msg + " date", v); - + LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/"); v = path; checkRoundTrip(msg + " url", v); - + const char source[] = "it must be a blue moon again"; std::vector data; // note, includes terminating '\0' copy(&source[0], &source[sizeof(source)], back_inserter(data)); - + v = data; checkRoundTrip(msg + " binary", v); - + v = LLSD::emptyMap(); checkRoundTrip(msg + " empty map", v); - + v = LLSD::emptyMap(); v["name"] = "luke"; //v.insert("name", "luke"); v["age"] = 3; //v.insert("age", 3); checkRoundTrip(msg + " map", v); - + v.clear(); v["a"]["1"] = true; v["b"]["0"] = false; checkRoundTrip(msg + " nested maps", v); - + v = LLSD::emptyArray(); checkRoundTrip(msg + " empty array", v); - + v = LLSD::emptyArray(); v.append("ali"); v.append(28); checkRoundTrip(msg + " array", v); - + v.clear(); v[0][0] = true; v[1][0] = false; @@ -468,7 +496,7 @@ namespace tut fillmap(v, 10, 3); // 10^6 maps checkRoundTrip(msg + " many nested maps", v); } - + typedef tut::test_group TestLLSDSerializeGroup; typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject; TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization"); @@ -476,35 +504,106 @@ namespace tut template<> template<> void TestLLSDSerializeObject::test<1>() { - mFormatter = new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY); - mParser = new LLSDNotationParser(); + setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY), + new LLSDNotationParser()); doRoundTripTests("pretty binary notation serialization"); } template<> template<> void TestLLSDSerializeObject::test<2>() { - mFormatter = new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE); - mParser = new LLSDNotationParser(); + setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE), + new LLSDNotationParser()); doRoundTripTests("raw binary notation serialization"); } template<> template<> void TestLLSDSerializeObject::test<3>() { - mFormatter = new LLSDXMLFormatter(); - mParser = new LLSDXMLParser(); + setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser()); doRoundTripTests("xml serialization"); } template<> template<> void TestLLSDSerializeObject::test<4>() { - mFormatter = new LLSDBinaryFormatter(); - mParser = new LLSDBinaryParser(); + setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser()); doRoundTripTests("binary serialization"); } + template<> template<> + void TestLLSDSerializeObject::test<5>() + { + mFormatter = [](const LLSD& sd, std::ostream& str) + { + LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY); + }; + setParser(LLSDSerialize::deserialize); + doRoundTripTests("serialize(LLSD_BINARY)"); + }; + + template<> template<> + void TestLLSDSerializeObject::test<6>() + { + mFormatter = [](const LLSD& sd, std::ostream& str) + { + LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML); + }; + setParser(LLSDSerialize::deserialize); + doRoundTripTests("serialize(LLSD_XML)"); + }; + + template<> template<> + void TestLLSDSerializeObject::test<7>() + { + mFormatter = [](const LLSD& sd, std::ostream& str) + { + LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION); + }; + setParser(LLSDSerialize::deserialize); + // In this test, serialize(LLSD_NOTATION) emits a header recognized by + // deserialize(). + doRoundTripTests("serialize(LLSD_NOTATION)"); + }; + + template<> template<> + void TestLLSDSerializeObject::test<8>() + { + setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE), + new LLSDNotationParser()); + setParser(LLSDSerialize::deserialize); + // This is an interesting test because LLSDNotationFormatter does not + // emit an llsd/notation header. + doRoundTripTests("LLSDNotationFormatter -> deserialize"); + }; + + template<> template<> + void TestLLSDSerializeObject::test<9>() + { + setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE), + new LLSDXMLParser()); + setParser(LLSDSerialize::deserialize); + // This is an interesting test because LLSDXMLFormatter does not + // emit an LLSD/XML header. + doRoundTripTests("LLSDXMLFormatter -> deserialize"); + }; + +/*==========================================================================*| + // We do not expect this test to succeed. Without a header, neither + // notation LLSD nor binary LLSD reliably start with a distinct character, + // the way XML LLSD starts with '<'. By convention, we default to notation + // rather than binary. + template<> template<> + void TestLLSDSerializeObject::test<10>() + { + setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE), + new LLSDBinaryParser()); + setParser(LLSDSerialize::deserialize); + // This is an interesting test because LLSDBinaryFormatter does not + // emit an LLSD/Binary header. + doRoundTripTests("LLSDBinaryFormatter -> deserialize"); + }; +|*==========================================================================*/ /** * @class TestLLSDParsing @@ -555,7 +654,7 @@ namespace tut public: TestLLSDXMLParsing() {} }; - + typedef tut::test_group TestLLSDXMLParsingGroup; typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject; TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing"); @@ -586,8 +685,8 @@ namespace tut LLSD(), LLSDParser::PARSE_FAILURE); } - - + + template<> template<> void TestLLSDXMLParsingObject::test<2>() { @@ -596,7 +695,7 @@ namespace tut v["amy"] = 23; v["bob"] = LLSD(); v["cam"] = 1.23; - + ensureParse( "unknown data type", "" @@ -607,16 +706,16 @@ namespace tut v, v.size() + 1); } - + template<> template<> void TestLLSDXMLParsingObject::test<3>() { // test handling of nested bad data - + LLSD v; v["amy"] = 23; v["cam"] = 1.23; - + ensureParse( "map with html", "" @@ -626,7 +725,7 @@ namespace tut "", v, v.size() + 1); - + v.clear(); v["amy"] = 23; v["cam"] = 1.23; @@ -639,7 +738,7 @@ namespace tut "", v, v.size() + 1); - + v.clear(); v["amy"] = 23; v["bob"] = LLSD::emptyMap(); @@ -661,7 +760,7 @@ namespace tut v[0] = 23; v[1] = LLSD(); v[2] = 1.23; - + ensureParse( "array value of html", "" @@ -671,7 +770,7 @@ namespace tut "", v, v.size() + 1); - + v.clear(); v[0] = 23; v[1] = LLSD::emptyMap(); @@ -1225,7 +1324,7 @@ namespace tut vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c'; vec[3] = '3'; vec[4] = '2'; vec[5] = '1'; LLSD value = vec; - + vec.resize(11); vec[0] = 'b'; // for binary vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c'; @@ -1694,85 +1793,83 @@ namespace tut ensureBinaryAndXML("map", test); } - struct TestPythonCompatible + // helper for TestPythonCompatible + static std::string import_llsd("import os.path\n" + "import sys\n" + "try:\n" + // new freestanding llsd package + " import llsd\n" + "except ImportError:\n" + // older llbase.llsd module + " from llbase import llsd\n"); + + // helper for TestPythonCompatible + template + void python(const std::string& desc, const CONTENT& script, int expect=0) { - TestPythonCompatible(): - // Note the peculiar insertion of __FILE__ into this string. Since - // this script is being written into a platform-dependent temp - // directory, we can't locate indra/lib/python relative to - // Python's __file__. Use __FILE__ instead, navigating relative - // to this C++ source file. Use Python raw-string syntax so - // Windows pathname backslashes won't mislead Python's string - // scanner. - import_llsd("import os.path\n" - "import sys\n" - "from llbase import llsd\n") - {} - ~TestPythonCompatible() {} + auto PYTHON(LLStringUtil::getenv("PYTHON")); + ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty()); - std::string import_llsd; - - template - void python(const std::string& desc, const CONTENT& script, int expect=0) - { - auto PYTHON(LLStringUtil::getenv("PYTHON")); - ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty()); - - NamedTempFile scriptfile("py", script); + NamedTempFile scriptfile("py", script); #if LL_WINDOWS - std::string q("\""); - std::string qPYTHON(q + PYTHON + q); - std::string qscript(q + scriptfile.getName() + q); - int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL); - if (rc == -1) - { - char buffer[256]; - strerror_s(buffer, errno); // C++ can infer the buffer size! :-O - ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false); - } - else - { - ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect); - } + std::string q("\""); + std::string qPYTHON(q + PYTHON + q); + std::string qscript(q + scriptfile.getName() + q); + int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL); + if (rc == -1) + { + char buffer[256]; + strerror_s(buffer, errno); // C++ can infer the buffer size! :-O + ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false); + } + else + { + ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect); + } #else // LL_DARWIN, LL_LINUX - LLProcess::Params params; - params.executable = PYTHON; - params.args.add(scriptfile.getName()); - LLProcessPtr py(LLProcess::create(params)); - ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py)); - // Implementing timeout would mean messing with alarm() and - // catching SIGALRM... later maybe... - int status(0); - if (waitpid(py->getProcessID(), &status, 0) == -1) + LLProcess::Params params; + params.executable = PYTHON; + params.args.add(scriptfile.getName()); + LLProcessPtr py(LLProcess::create(params)); + ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py)); + // Implementing timeout would mean messing with alarm() and + // catching SIGALRM... later maybe... + int status(0); + if (waitpid(py->getProcessID(), &status, 0) == -1) + { + int waitpid_errno(errno); + ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: " + "waitpid() errno " << waitpid_errno), + waitpid_errno, ECHILD); + } + else + { + if (WIFEXITED(status)) { - int waitpid_errno(errno); - ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: " - "waitpid() errno " << waitpid_errno), - waitpid_errno, ECHILD); + int rc(WEXITSTATUS(status)); + ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), + rc, expect); + } + else if (WIFSIGNALED(status)) + { + ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)), + false); } else { - if (WIFEXITED(status)) - { - int rc(WEXITSTATUS(status)); - ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), - rc, expect); - } - else if (WIFSIGNALED(status)) - { - ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)), - false); - } - else - { - ensure(STRINGIZE(desc << " script produced impossible status " << status), - false); - } + ensure(STRINGIZE(desc << " script produced impossible status " << status), + false); } -#endif } +#endif + } + + struct TestPythonCompatible + { + TestPythonCompatible() {} + ~TestPythonCompatible() {} }; typedef tut::test_group TestPythonCompatibleGroup; @@ -1798,25 +1895,33 @@ namespace tut "print('Running on', sys.platform)\n"); } - // helper for test<3> - static void writeLLSDArray(std::ostream& out, const LLSD& array) + // helper for test<3> - test<7> + static void writeLLSDArray(const FormatterFunction& serialize, + std::ostream& out, const LLSD& array) { - BOOST_FOREACH(LLSD item, llsd::inArray(array)) + for (const LLSD& item : llsd::inArray(array)) { - LLSDSerialize::toNotation(item, out); - // It's important to separate with newlines because Python's llsd - // module doesn't support parsing from a file stream, only from a - // string, so we have to know how much of the file to read into a - // string. - out << '\n'; + // It's important to delimit the entries in this file somehow + // because, although Python's llsd.parse() can accept a file + // stream, the XML parser expects EOF after a single outer element + // -- it doesn't just stop. So we must extract a sequence of bytes + // strings from the file. But since one of the serialization + // formats we want to test is binary, we can't pick any single + // byte value as a delimiter! Use a binary integer length prefix + // instead. + std::ostringstream buffer; + serialize(item, buffer); + auto buffstr{ buffer.str() }; + int bufflen{ static_cast(buffstr.length()) }; + out.write(reinterpret_cast(&bufflen), sizeof(bufflen)); + out.write(buffstr.c_str(), buffstr.length()); } } - template<> template<> - void TestPythonCompatibleObject::test<3>() + // helper for test<3> - test<7> + static void toPythonUsing(const std::string& desc, + const FormatterFunction& serialize) { - set_test_name("verify sequence to Python"); - LLSD cdata(llsd::array(17, 3.14, "This string\n" "has several\n" @@ -1836,7 +1941,7 @@ namespace tut " except StopIteration:\n" " pass\n" " else:\n" - " assert False, 'Too many data items'\n"; + " raise AssertionError('Too many data items')\n"; // Create an llsdXXXXXX file containing 'data' serialized to // notation. @@ -1845,32 +1950,128 @@ namespace tut // takes a callable. To this callable it passes the // std::ostream with which it's writing the // NamedTempFile. - boost::bind(writeLLSDArray, _1, cdata)); + [serialize, cdata] + (std::ostream& out) + { writeLLSDArray(serialize, out, cdata); }); - python("read C++ notation", + python("read C++ " + desc, placeholders::arg1 << import_llsd << - "def parse_each(iterable):\n" - " for item in iterable:\n" - " yield llsd.parse(item)\n" << - pydata << + "from functools import partial\n" + "import io\n" + "import struct\n" + "lenformat = struct.Struct('i')\n" + "def parse_each(inf):\n" + " for rawlen in iter(partial(inf.read, lenformat.size), b''):\n" + " len = lenformat.unpack(rawlen)[0]\n" + // Since llsd.parse() has no max_bytes argument, instead of + // passing the input stream directly to parse(), read the item + // into a distinct bytes object and parse that. + " data = inf.read(len)\n" + " try:\n" + " frombytes = llsd.parse(data)\n" + " except llsd.LLSDParseError as err:\n" + " print(f'*** {err}')\n" + " print(f'Bad content:\\n{data!r}')\n" + " raise\n" + // Also try parsing from a distinct stream. + " stream = io.BytesIO(data)\n" + " fromstream = llsd.parse(stream)\n" + " assert frombytes == fromstream\n" + " yield frombytes\n" + << pydata << // Don't forget raw-string syntax for Windows pathnames. "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n"); } + template<> template<> + void TestPythonCompatibleObject::test<3>() + { + set_test_name("to Python using LLSDSerialize::serialize(LLSD_XML)"); + toPythonUsing("LLSD_XML", + [](const LLSD& sd, std::ostream& out) + { LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_XML); }); + } + template<> template<> void TestPythonCompatibleObject::test<4>() { - set_test_name("verify sequence from Python"); + set_test_name("to Python using LLSDSerialize::serialize(LLSD_NOTATION)"); + toPythonUsing("LLSD_NOTATION", + [](const LLSD& sd, std::ostream& out) + { LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_NOTATION); }); + } + template<> template<> + void TestPythonCompatibleObject::test<5>() + { + set_test_name("to Python using LLSDSerialize::serialize(LLSD_BINARY)"); + toPythonUsing("LLSD_BINARY", + [](const LLSD& sd, std::ostream& out) + { LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_BINARY); }); + } + + template<> template<> + void TestPythonCompatibleObject::test<6>() + { + set_test_name("to Python using LLSDSerialize::toXML()"); + toPythonUsing("toXML()", LLSDSerialize::toXML); + } + + template<> template<> + void TestPythonCompatibleObject::test<7>() + { + set_test_name("to Python using LLSDSerialize::toNotation()"); + toPythonUsing("toNotation()", LLSDSerialize::toNotation); + } + +/*==========================================================================*| + template<> template<> + void TestPythonCompatibleObject::test<8>() + { + set_test_name("to Python using LLSDSerialize::toBinary()"); + // We don't expect this to work because, without a header, + // llsd.parse() will assume notation rather than binary. + toPythonUsing("toBinary()", LLSDSerialize::toBinary); + } +|*==========================================================================*/ + + // helper for test<8> - test<12> + bool itemFromStream(std::istream& istr, LLSD& item, const ParserFunction& parse) + { + // reset the output value for debugging clarity + item.clear(); + // We use an int length prefix as a foolproof delimiter even for + // binary serialized streams. + int length{ 0 }; + istr.read(reinterpret_cast(&length), sizeof(length)); +// return parse(istr, item, length); + // Sadly, as of 2022-12-01 it seems we can't really trust our LLSD + // parsers to honor max_bytes: this test works better when we read + // each item into its own distinct LLMemoryStream, instead of passing + // the original istr with a max_bytes constraint. + std::vector buffer(length); + istr.read(reinterpret_cast(buffer.data()), length); + LLMemoryStream stream(buffer.data(), length); + return parse(stream, item, length); + } + + // helper for test<8> - test<12> + void fromPythonUsing(const std::string& pyformatter, + const ParserFunction& parse= + [](std::istream& istr, LLSD& data, llssize max_bytes) + { return LLSDSerialize::deserialize(data, istr, max_bytes); }) + { // Create an empty data file. This is just a placeholder for our // script to write into. Create it to establish a unique name that // we know. NamedTempFile file("llsd", ""); - python("write Python notation", + python("Python " + pyformatter, placeholders::arg1 << import_llsd << + "import struct\n" + "lenformat = struct.Struct('i')\n" "DATA = [\n" " 17,\n" " 3.14,\n" @@ -1881,34 +2082,87 @@ namespace tut "]\n" // Don't forget raw-string syntax for Windows pathnames. // N.B. Using 'print' implicitly adds newlines. - "with open(r'" << file.getName() << "', 'w') as f:\n" + "with open(r'" << file.getName() << "', 'wb') as f:\n" " for item in DATA:\n" - " print(llsd.format_notation(item).decode(), file=f)\n"); + " serialized = llsd." << pyformatter << "(item)\n" + " f.write(lenformat.pack(len(serialized)))\n" + " f.write(serialized)\n"); std::ifstream inf(file.getName().c_str()); LLSD item; - // Notice that we're not doing anything special to parse out the - // newlines: LLSDSerialize::fromNotation ignores them. While it would - // seem they're not strictly necessary, going in this direction, we - // want to ensure that notation-separated-by-newlines works in both - // directions -- since in practice, a given file might be read by - // either language. - ensure_equals("Failed to read LLSD::Integer from Python", - LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED), - 1); - ensure_equals(item.asInteger(), 17); - ensure_equals("Failed to read LLSD::Real from Python", - LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED), - 1); - ensure_approximately_equals("Bad LLSD::Real value from Python", - item.asReal(), 3.14, 7); // 7 bits ~= 0.01 - ensure_equals("Failed to read LLSD::String from Python", - LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED), - 1); - ensure_equals(item.asString(), - "This string\n" - "has several\n" - "lines."); - + try + { + ensure("Failed to read LLSD::Integer from Python", + itemFromStream(inf, item, parse)); + ensure_equals(item.asInteger(), 17); + ensure("Failed to read LLSD::Real from Python", + itemFromStream(inf, item, parse)); + ensure_approximately_equals("Bad LLSD::Real value from Python", + item.asReal(), 3.14, 7); // 7 bits ~= 0.01 + ensure("Failed to read LLSD::String from Python", + itemFromStream(inf, item, parse)); + ensure_equals(item.asString(), + "This string\n" + "has several\n" + "lines."); + } + catch (const tut::failure& err) + { + std::cout << "for " << err.what() << ", item = " << item << std::endl; + throw; + } } + + template<> template<> + void TestPythonCompatibleObject::test<8>() + { + set_test_name("from Python XML using LLSDSerialize::deserialize()"); + fromPythonUsing("format_xml"); + } + + template<> template<> + void TestPythonCompatibleObject::test<9>() + { + set_test_name("from Python notation using LLSDSerialize::deserialize()"); + fromPythonUsing("format_notation"); + } + + template<> template<> + void TestPythonCompatibleObject::test<10>() + { + set_test_name("from Python binary using LLSDSerialize::deserialize()"); + fromPythonUsing("format_binary"); + } + + template<> template<> + void TestPythonCompatibleObject::test<11>() + { + set_test_name("from Python XML using fromXML()"); + // fromXML()'s optional 3rd param isn't max_bytes, it's emit_errors + fromPythonUsing("format_xml", + [](std::istream& istr, LLSD& data, llssize) + { return LLSDSerialize::fromXML(data, istr) > 0; }); + } + + template<> template<> + void TestPythonCompatibleObject::test<12>() + { + set_test_name("from Python notation using fromNotation()"); + fromPythonUsing("format_notation", + [](std::istream& istr, LLSD& data, llssize max_bytes) + { return LLSDSerialize::fromNotation(data, istr, max_bytes) > 0; }); + } + +/*==========================================================================*| + template<> template<> + void TestPythonCompatibleObject::test<13>() + { + set_test_name("from Python binary using fromBinary()"); + // We don't expect this to work because format_binary() emits a + // header, but fromBinary() won't recognize a header. + fromPythonUsing("format_binary", + [](std::istream& istr, LLSD& data, llssize max_bytes) + { return LLSDSerialize::fromBinary(data, istr, max_bytes) > 0; }); + } +|*==========================================================================*/ } diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py index 185e8e25c6..b9992538ba 100755 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py @@ -38,7 +38,7 @@ from io import StringIO from http.server import HTTPServer, BaseHTTPRequestHandler -from llbase import llsd +import llsd # we're in llcorehttp/tests ; testrunner.py is found in llmessage/tests sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index f823f1b845..adadb29286 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -1336,5 +1336,47 @@ void HttpCoroutineAdapter::trivialPostCoro(std::string url, LLCore::HttpRequest: } +/*static*/ +void HttpCoroutineAdapter::callbackHttpDel(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, + completionCallback_t failure) +{ + LLCoros::instance().launch("HttpCoroutineAdapter::genericDelCoro", + boost::bind(&HttpCoroutineAdapter::trivialDelCoro, url, policyId, success, failure)); +} + +/*static*/ +void HttpCoroutineAdapter::trivialDelCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, + completionCallback_t failure) +{ + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericDelCoro", policyId)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + + httpOpts->setWantHeaders(true); + + LL_INFOS("HttpCoroutineAdapter", "genericDelCoro") << "Generic DEL for " << url << LL_ENDL; + + LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + if (failure) + { + failure(httpResults); + } + } + else + { + if (success) + { + success(result); + } + } +} + + } // end namespace LLCoreHttpUtil diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 6f0b865f83..8df1425f2a 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -608,6 +608,9 @@ public: callbackHttpPost(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, postData, success, failure); } + static void callbackHttpDel(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success = NULL, + completionCallback_t failure = NULL); + /// Generic Get and post routines for HTTP via coroutines. /// These static methods do all required setup for the GET or POST operation. /// When the operation completes successfully they will put the success message in the log at INFO level, @@ -669,6 +672,7 @@ private: static void trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure); static void trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure); + static void trivialDelCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure); void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers); diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index 8548ed51e7..703bf08345 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -171,8 +171,11 @@ const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9; const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10; const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11; -const S32 ESTATE_MAX_MANAGERS = 15; -const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access, banned +const S32 ESTATE_MAX_MANAGERS = 20; +const S32 ESTATE_MAX_MANAGERS_OS = 15; // OpenSim +const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access +const S32 ESTATE_MAX_BANNED_IDS = 750; // max for banned +const S32 ESTATE_MAX_BANNED_IDS_OS = 500; // max for banned // OpenSim const S32 ESTATE_MAX_GROUP_IDS = (S32) ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET; // 'Sim Wide Delete' flags diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index 5ba0749e31..8e9b6c09e7 100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -33,8 +33,8 @@ import os import sys from http.server import HTTPServer, BaseHTTPRequestHandler -from llbase.fastest_elementtree import parse as xml_parse -from llbase import llsd +from llsd.fastest_elementtree import parse as xml_parse +import llsd from testrunner import freeport, run, debug, VERBOSE import time diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index ee663f8f99..c66e3e30a3 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -66,6 +66,14 @@ public: static const LLMaterialID null; + // Returns a 64 bits digest of the material Id, by XORing its two 64 bits + // long words. HB + inline U64 getDigest64() const + { + U64* tmp = (U64*)mID; + return tmp[0] ^ tmp[1]; + } + private: void parseFromBinary(const LLSD::Binary& pMaterialID); void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID); @@ -74,5 +82,23 @@ private: U8 mID[MATERIAL_ID_SIZE]; } ; +// std::hash implementation for LLMaterialID +namespace std +{ + template<> struct hash + { + inline size_t operator()(const LLMaterialID& id) const noexcept + { + return (size_t)id.getDigest64(); + } + }; +} + +// For use with boost containers. +inline size_t hash_value(const LLMaterialID& id) noexcept +{ + return (size_t)id.getDigest64(); +} + #endif // LL_LLMATERIALID_H diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index d0321156eb..1b06ff85c8 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -69,6 +69,7 @@ LLDragHandle::LLDragHandle(const LLDragHandle::Params& p) LLDragHandle::~LLDragHandle() { + gFocusMgr.removeKeyboardFocusWithoutCallback(this); removeChild(mTitleBox); delete mTitleBox; } diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 637153426a..d48c662f5c 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -196,6 +196,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) LLFolderViewItem::~LLFolderViewItem() { mViewModelItem = NULL; + gFocusMgr.removeKeyboardFocusWithoutCallback(this); } BOOL LLFolderViewItem::postBuild() diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index bb0f4440c9..67bab51bfd 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -89,6 +89,8 @@ LLLayoutPanel::~LLLayoutPanel() // probably not necessary, but... delete mResizeBar; mResizeBar = NULL; + + gFocusMgr.removeKeyboardFocusWithoutCallback(this); } F32 LLLayoutPanel::getAutoResizeFactor() const diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index 24794305ac..13ef0fdb7f 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -70,6 +70,11 @@ LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p) } } +LLResizeHandle::~LLResizeHandle() +{ + gFocusMgr.removeKeyboardFocusWithoutCallback(this); +} + BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask) { diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h index 7541b9e6c0..ae20ecaa77 100644 --- a/indra/llui/llresizehandle.h +++ b/indra/llui/llresizehandle.h @@ -45,6 +45,7 @@ public: Params(); }; + ~LLResizeHandle(); protected: LLResizeHandle(const LLResizeHandle::Params&); friend class LLUICtrlFactory; diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 98801643c1..fe6f5bd945 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -908,6 +908,7 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require continue; } + // Got an item. Load it up. // If not declared, assume it's a string if (!declared) { diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index e9d5f8c17f..b69c12176f 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.14 +6.6.15 diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 7edb17e913..d61d26a995 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -240,6 +240,12 @@ NoAudio + nofmod + + map-to + UseMediaPluginsForStreamingAudio + + noninteractive desc diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f75feff13a..e40e03665a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9904,6 +9904,17 @@ Backup 0 + UseMediaPluginsForStreamingAudio + + Comment + Use media plugins (VLC) for streaming audio. + Persist + 1 + Type + Boolean + Value + 0 + NoHardwareProbe Comment @@ -14555,11 +14566,11 @@ Change of this parameter will affect the layout of buttons in notification toast ShowBanLines Comment - Show in-world ban/access borders + Show in-world ban/access borders, 0 - do not show, 1 - show on collision, 2 - show on proximity Persist 1 Type - Boolean + S32 Value 1 @@ -22265,17 +22276,6 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 - 360CaptureUseInterestListCap - - Comment - Flag if set, uses the new InterestList cap to ask the simulator for full content - Persist - 1 - Type - Boolean - Value - 1 - 360CaptureJPEGEncodeQuality Comment @@ -23680,6 +23680,39 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 + StatsReportMaxDuration + + Comment + Maximum seconds for viewer stats file data, prevents huge file + Persist + 1 + Type + F32 + Value + 300 + + StatsReportFileInterval + + Comment + Interval to save viewer stats file data + Persist + 1 + Type + F32 + Value + 0.2 + + StatsReportSkipZeroDataSaves + + Comment + In viewer stats data file, skip saving entry if there is no data + Persist + 0 + Type + Boolean + Value + 0 + FSNetMapPhantomOpacity Comment @@ -26405,5 +26438,16 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 + FSSortAttachmentSpotsAlphabetically + + Comment + Sorts the attachment spots in the "Attach to" menus alphabetically + Persist + 1 + Type + Boolean + Value + 1 + diff --git a/indra/newview/fsareasearch.cpp b/indra/newview/fsareasearch.cpp index 1e76d27428..b81a20454f 100644 --- a/indra/newview/fsareasearch.cpp +++ b/indra/newview/fsareasearch.cpp @@ -174,11 +174,6 @@ FSAreaSearch::FSAreaSearch(const LLSD& key) : mRlvBehaviorCallbackConnection() { LLViewerRegion::sFSAreaSearchActive = true; - if( LLViewerRegion* region = gAgent.getRegion() ) - { - checkRegion(); - } - mFactoryMap["area_search_list_panel"] = LLCallbackMap(createPanelList, this); mFactoryMap["area_search_find_panel"] = LLCallbackMap(createPanelFind, this); mFactoryMap["area_search_filter_panel"] = LLCallbackMap(createPanelFilter, this); @@ -190,24 +185,11 @@ FSAreaSearch::FSAreaSearch(const LLSD& key) : mParcelChangedObserver = std::make_unique(this); LLViewerParcelMgr::getInstance()->addObserver(mParcelChangedObserver.get()); - mRegionChangeConnection = gAgent.addRegionChangedCallback(boost::bind(&FSAreaSearch::checkRegion, this)); } FSAreaSearch::~FSAreaSearch() { LLViewerRegion::sFSAreaSearchActive = false; - - // Tell the Simulator not to send us everything anymore - // and revert to the regular "keyhole" frustum of interest - // list updates. - if( !LLApp::isExiting() ) - { - if( LLViewerRegion* region = gAgent.getRegion() ) - { - region->useFullUpdateInterestListMode(false); - } - } - if (!gIdleCallbacks.deleteFunction(idle, this)) { LL_WARNS("FSAreaSearch") << "FSAreaSearch::~FSAreaSearch() failed to delete callback" << LL_ENDL; @@ -232,11 +214,6 @@ FSAreaSearch::~FSAreaSearch() LLViewerParcelMgr::getInstance()->removeObserver(mParcelChangedObserver.get()); mParcelChangedObserver = nullptr; } - - if (mRegionChangeConnection.connected()) - { - mRegionChangeConnection.disconnect(); - } } BOOL FSAreaSearch::postBuild() @@ -343,28 +320,24 @@ void FSAreaSearch::updateRlvRestrictions(ERlvBehaviour behavior) void FSAreaSearch::checkRegion() { - static LLUUID last_region_id = LLUUID::null; - auto last_region = LLWorld::instance().getRegionFromID(last_region_id); - // Check if we changed region, if so reset the interest list to full, - LLViewerRegion* region = gAgent.getRegion(); - if( region && (region != last_region) ) - { - region->useFullUpdateInterestListMode(true, true); // we force this because we want a true count - if ( mActive ) + if (mActive) + { + // Check if we changed region, and if we did, clear the object details cache. + if (LLViewerRegion* region = gAgent.getRegion(); region && (region != mLastRegion)) { - // and if we did and are active, clear the object details cache. - if( !mExcludeNeighborRegions ) + if (!mExcludeNeighborRegions) { std::vector uniqueRegions; region->getNeighboringRegions(uniqueRegions); - if( std::find( uniqueRegions.begin(), uniqueRegions.end(), last_region ) != uniqueRegions.end() ) + if (std::find(uniqueRegions.begin(), uniqueRegions.end(), mLastRegion) != uniqueRegions.end()) { // Crossed into a neighboring region, no need to clear everything. - last_region_id = region->getRegionID(); + mLastRegion = region; return; } // else teleported into a new region } + mLastRegion = region; mRequested = 0; mObjectDetails.clear(); mRegionRequests.clear(); @@ -374,14 +347,7 @@ void FSAreaSearch::checkRegion() mPanelList->setAgentLastPosition(gAgent.getPositionGlobal()); mRefresh = true; } - if( last_region ) - { - // we clear the old region status, because the instance may persist for us - // but the region itself will have reset when we left. - last_region->clearFullUpdateInterestList(); - } } - last_region_id = region->getRegionID(); } void FSAreaSearch::refreshList(bool cache_clear) diff --git a/indra/newview/fsareasearch.h b/indra/newview/fsareasearch.h index b7dc2be0f3..95939f17d7 100644 --- a/indra/newview/fsareasearch.h +++ b/indra/newview/fsareasearch.h @@ -213,8 +213,7 @@ private: typedef std::map name_cache_connection_map_t; name_cache_connection_map_t mNameCacheConnections; - boost::signals2::connection mRegionChangeConnection; // reset interest list verbosity after TP - + LLViewerRegion* mLastRegion; class FSParcelChangeObserver; friend class FSParcelChangeObserver; diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp index 8da9593e06..94bb977703 100644 --- a/indra/newview/fschathistory.cpp +++ b/indra/newview/fschathistory.cpp @@ -96,7 +96,7 @@ public: // requests will be throttled from a non-trusted browser LLObjectIMHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params.size() < 1) { diff --git a/indra/newview/fsfloaterposestand.cpp b/indra/newview/fsfloaterposestand.cpp index 47e0d2f60b..f44e30c166 100644 --- a/indra/newview/fsfloaterposestand.cpp +++ b/indra/newview/fsfloaterposestand.cpp @@ -23,7 +23,7 @@ FSFloaterPoseStand::FSFloaterPoseStand(const LLSD& key) : LLFloater(key), - mComboPose(NULL), + mComboPose(nullptr), mPoseStandLock(false), mAOPaused(false) { diff --git a/indra/newview/fsfloaterradar.cpp b/indra/newview/fsfloaterradar.cpp index ad6d8b6625..b7cbb85a14 100644 --- a/indra/newview/fsfloaterradar.cpp +++ b/indra/newview/fsfloaterradar.cpp @@ -30,7 +30,7 @@ FSFloaterRadar::FSFloaterRadar(const LLSD& key) : LLFloater(key), - mRadarPanel(NULL) + mRadarPanel(nullptr) { } diff --git a/indra/newview/fsfloaterwearablefavorites.cpp b/indra/newview/fsfloaterwearablefavorites.cpp index bbb1f50751..4fa8dd5927 100644 --- a/indra/newview/fsfloaterwearablefavorites.cpp +++ b/indra/newview/fsfloaterwearablefavorites.cpp @@ -135,8 +135,7 @@ BOOL FSFloaterWearableFavorites::postBuild() mOptionsButton = getChild("options_btn"); - LLToggleableMenu* options_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_fs_wearable_favorites.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (options_menu) + if (LLToggleableMenu* options_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_fs_wearable_favorites.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); options_menu) { mOptionsMenuHandle = options_menu->getHandle(); mOptionsButton->setMenu(options_menu, LLMenuButton::MP_BOTTOM_LEFT); @@ -204,8 +203,7 @@ BOOL FSFloaterWearableFavorites::handleKeyHere(KEY key, MASK mask) // static std::optional FSFloaterWearableFavorites::getWearableFavoritesFolderID() { - LLUUID fs_root_cat_id = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER); - if (!fs_root_cat_id.isNull()) + if (LLUUID fs_root_cat_id = gInventory.findCategoryByName(ROOT_FIRESTORM_FOLDER); !fs_root_cat_id.isNull()) { LLInventoryModel::item_array_t* items; LLInventoryModel::cat_array_t* cats; @@ -339,8 +337,7 @@ bool FSFloaterWearableFavorites::onOptionsMenuItemChecked(const LLSD& userdata) void FSFloaterWearableFavorites::onDoubleClick() { - LLUUID selected_item_id = mItemsList->getSelectedUUID(); - if (selected_item_id.notNull()) + if (LLUUID selected_item_id = mItemsList->getSelectedUUID(); selected_item_id.notNull()) { uuid_vec_t ids; ids.push_back(selected_item_id); diff --git a/indra/newview/fsgridhandler.cpp b/indra/newview/fsgridhandler.cpp index 8e97d8c519..539acc2b63 100644 --- a/indra/newview/fsgridhandler.cpp +++ b/indra/newview/fsgridhandler.cpp @@ -1437,7 +1437,7 @@ public: } } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params.size() < 2) { diff --git a/indra/newview/fskeywords.cpp b/indra/newview/fskeywords.cpp index 88269625cf..b015ef39a4 100644 --- a/indra/newview/fskeywords.cpp +++ b/indra/newview/fskeywords.cpp @@ -120,9 +120,9 @@ bool FSKeywords::chatContainsKeyword(const LLChat& chat, bool is_local) if (sFSKeywordMatchWholeWords) { - for (std::vector::iterator it = mWordList.begin(); it != mWordList.end(); ++it) + for (const auto& word : mWordList) { - if (boost::regex_search(source, boost::regex("\\b" + (*it) + "\\b"))) + if (boost::regex_search(source, boost::regex("\\b" + word + "\\b"))) { return true; } @@ -130,9 +130,9 @@ bool FSKeywords::chatContainsKeyword(const LLChat& chat, bool is_local) } else { - for (std::vector::iterator it = mWordList.begin(); it != mWordList.end(); ++it) + for (const auto& word : mWordList) { - if (source.find((*it)) != std::string::npos) + if (source.find(word) != std::string::npos) { return true; } @@ -145,30 +145,27 @@ bool FSKeywords::chatContainsKeyword(const LLChat& chat, bool is_local) // FIRE-10178: Keyword Alerts in group IM do not work unless the group is in the foreground void FSKeywords::notify(const LLChat& chat) { - if (chat.mFromID != gAgentID || chat.mFromName == SYSTEM_FROM) + if ((chat.mFromID != gAgentID || chat.mFromName == SYSTEM_FROM) && !chat.mMuted && !LLMuteList::getInstance()->isMuted(chat.mFromID)) { - if (!chat.mMuted && !LLMuteList::getInstance()->isMuted(chat.mFromID)) + static LLCachedControl PlayModeUISndFSKeywordSound(gSavedPerAccountSettings, "PlayModeUISndFSKeywordSound"); + if (PlayModeUISndFSKeywordSound) { - static LLCachedControl PlayModeUISndFSKeywordSound(gSavedPerAccountSettings, "PlayModeUISndFSKeywordSound"); - if (PlayModeUISndFSKeywordSound) - { - LLUI::getInstance()->mAudioCallback(LLUUID(gSavedPerAccountSettings.getString("UISndFSKeywordSound"))); - } + LLUI::getInstance()->mAudioCallback(LLUUID(gSavedPerAccountSettings.getString("UISndFSKeywordSound"))); + } - static LLCachedControl FSEnableGrowl(gSavedSettings, "FSEnableGrowl"); - if (FSEnableGrowl) + static LLCachedControl FSEnableGrowl(gSavedSettings, "FSEnableGrowl"); + if (FSEnableGrowl) + { + std::string msg = chat.mFromName; + if (is_irc_me_prefix(chat.mText)) { - std::string msg = chat.mFromName; - if (is_irc_me_prefix(chat.mText)) - { - msg = msg + chat.mText.substr(3); - } - else - { - msg = msg + ": " + chat.mText; - } - GrowlManager::notify("Keyword Alert", msg, GROWL_KEYWORD_ALERT_TYPE); + msg = msg + chat.mText.substr(3); } + else + { + msg = msg + ": " + chat.mText; + } + GrowlManager::notify("Keyword Alert", msg, GROWL_KEYWORD_ALERT_TYPE); } } } diff --git a/indra/newview/fsmoneytracker.cpp b/indra/newview/fsmoneytracker.cpp index 54c36342fc..ae0aca659e 100644 --- a/indra/newview/fsmoneytracker.cpp +++ b/indra/newview/fsmoneytracker.cpp @@ -148,16 +148,13 @@ void FSMoneyTrackerListMenu::onContextMenuItemClick(const LLSD& userdata) if (option == "copy") { - FSMoneyTracker* floater = LLFloaterReg::findTypedInstance("money_tracker"); - if (floater) + if (FSMoneyTracker* floater = LLFloaterReg::findTypedInstance("money_tracker"); floater) { std::string copy_text; LLNameListCtrl* list = floater->getChild("payment_list"); - std::vector selected = list->getAllSelected(); - for (std::vector::iterator it = selected.begin(); it != selected.end(); ++it) + for (auto item : list->getAllSelected()) { - const LLScrollListItem* item = *it; copy_text += ( (copy_text.empty() ? "" : "\n") + item->getColumn(0)->getValue().asString() + ";" + item->getColumn(1)->getValue().asString() + ";" diff --git a/indra/newview/fsnearbychathub.cpp b/indra/newview/fsnearbychathub.cpp index 31f0567772..e607f503d5 100644 --- a/indra/newview/fsnearbychathub.cpp +++ b/indra/newview/fsnearbychathub.cpp @@ -48,10 +48,10 @@ #include "rlvactions.h" #include "rlvhandler.h" -static const U32 NAME_PREDICTION_MINIMUM_LENGTH = 3; +constexpr U32 NAME_PREDICTION_MINIMUM_LENGTH = 3; // *HACK* chat bar cannot return its correct height for some reason -static const S32 MAGIC_CHAT_BAR_PAD = 5; +constexpr S32 MAGIC_CHAT_BAR_PAD = 5; struct LLChatTypeTrigger { std::string name; @@ -237,8 +237,8 @@ bool matchChatTypeTrigger(const std::string& in_str, std::string* out_str) S32 FSNearbyChat::sLastSpecialChatChannel = 0; FSNearbyChat::FSNearbyChat() : - mDefaultChatBar(NULL), - mFocusedInputEditor(NULL) + mDefaultChatBar(nullptr), + mFocusedInputEditor(nullptr) { gSavedSettings.getControl("MainChatbarVisible")->getSignal()->connect(boost::bind(&FSNearbyChat::onDefaultChatBarButtonClicked, this)); } @@ -847,7 +847,7 @@ public: LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_THROTTLE) { } // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { bool retval = false; diff --git a/indra/newview/fspanelblocklist.cpp b/indra/newview/fspanelblocklist.cpp index cb45a75384..486532f7ee 100644 --- a/indra/newview/fspanelblocklist.cpp +++ b/indra/newview/fspanelblocklist.cpp @@ -132,12 +132,11 @@ BOOL FSPanelBlockList::handleKeyHere(KEY key, MASK mask) void FSPanelBlockList::selectBlocked(const LLUUID& mute_id) { mBlockedList->deselectAllItems(); - std::vector items = mBlockedList->getAllData(); - for (std::vector::iterator it = items.begin(); it != items.end(); it++) + for (auto item : mBlockedList->getAllData()) { - if ((*it)->getColumn(3)->getValue().asUUID() == mute_id) + if (item->getColumn(3)->getValue().asUUID() == mute_id) { - (*it)->setSelected(TRUE); + item->setSelected(TRUE); break; } } @@ -171,17 +170,15 @@ void FSPanelBlockList::refreshBlockedList() { mBlockedList->deleteAllItems(); - std::vector mutes = LLMuteList::getInstance()->getMutes(); - std::vector::iterator it; - for (it = mutes.begin(); it != mutes.end(); ++it) + for (const auto& mute : LLMuteList::getInstance()->getMutes()) { LLScrollListItem::Params item_p; - item_p.enabled(TRUE); + item_p.enabled(true); item_p.value(LLUUID::generateNewID()); // can't link UUID of blocked item directly because of mutes by name - item_p.columns.add().column("item_name").value(it->mName); - item_p.columns.add().column("item_type").value(it->getDisplayType()); - item_p.columns.add().column("item_mute_type").value(it->mType); - item_p.columns.add().column("item_mute_uuid").value(it->mID); + item_p.columns.add().column("item_name").value(mute.mName); + item_p.columns.add().column("item_type").value(mute.getDisplayType()); + item_p.columns.add().column("item_mute_type").value(mute.mType); + item_p.columns.add().column("item_mute_uuid").value(mute.mID); mBlockedList->addRow(item_p, ADD_BOTTOM); } @@ -208,11 +205,10 @@ void FSPanelBlockList::removeMutes() // list after each removal, sending us straight into a crash! LLMuteList::getInstance()->removeObserver(this); - std::vector selected_items = mBlockedList->getAllSelected(); - for (std::vector::iterator it = selected_items.begin(); it != selected_items.end(); it++) + for (auto item : mBlockedList->getAllSelected()) { - std::string name = (*it)->getColumn(COL_NAME)->getValue().asString(); - LLUUID id = (*it)->getColumn(COL_UUID)->getValue().asUUID(); + std::string name = item->getColumn(COL_NAME)->getValue().asString(); + LLUUID id = item->getColumn(COL_UUID)->getValue().asUUID(); LLMute mute(id, name); LLMuteList::getInstance()->remove(mute); } diff --git a/indra/newview/fspanellogin.cpp b/indra/newview/fspanellogin.cpp index 0b6802a406..4972c0fe38 100644 --- a/indra/newview/fspanellogin.cpp +++ b/indra/newview/fspanellogin.cpp @@ -95,7 +95,7 @@ class LLLoginLocationAutoHandler : public LLCommandHandler public: // don't allow from external browsers LLLoginLocationAutoHandler() : LLCommandHandler("location_login", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) { diff --git a/indra/newview/fspanelradar.cpp b/indra/newview/fspanelradar.cpp index b0eb1e168d..65b21e77fc 100644 --- a/indra/newview/fspanelradar.cpp +++ b/indra/newview/fspanelradar.cpp @@ -89,7 +89,7 @@ FSPanelRadar::FSPanelRadar() mFSRadarColumnConfigConnection(), mLastResizeDelta(0) { - mButtonsUpdater = new FSButtonsUpdater(boost::bind(&FSPanelRadar::updateButtons, this)); + mButtonsUpdater = std::make_unique(boost::bind(&FSPanelRadar::updateButtons, this)); mCommitCallbackRegistrar.add("Radar.AddFriend", boost::bind(&FSPanelRadar::onAddFriendButtonClicked, this)); mCommitCallbackRegistrar.add("Radar.Gear", boost::bind(&FSPanelRadar::onGearButtonClicked, this, _1)); @@ -117,9 +117,8 @@ FSPanelRadar::~FSPanelRadar() mFSRadarColumnConfigConnection.disconnect(); } - delete mButtonsUpdater; - - if (mOptionsMenuHandle.get()) mOptionsMenuHandle.get()->die(); + if (mOptionsMenuHandle.get()) + mOptionsMenuHandle.get()->die(); } BOOL FSPanelRadar::postBuild() @@ -152,8 +151,7 @@ BOOL FSPanelRadar::postBuild() mRadarGearButton = getChild("gear_btn"); mOptionsButton = getChild("options_btn"); - LLToggleableMenu* options_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_fs_radar_options.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (options_menu) + if (LLToggleableMenu* options_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_fs_radar_options.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); options_menu) { mOptionsMenuHandle = options_menu->getHandle(); mOptionsButton->setMenu(options_menu, LLMenuButton::MP_BOTTOM_LEFT); @@ -204,8 +202,7 @@ void FSPanelRadar::updateButtons() LLUUID FSPanelRadar::getCurrentItemID() const { - LLScrollListItem* item = mRadarList->getFirstSelected(); - if (item) + if (LLScrollListItem* item = mRadarList->getFirstSelected(); item) { return item->getUUID(); } @@ -251,21 +248,14 @@ void FSPanelRadar::onRadarListDoubleClicked() LLUUID clicked_id = item->getUUID(); std::string name = item->getColumn(mRadarList->getColumn("name")->mIndex)->getValue().asString(); - FSRadar* radar = FSRadar::getInstance(); - if (radar) - { - radar->zoomAvatar(clicked_id, name); - } + FSRadar::getInstance()->zoomAvatar(clicked_id, name); } void FSPanelRadar::onRadarListCommitted() { - uuid_vec_t selected_uuids; - LLUUID sVal = mRadarList->getSelectedValue().asUUID(); - if (sVal.notNull()) + if (LLUUID sVal = mRadarList->getSelectedValue().asUUID(); sVal.notNull()) { - selected_uuids.push_back(sVal); - mMiniMap->setSelected(selected_uuids); + mMiniMap->setSelected({ sVal }); } updateButtons(); @@ -274,8 +264,7 @@ void FSPanelRadar::onRadarListCommitted() void FSPanelRadar::onAddFriendButtonClicked() { - LLUUID id = getCurrentItemID(); - if (id.notNull()) + if (LLUUID id = getCurrentItemID(); id.notNull()) { LLAvatarActions::requestFriendshipDialog(id); } @@ -301,14 +290,10 @@ void FSPanelRadar::onGearButtonClicked(LLUICtrl* btn) void FSPanelRadar::requestUpdate() { - FSRadar* radar = FSRadar::getInstance(); - if (radar) - { - std::vector entries; - LLSD stats; - radar->getCurrentData(entries, stats); - updateList(entries, stats); - } + std::vector entries; + LLSD stats; + FSRadar::getInstance()->getCurrentData(entries, stats); + updateList(entries, stats); } void FSPanelRadar::updateList(const std::vector& entries, const LLSD& stats) @@ -422,21 +407,21 @@ void FSPanelRadar::updateList(const std::vector& entries, const LLSD& stat radarNameCell->setColor(LLColor4(options["name_color"])); } - LLScrollListText* voiceLevelCell = (LLScrollListText*)row->getColumn(voiceLevelColumnIndex); if (entry.has("voice_level_icon")) { + LLScrollListText* voiceLevelCell = (LLScrollListText*)row->getColumn(voiceLevelColumnIndex); voiceLevelCell->setValue(entry["voice_level_icon"].asString()); } - LLScrollListText* flagsCell = (LLScrollListText*)row->getColumn(flagsColumnIndex); if (entry.has("flags")) { + LLScrollListText* flagsCell = (LLScrollListText*)row->getColumn(flagsColumnIndex); flagsCell->setValue(flagsColumnValues[entry["flags"].asInteger()]); } - LLScrollListText* ageCell = (LLScrollListText*)row->getColumn(ageColumnIndex); if (options.has("age_color")) { + LLScrollListText* ageCell = (LLScrollListText*)row->getColumn(ageColumnIndex); ageCell->setColor(LLColor4(options["age_color"])); } } @@ -477,7 +462,7 @@ void FSPanelRadar::onColumnDisplayModeChanged() std::vector column_params = mRadarList->getColumnInitParams(); S32 column_padding = mRadarList->getColumnPadding(); - LLFloater* parent_floater = nullptr; + LLFloater* parent_floater{ nullptr }; LLView* parent = getParent(); while (parent) { @@ -493,8 +478,8 @@ void FSPanelRadar::onColumnDisplayModeChanged() return; } - S32 default_width = 0; - S32 new_width = 0; + S32 default_width{ 0 }; + S32 new_width{ 0 }; S32 min_width, min_height; parent_floater->getResizeLimits(&min_width, &min_height); @@ -558,8 +543,7 @@ void FSPanelRadar::onColumnVisibilityChecked(const LLSD& userdata) U32 column_config = gSavedSettings.getU32("FSRadarColumnConfig"); U32 new_value; - U32 enabled = (mColumnBits[column] & column_config); - if (enabled) + if (U32 enabled = (mColumnBits[column] & column_config); enabled) { new_value = (column_config & ~mColumnBits[column]); } diff --git a/indra/newview/fspanelradar.h b/indra/newview/fspanelradar.h index 06550237cc..ecea395e85 100644 --- a/indra/newview/fspanelradar.h +++ b/indra/newview/fspanelradar.h @@ -92,7 +92,7 @@ private: LLHandle mOptionsMenuHandle; - FSRadar::Updater* mButtonsUpdater; + std::unique_ptr mButtonsUpdater; std::string mFilterSubString; std::string mFilterSubStringOrig; diff --git a/indra/newview/fsradar.cpp b/indra/newview/fsradar.cpp index db3be003ca..607ccff3f8 100644 --- a/indra/newview/fsradar.cpp +++ b/indra/newview/fsradar.cpp @@ -290,14 +290,13 @@ void FSRadar::updateRadarList() // Skip modelling this avatar if its basic data is either inaccessible, or it's a dummy placeholder auto ent = getEntry(avId); - LLViewerRegion* reg = world->getRegionFromPosGlobal(avPos); if (!ent) // don't update this radar listing if data is inaccessible { continue; } // Try to get the avatar's viewer object - we will need it anyway later - LLVOAvatar* avVo = (LLVOAvatar*)gObjectList.findObject(avId); + LLVOAvatar* avVo = static_cast(gObjectList.findObject(avId)); static LLUICachedControl sFSShowDummyAVsinRadar("FSShowDummyAVsinRadar"); if (!sFSShowDummyAVsinRadar && avVo && avVo->mIsDummy) @@ -315,7 +314,7 @@ void FSRadar::updateRadarList() } LLUUID avRegion; - if (reg) + if (LLViewerRegion* reg = world->getRegionFromPosGlobal(avPos); reg) { avRegion = reg->getRegionID(); } @@ -595,11 +594,10 @@ void FSRadar::updateRadarList() // Voice power level indicator if (voice_client->voiceEnabled() && voice_client->isVoiceWorking()) { - LLSpeaker* speaker = speakermgr->findSpeaker(avId); - if (speaker && speaker->isInVoiceChannel()) + if (LLSpeaker* speaker = speakermgr->findSpeaker(avId); speaker && speaker->isInVoiceChannel()) { EVoicePowerLevel power_level = voice_client->getPowerLevel(avId); - + switch (power_level) { case VPL_PTT_Off: @@ -703,8 +701,7 @@ void FSRadar::updateRadarList() } static LLCachedControl sRadarAlertChannel(gSavedSettings, "RadarAlertChannel"); - U32 num_entering = (U32)mRadarEnterAlerts.size(); - if (num_entering > 0) + if (U32 num_entering = (U32)mRadarEnterAlerts.size(); num_entering > 0) { mRadarFrameCount++; U32 num_this_pass = llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_entering); @@ -732,8 +729,8 @@ void FSRadar::updateRadarList() msg = llformat("%d,%d", mRadarFrameCount, num_this_pass); } } - U32 num_leaving = (U32)mRadarLeaveAlerts.size(); - if (num_leaving > 0) + + if (U32 num_leaving = (U32)mRadarLeaveAlerts.size(); num_leaving > 0) { mRadarFrameCount++; U32 num_this_pass = llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_leaving); @@ -1010,10 +1007,9 @@ void FSRadar::zoomAvatar(const LLUUID& avatar_id, std::string_view name) void FSRadar::updateNames() { - const entry_map_t::iterator it_end = mEntryList.end(); - for (entry_map_t::iterator it = mEntryList.begin(); it != it_end; ++it) + for (auto& [av_id, entry] : mEntryList) { - it->second->updateName(); + entry->updateName(); } } diff --git a/indra/newview/fsradarlistctrl.cpp b/indra/newview/fsradarlistctrl.cpp index 57e1d5a9c9..7841749bfd 100644 --- a/indra/newview/fsradarlistctrl.cpp +++ b/indra/newview/fsradarlistctrl.cpp @@ -43,25 +43,23 @@ BOOL FSRadarListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); if ( (mContextMenu) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) { - std::vector selected_items = getAllSelected(); - if (selected_items.size() > 1) + if (std::vector selected_items = getAllSelected(); selected_items.size() > 1) { uuid_vec_t selected_uuids; - for (std::vector::iterator it = selected_items.begin(); it != selected_items.end(); ++it) + for (auto selected_item : selected_items) { - selected_uuids.push_back((*it)->getUUID()); + selected_uuids.emplace_back(selected_item->getUUID()); } mContextMenu->show(this, selected_uuids, x, y); } else { - LLScrollListItem* hit_item = hitItem(x, y); - if (hit_item) + if (LLScrollListItem* hit_item = hitItem(x, y); hit_item) { selectByID(hit_item->getValue()); LLUUID av = hit_item->getValue(); uuid_vec_t selected_uuids; - selected_uuids.push_back(av); + selected_uuids.emplace_back(av); mContextMenu->show(this, selected_uuids, x, y); } } diff --git a/indra/newview/fsslurlcommand.cpp b/indra/newview/fsslurlcommand.cpp index f0a8427c00..ae246662cb 100644 --- a/indra/newview/fsslurlcommand.cpp +++ b/indra/newview/fsslurlcommand.cpp @@ -46,7 +46,7 @@ public: // not allowed from outside the app FSSlurlCommandHandler() : LLCommandHandler("firestorm", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params.size() < 2) { @@ -253,7 +253,7 @@ public: // not allowed from outside the app FSHelpSlurlCommandHandler() : LLCommandHandler("fshelp", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params.size() < 2) { diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index 37b8e02b0d..f0fb4c42d3 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -564,16 +564,13 @@ StrCpy $INSTSHORTCUT "${SHORTCUT}" # MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY # MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME # Couldn't get NSIS to expand $MultiUser.InstallMode into the function name at Call time -# Replaced this with Call un.CheckIfAdministrator since there currently is no InstallMode -##${If} $MultiUser.InstallMode == 'AllUsers' +${If} $MultiUser.InstallMode == 'AllUsers' ##MessageBox MB_OK "Uninstalling for all users" -## Call un.MultiUser.InstallMode.AllUsers -##${Else} + Call un.MultiUser.InstallMode.AllUsers +${Else} ##MessageBox MB_OK "Uninstalling for current user" -## Call un.MultiUser.InstallMode.CurrentUser -##${EndIf} -Call un.CheckIfAdministrator -# + Call un.MultiUser.InstallMode.CurrentUser +${EndIf} # Make sure we're not running Call un.CloseSecondLife @@ -603,7 +600,7 @@ Call un.UserSettingsFiles SectionEnd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Make sure the user can install +;; Make sure the user can install/uninstall ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function CheckIfAdministrator DetailPrint $(CheckAdministratorInstDP) @@ -617,21 +614,6 @@ lbl_is_admin: FunctionEnd -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Make sure the user can uninstall -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -Function un.CheckIfAdministrator - DetailPrint $(CheckAdministratorUnInstDP) - UserInfo::GetAccountType - Pop $R0 - StrCmp $R0 "Admin" lbl_is_admin - MessageBox MB_OK $(CheckAdministratorUnInstMB) - Quit -lbl_is_admin: - Return - -FunctionEnd - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Function CheckWillUninstallV2 ;; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index bda364b82d..754b991642 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -440,6 +440,7 @@ LLAgent::LLAgent() : mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), mTeleportState(TELEPORT_NONE), mRegionp(NULL), + mInterestListMode(LLViewerRegion::IL_MODE_DEFAULT), mAgentOriginGlobal(), mPositionGlobal(), @@ -1056,11 +1057,19 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal // static void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp) -{ - if (regionp && regionp->getRegionID() == region_id) +{ // Changed regions and now have the region capabilities + if (regionp) { - regionp->requestSimulatorFeatures(); - LLAppViewer::instance()->updateNameLookupUrl(regionp); + if (regionp->getRegionID() == region_id) + { + regionp->requestSimulatorFeatures(); + LLAppViewer::instance()->updateNameLookupUrl(regionp); + } + + if (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360) + { + gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360); + } } } @@ -1557,26 +1566,21 @@ LLVector3 LLAgent::getReferenceUpVector() void LLAgent::pitch(F32 angle) { // don't let user pitch if pointed almost all the way down or up - mFrameAgent.pitch(clampPitchToLimits(angle)); -} - -// Radians, positive is forward into ground -//----------------------------------------------------------------------------- -// clampPitchToLimits() -//----------------------------------------------------------------------------- -F32 LLAgent::clampPitchToLimits(F32 angle) -{ // A dot B = mag(A) * mag(B) * cos(angle between A and B) // so... cos(angle between A and B) = A dot B / mag(A) / mag(B) // = A dot B for unit vectors LLVector3 skyward = getReferenceUpVector(); - const F32 look_down_limit = 179.f * DEG_TO_RAD;; - const F32 look_up_limit = 1.f * DEG_TO_RAD; + // SL-19286 Avatar is upside down when viewed from below + // after left-clicking the mouse on the avatar and dragging down + // + // The issue is observed on angle below 10 degrees + const F32 look_down_limit = 179.f * DEG_TO_RAD; + const F32 look_up_limit = 10.f * DEG_TO_RAD; - F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward ); + F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward); // clamp pitch to limits if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit)) @@ -1587,8 +1591,11 @@ F32 LLAgent::clampPitchToLimits(F32 angle) { angle = look_up_limit - angle_from_skyward; } - - return angle; + + if (fabs(angle) > 1e-4) + { + mFrameAgent.pitch(angle); + } } @@ -3483,39 +3490,60 @@ void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferr handlePreferredMaturityResult(maturity); } +// Using a new capability, tell the simulator that we want it to send everything +// it knows about and not just what is in front of the camera, in its view +// frustum. We need this feature so that the contents of the region that appears +// in the 6 snapshots which we cannot see and is normally not "considered", is +// also rendered. Typically, this is turned on when the 360 capture floater is +// opened and turned off when it is closed. +// Note: for this version, we do not have a way to determine when "everything" +// has arrived and has been rendered so for now, the proposal is that users +// will need to experiment with the low resolution version and wait for some +// (hopefully) small period of time while the full contents resolves. +// Pass in a flag to ask the simulator/interest list to "send everything" or +// not (the default mode) +void LLAgent::changeInterestListMode(const std::string &new_mode) +{ + if (new_mode != mInterestListMode) + { + mInterestListMode = new_mode; + + // Change interest list mode for all regions. If they are already set for the current mode, + // the setting will have no effect. + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); + ++iter) + { + LLViewerRegion *regionp = *iter; + if (regionp && regionp->isAlive() && regionp->capabilitiesReceived()) + { + regionp->setInterestListMode(mInterestListMode); + } + } + } + else + { + LL_DEBUGS("360Capture") << "Agent interest list mode is already set to " << mInterestListMode << LL_ENDL; + } +} + bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure) { - if (!getRegion()) + if (getRegion()) { - return false; + return getRegion()->requestPostCapability(capName, postData, cbSuccess, cbFailure); } - std::string url = getRegion()->getCapability(capName); - - if (url.empty()) - { - LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL; - return false; - } - - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, mHttpPolicy, postData, cbSuccess, cbFailure); - return true; + return false; } bool LLAgent::requestGetCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure) { - std::string url; - - url = getRegionCapability(capName); - - if (url.empty()) + if (getRegion()) { - LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL; - return false; + return getRegion()->requestGetCapability(capName, cbSuccess, cbFailure); } - - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(url, mHttpPolicy, cbSuccess, cbFailure); - return true; + return false; } BOOL LLAgent::getAdminOverride() const diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 27c73e32dc..d21eedb66a 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -298,10 +298,16 @@ public: boost::signals2::connection addRegionChangedCallback(const region_changed_signal_t::slot_type& cb); void removeRegionChangedCallback(boost::signals2::connection callback); + + void changeInterestListMode(const std::string & new_mode); + const std::string & getInterestListMode() const { return mInterestListMode; } + private: LLViewerRegion *mRegionp; region_changed_signal_t mRegionChangedSignal; + std::string mInterestListMode; // How agent wants regions to send updates + //-------------------------------------------------------------------- // History //-------------------------------------------------------------------- @@ -638,7 +644,6 @@ public: void roll(F32 angle); void yaw(F32 angle); LLVector3 getReferenceUpVector(); - F32 clampPitchToLimits(F32 angle); //-------------------------------------------------------------------- // Autopilot diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index edd63423c4..936005eccc 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -434,10 +434,15 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi // if is avatar - don't do any funk heuristics to position the focal point // see DEV-30589 - if (object->isAvatar() || (object->isAnimatedObject() && object->getControlAvatar())) + if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar())) { return original_focus_point - obj_pos; } + if (object->isAvatar()) + { + LLVOAvatar* av = object->asAvatar(); + return original_focus_point - av->getCharacterPosition(); + } LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation LLVector3 object_extents = object->getScale(); @@ -1871,13 +1876,24 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) LL_WARNS() << "Null avatar drawable!" << LL_ENDL; return LLVector3d::zero; } + head_offset.clearVec(); + F32 fixup; + if (gAgentAvatarp->hasPelvisFixup(fixup)) + { + head_offset[VZ] -= fixup; + } + if (gAgentAvatarp->isSitting()) + { + head_offset.mdV[VZ] += 0.1; + } + if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent()) { gAgentAvatarp->updateHeadOffset(); - head_offset.mdV[VX] = gAgentAvatarp->mHeadOffset.mV[VX]; - head_offset.mdV[VY] = gAgentAvatarp->mHeadOffset.mV[VY]; - head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ] + 0.1f; + head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX]; + head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY]; + head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix(); camera_position_global = gAgent.getPosGlobalFromAgent ((gAgentAvatarp->getPosition()+ @@ -1885,11 +1901,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } else { - head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ]; - if (gAgentAvatarp->isSitting()) - { - head_offset.mdV[VZ] += 0.1; - } + head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global; head_offset = head_offset * gAgentAvatarp->getRenderRotation(); camera_position_global = camera_position_global + head_offset; diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 8e96591286..20c5d75bdf 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -35,6 +35,7 @@ #include "llcommandhandler.h" #include "llslurl.h" #include "llurldispatcher.h" +#include "llviewernetwork.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" @@ -153,7 +154,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const params.append(event_data["x"]); params.append(event_data["y"]); params.append(event_data["z"]); - LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true); + LLCommandDispatcher::dispatch("teleport", params, LLSD(), LLGridManager::getInstance()->getGrid(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true); // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat" // should we just compose LLCommandHandler and LLDispatchListener? } diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp index a48d5dea56..3fdaff64a4 100644 --- a/indra/newview/llagentui.cpp +++ b/indra/newview/llagentui.cpp @@ -104,9 +104,9 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const if (!region || !parcel) return FALSE; - S32 pos_x = S32(agent_pos_region.mV[VX]); - S32 pos_y = S32(agent_pos_region.mV[VY]); - S32 pos_z = S32(agent_pos_region.mV[VZ]); + S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f); + S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f); + S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f); // Round the numbers based on the velocity F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared(); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 0a9e67505e..a274dc6346 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -41,7 +41,7 @@ #include "llinventoryobserver.h" #include "llinventorypanel.h" #include "lllocaltextureobject.h" -#include "llmd5.h" +#include "llmd5.h" // [Legacy Bake] #include "llnotificationsutil.h" #include "lloutfitobserver.h" #include "llsidepanelappearance.h" diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 771d7398da..54c6c49adc 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -41,7 +41,9 @@ #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" +#include "llmd5.h" #include "llnotificationsutil.h" +#include "llmd5.h" #include "lloutfitobserver.h" #include "lloutfitslist.h" #include "llselectmgr.h" @@ -154,7 +156,10 @@ public: // requests will be throttled from a non-trusted browser LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { // support secondlife:///app/appearance/show, but for now we just // make all secondlife:///app/appearance SLapps behave this way @@ -5040,8 +5045,10 @@ public: // not allowed from outside the app LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& tokens, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { LLSD::UUID folder_uuid; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8eedfbbc88..d783a6ef23 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1789,7 +1789,12 @@ bool LLAppViewer::doFrame() LLFloaterSimpleOutfitSnapshot::update(); gGLActive = FALSE; } - } + + if (LLViewerStatsRecorder::instanceExists()) + { + LLViewerStatsRecorder::instance().idle(); + } + } } { diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index e80bc3fe7a..a9aa6ca958 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llappearancemgr.h" #include "llinventorymodel.h" +#include "llstartup.h" #include "lltooldraganddrop.h" // pack_permissions_slam #include "llviewerinventory.h" #include "llviewerregion.h" @@ -488,7 +489,7 @@ void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id) { LLTimer timer; bool expected = mAttachmentRequests.getTime(inv_item_id, timer); - if (!expected) + if (!expected && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT) { LLInventoryItem *item = gInventory.getItem(inv_item_id); LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: " @@ -532,11 +533,15 @@ void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id) LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL; } } - else + else if (!LLApp::isExiting()) { LL_WARNS() << "ATT unexpected detach for " << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; } + else + { + LL_DEBUGS("Avatar") << "ATT detach on shutdown for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL; + } // LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking " // << (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL; diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index d2f191036a..18fa0cf083 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -45,7 +45,7 @@ public: // requests will be throttled from a non-trusted browser LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { std::string action( "" ); if ( params.size() >= 1 ) diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 9dffa92fe4..c3873f1b2e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -88,7 +88,7 @@ public: // requests will be throttled from a non-trusted browser LLObjectIMHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params.size() < 1) { diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 2d3fea0451..a97e58aeaf 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -65,7 +65,7 @@ class LLObjectHandler : public LLCommandHandler public: LLObjectHandler() : LLCommandHandler("object", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params.size() < 2) return false; diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp index 518f5bc374..46ec97d5c0 100644 --- a/indra/newview/llcommanddispatcherlistener.cpp +++ b/indra/newview/llcommanddispatcherlistener.cpp @@ -64,10 +64,10 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const // But for testing, allow a caller to specify untrusted. trusted_browser = params["trusted"].asBoolean(); } - LLCommandDispatcher::dispatch( - params["cmd"], + LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], + "", NULL, LLCommandHandler::NAV_TYPE_CLICKED, trusted_browser); diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 9640b05b06..caa27e530b 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -62,6 +62,7 @@ public: bool dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web, const std::string& nav_type, bool trusted_browser); @@ -98,6 +99,7 @@ void LLCommandHandlerRegistry::add(const char* cmd, bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web, const std::string& nav_type, bool trusted_browser) @@ -165,7 +167,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, } } if (!info.mHandler) return false; - return info.mHandler->handle(params, query_map, web); + return info.mHandler->handle(params, query_map, grid, web); } void LLCommandHandlerRegistry::notifySlurlBlocked() @@ -220,12 +222,13 @@ LLCommandHandler::~LLCommandHandler() bool LLCommandDispatcher::dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web, const std::string& nav_type, bool trusted_browser) { return LLCommandHandlerRegistry::instance().dispatch( - cmd, params, query_map, web, nav_type, trusted_browser); + cmd, params, query_map, grid, web, nav_type, trusted_browser); } static std::string lookup(LLCommandHandler::EUntrustedAccess value); diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 486feecca6..1a354b04f7 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -42,7 +42,7 @@ public: LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { } // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (tokens.size() < 1) return false; @@ -90,6 +90,7 @@ public: virtual bool handle(const LLSD& params, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web) = 0; // For URL secondlife:///app/foo/bar/baz?cat=1&dog=2 // @params - array of "bar", "baz", possibly empty @@ -106,6 +107,7 @@ public: static bool dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web, const std::string& nav_type, bool trusted_browser); diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 6afff307a1..c9ae7dc9d6 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -47,6 +47,7 @@ LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewer mGlobalScale(1.0f), mMarkedForDeath(false), mRootVolp(NULL), + mControlAVBridge(NULL), mScaleConstraintFixup(1.0), mRegionChanged(false) { @@ -379,6 +380,12 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time) } } +void LLControlAvatar::markDead() +{ + super::markDead(); + mControlAVBridge = NULL; +} + bool LLControlAvatar::computeNeedsUpdate() { computeUpdatePeriod(); diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h index e079db042c..e448efbfb5 100644 --- a/indra/newview/llcontrolavatar.h +++ b/indra/newview/llcontrolavatar.h @@ -35,9 +35,12 @@ class LLControlAvatar: { LOG_CLASS(LLControlAvatar); + using super = LLVOAvatar; + public: LLControlAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - virtual void initInstance(); // Called after construction to initialize the class. + virtual void initInstance(); // Called after construction to initialize the class. + virtual void markDead(); virtual ~LLControlAvatar(); // If this is an attachment, return the avatar it is attached to. Otherwise NULL. @@ -90,6 +93,7 @@ public: F32 mGlobalScale; LLVOVolume *mRootVolp; + class LLControlAVBridge* mControlAVBridge; bool mMarkedForDeath; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 5a5dd78754..191a1f9c2e 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -770,6 +770,19 @@ void LLDrawable::movePartition() if (part) { part->move(this, getSpatialGroup()); + + // SL-18251 "On-screen animesh characters using pelvis offset animations + // disappear when root goes off-screen" + // + // Update extents of the root node when Control Avatar changes it's bounds + if (mRenderType == LLPipeline::RENDER_TYPE_CONTROL_AV && isRoot()) + { + LLControlAvatar* controlAvatar = dynamic_cast(getVObj().get()); + if (controlAvatar && controlAvatar->mControlAVBridge) + { + ((LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0))->setState(LLViewerOctreeGroup::DIRTY); + } + } } } @@ -1231,10 +1244,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() { setSpatialBridge(new LLHUDBridge(this, getRegion())); } - else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) - { - setSpatialBridge(new LLControlAVBridge(this, getRegion())); - } + else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) + { + setSpatialBridge(new LLControlAVBridge(this, getRegion())); + mVObjp->getControlAvatar()->mControlAVBridge = (LLControlAVBridge*)getSpatialBridge(); + } // check HUD first, because HUD is also attachment else if (mVObjp->isAttachment()) { diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 926b988f3c..15e1ab3f66 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -47,8 +47,10 @@ class LLEventHandler : public LLCommandHandler public: // requires trusted browser to trigger LLEventHandler() : LLCommandHandler("event", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (params.size() < 2) { diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm index e5965abbd6..4dd8bea4e1 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -103,7 +103,6 @@ std::unique_ptr> doLoadDialog(const std::vector* allowed_types, } } -std::unique_ptr doSaveDialog(const std::string* file, +std::unique_ptr doSaveDialog(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index 98be1570d3..e79535f498 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -48,32 +48,9 @@ #include "llviewerregion.h" #include "llviewerwindow.h" #include "pipeline.h" -#include "llworld.h" // needed for getRegionByID(); + #include -// Fix 360 capture missing objects after TP -void LLFloater360Capture::checkRegion() -{ - static LLUUID last_region_id = LLUUID::null; - auto last_region = LLWorld::instance().getRegionFromID(last_region_id); - - // Check if we changed region, if so reset the interest list to full, - LLViewerRegion* region = gAgent.getRegion(); - if( region && (region != last_region) ) - { - region->useFullUpdateInterestListMode(true, true); - if( last_region ) - { - // we clear the old region status, because the instance may persist for us - // but the region itself will have reset when we left. - last_region->clearFullUpdateInterestList(); - } - } - last_region_id = region->getRegionID(); -} - -// - LLFloater360Capture::LLFloater360Capture(const LLSD& key) : LLFloater(key) { @@ -87,21 +64,10 @@ LLFloater360Capture::LLFloater360Capture(const LLSD& key) // such time as we ask it not to (the dtor). If we crash or // otherwise, exit before this is turned off, the Simulator // will take care of cleaning up for us. - if (gSavedSettings.getBOOL("360CaptureUseInterestListCap")) - { -// Fix 360 capture missing objects after TP - // send everything to us for as long as this floater is open - // const bool send_everything = true; - // changeInterestListMode(send_everything); - // } - // } - if( LLViewerRegion* region = gAgent.getRegion() ) - { - checkRegion(); - } - } - mRegionChangeConnection = gAgent.addRegionChangedCallback(boost::bind(&LLFloater360Capture::checkRegion, this)); -// + mStartILMode = gAgent.getInterestListMode(); + + // send everything to us for as long as this floater is open + gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360); } LLFloater360Capture::~LLFloater360Capture() @@ -113,27 +79,16 @@ LLFloater360Capture::~LLFloater360Capture() mWebBrowser->unloadMediaSource(); } - // Tell the Simulator not to send us everything anymore - // and revert to the regular "keyhole" frustum of interest + // Restore interest list mode to the state when started + // Normally LLFloater360Capture tells the Simulator send everything + // and now reverts to the regular "keyhole" frustum of interest // list updates. - if (!LLApp::isExiting() && gSavedSettings.getBOOL("360CaptureUseInterestListCap")) + if (!LLApp::isExiting() && + gSavedSettings.getBOOL("360CaptureUseInterestListCap") && + mStartILMode != gAgent.getInterestListMode()) { -// Fix 360 capture missing objects after TP -// const bool send_everything = false; -// changeInterestListMode(send_everything); -// } -// } - - if( LLViewerRegion* region = gAgent.getRegion() ) - { - region->useFullUpdateInterestListMode(false); - } + gAgent.changeInterestListMode(mStartILMode); } - if (mRegionChangeConnection.connected()) - { - mRegionChangeConnection.disconnect(); - } -// } BOOL LLFloater360Capture::postBuild() @@ -216,54 +171,6 @@ void LLFloater360Capture::onChooseQualityRadioGroup() setSourceImageSize(); } -// Area search improvements - allow area search and 360 to coexist nicely. -// Code moved to LLViewerRegion.cpp -// Using a new capability, tell the simulator that we want it to send everything -// it knows about and not just what is in front of the camera, in its view -// frustum. We need this feature so that the contents of the region that appears -// in the 6 snapshots which we cannot see and is normally not "considered", is -// also rendered. Typically, this is turned on when the 360 capture floater is -// opened and turned off when it is closed. -// Note: for this version, we do not have a way to determine when "everything" -// has arrived and has been rendered so for now, the proposal is that users -// will need to experiment with the low resolution version and wait for some -// (hopefully) small period of time while the full contents resolves. -// Pass in a flag to ask the simulator/interest list to "send everything" or -// not (the default mode) -// void LLFloater360Capture::changeInterestListMode(bool send_everything) -// { -// LLSD body; -// if (send_everything) -// { -// body["mode"] = LLSD::String("360"); -// } -// else -// { -// body["mode"] = LLSD::String("default"); -// } - -// if (gAgent.requestPostCapability("InterestList", body, [](const LLSD & response) -// { -// LL_INFOS("360Capture") << -// "InterestList capability responded: \n" << -// ll_pretty_print_sd(response) << -// LL_ENDL; -// })) -// { -// LL_INFOS("360Capture") << -// "Successfully posted an InterestList capability request with payload: \n" << -// ll_pretty_print_sd(body) << -// LL_ENDL; -// } -// else -// { -// LL_INFOS("360Capture") << -// "Unable to post an InterestList capability request with payload: \n" << -// ll_pretty_print_sd(body) << -// LL_ENDL; -// } -// } -// // There is is a setting (360CaptureSourceImageSize) that holds the size // (width == height since it's a square) of each of the 6 source snapshots. @@ -683,11 +590,8 @@ void LLFloater360Capture::capture360Images() // display time to encode all 6 images. It tends to be a fairly linear // time for each so we don't need to worry about displaying the time // for each - this gives us plenty to use for optimizing - LL_INFOS("360Capture") << - "Time to encode and save 6 images was " << - encode_time_total << - " seconds" << - LL_ENDL; + LL_INFOS("360Capture") << "Time to encode and save 6 images was " << + encode_time_total << " seconds" << LL_ENDL; // Write the JavaScript file footer (the bottom of the file after the // declarations of the actual data URLs array). The footer comprises of @@ -719,7 +623,7 @@ void LLFloater360Capture::capture360Images() // as a change - only the subsequent 5 are if (camera_changed_times < 5) { - LL_INFOS("360Capture") << "Warning: we only captured " << camera_changed_times << " images." << LL_ENDL; + LL_WARNS("360Capture") << "360 image capture expected 5 or more images, only captured " << camera_changed_times << " images." << LL_ENDL; } // now we have the 6 shots saved in a well specified location, diff --git a/indra/newview/llfloater360capture.h b/indra/newview/llfloater360capture.h index ccaab5ce6d..3fb2c7f3c7 100644 --- a/indra/newview/llfloater360capture.h +++ b/indra/newview/llfloater360capture.h @@ -50,14 +50,9 @@ class LLFloater360Capture: void onOpen(const LLSD& key) override; void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; - // void changeInterestListMode(bool send_everything); // Area search improvements - code relocated to LLViewerRegion - const std::string getHTMLBaseFolder(); void capture360Images(); - // make 360 work properly after region crossing/TP - void checkRegion(); - boost::signals2::connection mRegionChangeConnection; - // + const std::string makeFullPathToJS(const std::string filename); void writeDataURLHeader(const std::string filename); void writeDataURLFooter(const std::string filename); @@ -96,6 +91,8 @@ class LLFloater360Capture: std::string mImageSaveDir; LLPointer mRawImages[6]; + + std::string mStartILMode; }; #endif // LL_FLOATER_360CAPTURE_H diff --git a/indra/newview/llfloatercamerapresets.cpp b/indra/newview/llfloatercamerapresets.cpp index 300c945a85..a1cbffd094 100644 --- a/indra/newview/llfloatercamerapresets.cpp +++ b/indra/newview/llfloatercamerapresets.cpp @@ -24,6 +24,7 @@ */ #include "llviewerprecompiledheaders.h" +#include "llfloatercamera.h" #include "llfloatercamerapresets.h" #include "llfloaterreg.h" #include "llnotificationsutil.h" @@ -40,7 +41,8 @@ LLFloaterCameraPresets::~LLFloaterCameraPresets() BOOL LLFloaterCameraPresets::postBuild() { mPresetList = getChild("preset_list"); - + mPresetList->setCommitCallback(boost::bind(&LLFloaterCameraPresets::onSelectionChange, this)); + mPresetList->setCommitOnSelectionChange(true); LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCameraPresets::populateList, this)); return TRUE; @@ -58,6 +60,7 @@ void LLFloaterCameraPresets::populateList() std::list preset_names; presetsMgr->loadPresetNamesFromDir(PRESETS_CAMERA, preset_names, DEFAULT_BOTTOM); + std::string active_preset = gSavedSettings.getString("PresetCameraActive"); for (std::list::const_iterator it = preset_names.begin(); it != preset_names.end(); ++it) { @@ -66,6 +69,19 @@ void LLFloaterCameraPresets::populateList() LLCameraPresetFlatItem* item = new LLCameraPresetFlatItem(name, is_default); item->postBuild(); mPresetList->addItem(item); + if(name == active_preset) + { + mPresetList->selectItem(item); + } + } +} + +void LLFloaterCameraPresets::onSelectionChange() +{ + LLCameraPresetFlatItem* selected_preset = dynamic_cast(mPresetList->getSelectedItem()); + if(selected_preset) + { + LLFloaterCamera::switchToPreset(selected_preset->getPresetName()); } } diff --git a/indra/newview/llfloatercamerapresets.h b/indra/newview/llfloatercamerapresets.h index 66430fa399..4430a4209e 100644 --- a/indra/newview/llfloatercamerapresets.h +++ b/indra/newview/llfloatercamerapresets.h @@ -38,6 +38,7 @@ class LLFloaterCameraPresets : public LLFloater virtual void onOpen(const LLSD& key); void populateList(); + void onSelectionChange(); private: LLFloaterCameraPresets(const LLSD& key); @@ -58,6 +59,8 @@ public: virtual void onMouseEnter(S32 x, S32 y, MASK mask); virtual void onMouseLeave(S32 x, S32 y, MASK mask); + std::string getPresetName() { return mPresetName; } + private: void onDeleteBtnClick(); void onResetBtnClick(); diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 33bf76ee21..6da14295d1 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -92,8 +92,10 @@ class LLExperienceHandler : public LLCommandHandler public: LLExperienceHandler() : LLCommandHandler("experience", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if(params.size() != 2 || params[1].asString() != "profile") return false; diff --git a/indra/newview/llfloaterhandler.cpp b/indra/newview/llfloaterhandler.cpp index 8ebb14149c..b66049de7f 100644 --- a/indra/newview/llfloaterhandler.cpp +++ b/indra/newview/llfloaterhandler.cpp @@ -49,7 +49,7 @@ LLFloater* get_parent_floater(LLView* view) } -bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, LLMediaCtrl *web) +bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, const std::string& grid, LLMediaCtrl *web) { if (params.size() < 1) return false; LLFloater* floater = NULL; diff --git a/indra/newview/llfloaterhandler.h b/indra/newview/llfloaterhandler.h index 5915642d66..959c972275 100644 --- a/indra/newview/llfloaterhandler.h +++ b/indra/newview/llfloaterhandler.h @@ -33,7 +33,7 @@ class LLFloaterHandler { public: LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web); + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web); }; #endif diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 3edc5a7e11..1c81e0aaaf 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -967,8 +967,10 @@ public: LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& tokens, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { bool retval = false; // Need at least 2 tokens to have a valid message. diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index af1932a85e..1254aa2c7a 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -3031,7 +3031,7 @@ BOOL LLPanelEstateAccess::postBuild() if (banned_name_list) { banned_name_list->setCommitOnSelectionChange(TRUE); - banned_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + banned_name_list->setMaxItemCount(LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS); // OpenSim } getChild("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2)); @@ -3044,7 +3044,7 @@ BOOL LLPanelEstateAccess::postBuild() if (manager_name_list) { manager_name_list->setCommitOnSelectionChange(TRUE); - manager_name_list->setMaxItemCount(ESTATE_MAX_MANAGERS * 4); // Allow extras for dupe issue + manager_name_list->setMaxItemCount((LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_MANAGERS : ESTATE_MAX_MANAGERS_OS) * 4); // Allow extras for dupe issue // OpenSim } childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickAddEstateManager, this)); @@ -3175,10 +3175,10 @@ void LLPanelEstateAccess::onClickAddBannedAgent() { LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list"); if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) + if (list->getItemCount() >= (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS)) // OpenSim { LLSD args; - args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + args["MAX_BANNED"] = llformat("%d", (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS)); // OpenSim LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args); return; } @@ -3210,10 +3210,10 @@ void LLPanelEstateAccess::onClickAddEstateManager() { LLCtrlListInterface *list = childGetListInterface("estate_manager_name_list"); if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_MANAGERS) + if (list->getItemCount() >= (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_MANAGERS : ESTATE_MAX_MANAGERS_OS)) // OpenSim { // Tell user they can't add more managers LLSD args; - args["MAX_MANAGER"] = llformat("%d", ESTATE_MAX_MANAGERS); + args["MAX_MANAGER"] = llformat("%d", (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_MANAGERS : ESTATE_MAX_MANAGERS_OS)); // OpenSim LLNotificationsUtil::add("MaxManagersOnRegion", args); } else @@ -3416,13 +3416,13 @@ void LLPanelEstateAccess::accessAddCore3(const uuid_vec_t& ids, std::vectorgetChild("banned_avatar_name_list"); LLNameListCtrl* em_list = panel->getChild("estate_manager_name_list"); int currentCount = (name_list ? name_list->getItemCount() : 0); - if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) + if (ids.size() + currentCount > (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS)) // OpenSim { LLSD args; args["NUM_ADDED"] = llformat("%d", ids.size()); - args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + args["MAX_AGENTS"] = llformat("%d", (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS)); // OpenSim args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); - args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_ACCESS_IDS); + args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS)); // OpenSim LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); delete change_info; return; @@ -3801,7 +3801,7 @@ void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url) { LLStringUtil::format_map_t args; args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size()); - args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + args["[MAXBANNED]"] = llformat("%d", (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_BANNED_IDS : ESTATE_MAX_BANNED_IDS_OS)); // OpenSim std::string msg = LLTrans::getString("RegionInfoBannedResidents", args); panel->getChild("ban_resident_label")->setValue(LLSD(msg)); @@ -3863,7 +3863,7 @@ void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url) { LLStringUtil::format_map_t args; args["[ESTATEMANAGERS]"] = llformat("%d", result["Managers"].size()); - args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); + args["[MAXMANAGERS]"] = llformat("%d", (LLGridManager::instance().isInSecondLife() ? ESTATE_MAX_MANAGERS : ESTATE_MAX_MANAGERS_OS)); // OpenSim std::string msg = LLTrans::getString("RegionInfoEstateManagers", args); panel->getChild("estate_manager_label")->setValue(LLSD(msg)); diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index a9b802f5c3..e684e393b2 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -49,7 +49,7 @@ class LLSearchHandler : public LLCommandHandler public: // requires trusted browser to trigger LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { } - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch")) { diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index e773c407d3..d74b35498d 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -49,6 +49,7 @@ #include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "lluictrlfactory.h" +#include "llviewerobjectlist.h" #include "llviewerwindow.h" #include "llfloaterregioninfo.h" @@ -89,7 +90,9 @@ LLFloaterTopObjects::LLFloaterTopObjects(const LLSD& key) mCommitCallbackRegistrar.add("TopObjects.GetByParcelName", boost::bind(&LLFloaterTopObjects::onGetByParcelName, this)); mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this)); + // TP to object + //mCommitCallbackRegistrar.add("TopObjects.TeleportToSelected", boost::bind(&LLFloaterTopObjects::teleportToSelectedObject, this)); mCommitCallbackRegistrar.add("TopObjects.TeleportToObject", boost::bind(&LLFloaterTopObjects::onTeleportToObject, this)); // Estate kick avatar mCommitCallbackRegistrar.add("TopObjects.Kick", boost::bind(&LLFloaterTopObjects::onKick, this)); @@ -106,10 +109,11 @@ LLFloaterTopObjects::~LLFloaterTopObjects() // virtual BOOL LLFloaterTopObjects::postBuild() { - LLScrollListCtrl *objects_list = getChild("objects_list"); - getChild("objects_list")->setFocus(TRUE); - objects_list->setDoubleClickCallback(onDoubleClickObjectsList, this); - objects_list->setCommitOnSelectionChange(TRUE); + mObjectsScrollList = getChild("objects_list"); + mObjectsScrollList->setFocus(TRUE); + mObjectsScrollList->setDoubleClickCallback(onDoubleClickObjectsList, this); + mObjectsScrollList->setCommitOnSelectionChange(TRUE); + mObjectsScrollList->setCommitCallback(boost::bind(&LLFloaterTopObjects::onSelectionChanged, this)); setDefaultBtn("show_beacon_btn"); @@ -453,6 +457,8 @@ void LLFloaterTopObjects::clearList() mObjectListData.clear(); mObjectListIDs.clear(); mtotalScore = 0.f; + + onSelectionChanged(); } @@ -541,12 +547,53 @@ void LLFloaterTopObjects::showBeacon() } // TP to object +//void LLFloaterTopObjects::teleportToSelectedObject() +//{ +// std::vector selected_items = mObjectsScrollList->getAllSelected(); +// if (selected_items.size() == 1) +// { +// LLScrollListItem* first_selected = selected_items.front(); +// +// LLVector3d teleport_location; +// LLViewerObject* viewer_object = gObjectList.findObject(first_selected->getUUID()); +// if (viewer_object == NULL) +// { +// // If we cannot find the object in the viewer list, teleport to the last reported position +// std::string pos_string = first_selected->getColumn(3)->getValue().asString(); +// +// F32 x, y, z; +// S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z); +// if (matched != 3) return; +// +// LLVector3 pos_agent(x, y, z); +// teleport_location = gAgent.getPosGlobalFromAgent(pos_agent); +// } +// else +// { +// // If we can find the object in the viewer list, teleport to the known current position +// teleport_location = viewer_object->getPositionGlobal(); +// } +// gAgent.teleportViaLocationLookAt(teleport_location); +// } +//} +// +//void LLFloaterTopObjects::onSelectionChanged() +//{ +// getChildView("teleport_btn")->setEnabled(mObjectsScrollList->getNumSelected() == 1); +//} +// +void LLFloaterTopObjects::onSelectionChanged() +{ + bool enabled = mObjectsScrollList->getNumSelected() == 1; + childSetEnabled("teleport_to_btn", enabled); + childSetEnabled("profile_btn", enabled); + childSetEnabled("script_info_btn", enabled); + childSetEnabled("estate_kick_btn", enabled); +} + void LLFloaterTopObjects::onTeleportToObject() { - LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; - - LLScrollListItem* first_selected = list->getFirstSelected(); + LLScrollListItem* first_selected = mObjectsScrollList->getFirstSelected(); if (!first_selected) return; std::string pos_string = first_selected->getColumn(3)->getValue().asString(); @@ -565,10 +612,7 @@ void LLFloaterTopObjects::onTeleportToObject() // Estate kick avatar void LLFloaterTopObjects::onKick() { - LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; - - LLScrollListItem* first_selected = list->getFirstSelected(); + LLScrollListItem* first_selected = mObjectsScrollList->getFirstSelected(); if (!first_selected) return; const LLUUID& objectId = first_selected->getUUID(); @@ -579,10 +623,7 @@ void LLFloaterTopObjects::onKick() // Show profile void LLFloaterTopObjects::onProfile() { - LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; - - LLScrollListItem* first_selected = list->getFirstSelected(); + LLScrollListItem* first_selected = mObjectsScrollList->getFirstSelected(); if (!first_selected) return; const LLUUID& objectId = first_selected->getUUID(); @@ -593,10 +634,7 @@ void LLFloaterTopObjects::onProfile() // Enable avatar-specific buttons if current selection is an avatar void LLFloaterTopObjects::onAvatarCheck(const LLUUID& avatar_id, LLAvatarName av_name) { - LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; - - LLScrollListItem* first_selected = list->getFirstSelected(); + LLScrollListItem* first_selected = mObjectsScrollList->getFirstSelected(); if (!first_selected) return; if (first_selected->getUUID() == avatar_id) @@ -611,10 +649,7 @@ void LLFloaterTopObjects::onAvatarCheck(const LLUUID& avatar_id, LLAvatarName av // Script info void LLFloaterTopObjects::onScriptInfo() { - LLScrollListCtrl* list = getChild("objects_list"); - if (!list) return; - - LLScrollListItem* first_selected = list->getFirstSelected(); + LLScrollListItem* first_selected = mObjectsScrollList->getFirstSelected(); if (!first_selected) return; const LLUUID& objectId = first_selected->getUUID(); diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h index 495ff41eff..deb0444e39 100644 --- a/indra/newview/llfloatertopobjects.h +++ b/indra/newview/llfloatertopobjects.h @@ -31,6 +31,7 @@ #include "llavatarname.h" class LLUICtrl; +class LLScrollListCtrl; // Bits for simulator performance query flags enum LAND_STAT_FLAGS @@ -76,6 +77,7 @@ private: void initColumns(LLCtrlListInterface *list); void onCommitObjectsList(); + void onSelectionChanged(); static void onDoubleClickObjectsList(void* data); void onClickShowBeacon(); @@ -103,6 +105,8 @@ private: void onGetByParcelName(); void showBeacon(); + // TP to object + //void teleportToSelectedObject(); private: std::string mMethod; @@ -119,6 +123,7 @@ private: F32 mtotalScore; static LLFloaterTopObjects* sInstance; + LLScrollListCtrl* mObjectsScrollList; }; #endif diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index dcd67c2fb3..e94ac4dac1 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -132,8 +132,10 @@ public: // requires trusted browser to trigger LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { // FIRE-17927: Viewer crashes when opening worldmap SLURL command from login panel if (LLStartUp::getStartupState() < STATE_STARTED) @@ -178,7 +180,10 @@ public: { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap")) { diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 8290b9614e..92b0a14e72 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -885,6 +885,12 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV gGL.end(); } +void LLViewerParcelMgr::resetCollisionTimer() +{ + mCollisionTimer.reset(); + mRenderCollision = TRUE; +} + void draw_line_cube(F32 width, const LLVector3& center) { width = 0.5f * width; diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 738667be9e..94571ab731 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -94,8 +94,10 @@ public: return true; } - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& tokens, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_STARTED) { diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 9214d29e55..6f9e88468b 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -2373,13 +2373,19 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) from_group = message_data["from_group"].asString() == "Y"; } + EInstantMessage dialog = static_cast(message_data["dialog"].asInteger()); + LLUUID session_id = message_data["transaction-id"].asUUID(); + if (session_id.isNull() && dialog == IM_FROM_TASK) + { + session_id = message_data["asset_id"].asUUID(); + } LLIMProcessing::processNewMessage( message_data["from_agent_id"].asUUID(), from_group, message_data["to_agent_id"].asUUID(), message_data.has("offline") ? static_cast(message_data["offline"].asInteger()) : IM_OFFLINE, - static_cast(message_data["dialog"].asInteger()), - message_data["transaction-id"].asUUID(), + dialog, + session_id, static_cast(message_data["timestamp"].asInteger()), message_data["from_agent_name"].asString(), message_data["message"].asString(), diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d5570cd6f7..c9ed2693f4 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -7514,8 +7514,11 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } // FIRE-21200: Attachment Points List in Alphabetical Order - attach_menu->getItems()->sort(LLViewerAttachMenu::sort()); - attach_hud_menu->getItems()->sort(LLViewerAttachMenu::sort()); + if (gSavedSettings.getBOOL("FSSortAttachmentSpotsAlphabetically")) + { + attach_menu->getItems()->sort(LLViewerAttachMenu::sort()); + attach_hud_menu->getItems()->sort(LLViewerAttachMenu::sort()); + } // } } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ae2fd6a9a2..8e4749fa5a 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -223,8 +223,7 @@ bool contains_nocopy_items(const LLUUID& id) return false; } -// Generates a string containing the path to the item specified by -// item_id. +// Generates a string containing the path to the item specified by id. void append_path(const LLUUID& id, std::string& path) { std::string temp; @@ -244,6 +243,36 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } +// Generates a string containing the path name of the object. +std::string make_path(const LLInventoryObject* object) +{ + std::string path; + append_path(object->getUUID(), path); + return path + "/" + object->getName(); +} + +// Generates a string containing the path name of the object specified by id. +std::string make_inventory_path(const LLUUID& id) +{ + if (LLInventoryObject* object = gInventory.getObject(id)) + return make_path(object); + return ""; +} + +// Generates a string containing the path name and id of the object. +std::string make_info(const LLInventoryObject* object) +{ + return "'" + make_path(object) + "' (" + object->getUUID().asString() + ")"; +} + +// Generates a string containing the path name and id of the object specified by id. +std::string make_inventory_info(const LLUUID& id) +{ + if (LLInventoryObject* object = gInventory.getObject(id)) + return make_info(object); + return " (" + id.asString() + ")"; +} + void update_marketplace_folder_hierarchy(const LLUUID cat_id) { // When changing the marketplace status of a folder, the only thing that needs to happen is @@ -1542,6 +1571,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol if (copy) { // Copy the item + LL_INFOS("SLM") << "Copy item '" << make_info(viewer_inv_item) << "' to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL; LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder)); copy_inventory_item( gAgent.getID(), @@ -1553,6 +1583,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol } else { + LL_INFOS("SLM") << "Move item '" << make_info(viewer_inv_item) << "' to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL; // Reparent the item gInventory.changeItemParent(viewer_inv_item, dest_folder, true); } @@ -1599,6 +1630,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU } else { + LL_INFOS("SLM") << "Move category " << make_info(viewer_inv_cat) << " to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL; // Reparent the folder gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false); // Check the destination folder recursively for no copy items and promote the including folders if any diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index a99886385b..006be790f3 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -85,9 +85,19 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items); -// Generates a string containing the path to the item specified by item_id. +// Generates a string containing the path to the object specified by id (not including the object name). void append_path(const LLUUID& id, std::string& path); +// Generates a string containing the path name of the object. +std::string make_path(const LLInventoryObject* object); +// Generates a string containing the path name of the object specified by id. +std::string make_inventory_path(const LLUUID& id); + +// Generates a string containing the path name and id of the object. +std::string make_info(const LLInventoryObject* object); +// Generates a string containing the path name and id of the object specified by id. +std::string make_inventory_info(const LLUUID& id); + typedef boost::function validation_callback_t; bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5f931893b4..999e95ca2b 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -62,6 +62,7 @@ #include "bufferarray.h" #include "bufferstream.h" #include "llcorehttputil.h" +#include "hbxxh.h" // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" #include "rlvlocks.h" @@ -518,17 +519,16 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, items = get_ptr_in_map(mParentChildItemTree, cat_id); } -LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const +LLInventoryModel::digest_t LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const { LLInventoryModel::cat_array_t* cat_array; LLInventoryModel::item_array_t* item_array; getDirectDescendentsOf(cat_id,cat_array,item_array); - LLMD5 item_name_hash; if (!item_array) { - item_name_hash.finalize(); - return item_name_hash; + return LLUUID::null; } + HBXXH128 item_name_hash; for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin(); iter != item_array->end(); iter++) @@ -538,8 +538,7 @@ LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const continue; item_name_hash.update(item->getName()); } - item_name_hash.finalize(); - return item_name_hash; + return item_name_hash.digest(); } // SJB: Added version to lock the arrays to catch potential logic bugs @@ -763,6 +762,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, const std::string& pname, inventory_func_type callback) { + LL_DEBUGS(LOG_INV) << "Create '" << pname << "' in '" << make_inventory_path(parent_id) << "'" << LL_ENDL; LLUUID id; if (!isInventoryUsable()) { @@ -854,6 +854,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, cat->packMessage(msg); gAgent.sendReliableMessage(); + LL_INFOS(LOG_INV) << "Created new category '" << make_inventory_path(id) << "'" << LL_ENDL; // return the folder id of the newly created folder return id; } @@ -1503,6 +1504,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) LLPointer cat = getCategory(object_id); if(cat && (cat->getParentUUID() != cat_id)) { + LL_DEBUGS(LOG_INV) << "Move category '" << make_path(cat) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL; cat_array_t* cat_array; cat_array = getUnlockedCatArray(cat->getParentUUID()); if(cat_array) vector_replace_with_last(*cat_array, cat); @@ -1515,6 +1517,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id) LLPointer item = getItem(object_id); if(item && (item->getParentUUID() != cat_id)) { + LL_DEBUGS(LOG_INV) << "Move item '" << make_path(item) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL; item_array_t* item_array; item_array = getUnlockedItemArray(item->getParentUUID()); if(item_array) vector_replace_with_last(*item_array, item); @@ -1533,14 +1536,14 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, { if (item->getParentUUID() == new_parent_id) { - LL_DEBUGS(LOG_INV) << "'" << item->getName() << "' (" << item->getUUID() - << ") is already in folder " << new_parent_id << LL_ENDL; + LL_DEBUGS(LOG_INV) << make_info(item) << " is already in folder " << make_inventory_info(new_parent_id) << LL_ENDL; } else { - LL_INFOS(LOG_INV) << "Moving '" << item->getName() << "' (" << item->getUUID() - << ") from " << item->getParentUUID() << " to folder " - << new_parent_id << LL_ENDL; + LL_INFOS(LOG_INV) << "Move item " << make_info(item) + << " from " << make_inventory_info(item->getParentUUID()) + << " to " << make_inventory_info(new_parent_id) << LL_ENDL; + // Locked folder if ((isObjectDescendentOf(item->getUUID(), AOEngine::instance().getAOFolder()) @@ -1599,6 +1602,10 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, } // + LL_INFOS(LOG_INV) << "Move category " << make_info(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); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index c907bd9733..b826ae22e4 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -39,7 +39,6 @@ #include "llpermissionsflags.h" #include "llviewerinventory.h" #include "llstring.h" -#include "llmd5.h" #include "httpcommon.h" #include "httprequest.h" #include "httpoptions.h" @@ -268,8 +267,9 @@ public: cat_array_t*& categories, item_array_t*& items) const; + typedef LLUUID digest_t; // To clarify the actual usage of this "UUID" // Compute a hash of direct descendant names (for detecting child name changes) - LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const; + digest_t hashDirectDescendentNames(const LLUUID& cat_id) const; // Starting with the object specified, add its descendants to the // array provided, but do not add the inventory object specified diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index e4a985cb8e..897495a10e 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -677,7 +677,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) // computed, or (b) a name has changed. if (!cat_data.mIsNameHashInitialized || (mask & LLInventoryObserver::LABEL)) { - LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id); + digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id); if (cat_data.mItemNameHash != item_name_hash) { cat_data.mIsNameHashInitialized = true; @@ -738,7 +738,7 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t { if(init_name_hash) { - LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id); + digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id); mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents,item_name_hash))); } else @@ -764,11 +764,10 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData( , mDescendentsCount(num_descendents) , mIsNameHashInitialized(false) { - mItemNameHash.finalize(); } LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData( - const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash) + const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash) : mCatID(cat_id) , mCallback(cb) diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 36d8ee3f59..4af8102055 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -28,7 +28,6 @@ #define LL_LLINVENTORYOBSERVERS_H #include "lluuid.h" -#include "llmd5.h" #include #include @@ -271,14 +270,15 @@ public: void removeCategory(const LLUUID& cat_id); protected: + typedef LLUUID digest_t; // To clarify the actual usage of this "UUID" struct LLCategoryData { LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents); - LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash); + LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash); callback_t mCallback; S32 mVersion; S32 mDescendentsCount; - LLMD5 mItemNameHash; + digest_t mItemNameHash; bool mIsNameHashInitialized; LLUUID mCatID; }; diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp index 2521d3ce1f..d4cef127e5 100644 --- a/indra/newview/llloginhandler.cpp +++ b/indra/newview/llloginhandler.cpp @@ -90,6 +90,7 @@ void LLLoginHandler::parse(const LLSD& queryMap) bool LLLoginHandler::handle(const LLSD& tokens, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web) { // do nothing if we are already logged in diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h index 1f2eacd094..2579341dbf 100644 --- a/indra/newview/llloginhandler.h +++ b/indra/newview/llloginhandler.h @@ -35,7 +35,7 @@ class LLLoginHandler : public LLCommandHandler public: // allow from external browsers LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { } - /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web); + /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web); // Fill in our internal fields from a SLURL like // secondlife:///app/login?first=Bob&last=Dobbs diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 843dc66fbc..8f1ec8584b 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -93,7 +93,11 @@ private: bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); } }; - + + // definitions follow class + friend std::hash; + friend size_t hash_value(const TEMaterialPair&) noexcept; + friend inline bool operator<( const LLMaterialMgr::TEMaterialPair& lhs, const LLMaterialMgr::TEMaterialPair& rhs) @@ -102,13 +106,6 @@ private: (lhs.materialID < rhs.materialID); } - struct TEMaterialPairHasher - { - enum { bucket_size = 8 }; - size_t operator()(const TEMaterialPair& key_value) const { return *((size_t*)key_value.materialID.get()); } // cheesy, but effective - bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; } - }; - typedef std::set material_queue_t; typedef std::map get_queue_t; typedef std::pair pending_material_t; @@ -116,7 +113,7 @@ private: typedef std::map get_callback_map_t; - typedef boost::unordered_map get_callback_te_map_t; + typedef boost::unordered_map get_callback_te_map_t; typedef std::set getall_queue_t; typedef std::map getall_pending_map_t; typedef std::map getall_callback_map_t; @@ -146,5 +143,23 @@ private: U32 getMaxEntries(const LLViewerRegion* regionp); }; +// std::hash implementation for TEMaterialPair +namespace std +{ + template<> struct hash + { + inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept + { + return size_t((p.te + 1) * p.materialID.getDigest64()); + } + }; +} + +// For use with boost containers. +inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept +{ + return size_t((p.te + 1) * p.materialID.getDigest64()); +} + #endif // LL_LLMATERIALMGR_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index b8cbd414ae..687afb4026 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -56,6 +56,7 @@ #include "llviewermessage.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" +#include "llviewerstatsrecorder.h" #include "llviewertexturelist.h" #include "llvolume.h" #include "llvolumemgr.h" @@ -1967,7 +1968,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes const LLUUID mesh_id = mesh_params.getSculptID(); LLSD header; - U32 header_size = 0; + llssize header_size = 0; if (data_size > 0) { llssize dsize = data_size; @@ -4268,6 +4269,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol } mLoadingMeshes[detail].erase(obj_iter); + + LLViewerStatsRecorder::instance().meshLoaded(); } } diff --git a/indra/newview/lloutfitobserver.cpp b/indra/newview/lloutfitobserver.cpp index 5bb69367aa..3ec5bcd9fc 100644 --- a/indra/newview/lloutfitobserver.cpp +++ b/indra/newview/lloutfitobserver.cpp @@ -34,7 +34,6 @@ LLOutfitObserver::LLOutfitObserver() : mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) { - mItemNameHash.finalize(); gInventory.addObserver(this); } @@ -83,7 +82,7 @@ bool LLOutfitObserver::checkCOF() return false; bool cof_changed = false; - LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cof); + LLUUID item_name_hash = gInventory.hashDirectDescendentNames(cof); if (item_name_hash != mItemNameHash) { cof_changed = true; diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index 77bb3543aa..56f2ceb8b1 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -28,7 +28,6 @@ #define LL_OUTFITOBSERVER_H #include "llsingleton.h" -#include "llmd5.h" /** * Outfit observer facade that provides simple possibility to subscribe on @@ -78,7 +77,7 @@ protected: bool mLastOutfitDirtiness; - LLMD5 mItemNameHash; + LLUUID mItemNameHash; private: signal_t mBOFReplaced; diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index d384de1123..ed3a589336 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1894,7 +1894,7 @@ class LLMetricSystemHandler : public LLCommandHandler public: LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_CLICK_ONLY) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { // change height units TRUE for meters and FALSE for feet BOOL new_value = (gSavedSettings.getBOOL("HeightUnits") == FALSE) ? TRUE : FALSE; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 1fceb59983..49d9c73ddc 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -99,7 +99,7 @@ class LLLoginLocationAutoHandler : public LLCommandHandler public: // don't allow from external browsers LLLoginLocationAutoHandler() : LLCommandHandler("location_login", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) { diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index b720038101..952de95a35 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -675,9 +675,9 @@ void LLPanelNearByMedia::refreshList() disabled_count++; } } - } + } mDisableAllCtrl->setEnabled((gSavedSettings.getBOOL("AudioStreamingMusic") || - gSavedSettings.getBOOL("AudioStreamingMedia")) && + gSavedSettings.getBOOL("AudioStreamingMedia")) && (media_inst->isAnyMediaShowing() || media_inst->isParcelMediaPlaying() || media_inst->isParcelAudioPlaying())); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 39eb6d82eb..87b8837d58 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -1500,25 +1500,23 @@ void LLPanelObject::deactivateStandardFields() getChildView("advanced_slice")->setVisible(FALSE); } -void LLPanelObject::activateMeshFields(LLViewerObject * objectp) +void LLPanelObject::activateMeshFields(LLViewerObject* objectp) { LLStringUtil::format_map_t args; static const char * dataFields[4] = { "LOWESTTRIS", "LOWTRIS", "MIDTRIS", "HIGHTRIS" }; - LLTextBox *num_tris = getChild("mesh_lod_num_tris"); - if (num_tris) + LLTextBox* num_tris = getChild("mesh_lod_num_tris"); + for (int i = 0; i < 4; i++) { - for (int i = 0; i < 4; i++) - { - args[dataFields[i]] = llformat("%d", objectp->mDrawable->getVOVolume()->getLODTriangleCount(i)); - } - num_tris->setText(getString("mesh_lod_num_tris_values",args)); - num_tris->setVisible(TRUE); + args[dataFields[i]] = llformat("%d", objectp->mDrawable->getVOVolume()->getLODTriangleCount(i)); } - childSetVisible("mesh_info_label", TRUE); - childSetVisible("lod_label", TRUE); - childSetVisible("lod_num_tris", TRUE); - childSetVisible("mesh_lod_label", TRUE); + num_tris->setText(getString("mesh_lod_num_tris_values",args)); + num_tris->setVisible(TRUE); + + childSetVisible("mesh_info_label", true); + childSetVisible("lod_label", true); + childSetVisible("lod_num_tris", true); + childSetVisible("mesh_lod_label", true); // Mesh specific display mComboLOD->setEnabled(TRUE); mComboLOD->setVisible(TRUE); @@ -1541,7 +1539,7 @@ void LLPanelObject::activateMeshFields(LLViewerObject * objectp) radius = objectp->getVolume() ? objectp->getVolume()->mLODScaleBias.scaledVec(objectp->getScale()).length() : objectp->getScale().length(); } - static const F32 max_distance = 512.f; + constexpr F32 max_distance = 512.f; F32 factor; F32 dlowest = llmin(radius / 0.03f, max_distance); F32 dlow = llmin(radius / 0.06f, max_distance); @@ -1591,7 +1589,7 @@ void LLPanelObject::activateMeshFields(LLViewerObject * objectp) setLODDistValues(tb, factor, dmid, dlow, dlowest); } -void LLPanelObject::setLODDistValues(LLTextBox * tb, F32 factor, F32 dmid, F32 dlow, F32 dlowest) +void LLPanelObject::setLODDistValues(LLTextBox* tb, F32 factor, F32 dmid, F32 dlow, F32 dlowest) { if (tb) { @@ -1607,11 +1605,11 @@ void LLPanelObject::setLODDistValues(LLTextBox * tb, F32 factor, F32 dmid, F32 d void LLPanelObject::deactivateMeshFields() { - childSetVisible("mesh_info_label", FALSE); - childSetVisible("lod_label", FALSE); - childSetVisible("lod_num_tris", FALSE); - childSetVisible("mesh_lod_num_tris", FALSE); - childSetVisible("mesh_lod_label", FALSE); + childSetVisible("mesh_info_label", false); + childSetVisible("lod_label", false); + childSetVisible("lod_num_tris", false); + childSetVisible("mesh_lod_num_tris", false); + childSetVisible("mesh_lod_label", false); // reset the debug setting as we are editing a new object gSavedSettings.setS32("ShowSpecificLODInEdit", -1); // @@ -1620,7 +1618,7 @@ void LLPanelObject::deactivateMeshFields() mComboLOD->setEnabled(FALSE); mComboLOD->setVisible(FALSE); - childSetVisible("object_radius", FALSE); + childSetVisible("object_radius", false); LLTextBox* tb = getChild("object_radius_value"); tb->setVisible(FALSE); diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 315ffa203a..b634a5485b 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -111,30 +111,34 @@ std::string click_action_to_string_value( U8 action); U8 string_value_to_click_action(std::string p_value) { - if(p_value == "Touch") + if (p_value == "Touch") { return CLICK_ACTION_TOUCH; } - if(p_value == "Sit") + if (p_value == "Sit") { return CLICK_ACTION_SIT; } - if(p_value == "Buy") + if (p_value == "Buy") { return CLICK_ACTION_BUY; } - if(p_value == "Pay") + if (p_value == "Pay") { return CLICK_ACTION_PAY; } - if(p_value == "Open") + if (p_value == "Open") { return CLICK_ACTION_OPEN; } - if(p_value == "Zoom") + if (p_value == "Zoom") { return CLICK_ACTION_ZOOM; } + if (p_value == "Ignore") + { + return CLICK_ACTION_IGNORE; + } if (p_value == "None") { return CLICK_ACTION_DISABLED; @@ -165,6 +169,9 @@ std::string click_action_to_string_value( U8 action) case CLICK_ACTION_ZOOM: return "Zoom"; break; + case CLICK_ACTION_IGNORE: + return "Ignore"; + break; case CLICK_ACTION_DISABLED: return "None"; break; @@ -334,12 +341,12 @@ void LLPanelPermissions::disableAll() combo_click_action->setEnabled(FALSE); combo_click_action->clear(); } - getChildView("B:")->setVisible( FALSE); - getChildView("O:")->setVisible( FALSE); - getChildView("G:")->setVisible( FALSE); - getChildView("E:")->setVisible( FALSE); - getChildView("N:")->setVisible( FALSE); - getChildView("F:")->setVisible( FALSE); + getChildView("B:")->setVisible(FALSE); + getChildView("O:")->setVisible(FALSE); + getChildView("G:")->setVisible(FALSE); + getChildView("E:")->setVisible(FALSE); + getChildView("N:")->setVisible(FALSE); + getChildView("F:")->setVisible(FALSE); } void LLPanelPermissions::refresh() @@ -1159,19 +1166,19 @@ void LLPanelPermissions::refresh() getChild("search_check")->setValue(include_in_search); getChild("search_check")->setTentative( !all_include_in_search); - // Click action (touch, sit, buy) + // Click action (touch, sit, buy, pay, open, play, open media, zoom, ignore) U8 click_action = 0; if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action)) { LLComboBox* combo_click_action = getChild("clickaction"); - if(combo_click_action) + if (combo_click_action) { const std::string combo_value = click_action_to_string_value(click_action); combo_click_action->setValue(LLSD(combo_value)); } } - if(LLSelectMgr::getInstance()->getSelection()->isAttachment()) + if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) { getChildView("checkbox for sale")->setEnabled(FALSE); getChildView("Edit Cost")->setEnabled(FALSE); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index dd33202980..4969e4a504 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -98,8 +98,10 @@ class LLParcelHandler : public LLCommandHandler public: // requires trusted browser to trigger LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (params.size() < 2) { diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index b2eb071c53..30f77c0e81 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -474,8 +474,10 @@ public: // requires trusted browser to trigger LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (params.size() < 1) return false; std::string agent_name = params[0]; @@ -522,8 +524,10 @@ public: return false; } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (params.size() < 2) return false; LLUUID avatar_id; @@ -652,9 +656,9 @@ public: // requires trusted browser to trigger FSAgentSelfHandler() : LLCommandHandler("agentself", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { - return gAgentHandler.handle(params, query_map, web); + return gAgentHandler.handle(params, query_map, grid, web); } }; FSAgentSelfHandler gAgentSelfHandler; diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp index 2be077de0b..1c521d8de5 100644 --- a/indra/newview/llpanelprofileclassifieds.cpp +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -108,7 +108,7 @@ public: return true; } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_STARTED) { diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 16cdbeab9a..089d71de14 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -89,8 +89,10 @@ public: return true; } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_STARTED) { diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 1c4f1f646b..f0d00e9728 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -39,7 +39,9 @@ #include "llinventorydefines.h" #include "llinventorymodel.h" #include "lllineeditor.h" +#include "llmd5.h" #include "llnotificationsutil.h" +#include "llmd5.h" #include "llresmgr.h" #include "roles_constants.h" #include "llscrollbar.h" diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 2091727291..4f48c548a1 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -41,6 +41,7 @@ #include "llinventorymodel.h" #include "llkeyboard.h" #include "lllineeditor.h" +#include "llmd5.h" #include "llhelp.h" #include "llnotificationsutil.h" #include "llresmgr.h" diff --git a/indra/newview/llsceneview.cpp b/indra/newview/llsceneview.cpp index 3b9f8b0a1d..7b498043dc 100644 --- a/indra/newview/llsceneview.cpp +++ b/indra/newview/llsceneview.cpp @@ -118,7 +118,7 @@ void LLSceneView::draw() U32 idx = object->isAttachment() ? 1 : 0; LLVolume* volume = object->getVolume(); - + F32 radius = object->getScale().magVec(); size[idx].push_back(radius); diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index b1eed81476..f5212a3026 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -312,7 +312,7 @@ void LLSettingsVOBase::onAssetDownloadComplete(const LLUUID &asset_id, S32 statu std::stringstream llsdstream(buffer); LLSD llsdsettings; - if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1)) + if (LLSDSerialize::deserialize(llsdsettings, llsdstream, LLSDSerialize::SIZE_UNLIMITED)) { settings = createFromLLSD(llsdsettings); } @@ -379,7 +379,7 @@ LLSettingsBase::ptr_t LLSettingsVOBase::importFile(const std::string &filename) return LLSettingsBase::ptr_t(); } - if (!LLSDSerialize::deserialize(settings, file, -1)) + if (!LLSDSerialize::deserialize(settings, file, LLSDSerialize::SIZE_UNLIMITED)) { LL_WARNS("SETTINGS") << "Unable to deserialize settings from '" << filename << "'" << LL_ENDL; return LLSettingsBase::ptr_t(); diff --git a/indra/newview/llshareavatarhandler.cpp b/indra/newview/llshareavatarhandler.cpp index 142e00c3f7..8c5ebb75ef 100644 --- a/indra/newview/llshareavatarhandler.cpp +++ b/indra/newview/llshareavatarhandler.cpp @@ -38,7 +38,7 @@ public: { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableAvatarShare")) { diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 4fa9c54b44..331abb9e98 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -888,7 +888,7 @@ void LLSidepanelTaskInfo::refresh() const BOOL all_include_in_search = LLSelectMgr::getInstance()->selectionGetIncludeInSearch(&include_in_search); getChildView("search_check")->setEnabled(has_change_sale_ability && all_volume); getChild("search_check")->setValue(include_in_search); - getChild("search_check")->setTentative( !all_include_in_search); + getChild("search_check")->setTentative(!all_include_in_search); // Click action (touch, sit, buy) U8 click_action = 0; @@ -1189,7 +1189,8 @@ static U8 string_value_to_click_action(std::string p_value) void LLSidepanelTaskInfo::onCommitClickAction(LLUICtrl* ctrl, void*) { LLComboBox* box = (LLComboBox*)ctrl; - if (!box) return; + if (!box) + return; std::string value = box->getValue().asString(); U8 click_action = string_value_to_click_action(value); doClickAction(click_action); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f2c3df36dc..a9b4bbe478 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -243,6 +243,59 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) return FALSE; } +void LLSpatialGroup::expandExtents(const LLVector4a* addingExtents, const LLXformMatrix& currentTransform) +{ + // Get coordinates of the adding extents + const LLVector4a& min = addingExtents[0]; + const LLVector4a& max = addingExtents[1]; + + // Get coordinates of all corners of the bounding box + LLVector3 corners[] = + { + LLVector3(min[0], min[1], min[2]), + LLVector3(min[0], min[1], max[2]), + LLVector3(min[0], max[1], min[2]), + LLVector3(min[0], max[1], max[2]), + LLVector3(max[0], min[1], min[2]), + LLVector3(max[0], min[1], max[2]), + LLVector3(max[0], max[1], min[2]), + LLVector3(max[0], max[1], max[2]) + }; + + // New extents (to be expanded) + LLVector3 extents[] = + { + LLVector3(mExtents[0].getF32ptr()), + LLVector3(mExtents[1].getF32ptr()) + }; + + LLQuaternion backwardRotation = ~currentTransform.getRotation(); + for (LLVector3& corner : corners) + { + // Make coordinates relative to the current position + corner -= currentTransform.getPosition(); + // Rotate coordinates backward to the current rotation + corner.rotVec(backwardRotation); + // Expand root extents on the current corner + for (int j = 0; j < 3; ++j) + { + if (corner[j] < extents[0][j]) + extents[0][j] = corner[j]; + if (corner[j] > extents[1][j]) + extents[1][j] = corner[j]; + } + } + + // Set new expanded extents + mExtents[0].load3(extents[0].mV); + mExtents[1].load3(extents[1].mV); + + // Calculate new center and size + mBounds[0].setAdd(mExtents[0], mExtents[1]); + mBounds[0].mul(0.5f); + mBounds[1].setSub(mExtents[0], mExtents[1]); + mBounds[1].mul(0.5f); +} BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) { @@ -4152,6 +4205,11 @@ public: if (vobj) { + if (vobj->getClickAction() == CLICK_ACTION_IGNORE && !LLFloater::isVisible(gFloaterTools)) + { + return false; + } + LLVector4a intersection; bool skip_check = false; if (vobj->isAvatar()) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index d0c67fdb0a..366c708178 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -309,6 +309,7 @@ public: BOOL addObject(LLDrawable *drawablep); BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE); BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group + void expandExtents(const LLVector4a* addingExtents, const LLXformMatrix& currentTransform); void shift(const LLVector4a &offset); void destroyGL(bool keep_occlusion = false); @@ -710,8 +711,10 @@ public: class LLControlAVBridge : public LLVolumeBridge { + using super = LLVolumeBridge; public: LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp); + virtual void updateSpatialExtents(); }; class LLHUDBridge : public LLVolumeBridge diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 98cb3b59ec..4af2aac1d4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1021,9 +1021,22 @@ bool idle_startup() #else void* window_handle = NULL; #endif - bool init = gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle()); - if(init) + if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle())) { + if (FALSE == gSavedSettings.getBOOL("UseMediaPluginsForStreamingAudio")) + { + LL_INFOS("AppInit") << "Using default impl to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(gAudiop->createDefaultStreamingAudioImpl()); + } + + // if the audio engine hasn't set up its own preferred handler for streaming audio + // then set up the generic streaming audio implementation which uses media plugins + if (NULL == gAudiop->getStreamingAudioImpl()) + { + LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + } + // Output device selection gAudiop->setDevice(LLUUID(gSavedSettings.getString("FSOutputDeviceUUID"))); @@ -1035,16 +1048,6 @@ bool idle_startup() delete gAudiop; gAudiop = NULL; } - - if (gAudiop) - { - // if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins - if (NULL == gAudiop->getStreamingAudioImpl()) - { - LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; - gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); - } - } } } @@ -4219,7 +4222,7 @@ LLSD transform_cert_args(LLPointer cert) // are actually arrays, and we want to format them as comma separated // strings, so special case those. LLSDSerialize::toXML(cert_info[iter->first], std::cout); - if((iter->first== std::string(CERT_KEY_USAGE)) || + if((iter->first == std::string(CERT_KEY_USAGE)) || (iter->first == std::string(CERT_EXTENDED_KEY_USAGE))) { value = ""; diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 6641c03645..e93261f406 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -1781,7 +1781,7 @@ class LLBalanceHandler : public LLCommandHandler public: // Requires "trusted" browser/URL source LLBalanceHandler() : LLCommandHandler("balance", UNTRUSTED_BLOCK) { } - bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (tokens.size() == 1 && tokens[0].asString() == "request") diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 1b86eb5d7c..412f638b15 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -2410,7 +2410,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response, LL_DEBUGS(LOG_TXT) << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; if (data_size > 0) { - LLViewerStatsRecorder::instance().textureFetch(data_size); // *TODO: set the formatted image data here directly to avoid the copy // Hold on to body for later copy @@ -2476,6 +2475,13 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response, mHaveAllData = TRUE; } mRequestedSize = data_size; + + if (mHaveAllData) + { + LLViewerStatsRecorder::instance().textureFetch(); + } + + // *TODO: set the formatted image data here directly to avoid the copy } else { @@ -2485,11 +2491,6 @@ S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response, mLoaded = TRUE; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - if (LLViewerStatsRecorder::instanceExists()) - { - // Do not create this instance inside thread - LLViewerStatsRecorder::instance().log(0.2f); - } return data_size ; } @@ -3646,8 +3647,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 return false; } - LLViewerStatsRecorder::instance().textureFetch(data_size); - LLViewerStatsRecorder::instance().log(0.1f); + LLViewerStatsRecorder::instance().textureFetch(); worker->lockWorkMutex(); @@ -3698,8 +3698,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 return false; } - LLViewerStatsRecorder::instance().textureFetch(data_size); - LLViewerStatsRecorder::instance().log(0.1f); + LLViewerStatsRecorder::instance().textureFetch(); worker->lockWorkMutex(); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index ab5d90b465..cd90fde11e 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -981,6 +981,8 @@ void LLTextureView::draw() if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID) { +// static S32 debug_count = 0; +// ++debug_count; // for breakpoints } F32 pri; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 136e764d27..0a78718bae 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -103,6 +103,8 @@ private: // Called by LLWorldMap when a region name has been resolved to a // location in-world, used by places-panel display. + static bool handleGrid(const LLSLURL& slurl); + friend class LLTeleportHandler; }; @@ -186,7 +188,7 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl, } bool handled = LLCommandDispatcher::dispatch( - slurl.getAppCmd(), path, query_map, web, nav_type, trusted_browser); + slurl.getAppCmd(), path, query_map, slurl.getGrid(), web, nav_type, trusted_browser); // // alert if we didn't handle this secondlife:///app/ SLURL @@ -219,6 +221,11 @@ bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, const std::string return true; } // +// if (!handleGrid(slurl)) +// { +// return true; +// } + // LLWorldMapMessage::getInstance()->sendNamedRegionRequest(slurl.getRegion(), // // LLURLDispatcherImpl::regionNameCallback, @@ -265,6 +272,31 @@ void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const LLSLURL& s } } +bool LLURLDispatcherImpl::handleGrid(const LLSLURL& slurl) +{ + if (LLGridManager::getInstance()->getGrid(slurl.getGrid()) + != LLGridManager::getInstance()->getGrid()) + { + LLSD args; + args["SLURL"] = slurl.getLocationString(); + args["CURRENT_GRID"] = LLGridManager::getInstance()->getGridLabel(); + std::string grid_label = + LLGridManager::getInstance()->getGridLabel(slurl.getGrid()); + + if (!grid_label.empty()) + { + args["GRID"] = grid_label; + } + else + { + args["GRID"] = slurl.getGrid(); + } + LLNotificationsUtil::add("CantTeleportToGrid", args); + return false; + } + return true; +} + /* static */ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const LLSLURL& slurl, const LLUUID& snapshot_id, bool teleport) { @@ -339,8 +371,10 @@ public: &LLTeleportHandler::from_event); } - bool handle(const LLSD& tokens, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& tokens, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { // construct a "normal" SLURL, resolve the region to // a global position, and teleport to it @@ -350,19 +384,19 @@ public: #ifdef OPENSIM LLSLURL slurl(tokens, true); - std::string grid = slurl.getGrid(); - std::string gatekeeper = LLGridManager::getInstance()->getGatekeeper(grid); + std::string url_grid = slurl.getGrid(); + std::string gatekeeper = LLGridManager::getInstance()->getGatekeeper(url_grid); std::string region_name = slurl.getRegion(); std::string dest; std::string current = LLGridManager::getInstance()->getGrid(); - if ((grid != current) && (!LLGridManager::getInstance()->isInOpenSim() || (!slurl.getHypergrid() && gatekeeper.empty()))) + if ((url_grid != current) && (!LLGridManager::getInstance()->isInOpenSim() || (!slurl.getHypergrid() && gatekeeper.empty()))) { dest = slurl.getSLURLString(); if (!dest.empty()) { LLSD args; args["SLURL"] = dest; - args["GRID"] = grid; + args["GRID"] = url_grid; args["CURRENT_GRID"] = current; LLNotificationsUtil::add("CantTeleportToGrid", args); return true; @@ -397,7 +431,7 @@ public: std::string region_name = LLURI::unescape(tokens[0]); - std::string callback_url = LLSLURL(region_name, coords).getSLURLString(); + std::string callback_url = LLSLURL(url_grid, region_name, coords).getSLURLString(); #endif // OPENSIM // diff --git a/indra/newview/llviewerattachmenu.cpp b/indra/newview/llviewerattachmenu.cpp index ed0a2fe342..cce9a5f7a4 100644 --- a/indra/newview/llviewerattachmenu.cpp +++ b/indra/newview/llviewerattachmenu.cpp @@ -90,8 +90,11 @@ void LLViewerAttachMenu::populateMenus(const std::string& attach_to_menu_name, c } // FIRE-21200: Attachment Points List in Alphabetical Order - attach_menu->getItems()->sort(LLViewerAttachMenu::sort()); - attach_hud_menu->getItems()->sort(LLViewerAttachMenu::sort()); + if (gSavedSettings.getBOOL("FSSortAttachmentSpotsAlphabetically")) + { + attach_menu->getItems()->sort(LLViewerAttachMenu::sort()); + attach_hud_menu->getItems()->sort(LLViewerAttachMenu::sort()); + } // } diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index eaae615117..2fab112aa2 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -97,7 +97,13 @@ void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI // } - // Record the URI we are going to be switching to + if (!gAudiop) + { + LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; + return; + } + + // Record the URI we are going to be switching to mNextStreamURI = streamURI; // Optional audio stream fading @@ -111,11 +117,6 @@ void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI switch (mFadeState) { case FADE_IDLE: - if (!gAudiop) - { - LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; - break; - } // If a stream is playing fade it out first if (!gAudiop->getInternetStreamURL().empty()) { @@ -128,28 +129,28 @@ void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI mFadeState = FADE_IN; LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl(); - if(stream && stream->supportsAdjustableBufferSizes()) - stream->setBufferSizes(gSavedSettings.getU32("FMODStreamBufferSize"),gSavedSettings.getU32("FMODDecodeBufferSize")); + if (stream && stream->supportsAdjustableBufferSizes()) + stream->setBufferSizes(gSavedSettings.getU32("FMODStreamBufferSize"), gSavedSettings.getU32("FMODDecodeBufferSize")); gAudiop->startInternetStream(mNextStreamURI); - startFading(); - registerIdleListener(); - break; } + startFading(); + break; + case FADE_OUT: startFading(); - registerIdleListener(); break; case FADE_IN: - registerIdleListener(); break; default: LL_WARNS() << "Unknown fading state: " << mFadeState << LL_ENDL; - break; + return; } + + registerIdleListener(); } // A return of false from onIdleUpdate means it will be called again next idle update. @@ -263,15 +264,12 @@ void LLViewerAudio::startFading() // This minimum fade time prevents divide by zero and negative times const F32 AUDIO_MUSIC_MINIMUM_FADE_TIME = 0.01f; - if(mDone) + if (mDone) { // The fade state here should only be one of FADE_IN or FADE_OUT, but, in case it is not, // rather than check for both states assume a fade in and check for the fade out case. - mFadeTime = AUDIO_MUSIC_FADE_IN_TIME; - if (LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT) - { - mFadeTime = AUDIO_MUSIC_FADE_OUT_TIME; - } + mFadeTime = LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT ? + AUDIO_MUSIC_FADE_OUT_TIME : AUDIO_MUSIC_FADE_IN_TIME; // Prevent invalid fade time mFadeTime = llmax(mFadeTime, AUDIO_MUSIC_MINIMUM_FADE_TIME); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 4fdfae515f..7b8bae17af 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -328,6 +328,7 @@ public: bool handle( const LLSD& params, const LLSD& query_map, + const std::string& grid, LLMediaCtrl* web) override { if (params.size() != 1) diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp index 1aa99ff382..c97c8c714b 100644 --- a/indra/newview/llviewerhelp.cpp +++ b/indra/newview/llviewerhelp.cpp @@ -46,7 +46,7 @@ public: // requests will be throttled from a non-trusted browser LLHelpHandler() : LLCommandHandler("help", UNTRUSTED_CLICK_ONLY) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { LLViewerHelp* vhelp = LLViewerHelp::getInstance(); if (! vhelp) diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 430fd1a86a..9e30b4a06b 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1710,9 +1710,9 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, // If the first LMB click is handled by the menu, skip the following double click static bool skip_double_click = false; - if (clicktype == CLICK_LEFT && down && !is_toolmgr_action) + if (clicktype == CLICK_LEFT && down) { - skip_double_click = handled; + skip_double_click = is_toolmgr_action ? false : handled; } if (double_click_sp && down) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 04b2b1de68..bd986760ae 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -237,8 +237,10 @@ public: // requires trusted browser to trigger LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) { if (params.size() < 1) { diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index 5a13731915..959e14e22e 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -63,6 +63,7 @@ LLViewerMediaFocus::~LLViewerMediaFocus() { // The destructor for LLSingletons happens at atexit() time, which is too late to do much. // Clean up in cleanupClass() instead. + gFocusMgr.removeKeyboardFocusWithoutCallback(this); } void LLViewerMediaFocus::setFocusFace(LLPointer objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4c819fc2e1..08860a9d6a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -123,8 +123,10 @@ #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" #include "llviewerstats.h" +#include "llviewerstatsrecorder.h" #include "llvoavatarself.h" #include "llvoicevivox.h" +#include "llworld.h" #include "llworldmap.h" #include "pipeline.h" #include "llviewerjoystick.h" @@ -391,6 +393,7 @@ void handle_debug_avatar_textures(void*); void handle_grab_baked_texture(void*); BOOL enable_grab_baked_texture(void*); void handle_dump_region_object_cache(void*); +void handle_reset_interest_lists(void *); BOOL enable_save_into_task_inventory(void*); @@ -1480,85 +1483,66 @@ class LLAdvancedDumpRegionObjectCache : public view_listener_t } }; -// Handle InterestListFullUpdate as a proper state toggle -// class LLAdvancedInterestListFullUpdate : public view_listener_t -// { -// bool handleEvent(const LLSD& userdata) -// { -// LLSD request; -// LLSD body; -// static bool using_360 = false; +class LLAdvancedToggleInterestList360Mode : public view_listener_t +{ +public: + bool handleEvent(const LLSD &userdata) + { + // Toggle the mode - regions will get updated + if (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360) + { + gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_DEFAULT); + } + else + { + gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360); + } + return true; + } +}; -// if (using_360) -// { -// body["mode"] = LLSD::String("default"); -// } -// else -// { -// body["mode"] = LLSD::String("360"); -// } -// using_360 = !using_360; - -// if (gAgent.requestPostCapability("InterestList", body, [](const LLSD& response) -// { -// LL_INFOS("Int") << -// "InterestList capability responded: \n" << -// ll_pretty_print_sd(response) << -// LL_ENDL; -// })) -// { -// LL_INFOS("360Capture") << -// "Successfully posted an InterestList capability request with payload: \n" << -// ll_pretty_print_sd(body) << -// LL_ENDL; -// return true; -// } -// else -// { -// LL_INFOS("360Capture") << -// "Unable to post an InterestList capability request with payload: \n" << -// ll_pretty_print_sd(body) << -// LL_ENDL; -// return false; -// } -// } -// }; -class LLAdvancedCheckInterestListFullUpdate : public view_listener_t +class LLAdvancedCheckInterestList360Mode : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLViewerRegion* regionp = gAgent.getRegion(); - if (regionp) - { - bool current_value = ( regionp->mFullUpdateInUseCount > 0 ); - return current_value; - } - return false; + return (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360); } }; -class LLAdvancedToggleInterestListFullUpdate : public view_listener_t + +class LLAdvancedToggleStatsRecorder : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerRegion* regionp = gAgent.getRegion(); - if (regionp) - { - bool current_value = ( regionp->mFullUpdateInUseCount > 0 ); - if(current_value) - { - regionp->useFullUpdateInterestListMode(false, true); - return false; - } - else - { - regionp->useFullUpdateInterestListMode(true); - return true; - } + bool handleEvent(const LLSD &userdata) + { + if (LLViewerStatsRecorder::instance().isEnabled()) + { // Turn off both recording and logging + LLViewerStatsRecorder::instance().enableObjectStatsRecording(false); } - return false; - } + else + { // Turn on both recording and logging + LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true); + } + return true; + } }; -// + +class LLAdvancedCheckStatsRecorder : public view_listener_t +{ + bool handleEvent(const LLSD &userdata) + { // Use the logging state as the indicator of whether the stats recorder is on + return LLViewerStatsRecorder::instance().isLogging(); + } +}; + +class LLAdvancedResetInterestLists : public view_listener_t +{ + bool handleEvent(const LLSD &userdata) + { // Reset all region interest lists + handle_reset_interest_lists(NULL); + return true; + } +}; + + class LLAdvancedBuyCurrencyTest : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -4792,6 +4776,22 @@ void handle_dump_region_object_cache(void*) } } +void handle_reset_interest_lists(void *) +{ + // Check all regions and reset their interest list + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); + ++iter) + { + LLViewerRegion *regionp = *iter; + if (regionp && regionp->isAlive() && regionp->capabilitiesReceived()) + { + regionp->resetInterestList(); + } + } +} + + void handle_dump_focus() { LLUICtrl *ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus()); @@ -5733,33 +5733,6 @@ void handle_duplicate_in_place(void*) LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE); } -/* dead code 30-apr-2008 -void handle_deed_object_to_group(void*) -{ - LLUUID group_id; - - LLSelectMgr::getInstance()->selectGetGroup(group_id); - LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT); -} - -BOOL enable_deed_object_to_group(void*) -{ - if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) return FALSE; - LLPermissions perm; - LLUUID group_id; - - if (LLSelectMgr::getInstance()->selectGetGroup(group_id) && - gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && - LLSelectMgr::getInstance()->selectGetPermissions(perm) && - perm.deedToGroup(gAgent.getID(), group_id)) - { - return TRUE; - } - return FALSE; -} - -*/ /* @@ -11632,6 +11605,25 @@ class LLWorldPostProcess : public view_listener_t } }; +class LLWorldCheckBanLines : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + S32 callback_data = userdata.asInteger(); + return gSavedSettings.getS32("ShowBanLines") == callback_data; + } +}; + +class LLWorldShowBanLines : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + S32 callback_data = userdata.asInteger(); + gSavedSettings.setS32("ShowBanLines", callback_data); + return true; + } +}; + void handle_flush_name_caches() { // Crash fix @@ -12170,6 +12162,8 @@ void initialize_menus() view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset"); view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset"); view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess"); + view_listener_t::addMenu(new LLWorldCheckBanLines() , "World.CheckBanLines"); + view_listener_t::addMenu(new LLWorldShowBanLines() , "World.ShowBanLines"); // Tools menu view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); @@ -12274,12 +12268,11 @@ void initialize_menus() // Advanced > World view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera"); view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache"); - - // Make InterestList a proper stateful toggle - // view_listener_t::addMenu(new LLAdvancedInterestListFullUpdate(), "Advanced.InterestListFullUpdate"); - view_listener_t::addMenu(new LLAdvancedCheckInterestListFullUpdate(), "Advanced.CheckInterestListFullUpdate"); - view_listener_t::addMenu(new LLAdvancedToggleInterestListFullUpdate(), "Advanced.ToggleInterestListFullUpdate"); - // + view_listener_t::addMenu(new LLAdvancedToggleStatsRecorder(), "Advanced.ToggleStatsRecorder"); + view_listener_t::addMenu(new LLAdvancedCheckStatsRecorder(), "Advanced.CheckStatsRecorder"); + view_listener_t::addMenu(new LLAdvancedToggleInterestList360Mode(), "Advanced.ToggleInterestList360Mode"); + view_listener_t::addMenu(new LLAdvancedCheckInterestList360Mode(), "Advanced.CheckInterestList360Mode"); + view_listener_t::addMenu(new LLAdvancedResetInterestLists(), "Advanced.ResetInterestLists"); // Advanced > UI commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 2cdca20243..7735b1af94 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -103,6 +103,7 @@ #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" #include "llviewerstats.h" +#include "llviewerstatsrecorder.h" #include "llviewertexteditor.h" #include "llviewerthrottle.h" #include "llviewerwindow.h" @@ -4675,68 +4676,71 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) continue; } - LLViewerObject *objectp = gObjectList.findObject(id); - if (objectp) + LLViewerObject *objectp = gObjectList.findObject(id); + if (objectp) + { + // FIRE-12004: Attachments getting lost on TP + static LLCachedControl fsExperimentalLostAttachmentsFix(gSavedSettings, "FSExperimentalLostAttachmentsFix"); + static LLCachedControl fsExperimentalLostAttachmentsFixKillDelay(gSavedSettings, "FSExperimentalLostAttachmentsFixKillDelay"); + if (fsExperimentalLostAttachmentsFix && + isAgentAvatarValid() && + (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE || gPostTeleportFinishKillObjectDelayTimer.getElapsedTimeF32() <= fsExperimentalLostAttachmentsFixKillDelay || gAgentAvatarp->isCrossingRegion()) && + (objectp->isAttachment() || objectp->isTempAttachment()) && + objectp->permYouOwner()) { - // FIRE-12004: Attachments getting lost on TP - static LLCachedControl fsExperimentalLostAttachmentsFix(gSavedSettings, "FSExperimentalLostAttachmentsFix"); - static LLCachedControl fsExperimentalLostAttachmentsFixKillDelay(gSavedSettings, "FSExperimentalLostAttachmentsFixKillDelay"); - if (fsExperimentalLostAttachmentsFix && - isAgentAvatarValid() && - (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE || gPostTeleportFinishKillObjectDelayTimer.getElapsedTimeF32() <= fsExperimentalLostAttachmentsFixKillDelay || gAgentAvatarp->isCrossingRegion()) && - (objectp->isAttachment() || objectp->isTempAttachment()) && - objectp->permYouOwner()) + // Simply ignore the request and don't kill the object - this should work... + + std::string reason; + if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) { - // Simply ignore the request and don't kill the object - this should work... - - std::string reason; - if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE) - { - reason = "tp"; - } - else if (gAgentAvatarp->isCrossingRegion()) - { - reason = "crossing"; - } - else - { - reason = "timer"; - gFSRefreshAttachmentsTimer.triggerRefresh(); - } - std::string message = "Region \"" + regionp->getName() + "\" tried to kill attachment: " + objectp->getAttachmentItemName() + " (" + reason + ") - Agent region: \"" + gAgent.getRegion()->getName() + "\""; - LL_WARNS("Messaging") << message << LL_ENDL; - - if (gSavedSettings.getBOOL("FSExperimentalLostAttachmentsFixReport")) - { - report_to_nearby_chat(message); - } - - continue; + reason = "tp"; } - // - - // Display green bubble on kill - if ( gShowObjectUpdates ) + else if (gAgentAvatarp->isCrossingRegion()) { - LLColor4 color(0.f,1.f,0.f,1.f); - gPipeline.addDebugBlip(objectp->getPositionAgent(), color); - LL_DEBUGS("MessageBlip") << "Kill blip for local " << local_id << " at " << objectp->getPositionAgent() << LL_ENDL; + reason = "crossing"; + } + else + { + reason = "timer"; + gFSRefreshAttachmentsTimer.triggerRefresh(); + } + std::string message = "Region \"" + regionp->getName() + "\" tried to kill attachment: " + objectp->getAttachmentItemName() + " (" + reason + ") - Agent region: \"" + gAgent.getRegion()->getName() + "\""; + LL_WARNS("Messaging") << message << LL_ENDL; + + if (gSavedSettings.getBOOL("FSExperimentalLostAttachmentsFixReport")) + { + report_to_nearby_chat(message); } - // Do the kill - gObjectList.killObject(objectp); + continue; + } + // + + // Display green bubble on kill + if ( gShowObjectUpdates ) + { + LLColor4 color(0.f,1.f,0.f,1.f); + gPipeline.addDebugBlip(objectp->getPositionAgent(), color); + LL_DEBUGS("MessageBlip") << "Kill blip for local " << local_id << " at " << objectp->getPositionAgent() << LL_ENDL; } - if(delete_object) - { - regionp->killCacheEntry(local_id); + // Do the kill + gObjectList.killObject(objectp); + } + + if(delete_object) + { + regionp->killCacheEntry(local_id); } // We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab, // which is using the object, release the mouse capture correctly when the object dies. // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical(). LLSelectMgr::getInstance()->removeObjectFromSelections(id); - } + + } // end for loop + + LLViewerStatsRecorder::instance().recordObjectKills(num_objects); } // area search @@ -6459,6 +6463,11 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) LandBuyAccessBlocked_AdultsOnlyContent -----------------------------------------------------------------------*/ + static LLCachedControl ban_lines_mode(gSavedSettings , "ShowBanLines" , LLViewerParcelMgr::PARCEL_BAN_LINES_ON_COLLISION); + if (ban_lines_mode == LLViewerParcelMgr::PARCEL_BAN_LINES_ON_COLLISION) + { + LLViewerParcelMgr::getInstance()->resetCollisionTimer(); + } if (handle_special_notification(notificationID, llsdBlock)) { return true; @@ -6664,6 +6673,13 @@ void process_alert_message(LLMessageSystem *msgsystem, void **user_data) { BOOL modal = FALSE; process_alert_core(message, modal); + + static LLCachedControl ban_lines_mode(gSavedSettings , "ShowBanLines" , LLViewerParcelMgr::PARCEL_BAN_LINES_ON_COLLISION); + if (ban_lines_mode == LLViewerParcelMgr::PARCEL_BAN_LINES_ON_COLLISION + && message.find("Cannot enter parcel") != std::string::npos) + { + LLViewerParcelMgr::getInstance()->resetCollisionTimer(); + } } } diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 2c5a68deab..2f700af553 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -417,7 +417,7 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* if (!objectp) { LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL; - recorder.objectUpdateFailure(entry->getLocalID(), OUT_FULL_CACHED, 0); + recorder.objectUpdateFailure(); return NULL; } justCreated = true; @@ -441,7 +441,6 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* objectp->setLastUpdateType(OUT_FULL_COMPRESSED); //newly cached objectp->setLastUpdateCached(TRUE); } - recorder.log(0.2f); LLVOAvatar::cullAvatarsByPixelArea(); return objectp; @@ -520,18 +519,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, for (i = 0; i < num_objects; i++) { - // timer is unused? - LLTimer update_timer; BOOL justCreated = FALSE; - S32 msg_size = 0; bool update_cache = false; //update object cache if it is a full-update or terse update if (compressed) { - S32 uncompressed_length = 2048; compressed_dp.reset(); - uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); + S32 uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); LL_DEBUGS("ObjectUpdate") << "got binary data from message to compressed_dpbuffer" << LL_ENDL; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i, 2048); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); @@ -553,7 +548,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, << " Flags: " << flags << " Region: " << regionp->getName() << " Region id: " << regionp->getRegionID() << LL_ENDL; - recorder.objectUpdateFailure(local_id, update_type, msg_size); + recorder.objectUpdateFailure(); continue; } else if ((flags & FLAGS_TEMPORARY_ON_REZ) == 0) @@ -581,7 +576,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only? { mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); - msg_size += sizeof(U32); getUUIDFromLocal(fullid, local_id, @@ -602,8 +596,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, update_cache = true; mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); - msg_size += sizeof(LLUUID); - msg_size += sizeof(U32); LL_DEBUGS("ObjectUpdate") << "Full Update, obj " << local_id << ", global ID " << fullid << " from " << mesgsys->getSender() << LL_ENDL; } objectp = findObject(fullid); @@ -664,7 +656,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (update_type == OUT_TERSE_IMPROVED) { // LL_INFOS() << "terse update for an unknown object (compressed):" << fullid << LL_ENDL; - recorder.objectUpdateFailure(local_id, update_type, msg_size); + recorder.objectUpdateFailure(); continue; } } @@ -673,12 +665,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (update_type != OUT_FULL) { //LL_INFOS() << "terse update for an unknown object:" << fullid << LL_ENDL; - recorder.objectUpdateFailure(local_id, update_type, msg_size); + recorder.objectUpdateFailure(); continue; } mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); - msg_size += sizeof(U8); } #ifdef IGNORE_DEAD @@ -686,7 +677,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { mNumDeadObjectUpdates++; //LL_INFOS() << "update for a dead object:" << fullid << LL_ENDL; - recorder.objectUpdateFailure(local_id, update_type, msg_size); + recorder.objectUpdateFailure(); continue; } #endif @@ -713,7 +704,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if (!objectp) { LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL; - recorder.objectUpdateFailure(local_id, update_type, msg_size); + recorder.objectUpdateFailure(); continue; } @@ -747,11 +738,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, if(!(flags & FLAGS_TEMPORARY_ON_REZ)) { - bCached = true; + bCached = true; LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags); - recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); + recorder.cacheFullUpdate(result); + } } - } #endif } else @@ -762,12 +753,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); } - recorder.objectUpdateEvent(local_id, update_type, objectp, msg_size); + recorder.objectUpdateEvent(update_type); objectp->setLastUpdateType(update_type); } - recorder.log(0.2f); - LLVOAvatar::cullAvatarsByPixelArea(); } @@ -800,28 +789,26 @@ void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys, for (S32 i = 0; i < num_objects; i++) { - S32 msg_size = 0; U32 id; U32 crc; U32 flags; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - msg_size += sizeof(U32) * 2; LL_DEBUGS("ObjectUpdate") << "got probe for id " << id << " crc " << crc << LL_ENDL; dumpStack("ObjectUpdateStack"); // Lookup data packer and add this id to cache miss lists if necessary. U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; - if(!regionp->probeCache(id, crc, flags, cache_miss_type)) - { - // Cache Miss. + if (regionp->probeCache(id, crc, flags, cache_miss_type)) + { // Cache Hit + recorder.cacheHitEvent(); + } + else + { // Cache Miss LL_DEBUGS("ObjectUpdate") << "cache miss for id " << id << " crc " << crc << " miss type " << (S32) cache_miss_type << LL_ENDL; - - recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size); - - continue; // no data packer, skip this object + recorder.cacheMissEvent(cache_miss_type); } } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 12d889cadb..8f675ee1ac 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -72,12 +72,16 @@ #include "llenvironment.h" -const F32 PARCEL_COLLISION_DRAW_SECS = 1.f; +const F32 PARCEL_BAN_LINES_DRAW_SECS_ON_COLLISION = 10.f; +const F32 PARCEL_COLLISION_DRAW_SECS_ON_PROXIMITY = 1.f; // Globals U8* LLViewerParcelMgr::sPackedOverlay = NULL; +S32 LLViewerParcelMgr::PARCEL_BAN_LINES_HIDE = 0; +S32 LLViewerParcelMgr::PARCEL_BAN_LINES_ON_COLLISION = 1; +S32 LLViewerParcelMgr::PARCEL_BAN_LINES_ON_PROXIMITY = 2; LLUUID gCurrentMovieID = LLUUID::null; @@ -940,13 +944,18 @@ void LLViewerParcelMgr::render() void LLViewerParcelMgr::renderParcelCollision() { + static LLCachedControl ban_lines_mode(gSavedSettings , "ShowBanLines" , PARCEL_BAN_LINES_ON_COLLISION); + // check for expiration - if (mCollisionTimer.getElapsedTimeF32() > PARCEL_COLLISION_DRAW_SECS) + F32 expiration = (ban_lines_mode == PARCEL_BAN_LINES_ON_PROXIMITY) + ? PARCEL_COLLISION_DRAW_SECS_ON_PROXIMITY + : PARCEL_BAN_LINES_DRAW_SECS_ON_COLLISION; + if (mCollisionTimer.getElapsedTimeF32() > expiration) { - mRenderCollision = FALSE; + mRenderCollision = false; } - if (mRenderCollision && gSavedSettings.getBOOL("ShowBanLines")) + if (mRenderCollision && ban_lines_mode != PARCEL_BAN_LINES_HIDE) { LLViewerRegion* regionp = gAgent.getRegion(); if (regionp) @@ -1914,8 +1923,11 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID) { // We're about to collide with this parcel - parcel_mgr.mRenderCollision = TRUE; - parcel_mgr.mCollisionTimer.reset(); + static LLCachedControl ban_lines_mode(gSavedSettings , "ShowBanLines" , PARCEL_BAN_LINES_ON_COLLISION); + if (ban_lines_mode == PARCEL_BAN_LINES_ON_PROXIMITY) + { + parcel_mgr.resetCollisionTimer(); + } // Differentiate this parcel if we are banned from it. if (sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID) diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index aef09cfa96..a44fff021d 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -219,6 +219,11 @@ public: void renderHighlightSegments(const U8* segments, LLViewerRegion* regionp); void renderCollisionSegments(U8* segments, BOOL use_pass, LLViewerRegion* regionp); + static S32 PARCEL_BAN_LINES_HIDE; + static S32 PARCEL_BAN_LINES_ON_COLLISION; + static S32 PARCEL_BAN_LINES_ON_PROXIMITY; + void resetCollisionTimer(); // Ban lines visibility timer + void sendParcelGodForceOwner(const LLUUID& owner_id); // make the selected parcel a content parcel. @@ -380,7 +385,7 @@ private: collision_update_signal_t* mCollisionUpdateSignal; // [/SL:KB] U8* mCollisionSegments; - BOOL mRenderCollision; + bool mRenderCollision; BOOL mRenderSelection; S32 mCollisionBanned; LLFrameTimer mCollisionTimer; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 4e069b5842..1cfc8629da 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -112,6 +112,9 @@ S32 LLViewerRegion::sLastCameraUpdated = 0; S32 LLViewerRegion::sNewObjectCreationThrottle = -1; LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup; +const std::string LLViewerRegion::IL_MODE_DEFAULT = "default"; +const std::string LLViewerRegion::IL_MODE_360 = "360"; + typedef std::map CapabilityMap; static void log_capabilities(const CapabilityMap &capmap); @@ -139,8 +142,8 @@ class LLRegionHandler : public LLCommandHandler public: // requests will be throttled from a non-trusted browser LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} - - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { // make sure that we at least have a region name int num_params = params.size(); @@ -151,6 +154,10 @@ public: // build a secondlife://{PLACE} SLurl from this SLapp std::string url = "secondlife://"; + if (!grid.empty()) + { + url += grid + "/secondlife/"; + } boost::regex name_rx("[A-Za-z0-9()_%]+"); boost::regex coord_rx("[0-9]+"); for (int i = 0; i < num_params; i++) @@ -657,6 +664,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mPaused(FALSE), mRegionCacheHitCount(0), mRegionCacheMissCount(0), + mInterestListMode(IL_MODE_DEFAULT), // BOM tests for OS mMaxBakes(LLGridManager::getInstance()->isInSecondLife()? LLAvatarAppearanceDefines::EBakedTextureIndex::BAKED_NUM_INDICES: @@ -1728,7 +1736,6 @@ BOOL LLViewerRegion::isViewerCameraStatic() void LLViewerRegion::killInvisibleObjects(F32 max_time) { - if(sFSAreaSearchActive){ return; } // FIRE-32668 Area Search improvements if(!sVOCacheCullingEnabled) { return; @@ -2832,14 +2839,10 @@ LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid) return NULL; } -void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type) +void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType cache_miss_type) { mRegionCacheMissCount++; -#if 0 - mCacheMissList.insert(CacheMissItem(id, miss_type)); -#else - mCacheMissList.push_back(CacheMissItem(id, miss_type)); -#endif + mCacheMissList.push_back(CacheMissItem(id, cache_miss_type)); } //check if a non-cacheable object is already created. @@ -2915,10 +2918,10 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss } } else - { + { // Total miss, don't have the object in cache // LL_INFOS() << "Cache miss for " << local_id << LL_ENDL; - addCacheMiss(local_id, CACHE_MISS_TYPE_FULL); - cache_miss_type = CACHE_MISS_TYPE_FULL; + addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL); + cache_miss_type = CACHE_MISS_TYPE_TOTAL; } return false; @@ -2926,7 +2929,7 @@ bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss void LLViewerRegion::addCacheMissFull(const U32 local_id) { - addCacheMiss(local_id, CACHE_MISS_TYPE_FULL); + addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL); } void LLViewerRegion::requestCacheMisses() @@ -2977,7 +2980,6 @@ void LLViewerRegion::requestCacheMisses() mCacheDirty = TRUE ; // LL_INFOS() << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << LL_ENDL; LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size()); - LLViewerStatsRecorder::instance().log(0.2f); mCacheMissList.clear(); } @@ -3537,6 +3539,9 @@ void LLViewerRegion::setCapabilitiesReceived(bool received) // This is a single-shot signal. Forget callbacks to save resources. mCapabilitiesReceivedSignal.disconnect_all_slots(); + + // Set the region to the desired interest list mode + setInterestListMode(gAgent.getInterestListMode()); } } @@ -3555,54 +3560,111 @@ void LLViewerRegion::logActiveCapabilities() const log_capabilities(mImpl->mCapabilities); } -// Area Search improvement -void LLViewerRegion::useFullUpdateInterestListMode(bool send_everything, bool force_update) + +bool LLViewerRegion::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure) { - static const char *FSLogTag = "InterestListMode"; - U32 previousCount = mFullUpdateInUseCount; - LLSD body; - LL_DEBUGS(FSLogTag) << "useFullUpdateInterestListMode" << " send_everything:" << send_everything << " inUse: " << mFullUpdateInUseCount << LL_ENDL; - if (send_everything) + std::string url = getCapability(capName); + + if (url.empty()) + { + LL_WARNS("Region") << "Could not retrieve region " << getRegionID() + << " POST capability \"" << capName << "\"" << LL_ENDL; + return false; + } + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, gAgent.getAgentPolicy(), postData, cbSuccess, cbFailure); + return true; +} + +bool LLViewerRegion::requestGetCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure) +{ + std::string url; + + url = getCapability(capName); + + if (url.empty()) + { + LL_WARNS("Region") << "Could not retrieve region " << getRegionID() + << " GET capability \"" << capName << "\"" << LL_ENDL; + return false; + } + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(url, gAgent.getAgentPolicy(), cbSuccess, cbFailure); + return true; +} + +bool LLViewerRegion::requestDelCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure) +{ + std::string url; + + url = getCapability(capName); + + if (url.empty()) + { + LL_WARNS("Region") << "Could not retrieve region " << getRegionID() << " DEL capability \"" << capName << "\"" << LL_ENDL; + return false; + } + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpDel(url, gAgent.getAgentPolicy(), cbSuccess, cbFailure); + return true; +} + +void LLViewerRegion::setInterestListMode(const std::string &new_mode) +{ + if (new_mode != mInterestListMode) + { + mInterestListMode = new_mode; + + if (mInterestListMode != std::string(IL_MODE_DEFAULT) && mInterestListMode != std::string(IL_MODE_360)) + { + LL_WARNS("360Capture") << "Region " << getRegionID() << " setInterestListMode() invalid interest list mode: " + << mInterestListMode << ", setting to default" << LL_ENDL; + mInterestListMode = IL_MODE_DEFAULT; + } + + LLSD body; + body["mode"] = mInterestListMode; + if (requestPostCapability("InterestList", body, + [](const LLSD &response) { + LL_DEBUGS("360Capture") << "InterestList capability responded: \n" + << ll_pretty_print_sd(response) << LL_ENDL; + })) + { + LL_DEBUGS("360Capture") << "Region " << getRegionID() + << " Successfully posted an InterestList capability request with payload: \n" + << ll_pretty_print_sd(body) << LL_ENDL; + } + else + { + LL_WARNS("360Capture") << "Region " << getRegionID() + << " Unable to post an InterestList capability request with payload: \n" + << ll_pretty_print_sd(body) << LL_ENDL; + } + } + else + { + LL_DEBUGS("360Capture") << "Region " << getRegionID() << "No change, skipping Interest List mode POST to " + << new_mode << " mode" << LL_ENDL; + } +} + + +void LLViewerRegion::resetInterestList() +{ + if (requestDelCapability("InterestList", [](const LLSD &response) { + LL_DEBUGS("360Capture") << "InterestList capability DEL responded: \n" << ll_pretty_print_sd(response) << LL_ENDL; + })) { - body["mode"] = LLSD::String("360"); - mFullUpdateInUseCount++; // we increment irrespective of the actual success as we're really just tracking the attempts. + LL_DEBUGS("360Capture") << "Region " << getRegionID() << " Successfully reset InterestList capability" << LL_ENDL; } else { - if(mFullUpdateInUseCount > 0) - { - mFullUpdateInUseCount--; // see above. - } - if(force_update) - { - mFullUpdateInUseCount=0; // when we are forcing the off state then we need to clear the count to zero. - } - body["mode"] = LLSD::String("default"); + LL_WARNS("360Capture") << "Region " << getRegionID() << " Unable to DEL InterestList capability request" << LL_ENDL; } - - if( force_update || ( send_everything && mFullUpdateInUseCount == 1 ) || ( ( !send_everything ) && mFullUpdateInUseCount == 0 && previousCount != 0) ) // Only send if this is the first enable or last disable. - { - if (gAgent.requestPostCapability("InterestList", body, - [](const LLSD &response) - { - LL_INFOS(FSLogTag) << "InterestList capability responded: \n" - << ll_pretty_print_sd(response) << LL_ENDL; - })) - { - LL_INFOS(FSLogTag) << "Successfully posted an InterestList capability request with payload: \n" - << ll_pretty_print_sd(body) << LL_ENDL; - } - else - { - LL_INFOS(FSLogTag) << "Unable to post an InterestList capability request with payload: \n" - << ll_pretty_print_sd(body) << LL_ENDL; - } - } - LL_DEBUGS(FSLogTag) << "useFullUpdateInterestListMode" << " (AFTER): inUse: " << mFullUpdateInUseCount << LL_ENDL; } -// -LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) + +LLSpatialPartition *LLViewerRegion::getSpatialPartition(U32 type) { if (type < mImpl->mObjectPartition.size() && type < PARTITION_VO_CACHE) { diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index e1ab37b890..b07578df75 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -32,6 +32,7 @@ #include #include +#include "llcorehttputil.h" #include "llwind.h" #include "v3dmath.h" #include "llstring.h" @@ -294,6 +295,16 @@ public: static bool isSpecialCapabilityName(const std::string &name); void logActiveCapabilities() const; + // Utilities to post and get via + // HTTP using the agent's policy settings and headers. + typedef LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t httpCallback_t; + bool requestPostCapability(const std::string &capName, + LLSD &postData, + httpCallback_t cbSuccess = NULL, + httpCallback_t cbFailure = NULL); + bool requestGetCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); + bool requestDelCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); + /// implements LLCapabilityProvider /*virtual*/ const LLHost& getHost() const; const U64 &getHandle() const { return mHandle; } @@ -351,11 +362,7 @@ public: bool dynamicPathfindingEnabled() const; bool avatarHoverHeightEnabled() const; -// Area search improvements - U32 mFullUpdateInUseCount {0}; - void clearFullUpdateInterestList(){ LL_DEBUGS("InterestListMode") << "Resetting for previous region" << LL_ENDL; mFullUpdateInUseCount = 0; }; - void useFullUpdateInterestListMode(bool full_update, bool force_update=false); -// + // #ifdef OPENSIM std::set getGods() { return mGodNames; }; @@ -364,9 +371,9 @@ public: typedef enum { - CACHE_MISS_TYPE_FULL = 0, - CACHE_MISS_TYPE_CRC, - CACHE_MISS_TYPE_NONE + CACHE_MISS_TYPE_TOTAL = 0, // total cache miss - object not in cache + CACHE_MISS_TYPE_CRC, // object in cache, but CRC doesn't match + CACHE_MISS_TYPE_NONE // not a miss: cache hit } eCacheMissType; typedef enum @@ -513,7 +520,15 @@ public: }; typedef std::set region_priority_list_t; -private: + void setInterestListMode(const std::string & new_mode); + const std::string & getInterestListMode() const { return mInterestListMode; } + + void resetInterestList(); + + static const std::string IL_MODE_DEFAULT; + static const std::string IL_MODE_360; + + private: static S32 sNewObjectCreationThrottle; LLViewerRegionImpl * mImpl; LLFrameTimer mRegionTimer; @@ -600,10 +615,10 @@ private: class CacheMissItem { public: - CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type){} + CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type) {} - U32 mID; //local object id - LLViewerRegion::eCacheMissType mType; //cache miss type + U32 mID; //local object id + LLViewerRegion::eCacheMissType mType; // cache miss type typedef std::list cache_miss_list_t; }; @@ -623,6 +638,9 @@ private: LLFrameTimer mMaterialsCapThrottleTimer; LLFrameTimer mRenderInfoRequestTimer; LLFrameTimer mRenderInfoReportTimer; + + // how the server interest list works + std::string mInterestListMode; }; inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp index b5ccf4ffa0..6372679a07 100644 --- a/indra/newview/llviewerstatsrecorder.cpp +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -28,24 +28,25 @@ #include "llviewerstatsrecorder.h" +#include "llcontrol.h" #include "llfile.h" #include "llviewerregion.h" #include "llviewerobject.h" +#include "llworld.h" - -// To do - something using region name or global position -#if LL_WINDOWS - static const std::string STATS_FILE_NAME("C:\\ViewerObjectCacheStats.csv"); -#else - static const std::string STATS_FILE_NAME("/tmp/viewerstats.csv"); -#endif +extern LLControlGroup gSavedSettings; LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL; LLViewerStatsRecorder::LLViewerStatsRecorder() : - mObjectCacheFile(NULL), + mStatsFile(NULL), mTimer(), - mStartTime(0.0), - mLastSnapshotTime(0.0) + mFileOpenTime(0.0), + mLastSnapshotTime(0.0), + mEnableStatsRecording(false), + mEnableStatsLogging(false), + mInterval(0.2), + mMaxDuration(300.f), + mSkipSaveIfZeros(false) { if (NULL != sInstance) { @@ -57,79 +58,70 @@ LLViewerStatsRecorder::LLViewerStatsRecorder() : LLViewerStatsRecorder::~LLViewerStatsRecorder() { - if (mObjectCacheFile != NULL) + if (mStatsFile) { - // last chance snapshot - writeToLog(0.f); - LLFile::close(mObjectCacheFile); - mObjectCacheFile = NULL; + writeToLog(0.f); // Save last data + closeStatsFile(); } } void LLViewerStatsRecorder::clearStats() { mObjectCacheHitCount = 0; - mObjectCacheHitSize = 0; mObjectCacheMissFullCount = 0; - mObjectCacheMissFullSize = 0; mObjectCacheMissCrcCount = 0; - mObjectCacheMissCrcSize = 0; mObjectFullUpdates = 0; - mObjectFullUpdatesSize = 0; mObjectTerseUpdates = 0; - mObjectTerseUpdatesSize = 0; mObjectCacheMissRequests = 0; - mObjectCacheMissResponses = 0; - mObjectCacheMissResponsesSize = 0; mObjectCacheUpdateDupes = 0; mObjectCacheUpdateChanges = 0; mObjectCacheUpdateAdds = 0; mObjectCacheUpdateReplacements = 0; mObjectUpdateFailures = 0; - mObjectUpdateFailuresSize = 0; - mTextureFetchSize = 0; + mTextureFetchCount = 0; + mMeshLoadedCount = 0; + mObjectKills = 0; } -void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size) +void LLViewerStatsRecorder::enableObjectStatsRecording(bool enable, bool logging /* false */) { - mObjectUpdateFailures++; - mObjectUpdateFailuresSize += msg_size; + mEnableStatsRecording = enable; + + // if logging is stopping, close the file + if (mStatsFile && !logging) + { + writeToLog(0.f); // Save last data + closeStatsFile(); + } + mEnableStatsLogging = logging; } -void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size) + + +void LLViewerStatsRecorder::recordCacheMissEvent(U8 cache_miss_type) { - if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type) + if (LLViewerRegion::CACHE_MISS_TYPE_TOTAL == cache_miss_type) { mObjectCacheMissFullCount++; - mObjectCacheMissFullSize += msg_size; } else { mObjectCacheMissCrcCount++; - mObjectCacheMissCrcSize += msg_size; } } -void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size) + +void LLViewerStatsRecorder::recordObjectUpdateEvent(const EObjectUpdateType update_type) { - switch (update_type) + switch (update_type) { case OUT_FULL: - mObjectFullUpdates++; - mObjectFullUpdatesSize += msg_size; + case OUT_FULL_COMPRESSED: + mObjectFullUpdates++; break; case OUT_TERSE_IMPROVED: mObjectTerseUpdates++; - mObjectTerseUpdatesSize += msg_size; - break; - case OUT_FULL_COMPRESSED: - mObjectCacheMissResponses++; - mObjectCacheMissResponsesSize += msg_size; - break; - case OUT_FULL_CACHED: - mObjectCacheHitCount++; - mObjectCacheHitSize += msg_size; break; default: LL_WARNS() << "Unknown update_type" << LL_ENDL; @@ -137,9 +129,9 @@ void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectU }; } -void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size) +void LLViewerStatsRecorder::recordCacheFullUpdate(LLViewerRegion::eCacheUpdateResult update_result) { - switch (update_result) + switch (update_result) { case LLViewerRegion::CACHE_UPDATE_DUPE: mObjectCacheUpdateDupes++; @@ -154,124 +146,176 @@ void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpd mObjectCacheUpdateReplacements++; break; default: - LL_WARNS() << "Unknown update_result type" << LL_ENDL; + LL_WARNS() << "Unknown update_result type " << (S32) update_result << LL_ENDL; break; }; } -void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count) -{ - mObjectCacheMissRequests += count; -} - void LLViewerStatsRecorder::writeToLog( F32 interval ) { + if (!mEnableStatsLogging || !mEnableStatsRecording) + { + return; + } + size_t data_size = 0; - F64 delta_time = LLTimer::getTotalSeconds() - mLastSnapshotTime; - S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; + F64 delta_time = LLFrameTimer::getTotalSeconds() - mLastSnapshotTime; + if (delta_time < interval) + return; - if ( delta_time < interval || total_objects == 0) return; + if (mSkipSaveIfZeros) + { + S32 total_events = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheUpdateDupes + + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; + if (total_events == 0) + { + LL_DEBUGS("ILXZeroData") << "ILX: not saving zero data" << LL_ENDL; + return; + } + } - mLastSnapshotTime = LLTimer::getTotalSeconds(); - LL_DEBUGS() << "ILX: " + mLastSnapshotTime = LLFrameTimer::getTotalSeconds(); + LL_DEBUGS("ILX") << "ILX: " << mObjectCacheHitCount << " hits, " << mObjectCacheMissFullCount << " full misses, " << mObjectCacheMissCrcCount << " crc misses, " << mObjectFullUpdates << " full updates, " << mObjectTerseUpdates << " terse updates, " << mObjectCacheMissRequests << " cache miss requests, " - << mObjectCacheMissResponses << " cache miss responses, " << mObjectCacheUpdateDupes << " cache update dupes, " << mObjectCacheUpdateChanges << " cache update changes, " << mObjectCacheUpdateAdds << " cache update adds, " - << mObjectCacheUpdateReplacements << " cache update replacements, " - << mObjectUpdateFailures << " update failures" + << mObjectCacheUpdateReplacements << " cache update replacements," + << mObjectUpdateFailures << " update failures," + << mTextureFetchCount << " texture fetches, " + << mMeshLoadedCount << " mesh loads, " + << mObjectKills << " object kills" << LL_ENDL; - - if (mObjectCacheFile == NULL) + + if (mStatsFile == NULL) { - mStartTime = LLTimer::getTotalSeconds(); - mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb"); - if (mObjectCacheFile) - { // Write column headers - std::ostringstream data_msg; - data_msg << "EventTime(ms)\t" - << "Cache Hits\t" - << "Cache Full Misses\t" - << "Cache Crc Misses\t" - << "Full Updates\t" - << "Terse Updates\t" - << "Cache Miss Requests\t" - << "Cache Miss Responses\t" - << "Cache Update Dupes\t" - << "Cache Update Changes\t" - << "Cache Update Adds\t" - << "Cache Update Replacements\t" - << "Update Failures\t" - << "Cache Hits bps\t" - << "Cache Full Misses bps\t" - << "Cache Crc Misses bps\t" - << "Full Updates bps\t" - << "Terse Updates bps\t" - << "Cache Miss Responses bps\t" - << "Texture Fetch bps\t" - << "\n"; + // Refresh settings + mInterval = gSavedSettings.getF32("StatsReportFileInterval"); + mSkipSaveIfZeros = gSavedSettings.getBOOL("StatsReportSkipZeroDataSaves"); + mMaxDuration = gSavedSettings.getF32("StatsReportMaxDuration"); - data_size = data_msg.str().size(); - if (fwrite(data_msg.str().c_str(), 1, data_size, mObjectCacheFile ) != data_size) + // Open the data file + makeStatsFileName(); + mStatsFile = LLFile::fopen(mStatsFileName, "wb"); + + if (mStatsFile) + { + LL_INFOS("ILX") << "ILX: Writing update information to " << mStatsFileName << LL_ENDL; + + mFileOpenTime = LLFrameTimer::getTotalSeconds(); + + // Write column headers + std::ostringstream col_headers; + col_headers << "Time (sec)," + << "Regions," + << "Active Cached Objects," + << "Cache Hits," + << "Cache Full Misses," + << "Cache Crc Misses," + << "Full Updates," + << "Terse Updates," + << "Cache Miss Requests," // Normally results in a Full Update from simulator + << "Cache Update Dupes," + << "Cache Update Changes," + << "Cache Update Adds," + << "Cache Update Replacements," + << "Update Failures," + << "Texture Count," + << "Mesh Load Count," + << "Object Kills" + << "\n"; + + data_size = col_headers.str().size(); + if (fwrite(col_headers.str().c_str(), 1, data_size, mStatsFile ) != data_size) { - LL_WARNS() << "failed to write full headers to " << STATS_FILE_NAME << LL_ENDL; + LL_WARNS() << "failed to write full headers to " << mStatsFileName << LL_ENDL; + // Close the file and turn off stats logging + closeStatsFile(); + return; } } else - { - //LL_WARNS() << "Couldn't open " << STATS_FILE_NAME << " for logging." << LL_ENDL; + { // Failed to open file + LL_WARNS() << "Couldn't open " << mStatsFileName << " for logging, turning off stats recording." << LL_ENDL; + mEnableStatsLogging = false; return; } } - std::ostringstream data_msg; + std::ostringstream stats_data; - data_msg << getTimeSinceStart() - << "\t " << mObjectCacheHitCount - << "\t" << mObjectCacheMissFullCount - << "\t" << mObjectCacheMissCrcCount - << "\t" << mObjectFullUpdates - << "\t" << mObjectTerseUpdates - << "\t" << mObjectCacheMissRequests - << "\t" << mObjectCacheMissResponses - << "\t" << mObjectCacheUpdateDupes - << "\t" << mObjectCacheUpdateChanges - << "\t" << mObjectCacheUpdateAdds - << "\t" << mObjectCacheUpdateReplacements - << "\t" << mObjectUpdateFailures - << "\t" << (mObjectCacheHitSize * 8 / delta_time) - << "\t" << (mObjectCacheMissFullSize * 8 / delta_time) - << "\t" << (mObjectCacheMissCrcSize * 8 / delta_time) - << "\t" << (mObjectFullUpdatesSize * 8 / delta_time) - << "\t" << (mObjectTerseUpdatesSize * 8 / delta_time) - << "\t" << (mObjectCacheMissResponsesSize * 8 / delta_time) - << "\t" << (mTextureFetchSize * 8 / delta_time) + stats_data << getTimeSinceStart() + << "," << LLWorld::getInstance()->getRegionList().size() + << "," << LLWorld::getInstance()->getNumOfActiveCachedObjects() + << "," << mObjectCacheHitCount + << "," << mObjectCacheMissFullCount + << "," << mObjectCacheMissCrcCount + << "," << mObjectFullUpdates + << "," << mObjectTerseUpdates + << "," << mObjectCacheMissRequests + << "," << mObjectCacheUpdateDupes + << "," << mObjectCacheUpdateChanges + << "," << mObjectCacheUpdateAdds + << "," << mObjectCacheUpdateReplacements + << "," << mObjectUpdateFailures + << "," << mTextureFetchCount + << "," << mMeshLoadedCount + << "," << mObjectKills << "\n"; - data_size = data_msg.str().size(); - if ( data_size != fwrite(data_msg.str().c_str(), 1, data_size, mObjectCacheFile )) + data_size = stats_data.str().size(); + if ( data_size != fwrite(stats_data.str().c_str(), 1, data_size, mStatsFile )) { - LL_WARNS() << "Unable to write complete column data to " << STATS_FILE_NAME << LL_ENDL; - } + LL_WARNS() << "Unable to write complete column data to " << mStatsFileName << LL_ENDL; + closeStatsFile(); + } clearStats(); + + if (getTimeSinceStart() >= mMaxDuration) + { // If file recording has been running for too long, stop it. + closeStatsFile(); + } +} + +void LLViewerStatsRecorder::closeStatsFile() +{ + if (mStatsFile) + { + LL_INFOS("ILX") << "ILX: Stopped writing update information to " << mStatsFileName << " after " << getTimeSinceStart() + << " seconds." << LL_ENDL; + LLFile::close(mStatsFile); + mStatsFile = NULL; + } + mEnableStatsLogging = false; +} + +void LLViewerStatsRecorder::makeStatsFileName() +{ + // Create filename - tbd: use pid? +#if LL_WINDOWS + std::string stats_file_name("SLViewerStats-"); +#else + std::string stats_file_name("slviewerstats-"); +#endif + + F64 now = LLFrameTimer::getTotalSeconds(); + std::string date_str = LLDate(now).asString(); + std::replace(date_str.begin(), date_str.end(), ':', '-'); // Make it valid for a filename + stats_file_name.append(date_str); + stats_file_name.append(".csv"); + mStatsFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, stats_file_name); } F32 LLViewerStatsRecorder::getTimeSinceStart() { - return (F32) (LLTimer::getTotalSeconds() - mStartTime); -} - -void LLViewerStatsRecorder::recordTextureFetch( S32 msg_size ) -{ - mTextureFetchSize += msg_size; + return (F32) (LLFrameTimer::getTotalSeconds() - mFileOpenTime); } - diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h index c974bea49d..b9fe02e54d 100644 --- a/indra/newview/llviewerstatsrecorder.h +++ b/indra/newview/llviewerstatsrecorder.h @@ -31,10 +31,6 @@ // This is a diagnostic class used to record information from the viewer // for analysis. -// This is normally 0. Set to 1 to enable viewer stats recording -#define LL_RECORD_VIEWER_STATS 0 - - #include "llframetimer.h" #include "llviewerobject.h" #include "llviewerregion.h" @@ -49,97 +45,132 @@ class LLViewerStatsRecorder : public LLSingleton ~LLViewerStatsRecorder(); public: - void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size) - { -#if LL_RECORD_VIEWER_STATS - recordObjectUpdateFailure(local_id, update_type, msg_size); -#endif + // Enable/disable stats recording. This is broken down into two + // flags so we can record stats without writing them to the log + // file. This is useful to analyzing updates for scene loading. + void enableObjectStatsRecording(bool enable, bool logging = false); + + bool isEnabled() const { return mEnableStatsRecording; } + bool isLogging() const { return mEnableStatsLogging; } + + void objectUpdateFailure() + { + if (mEnableStatsRecording) + { + mObjectUpdateFailures++; + } } - void cacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size) + void cacheMissEvent(U8 cache_miss_type) { -#if LL_RECORD_VIEWER_STATS - recordCacheMissEvent(local_id, update_type, cache_miss_type, msg_size); -#endif + if (mEnableStatsRecording) + { + recordCacheMissEvent(cache_miss_type); + } + } + + void cacheHitEvent() + { + if (mEnableStatsRecording) + { + mObjectCacheHitCount++; + } + } + + void objectUpdateEvent(const EObjectUpdateType update_type) + { + if (mEnableStatsRecording) + { + recordObjectUpdateEvent(update_type); + } } - void objectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size) - { -#if LL_RECORD_VIEWER_STATS - recordObjectUpdateEvent(local_id, update_type, objectp, msg_size); -#endif - } - - void cacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size) - { -#if LL_RECORD_VIEWER_STATS - recordCacheFullUpdate(local_id, update_type, update_result, objectp, msg_size); -#endif + void cacheFullUpdate(LLViewerRegion::eCacheUpdateResult update_result) + { + if (mEnableStatsRecording) + { + recordCacheFullUpdate(update_result); + } } void requestCacheMissesEvent(S32 count) { -#if LL_RECORD_VIEWER_STATS - recordRequestCacheMissesEvent(count); -#endif + if (mEnableStatsRecording) + { + mObjectCacheMissRequests += count; + } } - void textureFetch(S32 msg_size) + void textureFetch() { -#if LL_RECORD_VIEWER_STATS - recordTextureFetch(msg_size); -#endif + if (mEnableStatsRecording) + { + mTextureFetchCount += 1; + } } - void log(F32 interval) + void meshLoaded() { -#if LL_RECORD_VIEWER_STATS - writeToLog(interval); -#endif + if (mEnableStatsRecording) + { + mMeshLoadedCount += 1; + } + } + + void recordObjectKills(S32 num_objects) + { + if (mEnableStatsRecording) + { + mObjectKills += num_objects; + } + } + + void idle() + { + writeToLog(mInterval); } F32 getTimeSinceStart(); private: - void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size); - void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size); - void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size); - void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size); - void recordRequestCacheMissesEvent(S32 count); - void recordTextureFetch(S32 msg_size); + void recordCacheMissEvent(U8 cache_miss_type); + void recordObjectUpdateEvent(const EObjectUpdateType update_type); + void recordCacheFullUpdate(LLViewerRegion::eCacheUpdateResult update_result); void writeToLog(F32 interval); + void closeStatsFile(); + void makeStatsFileName(); static LLViewerStatsRecorder* sInstance; - LLFILE * mObjectCacheFile; // File to write data into + LLFILE * mStatsFile; // File to write data into + std::string mStatsFileName; + LLFrameTimer mTimer; - F64 mStartTime; + F64 mFileOpenTime; F64 mLastSnapshotTime; + F32 mInterval; // Interval between data log writes + F32 mMaxDuration; // Time limit on file + + bool mEnableStatsRecording; // Set to true to enable recording stats data + bool mEnableStatsLogging; // Set true to write stats to log file + bool mSkipSaveIfZeros; // Set true to skip saving stats if all values are zero S32 mObjectCacheHitCount; - S32 mObjectCacheHitSize; S32 mObjectCacheMissFullCount; - S32 mObjectCacheMissFullSize; S32 mObjectCacheMissCrcCount; - S32 mObjectCacheMissCrcSize; S32 mObjectFullUpdates; - S32 mObjectFullUpdatesSize; S32 mObjectTerseUpdates; - S32 mObjectTerseUpdatesSize; S32 mObjectCacheMissRequests; - S32 mObjectCacheMissResponses; - S32 mObjectCacheMissResponsesSize; S32 mObjectCacheUpdateDupes; S32 mObjectCacheUpdateChanges; S32 mObjectCacheUpdateAdds; S32 mObjectCacheUpdateReplacements; S32 mObjectUpdateFailures; - S32 mObjectUpdateFailuresSize; - S32 mTextureFetchSize; - + S32 mTextureFetchCount; + S32 mMeshLoadedCount; + S32 mObjectKills; void clearStats(); }; #endif // LLVIEWERSTATSRECORDER_H - diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index d5e04767f6..2d8fe3ae8a 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -1283,7 +1283,11 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLPointer item_p void LLViewerTextEditor::openEmbeddedCallingcard( LLInventoryItem* item, llwchar wc ) { - if(item && !item->getCreatorUUID().isNull()) + if (item && !item->getDescription().empty()) + { + LLAvatarActions::showProfile(LLUUID(item->getDescription())); + } + else if (item && !item->getCreatorUUID().isNull()) { LLAvatarActions::showProfile(item->getCreatorUUID()); } diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp index 2729253d18..20390a316a 100644 --- a/indra/newview/llviewerthrottle.cpp +++ b/indra/newview/llviewerthrottle.cpp @@ -84,7 +84,7 @@ LLViewerThrottleGroup::LLViewerThrottleGroup() } -LLViewerThrottleGroup::LLViewerThrottleGroup(const F32 settings[]) +LLViewerThrottleGroup::LLViewerThrottleGroup(const F32 settings[TC_EOF]) { mThrottleTotal = 0.f; S32 i; diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index b64e251649..958eefdaf9 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -40,6 +40,7 @@ #include "llviewerwearable.h" #include "llviewercontrol.h" #include "llviewerregion.h" +#include "llmd5.h" // [Legacy Bake] using namespace LLAvatarAppearanceDefines; diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 09a734bfb1..6bf3e9a765 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -98,7 +98,6 @@ public: // not the wearable asset itself. void refreshName(); // [Legacy Bake] - ///*virtual*/void addToBakedTextureHash(LLMD5& hash) const {} /*virtual*/void addToBakedTextureHash(LLMD5& hash) const; protected: diff --git a/indra/newview/llvoicecallhandler.cpp b/indra/newview/llvoicecallhandler.cpp index 1e993d1384..95e11abd82 100644 --- a/indra/newview/llvoicecallhandler.cpp +++ b/indra/newview/llvoicecallhandler.cpp @@ -38,7 +38,7 @@ public: { } - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableVoiceCall")) { diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 0839133b47..4978e9bb84 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -58,7 +58,7 @@ public: // requests will be throttled from a non-trusted browser LLVoiceHandler() : LLCommandHandler("voice", UNTRUSTED_THROTTLE) {} - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { if (params[0].asString() == "effects") { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bc71f00feb..afac7860e5 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5369,6 +5369,28 @@ LLControlAVBridge::LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regi mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV; } +void LLControlAVBridge::updateSpatialExtents() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE + + LLControlAvatar* controlAvatar = getVObj()->getControlAvatar(); + + LLSpatialGroup* root = (LLSpatialGroup*)mOctree->getListener(0); + + bool rootWasDirty = root->isDirty(); + + super::updateSpatialExtents(); // root becomes non-dirty here + + // SL-18251 "On-screen animesh characters using pelvis offset animations + // disappear when root goes off-screen" + // + // Expand extents to include Control Avatar placed outside of the bounds + if (controlAvatar && (rootWasDirty || controlAvatar->mPlaying)) + { + root->expandExtents(controlAvatar->mDrawable->getSpatialExtents(), *mDrawable->getXform()); + } +} + bool can_batch_texture(LLFace* facep) { if (facep->getTextureEntry()->getBumpmap()) @@ -6667,7 +6689,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; } - + static LLCachedControl max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); texture_index_channels = llmin(texture_index_channels, (S32) max_texture_index); diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 4b8a8a690f..3f0da307f2 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -110,13 +110,13 @@ BOOL LLPanelWearableOutfitItem::postBuild() { LLPanelWearableListItem::postBuild(); - LLViewerInventoryItem* inv_item = getItem(); - mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART); //if(mShowWidgets) // Make Add/Remove buttons work { // Make Add/Remove buttons work //addWidgetToRightSide("add_wearable"); //addWidgetToRightSide("remove_wearable"); + LLViewerInventoryItem* inv_item = getItem(); + mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART); addWidgetToRightSide("add_wearable", mShowWidgets); addWidgetToRightSide("remove_wearable", mShowWidgets); // @@ -255,7 +255,15 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, if(mShowWidgets) { setShowWidget("add_wearable", !is_worn); + + // Make Add/Remove buttons work + //// Body parts can't be removed, only replaced + //LLViewerInventoryItem* inv_item = getItem(); + //bool show_remove = is_worn && inv_item && (inv_item->getType() != LLAssetType::AT_BODYPART); + //setShowWidget("remove_wearable", show_remove); setShowWidget("remove_wearable", is_worn); + // + if(mHovered) { setWidgetsVisible(true); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index bec5a53947..3999471a33 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -50,6 +50,7 @@ #include "lltextureview.h" #include "lltracker.h" #include "llviewercamera.h" +#include "llviewernetwork.h" #include "llviewertexture.h" #include "llviewertexturelist.h" #include "llviewerregion.h" @@ -2012,7 +2013,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) // Invoke the event details floater if someone is clicking on an event. LLSD params(LLSD::emptyArray()); params.append(event_id); - LLCommandDispatcher::dispatch("event", params, LLSD(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true); + LLCommandDispatcher::dispatch("event", params, LLSD(), LLGridManager::getInstance()->getGrid(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true); break; } case MAP_ITEM_LAND_FOR_SALE: diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index a7a6915146..6e993b2a62 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -11950,7 +11950,7 @@ void LLPipeline::handleShadowDetailChanged() { skipRenderingShadows(); } - else + // else Ghosting fix for Whirly to try. just remove this for now. { LLViewerShaderMgr::instance()->setShaders(); } diff --git a/indra/newview/skins/default/html/ja/help-offline/index.html b/indra/newview/skins/default/html/ja/help-offline/index.html new file mode 100644 index 0000000000..aeaafe8216 --- /dev/null +++ b/indra/newview/skins/default/html/ja/help-offline/index.html @@ -0,0 +1,42 @@ + + + + + オフラインヘルプ + + + +
+

Second Lifeオフラインヘルプ

+

+ オンラインではなく、リモートでヘルプを取得しないように構成されています。 +
+ これは、さらに作業が完了するまで利用できるすべてのヘルプです。うん。 +

+
+ + diff --git a/indra/newview/skins/default/html/ja/loading-error/index.html b/indra/newview/skins/default/html/ja/loading-error/index.html index d969c03098..27d4425016 100644 --- a/indra/newview/skins/default/html/ja/loading-error/index.html +++ b/indra/newview/skins/default/html/ja/loading-error/index.html @@ -1,25 +1,99 @@ - - - -接続できません - - -

-

Second Lifeによるログインサーバーへの接続が確立できません。 -

-

インターネット接続を確認してください。 お使いのコンピュータやネットワークがファイヤウォールまたはプロキシにより保護されている場合は、Second Lifeによるネットワークへのアクセスが許可されていることを確認してください。 -

-
- - + + + + + 接続できません + + + +
+ unabletoconnect +
+

Second Lifeによるログインサーバーへの接続が確立できません。

+

+ インターネット接続を確認してください。 + お使いのコンピュータやネットワークがファイヤウォールまたはプロキシにより保護されている場合は、 + Second + Lifeによるネットワークへのアクセスが許可されていることを確認してください。 +

+
+ +
+
+ + diff --git a/indra/newview/skins/default/html/ja/loading/loading.html b/indra/newview/skins/default/html/ja/loading/loading.html index 35cf74a35f..ea576ed082 100644 --- a/indra/newview/skins/default/html/ja/loading/loading.html +++ b/indra/newview/skins/default/html/ja/loading/loading.html @@ -1,10 +1,22 @@ - - - - - - -
-
   ロード中... -
- + + + + + 読み込んでいます… + + + + loading +
+

   読み込んでいます…

+ + diff --git a/indra/newview/skins/default/xui/az/mime_types_linux.xml b/indra/newview/skins/default/xui/az/mime_types_linux.xml index 812ba1263c..b18206cb7e 100644 --- a/indra/newview/skins/default/xui/az/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/az/mime_types_linux.xml @@ -82,7 +82,6 @@ Şəkil -