diff options
| author | Mnikolenko Productengine <mnikolenko@productengine.com> | 2026-01-15 21:49:17 +0200 |
|---|---|---|
| committer | Mnikolenko Productengine <mnikolenko@productengine.com> | 2026-01-15 21:54:48 +0200 |
| commit | e4a079e14dea60d48342473fecb7762c29ad0456 (patch) | |
| tree | a3499be0247d2c8b559882c3d8348b150e2ae0f9 | |
| parent | a377ec310848657ca6f4b76bdf74aca9cfc6f9da (diff) | |
| parent | 106556538c6d7f4098bd204fcb87860f8e2bff6c (diff) | |
Merge branch 'develop' into project/flat-ui-fonts-update
137 files changed, 2024 insertions, 2229 deletions
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4c8d98ce2f..2101b9b5e8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -86,7 +86,7 @@ jobs: variants: ${{ matrix.configuration }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} @@ -95,14 +95,14 @@ jobs: with: python-version: "3.11" - name: Checkout build variables - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: secondlife/build-variables ref: master path: .build-variables - name: Checkout master-message-template - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: repository: secondlife/master-message-template path: .master-message-template @@ -112,7 +112,7 @@ jobs: - name: Cache autobuild packages id: cache-installables - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .autobuild-installables key: ${{ runner.os }}-64-${{ matrix.configuration }}-${{ hashFiles('autobuild.xml') }} @@ -265,7 +265,7 @@ jobs: - name: Upload executable if: steps.build.outputs.viewer_app - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: "${{ steps.build.outputs.artifact }}-app" path: | @@ -275,13 +275,13 @@ jobs: # artifact for that too. - name: Upload symbol file if: steps.build.outputs.symbolfile - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: "${{ steps.build.outputs.artifact }}-symbols" path: ${{ steps.build.outputs.symbolfile }} - name: Upload metadata - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: "${{ steps.build.outputs.artifact }}-metadata" # emitted by build.sh, possibly multiple lines @@ -289,7 +289,7 @@ jobs: ${{ steps.build.outputs.metadata }} - name: Upload physics package - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 # should only be set for viewer-private if: matrix.configuration == 'Release' && steps.build.outputs.physicstpv with: @@ -370,13 +370,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Download viewer exe - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: Windows-app path: _artifacts - name: Download Windows Symbols if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: Windows-symbols - name: Extract viewer pdb @@ -409,7 +409,7 @@ jobs: steps: - name: Download Mac Symbols if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: name: macOS-symbols - name: Post Mac symbols @@ -431,11 +431,11 @@ jobs: runs-on: ubuntu-latest if: needs.setup.outputs.release_run steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v7 with: pattern: "*-installer" - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v7 with: pattern: "*-metadata" diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index 5b31c584d5..800f3c42d1 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -23,4 +23,4 @@ jobs: path-to-signatures: signatures.json remote-organization-name: secondlife remote-repository-name: cla-signatures - allowlist: callum@mbp.localdomain,rye@lindenlab.com,rye,bot* + allowlist: callum@mbp.localdomain,rye@lindenlab.com,rye,signal@lindenlab.com,dependabot*,bot* diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 8f942fa11b..93bcafdea8 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -11,7 +11,7 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: python-version: 3.x diff --git a/autobuild.xml b/autobuild.xml index d58a785b6b..89b951c10c 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -106,11 +106,11 @@ <key>archive</key> <map> <key>hash</key> - <string>a4553df5b8fde2e9cd54ebb94c6efb8eb5fe3c38</string> + <string>61cc299413a32350175cf7139f64388d3d096ec7</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-boost/releases/download/v1.86.0-be1a669/boost-1.86-darwin64-13246092114.tar.zst</string> + <string>https://github.com/secondlife/3p-boost/releases/download/v1.90.0-c7a9feb/boost-1.90-darwin64-20977261894.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -120,11 +120,11 @@ <key>archive</key> <map> <key>hash</key> - <string>4a2a19dc5cb555e157ad894ba917f5a83a35b20d</string> + <string>6b93e323284bfab8ec20a7f3bc740c6915980bf8</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-boost/releases/download/v1.86.0-be1a669/boost-1.86-linux64-13246092114.tar.zst</string> + <string>https://github.com/secondlife/3p-boost/releases/download/v1.90.0-c7a9feb/boost-1.90-linux64-20977261894.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -134,11 +134,11 @@ <key>archive</key> <map> <key>hash</key> - <string>8a1fa9366bfe49009286e4805d7aaedb7c3df82e</string> + <string>c543437ca30a63dcd2538fffa89a43ef43f625fb</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-boost/releases/download/v1.86.0-be1a669/boost-1.86-windows64-13246092114.tar.zst</string> + <string>https://github.com/secondlife/3p-boost/releases/download/v1.90.0-c7a9feb/boost-1.90-windows64-20977261894.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -151,7 +151,7 @@ <key>copyright</key> <string>(see individual source files)</string> <key>version</key> - <string>1.86</string> + <string>1.90.0-c7a9feb</string> <key>name</key> <string>boost</string> <key>description</key> @@ -212,11 +212,11 @@ <key>archive</key> <map> <key>hash</key> - <string>bf2fe4e8272e990bc8687b3b37bf4bb2b2ad6eb4</string> + <string>9710f82a237b95aaafbbcf708b89f6015b80d85f</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r10/colladadom-2.3.0-r10-darwin64-13259816660.tar.zst</string> + <string>https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r11/colladadom-2.3.0-r11-darwin64-20980076767.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -226,11 +226,11 @@ <key>archive</key> <map> <key>hash</key> - <string>118e509ca464182ef4b94ee8c4aa5b14a6c52a94</string> + <string>6a1725b1bc13634eb4dd872a4f83c3f16497475f</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r10/colladadom-2.3.0-r10-linux64-13259816660.tar.zst</string> + <string>https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r11/colladadom-2.3.0-r11-linux64-20980076767.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -240,11 +240,11 @@ <key>archive</key> <map> <key>hash</key> - <string>d7aee1b2ec17bd88a2c27359281b58a11ec52d48</string> + <string>ba9eeb62ae3046d91f9e061db823c1863623b017</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r10/colladadom-2.3.0-r10-windows64-13259816660.tar.zst</string> + <string>https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r11/colladadom-2.3.0-r11-windows64-20980076767.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -257,7 +257,7 @@ <key>copyright</key> <string>Copyright 2006 Sony Computer Entertainment Inc.</string> <key>version</key> - <string>2.3.0-r10</string> + <string>2.3.0-r11</string> <key>name</key> <string>colladadom</string> </map> @@ -328,11 +328,11 @@ <key>archive</key> <map> <key>hash</key> - <string>e742b1e2d0a58d607b023bf55411041ac65e8a76</string> + <string>5eab8167cec442e8c156bb653012d7544cca6037</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r3/curl-7.54.1-13259824618-darwin64-13259824618.tar.zst</string> + <string>https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r4/curl-7.54.1-20982000504-darwin64-20982000504.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -342,11 +342,11 @@ <key>archive</key> <map> <key>hash</key> - <string>49621c70f385d37c95bcb69a9a24d86ac25f4781</string> + <string>3465bbe70cfba2814b1fd52094c62804f4067490</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r3/curl-7.54.1-13259824618-linux64-13259824618.tar.zst</string> + <string>https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r4/curl-7.54.1-20982000504-linux64-20982000504.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -356,11 +356,11 @@ <key>archive</key> <map> <key>hash</key> - <string>2522201692116cf0adb7203e169be9126885108c</string> + <string>0e64e20945eeb19259abf8e78400eb492e31eda7</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r3/curl-7.54.1-13259824618-windows64-13259824618.tar.zst</string> + <string>https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r4/curl-7.54.1-20982000504-windows64-20982000504.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -373,7 +373,7 @@ <key>copyright</key> <string>Copyright (c) 1996 - 2014, Daniel Stenberg, (daniel@haxx.se).</string> <key>version</key> - <string>7.54.1-13259824618</string> + <string>7.54.1-20982000504</string> <key>name</key> <string>curl</string> <key>description</key> @@ -634,11 +634,11 @@ <key>archive</key> <map> <key>hash</key> - <string>5e6c7b9aaf73d90d7feab846a4024193c48eff6c</string> + <string>550a90bca35bdbbd615afb1a1c02383cb3b6edbe</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r3/freetype-2.13.3-r3-darwin64-13259804885.tar.zst</string> + <string>https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r4/freetype-2.13.3-r4-darwin64-20935810762.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -648,11 +648,11 @@ <key>archive</key> <map> <key>hash</key> - <string>a9a3c371958e64a49b07d7be8f59218dfd6b0352</string> + <string>f52b05392962cb6a8e5f534d8687faa525d4960a</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r3/freetype-2.13.3-r3-linux64-13259804885.tar.zst</string> + <string>https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r4/freetype-2.13.3-r4-linux64-20935810762.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -662,11 +662,11 @@ <key>archive</key> <map> <key>hash</key> - <string>ad7fbc4a01607ec43d86035a49dadd43d6f2a4e5</string> + <string>3c30052adcbfec572562bb1e7927d7a8f4d93f3d</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r3/freetype-2.13.3-r3-windows64-13259804885.tar.zst</string> + <string>https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r4/freetype-2.13.3-r4-windows64-20935810762.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -679,7 +679,7 @@ <key>copyright</key> <string>Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.</string> <key>version</key> - <string>2.13.3-r3</string> + <string>2.13.3-r4</string> <key>name</key> <string>freetype</string> <key>description</key> @@ -1226,11 +1226,11 @@ <key>archive</key> <map> <key>hash</key> - <string>a453355ee032f79aea4142218a957085a22c7656</string> + <string>6fa10d5f44601dda6efc3eda1a9dab22525e7a9a</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-libpng/releases/download/v1.6.44-r2/libpng-1.6.44-r2-darwin64-13246065198.tar.zst</string> + <string>https://github.com/secondlife/3p-libpng/releases/download/v1.6.53-eea12b7/libpng-1.6.44-dev1.geea12b7-darwin64-20934739343.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -1240,11 +1240,11 @@ <key>archive</key> <map> <key>hash</key> - <string>75c7608646c9f5b99b1a9e3946326e2804a304d7</string> + <string>112b7f46f5923e6418dfa4bc13ebe2db6911c9b9</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-libpng/releases/download/v1.6.44-r2/libpng-1.6.44-r2-linux64-13246065198.tar.zst</string> + <string>https://github.com/secondlife/3p-libpng/releases/download/v1.6.53-eea12b7/libpng-1.6.44-dev1.geea12b7-linux64-20934739343.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -1254,11 +1254,11 @@ <key>archive</key> <map> <key>hash</key> - <string>09af51774c4ee7c03fe67a87dfc52e846aa625ea</string> + <string>2731c45f1e62e33b8612b3ee2b9c4cb39dafbfe2</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-libpng/releases/download/v1.6.44-r2/libpng-1.6.44-r2-windows64-13246065198.tar.zst</string> + <string>https://github.com/secondlife/3p-libpng/releases/download/v1.6.53-eea12b7/libpng-1.6.44-dev1.geea12b7-windows64-20934739343.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -1271,7 +1271,7 @@ <key>copyright</key> <string>Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson</string> <key>version</key> - <string>1.6.44-r2</string> + <string>1.6.53-eea12b7</string> <key>name</key> <string>libpng</string> <key>description</key> @@ -1316,11 +1316,11 @@ <key>archive</key> <map> <key>hash</key> - <string>372c92936d940b1cfb5ba34310691d4bb435c161</string> + <string>c1ad7ff9ec91049c93d2dcd832f81a00f8f4b4b9</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-libxml2/releases/download/v2.13.5-r2/libxml2-2.13.5-r2-darwin64-13246071272.tar.zst</string> + <string>https://github.com/secondlife/3p-libxml2/releases/download/v2.13.9-d53cd6f/libxml2-2.13.9-d53cd6f-darwin64-20936141417.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -1330,11 +1330,11 @@ <key>archive</key> <map> <key>hash</key> - <string>ba6fbc34112b1acab1c8615dcd13de983f3678d3</string> + <string>7fc2df91648661468a82754b26fd7dedfbef1d39</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-libxml2/releases/download/v2.13.5-r2/libxml2-2.13.5-r2-linux64-13246071272.tar.zst</string> + <string>https://github.com/secondlife/3p-libxml2/releases/download/v2.13.9-d53cd6f/libxml2-2.13.9-d53cd6f-linux64-20936141417.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -1344,11 +1344,11 @@ <key>archive</key> <map> <key>hash</key> - <string>71968c4b621636e8ae0c5680e631f4aa67561944</string> + <string>84828c26b67c33f0d3e565718943aa339582b34f</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-libxml2/releases/download/v2.13.5-r2/libxml2-2.13.5-r2-windows64-13246071272.tar.zst</string> + <string>https://github.com/secondlife/3p-libxml2/releases/download/v2.13.9-d53cd6f/libxml2-2.13.9-d53cd6f-windows64-20936141417.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -1361,7 +1361,7 @@ <key>copyright</key> <string>Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.</string> <key>version</key> - <string>2.13.5-r2</string> + <string>2.13.9-d53cd6f</string> <key>name</key> <string>libxml2</string> <key>description</key> @@ -1547,11 +1547,11 @@ <key>archive</key> <map> <key>hash</key> - <string>874a7d2bc843554aa4facd03b3a6d681f2b5150c</string> + <string>3692af717636da9c2b1e0f13eb084ce022b67f6c</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-meshoptimizer/releases/download/v220-r1/meshoptimizer-220.0.0-r1-darwin64-11968851109.tar.zst</string> + <string>https://github.com/secondlife/3p-meshoptimizer/releases/download/v1.0.1-9d6a006/meshoptimizer-1.0.1-9d6a006-darwin64-20867041007.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -1561,11 +1561,11 @@ <key>archive</key> <map> <key>hash</key> - <string>31a537f1a3d38ef85443214315111dd56a534d9a</string> + <string>22ad1be39a1196a1ca3902ba936460cb69252b9c</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-meshoptimizer/releases/download/v220-r1/meshoptimizer-220.0.0-r1-linux64-11968851109.tar.zst</string> + <string>https://github.com/secondlife/3p-meshoptimizer/releases/download/v1.0.1-9d6a006/meshoptimizer-1.0.1-9d6a006-linux64-20867041007.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -1575,11 +1575,11 @@ <key>archive</key> <map> <key>hash</key> - <string>6fd727a9ccb3e7a6c6b4ffef8179e266c032eb3e</string> + <string>2c9769f31da5de3920d7ee400d280398c911a30f</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-meshoptimizer/releases/download/v220-r1/meshoptimizer-220.0.0-r1-windows64-11968851109.tar.zst</string> + <string>https://github.com/secondlife/3p-meshoptimizer/releases/download/v1.0.1-9d6a006/meshoptimizer-1.0.1-9d6a006-windows64-20867041007.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -1671,11 +1671,11 @@ <key>archive</key> <map> <key>hash</key> - <string>b628d088e1f368a0cd51a6b66292aaf9a025e2d4</string> + <string>85179317015c5c91986000d69c9f61a01af7617f</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r3/minizip_ng-4.0.7-r3-darwin64-13246046977.tar.zst</string> + <string>https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r4/minizip_ng-4.0.7-r4-darwin64-20933148061.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -1685,11 +1685,11 @@ <key>archive</key> <map> <key>hash</key> - <string>492ce9175b730d43df63821c4481685e035af623</string> + <string>ef1524f507f44fed6f1c1f00ae274ddb8a1ac359</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r3/minizip_ng-4.0.7-r3-linux64-13246046977.tar.zst</string> + <string>https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r4/minizip_ng-4.0.7-r4-linux64-20933148061.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -1699,11 +1699,11 @@ <key>archive</key> <map> <key>hash</key> - <string>58773e707ff3490822b7b8217d7729ade2186632</string> + <string>90be39cf789b596377458f1ea78f415a9c281a8c</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r3/minizip_ng-4.0.7-r3-windows64-13246046977.tar.zst</string> + <string>https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r4/minizip_ng-4.0.7-r4-windows64-20933148061.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -1716,7 +1716,7 @@ <key>copyright</key> <string>This project uses the zlib license. Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler</string> <key>version</key> - <string>4.0.7-r3</string> + <string>4.0.7-r4</string> <key>name</key> <string>minizip-ng</string> <key>canonical_repo</key> @@ -2079,11 +2079,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>157193699127ac5056c5fc1a410f9c98d39731e2</string> + <string>e08f640fb423f878c288426c836189b30b0c8ad0</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r3/openssl-1.1.1w-r3-darwin64-13246054022.tar.zst</string> + <string>https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r4/openssl-1.1.1w-r4-darwin64-20981673556.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -2093,11 +2093,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>2e29c127dbd002d64ae55bc000f8b6ed0249fad7</string> + <string>d83a1e910762b792c90550ce2b8f51f9aaec7570</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r3/openssl-1.1.1w-r3-linux64-13246054022.tar.zst</string> + <string>https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r4/openssl-1.1.1w-r4-linux64-20981673556.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -2107,11 +2107,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>ae9ced89051e03a99628c99b9ac78530fdea1e5a</string> + <string>eec78c22e2d1eecf375aa0c6eff08fe67d2316f4</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r3/openssl-1.1.1w-r3-windows64-13246054022.tar.zst</string> + <string>https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r4/openssl-1.1.1w-r4-windows64-20981673556.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -2124,7 +2124,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>copyright</key> <string>Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)</string> <key>version</key> - <string>1.1.1w-r3</string> + <string>1.1.1w-r4</string> <key>name</key> <string>openssl</string> <key>description</key> @@ -2731,11 +2731,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>e363e3b889c52fda7601d7aeaa9832307034651e</string> + <string>4906257288c61b14d2e16116fc3139af35d3374f</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.3-r1/zlib_ng-2.2.3-dev0.g8aa13e3.d20250206-darwin64-13183604450.tar.zst</string> + <string>https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.5-0d88d03/zlib_ng-2.2.5-dev0.g0d88d03.d20260112-darwin64-20930307098.tar.zst</string> </map> <key>name</key> <string>darwin64</string> @@ -2745,11 +2745,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>3cdd52f7fb3691789d50f0b40ed6f5642321ff32</string> + <string>2b81a6a4ebd9ae5555d48b52eea7c2d875d68f60</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.3-r1/zlib_ng-2.2.3-dev0.g8aa13e3.d20250206-linux64-13183604450.tar.zst</string> + <string>https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.5-0d88d03/zlib_ng-2.2.5-dev0.g0d88d03.d20260112-linux64-20930307098.tar.zst</string> </map> <key>name</key> <string>linux64</string> @@ -2759,11 +2759,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>e802a28139328bb2421ad39e13d996d350d8106d</string> + <string>e2e0f964ba44fe2e6428e1e7ca262a3f80d92e65</string> <key>hash_algorithm</key> <string>sha1</string> <key>url</key> - <string>https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.3-r1/zlib_ng-2.2.3-dev0.g8aa13e3.d20250206-windows64-13183604450.tar.zst</string> + <string>https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.5-0d88d03/zlib_ng-2.2.5-dev0.g0d88d03.d20260112-windows64-20930307098.tar.zst</string> </map> <key>name</key> <string>windows64</string> @@ -2776,7 +2776,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>copyright</key> <string>Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler</string> <key>version</key> - <string>2.2.3-dev0.g8aa13e3.d20250206</string> + <string>2.2.5-0d88d03</string> <key>name</key> <string>zlib-ng</string> <key>canonical_repo</key> diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index b57c33c3e0..3bea85f3ea 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -20,48 +20,42 @@ if (WINDOWS) find_library(BOOST_CONTEXT_LIBRARY NAMES + libboost_context libboost_context-mt libboost_context-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_FIBER_LIBRARY NAMES + libboost_fiber libboost_fiber-mt libboost_fiber-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_FILESYSTEM_LIBRARY NAMES + libboost_filesystem libboost_filesystem-mt libboost_filesystem-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_PROGRAMOPTIONS_LIBRARY NAMES + libboost_program_options libboost_program_options-mt libboost_program_options-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - find_library(BOOST_REGEX_LIBRARY - NAMES - libboost_regex-mt - libboost_regex-mt${addrsfx} - PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - - find_library(BOOST_SYSTEM_LIBRARY - NAMES - libboost_system-mt - libboost_system-mt${addrsfx} - PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - find_library(BOOST_THREAD_LIBRARY NAMES + libboost_thread libboost_thread-mt libboost_thread-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_URL_LIBRARY NAMES + libboost_url libboost_url-mt libboost_url-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) @@ -70,48 +64,42 @@ else (WINDOWS) find_library(BOOST_CONTEXT_LIBRARY NAMES + boost_context boost_context-mt boost_context-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_FIBER_LIBRARY NAMES + boost_fiber boost_fiber-mt boost_fiber-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_FILESYSTEM_LIBRARY NAMES + boost_filesystem boost_filesystem-mt boost_filesystem-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_PROGRAMOPTIONS_LIBRARY NAMES + boost_program_options boost_program_options-mt boost_program_options-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - find_library(BOOST_REGEX_LIBRARY - NAMES - boost_regex-mt - boost_regex-mt${addrsfx} - PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - - find_library(BOOST_SYSTEM_LIBRARY - NAMES - boost_system-mt - boost_system-mt${addrsfx} - PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) - find_library(BOOST_THREAD_LIBRARY NAMES + boost_thread boost_thread-mt boost_thread-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) find_library(BOOST_URL_LIBRARY NAMES + boost_url boost_url-mt boost_url-mt${addrsfx} PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH) @@ -123,8 +111,6 @@ target_link_libraries(ll::boost INTERFACE ${BOOST_CONTEXT_LIBRARY} ${BOOST_FILESYSTEM_LIBRARY} ${BOOST_PROGRAMOPTIONS_LIBRARY} - ${BOOST_REGEX_LIBRARY} - ${BOOST_SYSTEM_LIBRARY} ${BOOST_THREAD_LIBRARY} ${BOOST_URL_LIBRARY}) diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 7f7eaf1855..19e4e8ed9d 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1424,6 +1424,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC size_t mem_size = pixels * bytes_per_pixel; alpha_data = (U8*)ll_aligned_malloc_32(mem_size); + if (!alpha_data) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate memory for morph texture: " << (S32)(mem_size) << LL_ENDL; + return; + } bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels @@ -1433,6 +1439,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO // returning only the alpha portion without locking up downstream U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA + if (!temp) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate temporary memory for morph texture readback: " << (S32)(mem_size << 2) << LL_ENDL; + return; + } if (bound_target) { @@ -1469,6 +1481,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // We just want GL_ALPHA, but that isn't supported in OGL core profile 4. static const size_t TEMP_BYTES_PER_PIXEL = 4; U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL); + if (!temp_data) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate temporary memory for morph texture: " << (S32)(mem_size * TEMP_BYTES_PER_PIXEL) << LL_ENDL; + return; + } glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data); for (size_t pixel = 0; pixel < pixels; pixel++) { alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3]; diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index bc45eb474a..c6513cdb66 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -17,14 +17,12 @@ set(llcharacter_SOURCE_FILES lljointsolverrp3.cpp llkeyframefallmotion.cpp llkeyframemotion.cpp - llkeyframemotionparam.cpp llkeyframestandmotion.cpp llkeyframewalkmotion.cpp llmotioncontroller.cpp llmotion.cpp llmultigesture.cpp llpose.cpp - llstatemachine.cpp lltargetingmotion.cpp llvisualparam.cpp ) @@ -45,14 +43,12 @@ set(llcharacter_HEADER_FILES lljointstate.h llkeyframefallmotion.h llkeyframemotion.h - llkeyframemotionparam.h llkeyframestandmotion.h llkeyframewalkmotion.h llmotion.h llmotioncontroller.h llmultigesture.h llpose.h - llstatemachine.h lltargetingmotion.h llvisualparam.h ) diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp deleted file mode 100644 index e4552b96c9..0000000000 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/** - * @file llkeyframemotionparam.cpp - * @brief Implementation of LLKeyframeMotion class. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "linden_common.h" - -#include "llkeyframemotionparam.h" -#include "llcharacter.h" -#include "llmath.h" -#include "m3math.h" -#include "lldir.h" -#include "llanimationstates.h" - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam class -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam() -// Class Constructor -//----------------------------------------------------------------------------- -LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id) -{ - mDefaultKeyframeMotion = NULL; - mCharacter = NULL; - - mEaseInDuration = 0.f; - mEaseOutDuration = 0.f; - mDuration = 0.f; - mPriority = LLJoint::LOW_PRIORITY; -} - - -//----------------------------------------------------------------------------- -// ~LLKeyframeMotionParam() -// Class Destructor -//----------------------------------------------------------------------------- -LLKeyframeMotionParam::~LLKeyframeMotionParam() -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - delete paramMotion.mMotion; - } - motionList.clear(); - } - mParameterizedMotions.clear(); -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onInitialize(LLCharacter *character) -//----------------------------------------------------------------------------- -LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character) -{ - mCharacter = character; - - if (!loadMotions()) - { - return STATUS_FAILURE; - } - - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - LLMotion* motion = paramMotion.mMotion; - motion->onInitialize(character); - - if (motion->getDuration() > mEaseInDuration) - { - mEaseInDuration = motion->getEaseInDuration(); - } - - if (motion->getEaseOutDuration() > mEaseOutDuration) - { - mEaseOutDuration = motion->getEaseOutDuration(); - } - - if (motion->getDuration() > mDuration) - { - mDuration = motion->getDuration(); - } - - if (motion->getPriority() > mPriority) - { - mPriority = motion->getPriority(); - } - - LLPose *pose = motion->getPose(); - - mPoseBlender.addMotion(motion); - for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState()) - { - LLPose *blendedPose = mPoseBlender.getBlendedPose(); - blendedPose->addJointState(jsp); - } - } - } - - return STATUS_SUCCESS; -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onActivate() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::onActivate() -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - paramMotion.mMotion->activate(mActivationTimestamp); - } - } - return true; -} - - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onUpdate() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask) -{ - LL_PROFILE_ZONE_SCOPED; - F32 weightFactor = 1.f / (F32)mParameterizedMotions.size(); - - // zero out all pose weights - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { -// LL_INFOS() << "Weight for pose " << paramMotion.mMotion->getName() << " is " << paramMotion.mMotion->getPose()->getWeight() << LL_ENDL; - paramMotion.mMotion->getPose()->setWeight(0.f); - } - } - - - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - const std::string& paramName = motion_pair.first; - F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName); - if (NULL == paramValue) // unexpected, but... - { - LL_WARNS() << "paramValue == NULL" << LL_ENDL; - continue; - } - - // DANGER! Do not modify mParameterizedMotions while using these pointers! - const ParameterizedMotion* firstMotion = NULL; - const ParameterizedMotion* secondMotion = NULL; - - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - paramMotion.mMotion->onUpdate(time, joint_mask); - - F32 distToParam = paramMotion.mParam - *paramValue; - - if ( distToParam <= 0.f) - { - // keep track of the motion closest to the parameter value - firstMotion = ¶mMotion; - } - else - { - // we've passed the parameter value - // so store the first motion we find as the second one we want to blend... - if (firstMotion && !secondMotion ) - { - secondMotion = ¶mMotion; - } - //...or, if we've seen no other motion so far, make sure we blend to this only - else if (!firstMotion) - { - firstMotion = ¶mMotion; - secondMotion = ¶mMotion; - } - } - } - - LLPose *firstPose; - LLPose *secondPose; - - if (firstMotion) - firstPose = firstMotion->mMotion->getPose(); - else - firstPose = NULL; - - if (secondMotion) - secondPose = secondMotion->mMotion->getPose(); - else - secondPose = NULL; - - // now modify weight of the subanim (only if we are blending between two motions) - if (firstMotion && secondMotion) - { - if (firstMotion == secondMotion) - { - firstPose->setWeight(weightFactor); - } - else if (firstMotion->mParam == secondMotion->mParam) - { - firstPose->setWeight(0.5f * weightFactor); - secondPose->setWeight(0.5f * weightFactor); - } - else - { - F32 first_weight = 1.f - - ((llclamp(*paramValue - firstMotion->mParam, 0.f, (secondMotion->mParam - firstMotion->mParam))) / - (secondMotion->mParam - firstMotion->mParam)); - first_weight = llclamp(first_weight, 0.f, 1.f); - - F32 second_weight = 1.f - first_weight; - - firstPose->setWeight(first_weight * weightFactor); - secondPose->setWeight(second_weight * weightFactor); - -// LL_INFOS() << "Parameter " << *paramName << ": " << *paramValue << LL_ENDL; -// LL_INFOS() << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << LL_ENDL; - } - } - else if (firstMotion && !secondMotion) - { - firstPose->setWeight(weightFactor); - } - } - - // blend poses - mPoseBlender.blendAndApply(); - - LL_INFOS() << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << LL_ENDL; - - return true; -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onDeactivate() -//----------------------------------------------------------------------------- -void LLKeyframeMotionParam::onDeactivate() -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - paramMotion.mMotion->onDeactivate(); - } - } -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::addKeyframeMotion() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value) -{ - LLMotion *newMotion = mCharacter->createMotion( id ); - - if (!newMotion) - { - return false; - } - - newMotion->setName(name); - - // now add motion to this list - mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value)); - - return true; -} - - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::setDefaultKeyframeMotion() -//----------------------------------------------------------------------------- -void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name) -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - if (paramMotion.mMotion->getName() == name) - { - mDefaultKeyframeMotion = paramMotion.mMotion; - } - } - } -} - -//----------------------------------------------------------------------------- -// loadMotions() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::loadMotions() -{ - //------------------------------------------------------------------------- - // Load named file by concatenating the character prefix with the motion name. - // Load data into a buffer to be parsed. - //------------------------------------------------------------------------- - //std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()) - // + "_" + getName() + ".llp"; - //RN: deprecated unused reference to "motion" directory - std::string path; - - - //------------------------------------------------------------------------- - // open the file - //------------------------------------------------------------------------- - S32 fileSize = 0; - LLAPRFile infile ; - infile.open(path, LL_APR_R, NULL, &fileSize); - apr_file_t* fp = infile.getFileHandle() ; - if (!fp || fileSize == 0) - { - LL_INFOS() << "ERROR: can't open: " << path << LL_ENDL; - return false; - } - - // allocate a text buffer - std::vector<char> text(fileSize+1); - - //------------------------------------------------------------------------- - // load data from file into buffer - //------------------------------------------------------------------------- - bool error = false; - char *p = &text[0]; - while ( 1 ) - { - if (apr_file_eof(fp) == APR_EOF) - { - break; - } - if (apr_file_gets(p, 1024, fp) != APR_SUCCESS) - { - error = true; - break; - } - while ( *(++p) ) - ; - } - - //------------------------------------------------------------------------- - // close the file - //------------------------------------------------------------------------- - infile.close(); - - //------------------------------------------------------------------------- - // check for error - //------------------------------------------------------------------------- - llassert( p <= (&text[0] + fileSize) ); - - if ( error ) - { - LL_INFOS() << "ERROR: error while reading from " << path << LL_ENDL; - return false; - } - - LL_INFOS() << "Loading parametric keyframe data for: " << getName() << LL_ENDL; - - //------------------------------------------------------------------------- - // parse the text and build keyframe data structures - //------------------------------------------------------------------------- - p = &text[0]; - S32 num; - char strA[80]; /* Flawfinder: ignore */ - char strB[80]; /* Flawfinder: ignore */ - F32 floatA = 0.0f; - - - //------------------------------------------------------------------------- - // get priority - //------------------------------------------------------------------------- - bool isFirstMotion = true; - num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */ - - while(1) - { - if (num == 0 || num == EOF) break; - if ((num != 3)) - { - LL_INFOS() << "WARNING: can't read parametric motion" << LL_ENDL; - return false; - } - - addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(std::string(strA)), strB, floatA); - if (isFirstMotion) - { - isFirstMotion = false; - setDefaultKeyframeMotion(strA); - } - - p = strstr(p, "\n"); - if (!p) - { - break; - } - - p++; - num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */ - } - - return true; -} - -// End diff --git a/indra/llcharacter/llkeyframemotionparam.h b/indra/llcharacter/llkeyframemotionparam.h deleted file mode 100644 index 8c57766e9b..0000000000 --- a/indra/llcharacter/llkeyframemotionparam.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file llkeyframemotionparam.h - * @brief Implementation of LLKeframeMotionParam class. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLKEYFRAMEMOTIONPARAM_H -#define LL_LLKEYFRAMEMOTIONPARAM_H - -//----------------------------------------------------------------------------- -// Header files -//----------------------------------------------------------------------------- - -#include <string> - -#include "llmotion.h" -#include "lljointstate.h" -#include "v3math.h" -#include "llquaternion.h" -#include "llkeyframemotion.h" - -//----------------------------------------------------------------------------- -// class LLKeyframeMotionParam -//----------------------------------------------------------------------------- -class LLKeyframeMotionParam : - public LLMotion -{ -public: - // Constructor - LLKeyframeMotionParam(const LLUUID &id); - - // Destructor - virtual ~LLKeyframeMotionParam(); - -public: - //------------------------------------------------------------------------- - // functions to support MotionController and MotionRegistry - //------------------------------------------------------------------------- - - // static constructor - // all subclasses must implement such a function and register it - static LLMotion *create(const LLUUID &id) { return new LLKeyframeMotionParam(id); } - -public: - //------------------------------------------------------------------------- - // animation callbacks to be implemented by subclasses - //------------------------------------------------------------------------- - - // motions must specify whether or not they loop - virtual bool getLoop() { - return true; - } - - // motions must report their total duration - virtual F32 getDuration() { - return mDuration; - } - - // motions must report their "ease in" duration - virtual F32 getEaseInDuration() { - return mEaseInDuration; - } - - // motions must report their "ease out" duration. - virtual F32 getEaseOutDuration() { - return mEaseOutDuration; - } - - // motions must report their priority - virtual LLJoint::JointPriority getPriority() { - return mPriority; - } - - virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } - - // called to determine when a motion should be activated/deactivated based on avatar pixel coverage - virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_KEYFRAME; } - - // run-time (post constructor) initialization, - // called after parameters have been set - // must return true to indicate success and be available for activation - virtual LLMotionInitStatus onInitialize(LLCharacter *character); - - // called when a motion is activated - // must return true to indicate success, or else - // it will be deactivated - virtual bool onActivate(); - - // called per time step - // must return true while it is active, and - // must return false when the motion is completed. - virtual bool onUpdate(F32 time, U8* joint_mask); - - // called when a motion is deactivated - virtual void onDeactivate(); - - virtual LLPose* getPose() { return mPoseBlender.getBlendedPose();} - -protected: - //------------------------------------------------------------------------- - // new functions defined by this subclass - //------------------------------------------------------------------------- - struct ParameterizedMotion - { - ParameterizedMotion(LLMotion* motion, F32 param) : mMotion(motion), mParam(param) {} - LLMotion* mMotion; - F32 mParam; - }; - - // add a motion and associated parameter triplet - bool addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value); - - // set default motion for LOD and retrieving blend constants - void setDefaultKeyframeMotion(char *); - - bool loadMotions(); - -protected: - //------------------------------------------------------------------------- - // Member Data - //------------------------------------------------------------------------- - - struct compare_motions - { - bool operator() (const ParameterizedMotion& a, const ParameterizedMotion& b) const - { - if (a.mParam != b.mParam) - return (a.mParam < b.mParam); - else - return a.mMotion < b.mMotion; - } - }; - - typedef std::set < ParameterizedMotion, compare_motions > motion_list_t; - typedef std::map <std::string, motion_list_t > motion_map_t; - motion_map_t mParameterizedMotions; - LLMotion* mDefaultKeyframeMotion; - LLCharacter* mCharacter; - LLPoseBlender mPoseBlender; - - F32 mEaseInDuration; - F32 mEaseOutDuration; - F32 mDuration; - LLJoint::JointPriority mPriority; - - LLUUID mTransactionID; -}; - -#endif // LL_LLKEYFRAMEMOTIONPARAM_H diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 0c262bf24a..c2cb174821 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -37,7 +37,6 @@ #include "llmotion.h" #include "llpose.h" #include "llframetimer.h" -#include "llstatemachine.h" #include "llstring.h" //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp deleted file mode 100644 index 38e9ef444c..0000000000 --- a/indra/llcharacter/llstatemachine.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/** - * @file llstatemachine.cpp - * @brief LLStateMachine implementation file. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llstatemachine.h" -#include "llapr.h" - -#define FSM_PRINT_STATE_TRANSITIONS (0) - -U32 LLUniqueID::sNextID = 0; - -bool operator==(const LLUniqueID &a, const LLUniqueID &b) -{ - return (a.mId == b.mId); -} - -bool operator!=(const LLUniqueID &a, const LLUniqueID &b) -{ - return (a.mId != b.mId); -} - -//----------------------------------------------------------------------------- -// LLStateDiagram -//----------------------------------------------------------------------------- -LLStateDiagram::LLStateDiagram() -{ - mDefaultState = NULL; - mUseDefaultState = false; -} - -LLStateDiagram::~LLStateDiagram() -{ - -} - -// add a state to the state graph -bool LLStateDiagram::addState(LLFSMState *state) -{ - mStates[state] = Transitions(); - return true; -} - -// add a directed transition between 2 states -bool LLStateDiagram::addTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition) -{ - StateMap::iterator state_it; - state_it = mStates.find(&start_state); - Transitions* state_transitions = NULL; - if (state_it == mStates.end() ) - { - addState(&start_state); - state_transitions = &mStates[&start_state]; - } - else - { - state_transitions = &state_it->second; - } - state_it = mStates.find(&end_state); - if (state_it == mStates.end() ) - { - addState(&end_state); - } - - Transitions::iterator transition_it = state_transitions->find(&transition); - if (transition_it != state_transitions->end()) - { - LL_ERRS() << "LLStateTable::addDirectedTransition() : transition already exists" << LL_ENDL; - return false; // transition already exists - } - - (*state_transitions)[&transition] = &end_state; - return true; -} - -// add an undirected transition between 2 states -bool LLStateDiagram::addUndirectedTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition) -{ - bool result; - result = addTransition(start_state, end_state, transition); - if (result) - { - result = addTransition(end_state, start_state, transition); - } - return result; -} - -// add a transition that exists for every state -void LLStateDiagram::addDefaultTransition(LLFSMState& end_state, LLFSMTransition& transition) -{ - mDefaultTransitions[&transition] = &end_state; -} - -// process a possible transition, and get the resulting state -LLFSMState* LLStateDiagram::processTransition(LLFSMState& start_state, LLFSMTransition& transition) -{ - // look up transition - //LLFSMState** dest_state = (mStates.getValue(&start_state))->getValue(&transition); - LLFSMState* dest_state = NULL; - StateMap::iterator state_it = mStates.find(&start_state); - if (state_it == mStates.end()) - { - return NULL; - } - Transitions::iterator transition_it = state_it->second.find(&transition); - - // try default transitions if state-specific transition not found - if (transition_it == state_it->second.end()) - { - dest_state = mDefaultTransitions[&transition]; - } - else - { - dest_state = transition_it->second; - } - - // if we have a destination state... - if (NULL != dest_state) - { - // ...return it... - return dest_state; - } - // ... otherwise ... - else - { - // ...look for default state... - if (mUseDefaultState) - { - // ...return it if we have it... - return mDefaultState; - } - else - { - // ...or else we're still in the same state. - return &start_state; - } - } -} - -void LLStateDiagram::setDefaultState(LLFSMState& default_state) -{ - mUseDefaultState = true; - mDefaultState = &default_state; -} - -S32 LLStateDiagram::numDeadendStates() -{ - S32 numDeadends = 0; - for (StateMap::value_type& state_pair : mStates) - { - if (state_pair.second.size() == 0) - { - numDeadends++; - } - } - return numDeadends; -} - -bool LLStateDiagram::stateIsValid(LLFSMState& state) -{ - if (mStates.find(&state) != mStates.end()) - { - return true; - } - return false; -} - -LLFSMState* LLStateDiagram::getState(U32 state_id) -{ - for (StateMap::value_type& state_pair : mStates) - { - if (state_pair.first->getID() == state_id) - { - return state_pair.first; - } - } - return NULL; -} - -bool LLStateDiagram::saveDotFile(const std::string& filename) -{ - LLAPRFile outfile ; - outfile.open(filename, LL_APR_W); - apr_file_t* dot_file = outfile.getFileHandle() ; - - if (!dot_file) - { - LL_WARNS() << "LLStateDiagram::saveDotFile() : Couldn't open " << filename << " to save state diagram." << LL_ENDL; - return false; - } - apr_file_printf(dot_file, "digraph StateMachine {\n\tsize=\"100,100\";\n\tfontsize=40;\n\tlabel=\"Finite State Machine\";\n\torientation=landscape\n\tratio=.77\n"); - - for (StateMap::value_type& state_pair : mStates) - { - apr_file_printf(dot_file, "\t\"%s\" [fontsize=28,shape=box]\n", state_pair.first->getName().c_str()); - } - apr_file_printf(dot_file, "\t\"All States\" [fontsize=30,style=bold,shape=box]\n"); - - for (Transitions::value_type& transition_pair : mDefaultTransitions) - { - apr_file_printf(dot_file, "\t\"All States\" -> \"%s\" [label = \"%s\",fontsize=24];\n", transition_pair.second->getName().c_str(), - transition_pair.second->getName().c_str()); - } - - if (mDefaultState) - { - apr_file_printf(dot_file, "\t\"All States\" -> \"%s\";\n", mDefaultState->getName().c_str()); - } - - - for (StateMap::value_type& state_pair : mStates) - { - LLFSMState *state = state_pair.first; - - for (Transitions::value_type& transition_pair : state_pair.second) - { - std::string state_name = state->getName(); - std::string target_name = transition_pair.second->getName(); - std::string transition_name = transition_pair.first->getName(); - apr_file_printf(dot_file, "\t\"%s\" -> \"%s\" [label = \"%s\",fontsize=24];\n", state->getName().c_str(), - target_name.c_str(), - transition_name.c_str()); - } - } - - apr_file_printf(dot_file, "}\n"); - - return true; -} - -std::ostream& operator<<(std::ostream &s, LLStateDiagram &FSM) -{ - if (FSM.mDefaultState) - { - s << "Default State: " << FSM.mDefaultState->getName() << "\n"; - } - - for (LLStateDiagram::Transitions::value_type& transition_pair : FSM.mDefaultTransitions) - { - s << "Any State -- " << transition_pair.first->getName() - << " --> " << transition_pair.second->getName() << "\n"; - } - - for (LLStateDiagram::StateMap::value_type& state_pair : FSM.mStates) - { - for (LLStateDiagram::Transitions::value_type& transition_pair : state_pair.second) - { - s << state_pair.first->getName() << " -- " << transition_pair.first->getName() - << " --> " << transition_pair.second->getName() << "\n"; - } - s << "\n"; - } - - return s; -} - -//----------------------------------------------------------------------------- -// LLStateMachine -//----------------------------------------------------------------------------- - -LLStateMachine::LLStateMachine() -{ - // we haven't received a starting state yet - mCurrentState = NULL; - mLastState = NULL; - mLastTransition = NULL; - mStateDiagram = NULL; -} - -LLStateMachine::~LLStateMachine() -{ - -} - -// returns current state -LLFSMState* LLStateMachine::getCurrentState() const -{ - return mCurrentState; -} - -// executes current state -void LLStateMachine::runCurrentState(void *data) -{ - mCurrentState->execute(data); -} - -// set current state -bool LLStateMachine::setCurrentState(LLFSMState *initial_state, void* user_data, bool skip_entry) -{ - llassert(mStateDiagram); - - if (mStateDiagram->stateIsValid(*initial_state)) - { - mLastState = mCurrentState = initial_state; - if (!skip_entry) - { - initial_state->onEntry(user_data); - } - return true; - } - - return false; -} - -bool LLStateMachine::setCurrentState(U32 state_id, void* user_data, bool skip_entry) -{ - llassert(mStateDiagram); - - LLFSMState* state = mStateDiagram->getState(state_id); - - if (state) - { - mLastState = mCurrentState = state; - if (!skip_entry) - { - state->onEntry(user_data); - } - return true; - } - - return false; -} - -void LLStateMachine::processTransition(LLFSMTransition& transition, void* user_data) -{ - llassert(mStateDiagram); - - if (NULL == mCurrentState) - { - LL_WARNS() << "mCurrentState == NULL; aborting processTransition()" << LL_ENDL; - return; - } - - LLFSMState* new_state = mStateDiagram->processTransition(*mCurrentState, transition); - - if (NULL == new_state) - { - LL_WARNS() << "new_state == NULL; aborting processTransition()" << LL_ENDL; - return; - } - - mLastTransition = &transition; - mLastState = mCurrentState; - - if (*mCurrentState != *new_state) - { - mCurrentState->onExit(user_data); - mCurrentState = new_state; - mCurrentState->onEntry(user_data); -#if FSM_PRINT_STATE_TRANSITIONS - LL_INFOS() << "Entering state " << mCurrentState->getName() << - " on transition " << transition.getName() << " from state " << - mLastState->getName() << LL_ENDL; -#endif - } -} - -void LLStateMachine::setStateDiagram(LLStateDiagram* diagram) -{ - mStateDiagram = diagram; -} diff --git a/indra/llcharacter/llstatemachine.h b/indra/llcharacter/llstatemachine.h deleted file mode 100644 index 9a33798d96..0000000000 --- a/indra/llcharacter/llstatemachine.h +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @file llstatemachine.h - * @brief LLStateMachine class header file. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLSTATEMACHINE_H -#define LL_LLSTATEMACHINE_H - -#include <string> - -#include "llerror.h" -#include <map> - -class LLUniqueID -{ - friend bool operator==(const LLUniqueID &a, const LLUniqueID &b); - friend bool operator!=(const LLUniqueID &a, const LLUniqueID &b); -protected: - static U32 sNextID; - U32 mId; -public: - LLUniqueID(){mId = sNextID++;} - virtual ~LLUniqueID(){} - U32 getID() {return mId;} -}; - -class LLFSMTransition : public LLUniqueID -{ -public: - LLFSMTransition() : LLUniqueID(){}; - virtual std::string getName()const { return "unnamed"; } -}; - -class LLFSMState : public LLUniqueID -{ -public: - LLFSMState() : LLUniqueID(){}; - virtual void onEntry(void *){}; - virtual void onExit(void *){}; - virtual void execute(void *){}; - virtual std::string getName() const { return "unnamed"; } -}; - -class LLStateDiagram -{ -typedef std::map<LLFSMTransition*, LLFSMState*> Transitions; - -friend std::ostream& operator<<(std::ostream &s, LLStateDiagram &FSM); -friend class LLStateMachine; - -protected: - typedef std::map<LLFSMState*, Transitions> StateMap; - StateMap mStates; - Transitions mDefaultTransitions; - LLFSMState* mDefaultState; - bool mUseDefaultState; - -public: - LLStateDiagram(); - virtual ~LLStateDiagram(); - -protected: - // add a state to the state graph, executed implicitly when adding transitions - bool addState(LLFSMState *state); - - // add a directed transition between 2 states - bool addTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition); - - // add an undirected transition between 2 states - bool addUndirectedTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition); - - // add a transition that is taken if none other exist - void addDefaultTransition(LLFSMState& end_state, LLFSMTransition& transition); - - // process a possible transition, and get the resulting state - LLFSMState* processTransition(LLFSMState& start_state, LLFSMTransition& transition); - - // add a transition that exists for every state - void setDefaultState(LLFSMState& default_state); - - // return total number of states with no outgoing transitions - S32 numDeadendStates(); - - // does this state exist in the state diagram? - bool stateIsValid(LLFSMState& state); - - // get a state pointer by ID - LLFSMState* getState(U32 state_id); - -public: - // save the graph in a DOT file for rendering and visualization - bool saveDotFile(const std::string& filename); -}; - -class LLStateMachine -{ -protected: - LLFSMState* mCurrentState; - LLFSMState* mLastState; - LLFSMTransition* mLastTransition; - LLStateDiagram* mStateDiagram; - -public: - LLStateMachine(); - virtual ~LLStateMachine(); - - // set state diagram - void setStateDiagram(LLStateDiagram* diagram); - - // process this transition - void processTransition(LLFSMTransition &transition, void* user_data); - - // returns current state - LLFSMState* getCurrentState() const; - - // execute current state - void runCurrentState(void *data); - - // set state by state pointer - bool setCurrentState(LLFSMState *initial_state, void* user_data, bool skip_entry = true); - - // set state by unique ID - bool setCurrentState(U32 state_id, void* user_data, bool skip_entry = true); -}; - -#endif //_LL_LLSTATEMACHINE_H diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 2de9deea70..32226a62e6 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -68,6 +68,7 @@ set(llcommon_SOURCE_FILES llmetricperformancetester.cpp llmortician.cpp llmutex.cpp + llpointer.cpp llptrto.cpp llpredicate.cpp llprocess.cpp @@ -101,6 +102,7 @@ set(llcommon_SOURCE_FILES lluri.cpp lluriparser.cpp lluuid.cpp + llwatchdog.cpp llworkerthread.cpp hbxxh.cpp u64.cpp @@ -240,6 +242,7 @@ set(llcommon_HEADER_FILES lluri.h lluriparser.h lluuid.h + llwatchdog.h llwin32headers.h llworkerthread.h hbxxh.h diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index c532620daa..f92bb98ba6 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -93,6 +93,7 @@ bool LLApp::sDisableCrashlogger = false; LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED}; LLAppErrorHandler LLApp::sErrorHandler = NULL; +bool gDisconnected = false; LLApp::LLApp() { diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 57f5a112d9..ce09c566a9 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -50,6 +50,8 @@ void clear_signals(); #endif +extern bool gDisconnected; + class LL_COMMON_API LLApp { public: diff --git a/indra/llcommon/llpointer.cpp b/indra/llcommon/llpointer.cpp new file mode 100755 index 0000000000..1bb7055b3a --- /dev/null +++ b/indra/llcommon/llpointer.cpp @@ -0,0 +1,43 @@ +/** + * @file llpointer.cpp + * @author Nat Goodspeed + * @date 2024-09-26 + * @brief Implementation for llpointer. + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llpointer.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" + +void LLPointerBase::wild_dtor(std::string_view msg) +{ +// LL_WARNS() << msg << LL_ENDL; + llassert_msg(false, msg); +} diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index 048547e4cc..d2dcf530e5 100644 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -26,8 +26,9 @@ #ifndef LLPOINTER_H #define LLPOINTER_H -#include "llerror.h" // *TODO: consider eliminating this -#include "llmutex.h" +#include <functional> +#include <string_view> +#include <utility> // std::swap() //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s @@ -42,8 +43,18 @@ //---------------------------------------------------------------------------- +class LLPointerBase +{ +protected: + // alert the coder that a referenced type's destructor did something very + // strange -- this is in a non-template base class so we can hide the + // implementation in llpointer.cpp + static void wild_dtor(std::string_view msg); +}; + // Note: relies on Type having ref() and unref() methods -template <class Type> class LLPointer +template <class Type> +class LLPointer: public LLPointerBase { public: template<typename Subclass> @@ -60,6 +71,13 @@ public: ref(); } + // Even though the template constructors below accepting + // (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to + // subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&) + // constructors, the compiler recognizes these as The Copy Constructor and + // The Move Constructor, respectively. In other words, even in the + // presence of the LLPointer<Subclass> constructors, we still must specify + // the LLPointer<Type> constructors. LLPointer(const LLPointer<Type>& ptr) : mPointer(ptr.mPointer) { @@ -98,39 +116,52 @@ public: const Type& operator*() const { return *mPointer; } Type& operator*() { return *mPointer; } - operator BOOL() const { return (mPointer != nullptr); } operator bool() const { return (mPointer != nullptr); } bool operator!() const { return (mPointer == nullptr); } bool isNull() const { return (mPointer == nullptr); } bool notNull() const { return (mPointer != nullptr); } operator Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } + template <typename Type1> + bool operator !=(Type1* ptr) const { return (mPointer != ptr); } + template <typename Type1> + bool operator ==(Type1* ptr) const { return (mPointer == ptr); } + template <typename Type1> + bool operator !=(const LLPointer<Type1>& ptr) const { return (mPointer != ptr.mPointer); } + template <typename Type1> + bool operator ==(const LLPointer<Type1>& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } LLPointer<Type>& operator =(Type* ptr) { - assign(ptr); + // copy-and-swap idiom, see http://gotw.ca/gotw/059.htm + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } + // Even though the template assignment operators below accepting + // (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to + // subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&) + // assignment operators, the compiler recognizes these as Copy Assignment + // and Move Assignment, respectively. In other words, even in the presence + // of the LLPointer<Subclass> assignment operators, we still must specify + // the LLPointer<Type> operators. LLPointer<Type>& operator =(const LLPointer<Type>& ptr) { - assign(ptr); + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } LLPointer<Type>& operator =(LLPointer<Type>&& ptr) { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } + LLPointer temp(std::move(ptr)); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } @@ -138,28 +169,32 @@ public: template<typename Subclass> LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) { - assign(ptr.get()); + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } template<typename Subclass> LLPointer<Type>& operator =(LLPointer<Subclass>&& ptr) { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } + LLPointer temp(std::move(ptr)); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } // Just exchange the pointers, which will not change the reference counts. static void swap(LLPointer<Type>& a, LLPointer<Type>& b) { - Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; + using std::swap; // per Swappable convention + swap(a.mPointer, b.mPointer); + } + + // Put swap() overload in the global namespace, per Swappable convention + friend void swap(LLPointer<Type>& a, LLPointer<Type>& b) + { + LLPointer<Type>::swap(a, b); } protected: @@ -184,191 +219,19 @@ protected: temp->unref(); if (mPointer != nullptr) { - LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; + wild_dtor("Unreference did assignment to non-NULL because of destructor"); unref(); } } } #endif // LL_LIBRARY_INCLUDE - void assign(const LLPointer<Type>& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - } - protected: Type* mPointer; }; -template <class Type> class LLConstPointer -{ - template<typename Subclass> - friend class LLConstPointer; -public: - LLConstPointer() : - mPointer(nullptr) - { - } - - LLConstPointer(const Type* ptr) : - mPointer(ptr) - { - ref(); - } - - LLConstPointer(const LLConstPointer<Type>& ptr) : - mPointer(ptr.mPointer) - { - ref(); - } - - LLConstPointer(LLConstPointer<Type>&& ptr) noexcept - { - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template<typename Subclass> - LLConstPointer(const LLConstPointer<Subclass>& ptr) : - mPointer(ptr.get()) - { - ref(); - } - - template<typename Subclass> - LLConstPointer(LLConstPointer<Subclass>&& ptr) noexcept : - mPointer(ptr.get()) - { - ptr.mPointer = nullptr; - } - - ~LLConstPointer() - { - unref(); - } - - const Type* get() const { return mPointer; } - const Type* operator->() const { return mPointer; } - const Type& operator*() const { return *mPointer; } - - operator BOOL() const { return (mPointer != nullptr); } - operator bool() const { return (mPointer != nullptr); } - bool operator!() const { return (mPointer == nullptr); } - bool isNull() const { return (mPointer == nullptr); } - bool notNull() const { return (mPointer != nullptr); } - - operator const Type*() const { return mPointer; } - bool operator !=(const Type* ptr) const { return (mPointer != ptr); } - bool operator ==(const Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } - - LLConstPointer<Type>& operator =(const Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - - return *this; - } - - LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr) - { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - return *this; - } - - LLConstPointer<Type>& operator =(LLConstPointer<Type>&& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template<typename Subclass> - LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) - { - if( mPointer != ptr.get() ) - { - unref(); - mPointer = ptr.get(); - ref(); - } - return *this; - } - - template<typename Subclass> - LLConstPointer<Type>& operator =(LLConstPointer<Subclass>&& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } - return *this; - } - - // Just exchange the pointers, which will not change the reference counts. - static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b) - { - const Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; - } - -protected: -#ifdef LL_LIBRARY_INCLUDE - void ref(); - void unref(); -#else // LL_LIBRARY_INCLUDE - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - const Type *temp = mPointer; - mPointer = nullptr; - temp->unref(); - if (mPointer != nullptr) - { - LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; - unref(); - } - } - } -#endif // LL_LIBRARY_INCLUDE - -protected: - const Type* mPointer; -}; +template <typename Type> +using LLConstPointer = LLPointer<const Type>; template<typename Type> class LLCopyOnWritePointer : public LLPointer<Type> @@ -418,38 +281,26 @@ private: bool mStayUnique; }; -template<typename Type> -bool operator!=(Type* lhs, const LLPointer<Type>& rhs) +template<typename Type0, typename Type1> +bool operator!=(Type0* lhs, const LLPointer<Type1>& rhs) { return (lhs != rhs.get()); } -template<typename Type> -bool operator==(Type* lhs, const LLPointer<Type>& rhs) +template<typename Type0, typename Type1> +bool operator==(Type0* lhs, const LLPointer<Type1>& rhs) { return (lhs == rhs.get()); } -// boost hash adapter -template <class Type> -struct boost::hash<LLPointer<Type>> -{ - typedef LLPointer<Type> argument_type; - typedef std::size_t result_type; - result_type operator()(argument_type const& s) const - { - return (std::size_t) s.get(); - } -}; - -// Adapt boost hash to std hash +// Specialize for std::hash namespace std { template<class Type> struct hash<LLPointer<Type>> { std::size_t operator()(LLPointer<Type> const& s) const noexcept { - return boost::hash<LLPointer<Type>>()(s); + return std::hash<Type*>()(s.get()); } }; } diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 670b740133..4a01ec567e 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -176,13 +176,13 @@ public: // In general, our streambuf might contain a number of different // physical buffers; iterate over those. bool keepwriting = true; - for (const_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end()); + for (auto bufi(boost::asio::buffer_sequence_begin(bufs)), bufend(boost::asio::buffer_sequence_end(bufs)); bufi != bufend && keepwriting; ++bufi) { // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents // Although apr_file_write() accepts const void*, we // manipulate const char* so we can increment the pointer. - const char* remainptr = boost::asio::buffer_cast<const char*>(*bufi); + const char* remainptr = static_cast<const char*>(bufi->data()); std::size_t remainlen = boost::asio::buffer_size(*bufi); while (remainlen) { @@ -377,14 +377,14 @@ public: // In general, the mutable_buffer_sequence returned by prepare() might // contain a number of different physical buffers; iterate over those. std::size_t tocommit(0); - for (mutable_buffer_sequence::const_iterator bufi(bufs.begin()), bufend(bufs.end()); + for (auto bufi(boost::asio::buffer_sequence_begin(bufs)), bufend(boost::asio::buffer_sequence_end(bufs)); bufi != bufend; ++bufi) { // http://www.boost.org/doc/libs/1_49_0_beta1/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.accessing_buffer_contents std::size_t toread(boost::asio::buffer_size(*bufi)); apr_size_t gotten(toread); apr_status_t err = apr_file_read(mPipe, - boost::asio::buffer_cast<void*>(*bufi), + bufi->data(), &gotten); // EAGAIN is exactly what we want from a nonblocking pipe. // Rather than waiting for data, it should return immediately. @@ -657,10 +657,7 @@ LLProcess::LLProcess(const LLSDOrParams& params): // case), e.g. by calling operator(), returns a reference to *the same // instance* of the wrapped type that's stored in our Block subclass. // That's important! We know 'params' persists throughout this method - // call; but without that guarantee, we'd have to assume that converting - // one of its members to std::string might return a different (temp) - // instance. Capturing the c_str() from a temporary std::string is Bad Bad - // Bad. But armed with this knowledge, when you see params.cwd().c_str(), + // call; but without that guarantee, when you see params.cwd().c_str(), // grit your teeth and smile and carry on. if (params.cwd.isProvided()) diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 692941a892..8c12ee7f12 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -240,7 +240,11 @@ void LLThread::tryRun() LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); main_queue->post( // Bind the current exception, rethrow it in main loop. - [exc = std::current_exception()]() { std::rethrow_exception(exc); }); + [exc = std::current_exception(), name = mName]() + { + LL_INFOS("THREAD") << "Rethrowing exception from thread " << name << LL_ENDL; + std::rethrow_exception(exc); + }); } #endif // else LL_WINDOWS } diff --git a/indra/newview/llwatchdog.cpp b/indra/llcommon/llwatchdog.cpp index 614d1afc2a..1bc1283d0b 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/llcommon/llwatchdog.cpp @@ -24,11 +24,12 @@ * $/LicenseInfo$ */ +// Precompiled header +#include "linden_common.h" -#include "llviewerprecompiledheaders.h" #include "llwatchdog.h" +#include "llmutex.h" #include "llthread.h" -#include "llappviewer.h" constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U; @@ -67,7 +68,9 @@ private: }; // LLWatchdogEntry -LLWatchdogEntry::LLWatchdogEntry() +LLWatchdogEntry::LLWatchdogEntry(const std::string& thread_name) + : mThreadName(thread_name) + , mThreadID(LLThread::currentID()) { } @@ -89,11 +92,16 @@ void LLWatchdogEntry::stop() LLWatchdog::getInstance()->remove(this); } } +std::string LLWatchdogEntry::getThreadName() const +{ + return mThreadName + llformat(": %d", mThreadID); +} // LLWatchdogTimeout const std::string UNINIT_STRING = "uninitialized"; -LLWatchdogTimeout::LLWatchdogTimeout() : +LLWatchdogTimeout::LLWatchdogTimeout(const std::string& thread_name) : + LLWatchdogEntry(thread_name), mTimeout(0.0f), mPingState(UNINIT_STRING) { @@ -175,7 +183,7 @@ void LLWatchdog::remove(LLWatchdogEntry* e) unlockThread(); } -void LLWatchdog::init() +void LLWatchdog::init(func_t set_error_state_callback) { if (!mSuspectsAccessMutex && !mTimer) { @@ -188,6 +196,7 @@ void LLWatchdog::init() // start needs to use the mSuspectsAccessMutex mTimer->start(); } + mCreateMarkerFnc = set_error_state_callback; } void LLWatchdog::cleanup() @@ -241,17 +250,23 @@ void LLWatchdog::run() { mTimer->stop(); } - if (LLAppViewer::instance()->logoutRequestSent()) + + // Sets error marker file + mCreateMarkerFnc(); + // Todo1: Warn user? + // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'. + std::string last_state = (*result)->getLastState(); + if (last_state.empty()) { - LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LOGOUT_FROZE); + LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName() + << " expired; assuming viewer is hung and crashing" << LL_ENDL; } else { - LLAppViewer::instance()->createErrorMarker(LAST_EXEC_FROZE); + LL_ERRS() << "Watchdog timer for thread " << (*result)->getThreadName() + << " expired with state: " << last_state + << "; assuming viewer is hung and crashing" << LL_ENDL; } - // Todo1: warn user? - // Todo2: We probably want to report even if 5 seconds passed, just not error 'yet'. - LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL; } } diff --git a/indra/newview/llwatchdog.h b/indra/llcommon/llwatchdog.h index b7dd55577e..fded881bb8 100644 --- a/indra/newview/llwatchdog.h +++ b/indra/llcommon/llwatchdog.h @@ -30,13 +30,17 @@ #ifndef LL_TIMER_H #include "lltimer.h" #endif +#include "llmutex.h" +#include "llsingleton.h" + +#include <functional> // LLWatchdogEntry is the interface used by the tasks that // need to be watched. class LLWatchdogEntry { public: - LLWatchdogEntry(); + LLWatchdogEntry(const std::string &thread_name); virtual ~LLWatchdogEntry(); // isAlive is accessed by the watchdog thread. @@ -46,12 +50,19 @@ public: virtual void reset() = 0; virtual void start(); virtual void stop(); + virtual std::string getLastState() const { return std::string(); } + typedef std::thread::id id_t; + std::string getThreadName() const; + +private: + id_t mThreadID; // ID of the thread being watched + std::string mThreadName; }; class LLWatchdogTimeout : public LLWatchdogEntry { public: - LLWatchdogTimeout(); + LLWatchdogTimeout(const std::string& thread_name); virtual ~LLWatchdogTimeout(); bool isAlive() const override; @@ -63,6 +74,7 @@ public: void setTimeout(F32 d); void ping(std::string_view state); const std::string& getState() {return mPingState; } + std::string getLastState() const override { return mPingState; } private: LLTimer mTimer; @@ -81,10 +93,12 @@ public: void add(LLWatchdogEntry* e); void remove(LLWatchdogEntry* e); - void init(); + typedef std::function<void()> func_t; + void init(func_t set_error_state_callback); void run(); void cleanup(); + private: void lockThread(); void unlockThread(); @@ -94,6 +108,11 @@ private: LLMutex* mSuspectsAccessMutex; LLWatchdogTimerThread* mTimer; U64 mLastClockCount; + + // At the moment watchdog expects app to set markers in mCreateMarkerFnc, + // but technically can be used to set any error states or do some cleanup + // or show warnings. + func_t mCreateMarkerFnc; }; #endif // LL_LLTHREADWATCHDOG_H diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 7efaebd569..67c23358ed 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -216,10 +216,15 @@ void LL::WorkQueueBase::callWork(const Work& work) LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase " << getKey() << LL_ENDL; + std::string name = getKey(); LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); main_queue->post( // Bind the current exception, rethrow it in main loop. - [exc = std::current_exception()]() { std::rethrow_exception(exc); }); + [exc = std::current_exception(), name]() + { + LL_INFOS("LLCoros") << "Rethrowing exception from WorkQueueBase::callWork " << name << LL_ENDL; + std::rethrow_exception(exc); + }); } else { @@ -276,12 +281,30 @@ bool LL::WorkQueue::done() bool LL::WorkQueue::post(const Work& callable) { - return mQueue.pushIfOpen(callable); + try + { + return mQueue.pushIfOpen(callable); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in WorkQueue::post" << LL_ENDL; + return false; + } } bool LL::WorkQueue::tryPost(const Work& callable) { - return mQueue.tryPush(callable); + try + { + return mQueue.tryPush(callable); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in WorkQueue::tryPost" << LL_ENDL; + return false; + } } LL::WorkQueue::Work LL::WorkQueue::pop_() diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h index 735ad38a26..573203a5b3 100644 --- a/indra/llcommon/workqueue.h +++ b/indra/llcommon/workqueue.h @@ -530,7 +530,11 @@ namespace LL reply, // Bind the current exception to transport back to the // originating WorkQueue. Once there, rethrow it. - [exc = std::current_exception()](){ std::rethrow_exception(exc); }); + [exc = std::current_exception()]() + { + LL_INFOS("LLCoros") << "Rethrowing exception from WorkQueueBase::postTo" << LL_ENDL; + std::rethrow_exception(exc); + }); } }, // if caller passed a TimePoint, pass it along to post() diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ca8a4199e8..35bc7065b1 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -709,8 +709,20 @@ U8* LLImageBase::allocateData(S32 size) mData = (U8*)ll_aligned_malloc_16(size); if (!mData) { - LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; - mBadBufferAllocation = true; + constexpr S32 MAX_TOLERANCE = 1024 * 1024 * 4; // 4 MB + if (size > MAX_TOLERANCE) + { + // If a big image failed to allocate, tollerate it for now. + // It's insightfull when crash logs without obvious cause are being analyzed, + // so a crash in a random location that normally is a mystery can get proper handling. + LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; + } + else + { + // We are too far gone if we can't allocate a small buffer. + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; + } } } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 6b14b68c78..1fb61673bd 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -27,10 +27,11 @@ #ifndef LL_LLIMAGE_H #define LL_LLIMAGE_H -#include "lluuid.h" -#include "llstring.h" +#include "llmutex.h" #include "llpointer.h" +#include "llstring.h" #include "lltrace.h" +#include "lluuid.h" constexpr S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 constexpr S32 MAX_IMAGE_MIP = 12; // 4096x4096 diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 7eba9494a6..e7ac6bdb31 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -615,6 +615,11 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco return false; } } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Bad memory allocation in J2C KDU" << LL_ENDL; + } catch (const KDUError& msg) { base.setLastError(msg.what()); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b3cb278d59..ecc5a7b0c5 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4943,9 +4943,17 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) mOctree(NULL), mOctreeTriangles(NULL) { - mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); - mCenter = mExtents+2; - *this = src; + try + { + mExtents = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * 3); + mCenter = mExtents + 2; + *this = src; + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLVolume") << "Bad memory allocation in LLVolumeFace" << LL_ENDL; + } } LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) @@ -5163,7 +5171,7 @@ void LLVolumeFace::remap() // Documentation for meshopt_generateVertexRemapMulti claims that remap should use vertice count // but all examples use indice count. There are out of bounds crashes when using vertice count. // To be on the safe side use bigger of the two. - std::vector<unsigned int> remap(llmax(mNumIndices, mNumVertices)); + std::vector<unsigned int> remap(llmax(mNumIndices, mNumVertices), 0); S32 remap_vertices_count = static_cast<S32>(LLMeshOptimizer::generateRemapMultiU16(&remap[0], mIndices, mNumIndices, @@ -5681,7 +5689,12 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) catch (std::bad_alloc&) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL; + LL_ERRS("LLVolume") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL; + } + catch (...) + { + LL_WARNS_ONCE("LLVolume") << "Mikktspace::genTangSpace() failed" << LL_ENDL; + return false; } @@ -5703,7 +5716,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) catch (std::bad_alloc&) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL; + LL_ERRS("LLVOLUME") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL; } U32 stream_count = data.w.empty() ? 4 : 5; @@ -5720,7 +5733,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) catch (std::bad_alloc&) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL; + LL_ERRS("LLVolume") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL; } } @@ -5732,7 +5745,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) if (mNumVertices == 0) { LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL; + LL_ERRS("LLVolume") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL; } if (!data.w.empty()) diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index bb0c94d513..d8f649140f 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -25,6 +25,7 @@ #include "linden_common.h" +#include "llmutex.h" #include "llvolumemgr.h" #include "llvolume.h" diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 196ecdcf7d..0e11dca876 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -155,6 +155,7 @@ class LLVector3 friend const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b); // Returns a * b; friend const LLVector3& operator*=(LLVector3 &a, F32 k); // Return a times scaler k friend const LLVector3& operator/=(LLVector3 &a, F32 k); // Return a divided by scaler k + friend const LLVector3& operator/=(LLVector3& a, const LLVector3& b); friend const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &b); // Returns a * b; friend LLVector3 operator-(const LLVector3 &a); // Return vector -a @@ -460,6 +461,14 @@ inline const LLVector3& operator/=(LLVector3& a, F32 k) return a; } +inline const LLVector3& operator/=(LLVector3& a, const LLVector3& b) +{ + a.mV[VX] /= b.mV[VX]; + a.mV[VY] /= b.mV[VY]; + a.mV[VZ] /= b.mV[VZ]; + return a; +} + inline LLVector3 operator-(const LLVector3& a) { return LLVector3(-a.mV[VX], -a.mV[VY], -a.mV[VZ]); diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp index 7339454367..76d51fdad0 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.cpp +++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp @@ -171,7 +171,6 @@ size_t LLMeshOptimizer::generateRemapMultiU32( // but providing indices helps with removing unused vertices U64 indeces_cmp = indices ? index_count : vertex_count; - // meshopt_generateVertexRemapMulti will throw an assert if (indices[i] >= vertex_count) return meshopt_generateVertexRemapMulti(&remap[0], indices, indeces_cmp, vertex_count, streams, sizeof(streams) / sizeof(streams[0])); } diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 10fd56a68e..4c3acb27f4 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -1316,6 +1316,9 @@ const char* LLAssetStorage::getErrorString(S32 status) case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE: return "Asset request: asset not found in database"; + case LL_ERR_NO_CAP: + return "Asset request: region or asset capability not available"; + case LL_ERR_EOF: return "End of file"; diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 6d6526757d..d5daa0cb8f 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -57,6 +57,7 @@ const int LL_ERR_ASSET_REQUEST_FAILED = -1; const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3; const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4; const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5; +const int LL_ERR_NO_CAP = -6; const int LL_ERR_PRICE_MISMATCH = -23018; // *TODO: these typedefs are passed into the cache via a legacy C function pointer diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 149741b9f9..e4c7deb1c5 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -112,9 +112,7 @@ void LLExperienceCache::initSingleton() constexpr size_t CORO_QUEUE_SIZE = 2048; LLCoprocedureManager::instance().initializePool("ExpCache", CORO_QUEUE_SIZE); - LLCoros::instance().launch("LLExperienceCache::idleCoro", - boost::bind(&LLExperienceCache::idleCoro, this)); - + LLCoros::instance().launch("LLExperienceCache::idleCoro", LLExperienceCache::idleCoro); } void LLExperienceCache::cleanup() @@ -246,6 +244,7 @@ const LLExperienceCache::cache_t& LLExperienceCache::getCached() return mCache; } +// static because used by coroutine and can outlive the instance void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests) { LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>(); @@ -254,6 +253,13 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + if (sShutdown) + { + return; + } + + LLExperienceCache* self = LLExperienceCache::getInstance(); + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); @@ -265,7 +271,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap // build dummy entries for the failed requests for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) { - LLSD exp = get(*it); + LLSD exp = self->get(*it); //leave the properties alone if we already have a cache entry for this xp if (exp.isUndefined()) { @@ -278,7 +284,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap exp["error"] = (LLSD::Integer)status.getType(); exp[QUOTA] = DEFAULT_QUOTA; - processExperience(*it, exp); + self->processExperience(*it, exp); } return; } @@ -294,7 +300,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap LL_DEBUGS("ExperienceCache") << "Received result for " << public_key << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; - processExperience(public_key, row); + self->processExperience(public_key, row); } LLSD error_ids = result["error_ids"]; @@ -310,7 +316,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap exp[MISSING] = true; exp[QUOTA] = DEFAULT_QUOTA; - processExperience(id, exp); + self->processExperience(id, exp); LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; } @@ -361,7 +367,7 @@ void LLExperienceCache::requestExperiences() if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) { // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself. LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "RequestExperiences", - boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) ); + boost::bind(&LLExperienceCache::requestExperiencesCoro, _1, ostr.str(), requests) ); ostr.str(std::string()); ostr << urlBase << "?page_size=" << PAGE_SIZE1; @@ -393,7 +399,7 @@ void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t mCapability = queryfn; } - +// static, because coro can outlive the instance void LLExperienceCache::idleCoro() { const F32 SECS_BETWEEN_REQUESTS = 0.5f; @@ -402,14 +408,15 @@ void LLExperienceCache::idleCoro() LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; do { - if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) + LLExperienceCache* self = LLExperienceCache::getInstance(); + if (self->mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) { - eraseExpired(); + self->eraseExpired(); } - if (!mRequestQueue.empty()) + if (!self->mRequestQueue.empty()) { - requestExperiences(); + self->requestExperiences(); } llcoro::suspendUntilTimeout(SECS_BETWEEN_REQUESTS); diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 4b344347d5..9ecdb9efca 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -144,9 +144,9 @@ private: std::string mCacheFileName; static bool sShutdown; // control for coroutines, they exist out of LLExperienceCache's scope, so they need a static control - void idleCoro(); + static void idleCoro(); void eraseExpired(); - void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); + static void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); void requestExperiences(); void fetchAssociatedExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLUUID, LLUUID, std::string, ExperienceGetFn_t); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 31bc76344c..c3e3e19ee9 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,11 +109,12 @@ public: PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, PARAMS_REFLECTION_PROBE = 0x90, + PARAMS_MAX = PARAMS_REFLECTION_PROBE, }; public: U16 mType; - virtual ~LLNetworkData() {}; + virtual ~LLNetworkData() = default; virtual bool pack(LLDataPacker &dp) const = 0; virtual bool unpack(LLDataPacker &dp) = 0; virtual bool operator==(const LLNetworkData& data) const = 0; @@ -319,7 +320,7 @@ public: bool fromLLSD(LLSD& sd); void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); - LLUUID getSculptTexture() const { return mSculptTexture; } + const LLUUID& getSculptTexture() const { return mSculptTexture; } U8 getSculptType() const { return mSculptType; } }; @@ -340,10 +341,10 @@ public: bool fromLLSD(LLSD& sd); void setLightTexture(const LLUUID& id) { mLightTexture = id; } - LLUUID getLightTexture() const { return mLightTexture; } + const LLUUID& getLightTexture() const { return mLightTexture; } bool isLightSpotlight() const { return mLightTexture.notNull(); } void setParams(const LLVector3& params) { mParams = params; } - LLVector3 getParams() const { return mParams; } + const LLVector3& getParams() const { return mParams; } }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 57be8570af..1a3a499b20 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1774,25 +1774,64 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) return; } - if (mUIOffset.empty()) + LLVector4a vert(x, y, z); + transform(vert); + mVerticesp[mCount] = vert; + + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +} + +void LLRender::transform(LLVector3& vert) +{ + if (!mUIOffset.empty()) { - mVerticesp[mCount].set(x,y,z); + vert += LLVector3(mUIOffset.back().getF32ptr()); + vert *= LLVector3(mUIScale.back().getF32ptr()); } - else +} + +void LLRender::transform(LLVector4a& vert) +{ + if (!mUIOffset.empty()) { - LLVector4a vert(x, y, z); vert.add(mUIOffset.back()); vert.mul(mUIScale.back()); - mVerticesp[mCount] = vert; } +} - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +void LLRender::untransform(LLVector3& vert) +{ + if (!mUIOffset.empty()) + { + vert /= LLVector3(mUIScale.back().getF32ptr()); + vert -= LLVector3(mUIOffset.back().getF32ptr()); + } +} + +void LLRender::batchTransform(LLVector4a* verts, U32 vert_count) +{ + if (!mUIOffset.empty()) + { + const LLVector4a& offset = mUIOffset.back(); + const LLVector4a& scale = mUIScale.back(); + + for (U32 i = 0; i < vert_count; ++i) + { + verts[i].add(offset); + verts[i].mul(scale); + } + } +} + +void LLRender::vertexBatchPreTransformed(const std::vector<LLVector4a>& verts) +{ + vertexBatchPreTransformed(verts.data(), narrow(verts.size())); } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1813,7 +1852,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1837,7 +1876,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 } } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U* colors, S32 vert_count) { if (mCount + vert_count > 4094) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 0801c12fb4..be8539433c 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -450,9 +450,16 @@ public: void diffuseColor4ubv(const U8* c); void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); - void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); - void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); + void transform(LLVector3& vert); + void transform(LLVector4a& vert); + void untransform(LLVector3& vert); + + void batchTransform(LLVector4a* verts, U32 vert_count); + + void vertexBatchPreTransformed(const std::vector<LLVector4a>& verts); + void vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); diff --git a/indra/llrender/lltexturemanagerbridge.cpp b/indra/llrender/lltexturemanagerbridge.cpp index c243f0697a..67838418bf 100644 --- a/indra/llrender/lltexturemanagerbridge.cpp +++ b/indra/llrender/lltexturemanagerbridge.cpp @@ -24,6 +24,8 @@ * $/LicenseInfo$ */ +#include "linden_common.h" + #include "lltexturemanagerbridge.h" // Define a null texture manager bridge. Applications must provide their own bridge implementaton. diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 878f1cb856..dafbca7433 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -28,6 +28,7 @@ #include "llflashtimer.h" #include "linden_common.h" +#include "llapp.h" #include "llfolderviewitem.h" #include "llfolderview.h" #include "llfolderviewmodel.h" @@ -1884,6 +1885,11 @@ void LLFolderViewFolder::updateHasFavorites(bool new_childs_value) void LLFolderViewFolder::onIdleUpdateFavorites(void* data) { LLFolderViewFolder* self = reinterpret_cast<LLFolderViewFolder*>(data); + if (gDisconnected || !self) + { + return; + } + if (self->mFavoritesDirtyFlags == FAVORITE_CLEANUP) { // parent or child already processed the update, clean the callback @@ -2359,9 +2365,10 @@ bool LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { // navigating is going to destroy views and change children // delay it untill handleDoubleClick processing is complete - doOnIdleOneTime([this]() - { - getViewModelItem()->navigateToFolder(false); + LLPointer<LLFolderViewModelItem> view_model_item = getViewModelItem(); + doOnIdleOneTime([view_model_item]() mutable + {; + view_model_item->navigateToFolder(false); }); } return true; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 350c1e6996..4956d93e1c 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -122,6 +122,7 @@ LLLineEditor::Params::Params() LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) : LLUICtrl(p), + mDefaultText(p.default_text), mMaxLengthBytes(p.max_length.bytes), mMaxLengthChars(p.max_length.chars), mCursorPos( 0 ), diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 3f762822ee..6384bfdc5f 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -202,6 +202,7 @@ public: void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } + void setDefaultText() { setText(mDefaultText); } void setText(const LLStringExplicit &new_text); const std::string& getText() const override { return mText.getString(); } @@ -347,6 +348,7 @@ protected: LLFontVertexBuffer mFontBufferSelection; LLFontVertexBuffer mFontBufferPostSelection; LLFontVertexBuffer mFontBufferLabel; + std::string mDefaultText; S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes S32 mMaxLengthChars; // Maximum number of characters in the string S32 mCursorPos; // I-beam is just after the mCursorPos-th character. diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 2ca2454040..6ba31c251e 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4404,3 +4404,17 @@ bool LLContextMenu::addChild(LLView* view, S32 tab_group) return addContextChild(view, tab_group); } +void LLContextMenu::deleteAllChildren() +{ + mHoverItem = nullptr; + LLMenuGL::deleteAllChildren(); +} + +void LLContextMenu::removeChild(LLView* ctrl) +{ + if (ctrl == mHoverItem) + { + mHoverItem = nullptr; + } + LLMenuGL::removeChild(ctrl); +} diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index eacf2c59d4..bca0a731fc 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -730,6 +730,8 @@ public: virtual bool handleRightMouseUp ( S32 x, S32 y, MASK mask ); virtual bool addChild (LLView* view, S32 tab_group = 0); + /*virtual*/ void deleteAllChildren(); + /*virtual*/ void removeChild(LLView* ctrl); LLHandle<LLContextMenu> getHandle() { return getDerivedHandle<LLContextMenu>(); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index d56c459560..c7c7435be2 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -93,6 +93,7 @@ #include "llinitparam.h" #include "llinstancetracker.h" #include "llmortician.h" +#include "llmutex.h" #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index b459c67dad..558ce6a7fd 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3185,6 +3185,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS if (cell_p.width.isProvided()) { new_column.width.pixel_width = cell_p.width; + new_column.width.pixel_width.choose(); } addColumn(new_column); columnp = mColumns[column]; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index fcdf3782ae..7689b93374 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -581,7 +581,7 @@ S32 LLTextEditor::indentLine( S32 pos, S32 spaces ) LLWString wtext = getWText(); if (wtext[pos] == ' ') { - delta_spaces += remove( pos, 1, false ); + delta_spaces -= remove( pos, 1, false ); } } } diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d1bae49784..8e08239ee6 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -814,6 +814,7 @@ LLWebRTCPeerConnectionImpl::~LLWebRTCPeerConnectionImpl() { mSignalingObserverList.clear(); mDataObserverList.clear(); + mPeerConnectionFactory.release(); if (mPendingJobs > 0) { RTC_LOG(LS_ERROR) << __FUNCTION__ << "Destroying a connection that has " << std::to_string(mPendingJobs) << " unfinished jobs that might cause workers to crash"; @@ -877,7 +878,6 @@ void LLWebRTCPeerConnectionImpl::terminate() } mPendingJobs--; }); - mPeerConnectionFactory.release(); } void LLWebRTCPeerConnectionImpl::setSignalingObserver(LLWebRTCSignalingObserver *observer) { mSignalingObserverList.emplace_back(observer); } @@ -1004,6 +1004,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti } webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions; + this->AddRef(); // CreateOffer will deref this when it's done. Without this, the callbacks never get called. mPeerConnection->CreateOffer(this, offerOptions); mPendingJobs--; }); diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 7a5404e615..185940e32d 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -205,6 +205,8 @@ public: }; virtual S32 getRefreshRate() { return mRefreshRate; } + + virtual void initWatchdog() {} // windows runs window as a thread and it needs a watchdog protected: LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags); virtual ~LLWindow(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f826a60ddd..9d05d7e5a4 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -49,6 +49,7 @@ #include "llthreadsafequeue.h" #include "stringize.h" #include "llframetimer.h" +#include "llwatchdog.h" // System includes #include <commdlg.h> @@ -364,7 +365,8 @@ static LLMonitorInfo sMonitorInfo; // the containing class a friend. struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool { - static const int MAX_QUEUE_SIZE = 2048; + static constexpr int MAX_QUEUE_SIZE = 2048; + static constexpr F32 WINDOW_TIMEOUT_SEC = 90.f; LLThreadSafeQueue<MSG> mMessageQueue; @@ -426,6 +428,50 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool PostMessage(windowHandle, WM_POST_FUNCTION_, wparam, LPARAM(ptr)); } + // Call from main thread. + void initTimeout() + { + // post into thread's queue to avoid threading issues + post([this]() + { + if (!mWindowTimeout) + { + mWindowTimeout = std::make_unique<LLWatchdogTimeout>("mainloop"); + // supposed to be executed within run(), + // so no point checking if thread is alive + resumeTimeout("TimeoutInit"); + } + }); + } +private: + // These timeout related functions are strictly for the thread. + void resumeTimeout(std::string_view state) + { + if (mWindowTimeout) + { + mWindowTimeout->setTimeout(WINDOW_TIMEOUT_SEC); + mWindowTimeout->start(state); + } + } + + void pauseTimeout() + { + if (mWindowTimeout) + { + mWindowTimeout->stop(); + } + } + + void pingTimeout(std::string_view state) + { + if (mWindowTimeout) + { + mWindowTimeout->setTimeout(WINDOW_TIMEOUT_SEC); + mWindowTimeout->ping(state); + } + } + +public: using FuncType = std::function<void()>; // call GetMessage() and pull enqueue messages for later processing HWND mWindowHandleThrd = NULL; @@ -436,6 +482,8 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool bool mGLReady = false; bool mGotGLBuffer = false; LLAtomicBool mDeleteOnExit = false; +private: + std::unique_ptr<LLWatchdogTimeout> mWindowTimeout; }; @@ -4595,6 +4643,11 @@ bool LLWindowWin32::getInputDevices(U32 device_type_filter, return false; } +void LLWindowWin32::initWatchdog() +{ + mWindowThread->initTimeout(); +} + F32 LLWindowWin32::getSystemUISize() { F32 scale_value = 1.f; @@ -4732,6 +4785,8 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem() return; } + pauseTimeout(); + IDXGIFactory4* p_factory = nullptr; HRESULT res = CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&p_factory); @@ -4835,6 +4890,8 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem() } mGotGLBuffer = true; + + resumeTimeout("checkDXMem"); } void LLWindowWin32::LLWindowWin32Thread::run() @@ -4850,6 +4907,9 @@ void LLWindowWin32::LLWindowWin32Thread::run() timeBeginPeriod(llclamp((U32) 1, tc.wPeriodMin, tc.wPeriodMax)); } + // Normally won't exist yet, but in case of re-init, make sure it's cleaned up + resumeTimeout("WindowThread"); + while (! getQueue().done()) { LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; @@ -4859,6 +4919,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() if (mWindowHandleThrd != 0) { + pingTimeout("messages"); MSG msg; BOOL status; if (mhDCThrd == 0) @@ -4886,6 +4947,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() { LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("w32t - Function Queue"); + pingTimeout("queue"); logger.onChange("runPending()"); //process any pending functions getQueue().runPending(); @@ -4900,6 +4962,7 @@ void LLWindowWin32::LLWindowWin32Thread::run() #endif } + pauseTimeout(); destroyWindow(); if (mDeleteOnExit) diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 0fc93ad0b1..8159092794 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -45,83 +45,82 @@ typedef void (*LLW32MsgCallback)(const MSG &msg); class LLWindowWin32 : public LLWindow { public: - /*virtual*/ void show(); - /*virtual*/ void hide(); - /*virtual*/ void close(); - /*virtual*/ bool getVisible(); - /*virtual*/ bool getMinimized(); - /*virtual*/ bool getMaximized(); - /*virtual*/ bool maximize(); - /*virtual*/ void minimize(); - /*virtual*/ void restore(); - /*virtual*/ bool getFullscreen(); - /*virtual*/ bool getPosition(LLCoordScreen *position); - /*virtual*/ bool getSize(LLCoordScreen *size); - /*virtual*/ bool getSize(LLCoordWindow *size); - /*virtual*/ bool setPosition(LLCoordScreen position); - /*virtual*/ bool setSizeImpl(LLCoordScreen size); - /*virtual*/ bool setSizeImpl(LLCoordWindow size); - /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL); - /*virtual*/ void setTitle(const std::string title); + void show() override; + void hide() override; + void close() override; + bool getVisible() override; + bool getMinimized() override; + bool getMaximized() override; + bool maximize() override; + void minimize() override; + void restore() override; + bool getFullscreen(); + bool getPosition(LLCoordScreen *position) override; + bool getSize(LLCoordScreen *size) override; + bool getSize(LLCoordWindow *size) override; + bool setPosition(LLCoordScreen position) override; + bool setSizeImpl(LLCoordScreen size) override; + bool setSizeImpl(LLCoordWindow size) override; + bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override; + void setTitle(const std::string title) override; void* createSharedContext() override; void makeContextCurrent(void* context) override; void destroySharedContext(void* context) override; - /*virtual*/ void toggleVSync(bool enable_vsync); - /*virtual*/ bool setCursorPosition(LLCoordWindow position); - /*virtual*/ bool getCursorPosition(LLCoordWindow *position); - /*virtual*/ bool getCursorDelta(LLCoordCommon* delta); - /*virtual*/ bool isWrapMouse() const override { return !mAbsoluteCursorPosition; }; - /*virtual*/ void showCursor(); - /*virtual*/ void hideCursor(); - /*virtual*/ void showCursorFromMouseMove(); - /*virtual*/ void hideCursorUntilMouseMove(); - /*virtual*/ bool isCursorHidden(); - /*virtual*/ void updateCursor(); - /*virtual*/ ECursorType getCursor() const; - /*virtual*/ void captureMouse(); - /*virtual*/ void releaseMouse(); - /*virtual*/ void setMouseClipping( bool b ); - /*virtual*/ bool isClipboardTextAvailable(); - /*virtual*/ bool pasteTextFromClipboard(LLWString &dst); - /*virtual*/ bool copyTextToClipboard(const LLWString &src); - /*virtual*/ void flashIcon(F32 seconds); - /*virtual*/ F32 getGamma(); - /*virtual*/ bool setGamma(const F32 gamma); // Set the gamma - /*virtual*/ void setFSAASamples(const U32 fsaa_samples); - /*virtual*/ U32 getFSAASamples(); - /*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma) - /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } - /*virtual*/ void gatherInput(); - /*virtual*/ void delayInputProcessing(); - /*virtual*/ void swapBuffers(); - /*virtual*/ void restoreGLContext() {}; + void toggleVSync(bool enable_vsync) override; + bool setCursorPosition(LLCoordWindow position) override; + bool getCursorPosition(LLCoordWindow *position) override; + bool getCursorDelta(LLCoordCommon* delta) override; + bool isWrapMouse() const override { return !mAbsoluteCursorPosition; }; + void showCursor() override; + void hideCursor() override; + void showCursorFromMouseMove() override; + void hideCursorUntilMouseMove() override; + bool isCursorHidden() override; + void updateCursor() override; + ECursorType getCursor() const override; + void captureMouse() override; + void releaseMouse() override; + void setMouseClipping( bool b ) override; + bool isClipboardTextAvailable() override; + bool pasteTextFromClipboard(LLWString &dst) override; + bool copyTextToClipboard(const LLWString &src) override; + void flashIcon(F32 seconds) override; + F32 getGamma() override; + bool setGamma(const F32 gamma) override; // Set the gamma + void setFSAASamples(const U32 fsaa_samples) override; + U32 getFSAASamples() override; + bool restoreGamma() override; // Restore original gamma table (before updating gamma) + ESwapMethod getSwapMethod() override { return mSwapMethod; } + void gatherInput() override; + void delayInputProcessing() override; + void swapBuffers() override; // handy coordinate space conversion routines - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to); - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to); - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to); - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to); - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to); - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to); + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override; + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override; + bool convertCoords(LLCoordWindow from, LLCoordGL *to) override; + bool convertCoords(LLCoordGL from, LLCoordWindow *to) override; + bool convertCoords(LLCoordScreen from, LLCoordGL *to) override; + bool convertCoords(LLCoordGL from, LLCoordScreen *to) override; - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions); - /*virtual*/ F32 getNativeAspectRatio(); - /*virtual*/ F32 getPixelAspectRatio(); - /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } + LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override; + F32 getNativeAspectRatio() override; + F32 getPixelAspectRatio() override; + void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } - /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b ); + bool dialogColorPicker(F32 *r, F32 *g, F32 *b ) override; - /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void bringToFront(); - /*virtual*/ void focusClient(); + void *getPlatformWindow() override; + void bringToFront() override; + void focusClient() override; - /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, bool b); - /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); - /*virtual*/ void updateLanguageTextInputArea(); - /*virtual*/ void interruptLanguageTextInput(); - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + void allowLanguageTextInput(LLPreeditor *preeditor, bool b) override; + void setLanguageTextInput( const LLCoordGL & pos ) override; + void updateLanguageTextInputArea() override; + void interruptLanguageTextInput() override; + void spawnWebBrowser(const std::string& escaped_url, bool async) override; - /*virtual*/ F32 getSystemUISize(); + F32 getSystemUISize() override; LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); @@ -129,14 +128,16 @@ public: static std::vector<std::string> getDynamicFallbackFontList(); static void setDPIAwareness(); - /*virtual*/ void* getDirectInput8(); - /*virtual*/ bool getInputDevices(U32 device_type_filter, + void* getDirectInput8() override; + bool getInputDevices(U32 device_type_filter, std::function<bool(std::string&, LLSD&, void*)> osx_callback, void* win_callback, - void* userdata); + void* userdata) override; U32 getRawWParam() { return mRawWParam; } + void initWatchdog() override; + protected: LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 562a30e8d1..5a83f8c541 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -157,9 +157,12 @@ LLControlVariable::LLControlVariable(const std::string& name, eControlType type, { if ((persist != PERSIST_NO) && mComment.empty()) { - // File isn't actually missing, but something is wrong with it - // so the main point is to warn user to reinstall - LLError::LLUserWarningMsg::showMissingFiles(); + std::string error_string = + "Second Life failed to initialize settings. Setting " + mName + " is invalid. " + "Either settings' files were supplied incorrectly or default files were corrupted." + "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " + "contact https://support.secondlife.com if issue persists after reinstall."; + LLError::LLUserWarningMsg::show(error_string); LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL; } //Push back versus setValue'ing here, since we don't want to call a signal yet @@ -990,7 +993,7 @@ U32 LLControlGroup::saveToFile(const std::string& filename, bool nondefault_only return num_saved; } -U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values) +U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values, bool error_when_no_comment) { LLSD settings; llifstream infile; @@ -1105,10 +1108,26 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v } } + std::string comment = control_map["Comment"].asString(); + if (!error_when_no_comment + && !set_default_values + && comment.empty()) + { + // Only error for default settings that should remind the developer to provide comments + // and otherwise indicate a problem with viewer's files. + // But permit this minor transgression in user's files. + // Otherwise user might have a hard time figuring out source of the error or how to fix it. + // Instead make setting to not persist so that unrecognized invalid settings won't be saved + // for the next run. + persist = LLControlVariable::PERSIST_NO; + comment = "Comment not provided, setting won't persist"; + LL_WARNS() << "Control " << name << " is missing a comment value. Setting will be marked as PERSIST_NO" << LL_ENDL; + } + declareControl(name, typeStringToEnum(control_map["Type"].asString()), control_map["Value"], - control_map["Comment"].asString(), + comment, persist, hidefromsettingseditor ); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index da7268bf45..c9bd0a8a32 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -278,7 +278,7 @@ public: // as the given type. U32 loadFromFileLegacy(const std::string& filename, bool require_declaration = true, eControlType declare_as = TYPE_STRING); U32 saveToFile(const std::string& filename, bool nondefault_only); - U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true); + U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true, bool error_when_no_comment = true); void resetToDefaults(); void incrCount(std::string_view name); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0c5f3f3fd9..0949a3b59f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -736,7 +736,6 @@ set(viewer_SOURCE_FILES llvovolume.cpp llvowater.cpp llvowlsky.cpp - llwatchdog.cpp llwearableitemslist.cpp llwearablelist.cpp llweb.cpp @@ -1414,7 +1413,6 @@ set(viewer_HEADER_FILES llvovolume.h llvowater.h llvowlsky.h - llwatchdog.h llwearableitemslist.h llwearablelist.h llweb.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 4703009f54..2aaedf9944 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -2026.01.0 +26.1.0 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fe31a00ba3..5a1a1187a0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4591,6 +4591,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>MapShowGridCoords</key> + <map> + <key>Comment</key> + <string>Shows/hides the grid coordinates of each region on the world map.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MiniMapAutoCenter</key> <map> <key>Comment</key> @@ -7335,7 +7346,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>32.0</real> + <real>48.0</real> </map> <key>RenderCPUBasis</key> <map> @@ -9058,7 +9069,7 @@ <key>Comment</key> <string>Show reflection probes in the transparency debug view</string> <key>Persist</key> - <integer>1</integer> + <integer>0</integer> <key>Type</key> <string>Boolean</string> <key>Value</key> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index b2c66b1bac..d884b32ac0 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -975,6 +975,10 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); } } + else + { + new_distance = llmin(new_distance, getCameraMaxZoomDistance()); + } mCameraFocusOffsetTarget = new_distance * camera_offset_unit; } @@ -1035,6 +1039,10 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters) new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); } } + else + { + new_distance = llmin(new_distance, getCameraMaxZoomDistance()); + } // Compute new camera offset mCameraFocusOffsetTarget = new_distance * camera_offset_unit; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 569fd30b21..e956fc024e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -343,9 +343,6 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; S32 gPendingMetricsUploads = 0; - -bool gDisconnected = false; - // Used to restore texture state after a mode switch LLFrameTimer gRestoreGLTimer; bool gRestoreGL = false; @@ -1239,7 +1236,7 @@ bool LLAppViewer::init() /*----------------------------------------------------------------------*/ // nat 2016-06-29 moved the following here from the former mainLoop(). - mMainloopTimeout = new LLWatchdogTimeout(); + mMainloopTimeout = new LLWatchdogTimeout("mainloop"); // Create IO Pump to use for HTTP Requests. gServicePump = new LLPumpIO(gAPRPoolp); @@ -1429,12 +1426,14 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df mainloop"); + pingMainloopTimeout("df mainloop"); // canonical per-frame event mainloop.post(newFrame); } { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df suspend"); + pingMainloopTimeout("df suspend"); // give listeners a chance to run llcoro::suspend(); // if one of our coroutines threw an uncaught exception, rethrow it now @@ -1470,6 +1469,7 @@ bool LLAppViewer::doFrame() { { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df pauseMainloopTimeout"); + pingMainloopTimeout("df idle"); // So that it will be aware of last state. pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! } @@ -1481,7 +1481,7 @@ bool LLAppViewer::doFrame() { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df resumeMainloopTimeout"); - resumeMainloopTimeout(); + resumeMainloopTimeout("df idle"); } } @@ -1496,7 +1496,7 @@ bool LLAppViewer::doFrame() } disconnectViewer(); - resumeMainloopTimeout(); + resumeMainloopTimeout("df snapshot n disconnect"); } // Render scene. @@ -2301,7 +2301,22 @@ void errorHandler(const std::string& title_string, const std::string& message_st } if (!message_string.empty()) { - OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + if (on_main_thread()) + { + // Prevent watchdog from killing us while dialog is up. + // Can't do pauseMainloopTimeout, since this may be called + // from threads and we are not going to need watchdog now. + LLAppViewer::instance()->pauseMainloopTimeout(); + + // todo: might want to have non-crashing timeout for OOM cases + // and needs a way to pause main loop. + OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + LLAppViewer::instance()->resumeMainloopTimeout(); + } + else + { + OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); + } } } @@ -2455,7 +2470,10 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name()); } - if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent)) + // Be softer for files in the user's folders, user can't just reinstall those + bool error_when_no_comment = !set_defaults && location_key != "User"; + + if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent, error_when_no_comment)) { // success! LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL; } @@ -3164,7 +3182,19 @@ bool LLAppViewer::initWindow() if (use_watchdog) { - LLWatchdog::getInstance()->init(); + LLWatchdog::getInstance()->init([]() + { + LLAppViewer* app = LLAppViewer::instance(); + if (app->logoutRequestSent()) + { + app->createErrorMarker(LAST_EXEC_LOGOUT_FROZE); + } + else + { + app->createErrorMarker(LAST_EXEC_FROZE); + } + }); + gViewerWindow->getWindow()->initWatchdog(); } LLNotificationsUI::LLNotificationManager::getInstance(); @@ -4510,7 +4540,19 @@ void LLAppViewer::purgeCacheImmediate() { LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false); - LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); + if (LLVOCache::instanceExists()) + { + LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); + } + else if (!mSecondInstance) + { + // LLVOCache requires parameters to be initialized, if it's not there, try manually + std::string mask = "*"; + std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "objectcache"); + LL_INFOS() << "Removing cache at " << cache_dir << LL_ENDL; + gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files + LLFile::rmdir(cache_dir); + } } std::string LLAppViewer::getSecondLifeTitle() const @@ -5825,7 +5867,7 @@ void LLAppViewer::initMainloopTimeout(std::string_view state) { if (!mMainloopTimeout) { - mMainloopTimeout = new LLWatchdogTimeout(); + mMainloopTimeout = new LLWatchdogTimeout("mainloop"); resumeMainloopTimeout(state); } } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 6b0d3e0b27..e1119419af 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -417,8 +417,6 @@ extern S32 gPendingMetricsUploads; extern F32 gSimLastTime; extern F32 gSimFrames; -extern bool gDisconnected; - extern LLFrameTimer gRestoreGLTimer; extern bool gRestoreGL; extern bool gUseWireframe; diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 6f6b89ea81..fb1426a235 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -29,8 +29,6 @@ #include "llavataractions.h" -#include "boost/lambda/lambda.hpp" // for lambda::constant - #include "llavatarnamecache.h" // IDEVO #include "llsd.h" #include "llnotifications.h" diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 76e308a966..2c9d74ed97 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -680,6 +680,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) LLNotifications::instance().add("RevokedModifyRights",args, payload); } } + // update modify permissions flags for affected objects + LLViewerObject::markObjectsForUpdate(agent_id); (mBuddyInfo[agent_id])->setRightsFrom(new_rights); } } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 322ee90541..da9378ad12 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -723,9 +723,13 @@ F32 LLDrawable::updateXform(bool undamped) mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); - if (isRoot() && mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) + if (isRoot() && mVObjp->isAnimatedObject()) { - mVObjp->getControlAvatar()->matchVolumeTransform(); + LLControlAvatar* cav = mVObjp->getControlAvatar(); + if (cav) + { + cav->matchVolumeTransform(); + } } if (mSpatialBridge) diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index bc45734e66..9d1b11880b 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -267,7 +267,7 @@ void LLDrawPoolAlpha::forwardRender(bool rigged) gGL.setColorMask(true, false); - if (!rigged) + if (!rigged && getType() == LLDrawPoolAlpha::POOL_ALPHA_POST_WATER) { //render "highlight alpha" on final non-rigged pass // NOTE -- hacky call here protected by !rigged instead of alongside "forwardRender" // so renderDebugAlpha is executed while gls_pipeline_alpha and depth GL state diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index de3752d879..f1b46f0533 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -56,6 +56,7 @@ namespace Details private: void eventPollCoro(std::string url); + void handleMessage(const std::string& msg_name, const LLSD& body); void handleMessage(const LLSD &content); bool mDone; @@ -95,21 +96,23 @@ namespace Details mSenderIp = sender.getIPandPort(); } + void LLEventPollImpl::handleMessage(const std::string &msg_name, const LLSD &body) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; + LLSD message; + message["sender"] = mSenderIp; + message["body"] = body; + + LLMessageSystem::dispatch(msg_name, message); + } + void LLEventPollImpl::handleMessage(const LLSD& content) { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; std::string msg_name = content["message"].asString(); LLSD message; - try - { - message["sender"] = mSenderIp; - message["body"] = content["body"]; - } - catch (std::bad_alloc&) - { - LLError::LLUserWarningMsg::showOutOfMemory(); - LL_ERRS("LLCoros") << "Bad memory allocation on message: " << msg_name << LL_ENDL; - } + message["sender"] = mSenderIp; + message["body"] = content["body"]; LLMessageSystem::dispatch(msg_name, message); } @@ -194,7 +197,7 @@ namespace Details break; } - LLSD httpResults = result["http_result"]; + LLSD &httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status) @@ -299,7 +302,7 @@ namespace Details } acknowledge = result["id"]; - LLSD events = result["events"]; + LLSD &events = result["events"]; if (acknowledge.isUndefined()) { @@ -310,20 +313,37 @@ namespace Details LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << acknowledge << ")" << LL_ENDL; - LLSD::array_const_iterator i = events.beginArray(); - LLSD::array_const_iterator end = events.endArray(); + LLSD::array_iterator i = events.beginArray(); + LLSD::array_iterator end = events.endArray(); for (; i != end; ++i) { if (i->has("message")) { if (main_queue) - { // shuttle to a sensible spot in the main thread instead + { + // Shuttle copy to a sensible spot in the main thread instead // of wherever this coroutine happens to be executing - const LLSD& msg = *i; - main_queue->post([this, msg]() + + LL::WorkQueue::Work work; + { + // LLSD is too smart for it's own good and may act like a smart + // pointer for the content of (*i), so instead of passing (*i) + // pass a prepared name and move ownership of "body", + // as we are not going to need "body" anywhere else. + std::string msg_name = (*i)["message"].asString(); + + // WARNING: This is a shallow copy! + // If something still retains the data (like in httpAdapter?) this might still + // result in a crash, if it does appear to be the case, make a deep copy or + // convert data to string and pass that string. + const LLSD body = (*i)["body"]; + (*i)["body"].clear(); + work = [this, msg_name, body]() { - handleMessage(msg); - }); + handleMessage(msg_name, body); + }; + } + main_queue->post(work); } else { diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp index 193a42f9f6..c3aad4ee65 100644 --- a/indra/newview/llexternaleditor.cpp +++ b/indra/newview/llexternaleditor.cpp @@ -46,9 +46,13 @@ LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env { LL_INFOS() << "Editor command is empty or not set, falling back to OS open handler" << LL_ENDL; #if LL_WINDOWS - static const std::string os_cmd = "%SystemRoot%\\explorer.exe \"%s\""; + std::string os_cmd = LLStringUtil::getenv("SystemRoot", ""); + if (!os_cmd.empty()) + { + os_cmd.append("\\explorer.exe \"%s\""); + } #elif LL_DARWIN - static const std::string os_cmd = "/usr/bin/open \"%s\""; + static const std::string os_cmd = "/usr/bin/open -t \"%s\""; #elif LL_LINUX static const std::string os_cmd = "/usr/bin/xdg-open \"%s\""; #endif diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index f08ef8d24a..7c631a7280 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2378,7 +2378,11 @@ F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius //the above calculation is too expensive //the below is a good estimation: bounding box of the bounding sphere: - F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; + F32 alpha = 1.f; + if (!is_approx_zero(radius)) // radius can be something like -1e-10 + { + alpha = 0.5f * (radius + screen_radius - d) / radius; + } alpha = llclamp(alpha, 0.f, 1.f) ; return alpha * alpha ; } diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 377710c170..98b3ca820b 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -1395,6 +1395,19 @@ bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata) { return !LLAgentPicksInfo::getInstance()->isPickLimitReached(); } + else if (param == "copy_slurl" + || param == "show_on_map") + { + LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + if (nullptr == item) + return false; // shouldn't happen as it is selected from existing items + + const LLUUID& asset_id = item->getAssetUUID(); + + // Favorites are supposed to be loaded first, it should be here already + LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL /*callback*/); + return nullptr != landmark; + } return false; } @@ -1425,10 +1438,17 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLVector3d posGlobal; LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); + // inventory item and asset exist, otherwise + // enableSelected wouldn't have let it get here, + // only need to check location validity if (!posGlobal.isExactlyZero()) { LLLandmarkActions::getSLURLfromPosGlobal(posGlobal, copy_slurl_to_clipboard_cb); } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } else if (action == "show_on_map") { @@ -1437,10 +1457,20 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) LLVector3d posGlobal; LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal); - if (!posGlobal.isExactlyZero() && worldmap_instance) + if (worldmap_instance) { - worldmap_instance->trackLocation(posGlobal); - LLFloaterReg::showInstance("world_map", "center"); + // inventory item and asset exist, otherwise + // enableSelected wouldn't have let it get here, + // only need to check location validity + if (!posGlobal.isExactlyZero()) + { + worldmap_instance->trackLocation(posGlobal); + LLFloaterReg::showInstance("world_map", "center"); + } + else + { + LLNotificationsUtil::add("LandmarkLocationUnknown"); + } } } else if (action == "create_pick") diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm index 6921cd6101..7262d18483 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -241,8 +241,13 @@ void doSaveDialogModeless(const std::string* file, NSURL* url = [NSURL fileURLWithPath:fileName]; [panel setNameFieldStringValue: fileName]; - [panel setDirectoryURL: url]; + NSURL *last_url = [[NSUserDefaults standardUserDefaults] URLForKey:@"NSNavLastRootDirectory"]; + if(!last_url) + { + NSURL *documents_url = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject; + [panel setDirectoryURL:documents_url]; + } [panel beginWithCompletionHandler:^(NSModalResponse result) { diff --git a/indra/newview/llfloatereditenvironmentbase.cpp b/indra/newview/llfloatereditenvironmentbase.cpp index a42c94f049..bc1f3045bb 100644 --- a/indra/newview/llfloatereditenvironmentbase.cpp +++ b/indra/newview/llfloatereditenvironmentbase.cpp @@ -262,7 +262,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons } else if (mInventoryItem) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); LLUUID parent_id = mInventoryItem->getParentUUID(); if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID())) { diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp index 7316d7617d..bb2378d864 100644 --- a/indra/newview/llfloatermarketplace.cpp +++ b/indra/newview/llfloatermarketplace.cpp @@ -39,6 +39,27 @@ LLFloaterMarketplace::~LLFloaterMarketplace() { } +void LLFloaterMarketplace::onOpen(const LLSD& key) +{ + Params params(key); + + if (!params.validateBlock()) + { + closeFloater(); + return; + } + + if (params.url().empty()) + { + openMarketplace(); + } + else + { + openMarketplaceURL(params.url); + set_current_url(params.url); // Fix looping back to previous url when using the viewer navigation bar + } +} + // just to override LLFloaterWebContent void LLFloaterMarketplace::onClose(bool app_quitting) { @@ -68,3 +89,18 @@ void LLFloaterMarketplace::openMarketplace() mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } } + +void LLFloaterMarketplace::openMarketplaceURL(const std::string& url) +{ + if (mCurrentURL != url) + { + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } +} + +// static +bool LLFloaterMarketplace::isMarketplaceURL(const std::string& url) +{ + static LLCachedControl<std::string> marketplace_url(gSavedSettings, "MarketplaceURL", "https://marketplace.secondlife.com/"); + return url.starts_with(marketplace_url()); +} diff --git a/indra/newview/llfloatermarketplace.h b/indra/newview/llfloatermarketplace.h index 9524c94eee..17979dae90 100644 --- a/indra/newview/llfloatermarketplace.h +++ b/indra/newview/llfloatermarketplace.h @@ -36,11 +36,14 @@ class LLFloaterMarketplace: public: void openMarketplace(); + void openMarketplaceURL(const std::string& url); + bool static isMarketplaceURL(const std::string& url); private: LLFloaterMarketplace(const LLSD& key); ~LLFloaterMarketplace(); bool postBuild() override; + void onOpen(const LLSD& key) override; void onClose(bool app_quitting) override; }; diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index f20fea01c5..dfd023e424 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -29,6 +29,7 @@ #include "llfloatermarketplacelistings.h" +#include "llcallbacklist.h" #include "llfloaterreg.h" #include "llfiltereditor.h" #include "llfolderview.h" @@ -231,7 +232,7 @@ void LLPanelMarketplaceListings::onTabChange() void LLPanelMarketplaceListings::onAddButtonClicked() { - LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); llassert(marketplacelistings_id.notNull()); LLFolderType::EType preferred_type = LLFolderType::lookup("category"); LLHandle<LLPanel> handle = getHandle(); @@ -351,7 +352,15 @@ public: if (added_category_type == LLFolderType::FT_MARKETPLACE_LISTINGS) { - mMarketplaceListingsFloater->initializeMarketPlace(); + LLHandle<LLFloater> handle = mMarketplaceListingsFloater->getHandle(); + doOnIdleOneTime([handle]() + { + LLFloaterMarketplaceListings* floater = (LLFloaterMarketplaceListings*)handle.get(); + if (floater) + { + floater->initializeMarketPlace(); + } + }); } } } @@ -415,7 +424,7 @@ bool LLFloaterMarketplaceListings::postBuild() // Fetch aggressively so we can interact with listings as soon as possible if (!fetchContents()) { - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); LLInventoryModelBackgroundFetch::instance().start(marketplacelistings_id, true); } @@ -513,8 +522,6 @@ void LLFloaterMarketplaceListings::setRootFolder() return; } - mRootFolderCreating = false; - // No longer need to observe new category creation if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) { @@ -524,6 +531,8 @@ void LLFloaterMarketplaceListings::setRootFolder() } llassert(!mCategoryAddedObserver); + mRootFolderCreating = false; + if (marketplacelistings_id == mRootFolderId) { LL_WARNS("SLM") << "Inventory warning: Marketplace listings folder already set" << LL_ENDL; @@ -566,7 +575,8 @@ void LLFloaterMarketplaceListings::setPanels() void LLFloaterMarketplaceListings::initializeMarketPlace() { - LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); + if (!mRootFolderCreating) + LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); } S32 LLFloaterMarketplaceListings::getFolderCount() @@ -909,7 +919,7 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key) LLUUID cat_id(key.asUUID()); if (cat_id.isNull()) { - cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + cat_id = gInventory.getMarketplaceListingsUUID(); } // Validates the folder diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp index fa491a4b27..bd8530abd7 100644 --- a/indra/newview/llfloaterobjectweights.cpp +++ b/indra/newview/llfloaterobjectweights.cpp @@ -208,7 +208,7 @@ void LLFloaterObjectWeights::draw() toggleRenderLoadingIndicators(false); } mTrianglesShown->setText(llformat("%d", total_tris)); - mPixelArea->setText(llformat("%d", pixel_area)); + mPixelArea->setText(llformat("%ld", (S64)pixel_area)); // value capped at 10M } LLFloater::draw(); } diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index d5e45c09e3..e497fb0914 100644 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -502,7 +502,7 @@ void LLFloaterPay::onGive(give_money_ptr info) amount = atoi(text_field->getValue().asString().c_str()); } - if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount) + if (amount > PAY_AMOUNT_NOTIFICATION) { LLUUID payee_id = LLUUID::null; bool is_group = false; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c5c1e01538..f23bd5f2e3 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -474,7 +474,8 @@ bool LLFloaterPreference::postBuild() getChild<LLUICtrl>("log_path_string")->setEnabled(false); // make it read-only but selectable - getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); + mLanguageCombobox = getChild<LLComboBox>("language_combobox"); + mLanguageCombobox->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); mTimeFormatCombobox = getChild<LLComboBox>("time_format_combobox"); mTimeFormatCombobox->setCommitCallback(boost::bind(&LLFloaterPreference::onTimeFormatChange, this)); @@ -516,18 +517,18 @@ bool LLFloaterPreference::postBuild() std::map<std::string, std::string>::iterator iter = labels.find(system_lang); if (iter != labels.end()) { - getChild<LLComboBox>("language_combobox")->add(iter->second, LLSD("default"), ADD_TOP, true); + mLanguageCombobox->add(iter->second, LLSD("default"), ADD_TOP, true); } else { LL_WARNS() << "Language \"" << system_lang << "\" is not in default_languages.xml" << LL_ENDL; - getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true); + mLanguageCombobox->add("System default", LLSD("default"), ADD_TOP, true); } } else { LL_WARNS() << "Failed to load labels from " << user_filename << ". Using default." << LL_ENDL; - getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true); + mLanguageCombobox->add("System default", LLSD("default"), ADD_TOP, true); } #ifndef LL_DISCORD @@ -1340,6 +1341,12 @@ void LLFloaterPreference::refresh() updateClickActionViews(); mTimeFormatCombobox->selectByValue(gSavedSettings.getBOOL("Use24HourClock") ? "1" : "0"); + + std::string current_language = gSavedSettings.getString("Language"); + if (current_language != "default" && !current_language.empty()) + { + mLanguageCombobox->selectByValue(LLSD(current_language)); + } } void LLFloaterPreference::onCommitWindowedMode() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index a2aa3ee8de..3028bec64a 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -237,6 +237,7 @@ private: LLButton* mEnablePopupBtn = nullptr; LLButton* mDisablePopupBtn = nullptr; LLComboBox* mTimeFormatCombobox = nullptr; + LLComboBox* mLanguageCombobox = nullptr; std::unique_ptr< ll::prefs::SearchData > mSearchData; bool mSearchDataDirty; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4cb6e7be96..1b5566a32d 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -538,6 +538,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid)); panel->setCtrlsEnabled(allow_modify); + panel->getChild<LLLineEditor>("estate_id")->setValue((S32)region_info.mEstateID); + + if (region) + { + panel->getChild<LLLineEditor>("grid_position_x")->setValue((S32)(region->getOriginGlobal()[VX] / 256)); + panel->getChild<LLLineEditor>("grid_position_y")->setValue((S32)(region->getOriginGlobal()[VY] / 256)); + } + else + { + panel->getChild<LLLineEditor>("grid_position_x")->setDefaultText(); + panel->getChild<LLLineEditor>("grid_position_y")->setDefaultText(); + } // DEBUG PANEL panel = tab->getChild<LLPanel>("Debug"); @@ -902,6 +914,9 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region) getChildView("apply_btn")->setEnabled(false); getChildView("access_text")->setEnabled(allow_modify); // getChildView("access_combo")->setEnabled(allow_modify); + getChildView("estate_id")->setEnabled(false); + getChildView("grid_position_x")->setEnabled(false); + getChildView("grid_position_y")->setEnabled(false); // now set in processRegionInfo for teen grid detection getChildView("kick_btn")->setEnabled(allow_modify); getChildView("kick_all_btn")->setEnabled(allow_modify); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 112008172e..5484ce6276 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -903,6 +903,39 @@ private: }; +F32 shader_timer_benchmark(std::vector<LLRenderTarget> & dest, TextureHolder & texHolder, U32 textures_count, LLVertexBuffer * buff, F32 &seconds) +{ + // run GPU timer benchmark + + //number of samples to take + const S32 samples = 64; + + { + ShaderProfileHelper initProfile; + dest[0].bindTarget(); + gBenchmarkProgram.bind(); + for (S32 c = 0; c < samples; ++c) + { + for (U32 i = 0; i < textures_count; ++i) + { + texHolder.bind(i); + buff->setBuffer(); + buff->drawArrays(LLRender::TRIANGLES, 0, 3); + } + } + gBenchmarkProgram.unbind(); + dest[0].flush(); + } + + F32 ms = gBenchmarkProgram.mTimeElapsed / 1000000.f; + seconds = ms / 1000.f; + + F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn; + F64 gpixels_drawn = samples_drawn / 1000000000.0; + F32 samples_sec = (F32)(gpixels_drawn / seconds); + return samples_sec * 4; // 4 bytes per sample +} + //----------------------------------------------------------------------------- // gpu_benchmark() // returns measured memory bandwidth of GPU in gigabytes per second @@ -944,9 +977,6 @@ F32 gpu_benchmark() //number of textures const U32 count = 32; - //number of samples to take - const S32 samples = 64; - //time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark. const F32 time_limit = 30; @@ -1036,33 +1066,15 @@ F32 gpu_benchmark() LLGLSLShader::unbind(); - // run GPU timer benchmark - { - ShaderProfileHelper initProfile; - dest[0].bindTarget(); - gBenchmarkProgram.bind(); - for (S32 c = 0; c < samples; ++c) - { - for (U32 i = 0; i < count; ++i) - { - texHolder.bind(i); - buff->setBuffer(); - buff->drawArrays(LLRender::TRIANGLES, 0, 3); - } - } - gBenchmarkProgram.unbind(); - dest[0].flush(); - } + // run GPU timer benchmark twice + F32 seconds = 0; + F32 gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds); - F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; + LL_INFOS("Benchmark") << "Memory bandwidth, 1st run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; - F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn; - F64 gpixels_drawn = samples_drawn / 1000000000.0; - F32 samples_sec = (F32)(gpixels_drawn/seconds); - F32 gbps = samples_sec*4; // 4 bytes per sample + gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds); - LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; + LL_INFOS("Benchmark") << "Memory bandwidth, final run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; return gbps; } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 7659e5f082..074cda1683 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -317,7 +317,7 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL // virtual bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - // Why is "new group" sufficient? + // "new group" is sufficient because update_group_floaters always calls that on group changes if (event->desc() == "new group") { setDirty(); diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 11f049564a..4327d281e5 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -301,7 +301,7 @@ void LLHUDNameTag::renderText() const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); label_top_rect.mBottom = label_top_rect.mTop - label_height; LLColor4 label_top_color = text_color; - label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; + label_top_color.mV[VALPHA] = bubble_opacity() * alpha_factor; mRoundedRectTopImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 848f28f933..542c0fdfdd 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -336,7 +336,7 @@ bool LLInvFVBridge::cutToClipboard() const LLInventoryObject* obj = gInventory.getObject(mUUID); if (obj && isItemMovable() && isItemRemovable()) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); const bool cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id); if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) || @@ -1378,7 +1378,7 @@ bool LLInvFVBridge::isInboxFolder() const bool LLInvFVBridge::isMarketplaceListingsFolder() const { - const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID folder_id = gInventory.getMarketplaceListingsUUID(); if (folder_id.isNull()) { @@ -1686,7 +1686,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const { std::string error_msg; LLInventoryModel* model = getInventoryModel(); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = model->getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id); @@ -1845,7 +1845,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) { LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); // Note: For a single item, if it's not a copy, then it's a move move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action)); } @@ -2678,7 +2678,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const bool move_is_into_current_outfit = (mUUID == current_outfit_id); @@ -3758,7 +3758,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) { LLInventoryCategory * cat = gInventory.getCategory(mUUID); if (!cat) return; - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); } else if ("copy_folder_uuid" == action) @@ -4012,7 +4012,7 @@ void LLFolderBridge::pasteFromClipboard() LLInventoryModel* model = getInventoryModel(); if (model && isClipboardPasteable()) { - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = model->getMarketplaceListingsUUID(); const bool paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); bool cut_from_marketplacelistings = false; @@ -4074,7 +4074,7 @@ void LLFolderBridge::perform_pasteFromClipboard() if (model && isClipboardPasteable()) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); @@ -4371,7 +4371,7 @@ void LLFolderBridge::pasteLinkFromClipboard() if(model) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const bool move_is_into_current_outfit = (mUUID == current_outfit_id); @@ -4471,7 +4471,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplace_listings_id = model->getMarketplaceListingsUUID(); const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); if (outfits_id == mUUID) @@ -5708,7 +5708,7 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const LLUUID from_folder_uuid = inv_item->getParentUUID(); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 3cc57e851f..458ea24d33 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -405,7 +405,7 @@ void update_all_marketplace_count(const LLUUID& cat_id) void update_all_marketplace_count() { // Get the marketplace root and launch the recursive exploration - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID(); if (!marketplace_listings_uuid.isNull()) { update_all_marketplace_count(marketplace_listings_uuid); @@ -1050,11 +1050,7 @@ void open_marketplace_listings() S32 depth_nesting_in_marketplace(LLUUID cur_uuid) { - // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none - // Todo: findCategoryUUIDForType is somewhat expensive with large - // flat root folders yet we use depth_nesting_in_marketplace at - // every turn, find a way to correctly cache this id. - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID(); if (marketplace_listings_uuid.isNull()) { return -1; @@ -3420,7 +3416,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); bool marketplacelistings_item = false; bool has_worn = false; bool needs_replacement = false; @@ -3601,7 +3597,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if (action == "wear" || action == "wear_add") { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID mp_id = gInventory.getMarketplaceListingsUUID(); std::copy_if(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids), @@ -4011,7 +4007,7 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root) // target listing *and* the original listing. So we need to keep track of both. // Note: do not however put the marketplace listings root itself in this list or the whole marketplace data will be rebuilt. sMarketplaceFolders.clear(); - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.isNull()) { return; diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f77088e0b1..24b0866041 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1726,7 +1726,7 @@ bool is_category_removable(const LLUUID& folder_id, bool check_worn) } } - const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID mp_id = gInventory.getMarketplaceListingsUUID(); if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) { return false; @@ -1768,7 +1768,7 @@ void LLInventoryGallery::paste() return; } - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (mSelectedItemIDs.size() == 1 && gInventory.isObjectDescendentOf(*mSelectedItemIDs.begin(), marketplacelistings_id)) { return; @@ -2114,7 +2114,7 @@ void LLInventoryGallery::pasteAsLink() } const LLUUID& current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); std::vector<LLUUID> objects; @@ -3333,7 +3333,7 @@ bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const bool move_is_into_current_outfit = (folder_id == current_outfit_id); @@ -3727,7 +3727,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); //const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const bool move_is_into_current_outfit = (dest_id == current_outfit_id); const bool move_is_into_marketplacelistings = model->isObjectDescendentOf(dest_id, marketplacelistings_id); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index fe007a78cd..1c1bb35723 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -400,7 +400,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) if (can_copy) { - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (itemp) { move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation); @@ -419,7 +419,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) // option == 0 Move no copy item(s) // option == 1 Don't move no copy item(s) (leave them behind) bool copy_and_move = option == 0; - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); // main inventory only allows one item? LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front()); @@ -535,7 +535,7 @@ bool can_list_on_marketplace(const LLUUID &id) if (can_list) { std::string error_msg; - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id); @@ -1033,7 +1033,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men // Marketplace bool can_list = false; - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType()) { if (is_folder) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 043fd7003d..7056ed1ce4 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -975,6 +975,15 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID()); } +const LLUUID LLInventoryModel::getMarketplaceListingsUUID() +{ + if (mMarketplaceListingsUUID.isNull()) + { + mMarketplaceListingsUUID = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + } + return mMarketplaceListingsUUID; +} + // Convenience function to create a new category. You could call // updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be @@ -1692,7 +1701,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask |= LLInventoryObserver::LABEL; } // Under marketplace, category labels are quite complex and need extra upate - const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_id = getMarketplaceListingsUUID(); if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id)) { mask |= LLInventoryObserver::LABEL; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 2859923df9..9fbabec8f3 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -329,6 +329,8 @@ public: // user specified one or it does not exist, creates default category if it is missing. const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const; + const LLUUID getMarketplaceListingsUUID(); + // Get whatever special folder this object is a child of, if any. const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; @@ -361,6 +363,8 @@ public: private: mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups + LLUUID mMarketplaceListingsUUID; + //-------------------------------------------------------------------- // Count //-------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 1e5f771ba7..82eefb50ac 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -828,7 +828,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() // Intent is for marketplace request to happen after // main inventory is done, unless requested by floater mRecursiveMarketplaceFetchStarted = true; - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { mFetchFolderQueue.emplace_front(marketplacelistings_id, FT_FOLDER_AND_CONTENT); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index cde87ede9b..8d57a4e7bb 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1849,6 +1849,7 @@ void LLInventoryPanel::purgeSelectedItems() { if (!mFolderRoot.get()) return; + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); const std::set<LLFolderViewItem*> inventory_selected = mFolderRoot.get()->getSelectionList(); if (inventory_selected.empty()) return; LLSD args; @@ -1858,12 +1859,17 @@ void LLInventoryPanel::purgeSelectedItems() it != end_it; ++it) { + // Selection allows items outside trash folder, only count the ones inside. LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID(); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH); - count += items.size() + cats.size(); - selected_items.push_back(item_id); + LLInventoryObject* obj = gInventory.getObject(item_id); + if (obj->getParentUUID() == trash_id) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH); + count += items.size() + cats.size(); + selected_items.push_back(item_id); + } } args["COUNT"] = static_cast<S32>(count); LLNotificationsUtil::add("PurgeSelectedItems", args, LLSD(), boost::bind(callbackPurgeSelectedItems, _1, _2, selected_items)); diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index 3fa0ab99f3..b25a42a938 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -147,29 +147,66 @@ void LLLandmarkList::processGetAssetReply( else { // failed to parse, shouldn't happen + LL_WARNS("Landmarks") << "Failed to parse landmark " << uuid << LL_ENDL; gLandmarkList.eraseCallbacks(uuid); } } else { // got a good status, but no file, shouldn't happen + LL_WARNS("Landmarks") << "Empty buffer for landmark " << uuid << LL_ENDL; gLandmarkList.eraseCallbacks(uuid); } + + // We got this asset, remove it from retry and bad lists. + gLandmarkList.mRetryList.erase(uuid); + gLandmarkList.mBadList.erase(uuid); } else { - // SJB: No use case for a notification here. Use LL_DEBUGS() instead - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) + if (LL_ERR_NO_CAP == status) + { + // A problem with asset cap, always allow retrying. + // Todo: should this reschedule? + gLandmarkList.mRequestedList.erase(uuid); + gLandmarkList.eraseCallbacks(uuid); + // If there was a previous request, it likely failed due to an obsolete cap + // so clear the retry marker to allow multiple retries. + gLandmarkList.mRetryList.erase(uuid); + return; + } + if (gLandmarkList.mBadList.find(uuid) != gLandmarkList.mBadList.end()) + { + // Already on the 'bad' list, ignore + gLandmarkList.mRequestedList.erase(uuid); + gLandmarkList.eraseCallbacks(uuid); + return; + } + if (LL_ERR_ASSET_REQUEST_FAILED == status + && gLandmarkList.mRetryList.find(uuid) == gLandmarkList.mRetryList.end()) + { + // There is a number of reasons why an asset request can fail, + // like a cap being obsolete due to user teleporting. + // Let viewer rerequest at least once more. + // Todo: should this reshchedule? + gLandmarkList.mRetryList.emplace(uuid); + gLandmarkList.mRequestedList.erase(uuid); + gLandmarkList.eraseCallbacks(uuid); + return; + } + + if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status) { - LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL; - //LLNotificationsUtil::add("LandmarkMissing"); + LL_WARNS("Landmarks") << "Missing Landmark " << uuid << LL_ENDL; } else { - LL_WARNS("Landmarks") << "Unable to load Landmark" << LL_ENDL; - //LLNotificationsUtil::add("UnableToLoadLandmark"); + LL_WARNS("Landmarks") << "Unable to load Landmark " << uuid + << ". asset status: " << status + << ". Extended status: " << (S64)ext_status << LL_ENDL; } + gLandmarkList.mRetryList.erase(uuid); gLandmarkList.mBadList.insert(uuid); gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests gLandmarkList.eraseCallbacks(uuid); diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h index fb8b5a1960..76b5b97211 100644 --- a/indra/newview/lllandmarklist.h +++ b/indra/newview/lllandmarklist.h @@ -72,6 +72,7 @@ protected: typedef std::set<LLUUID> landmark_uuid_list_t; landmark_uuid_list_t mBadList; + landmark_uuid_list_t mRetryList; typedef std::map<LLUUID,F32> landmark_requested_list_t; landmark_requested_list_t mRequestedList; diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 6e56aac270..1329b1308d 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -596,7 +596,7 @@ void LLLocalBitmap::updateUserVolumes(LLUUID old_id, LLUUID new_id, U32 channel) if (object->isSculpted() && object->getVolume() && object->getVolume()->getParams().getSculptID() == old_id) { - LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams* old_params = object->getSculptParams(); LLSculptParams new_params(*old_params); new_params.setSculptTexture(new_id, (*old_params).getSculptType()); object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, true); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index ac2f52a262..30f634f6d4 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -850,7 +850,7 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot // Get/Post/Put requests to the SLM Server using the SLM API void LLMarketplaceData::getSLMListings() { - const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplaceFolderId = gInventory.getMarketplaceListingsUUID(); setUpdating(marketplaceFolderId, true); LLCoros::instance().launch("getSLMListings", @@ -1757,7 +1757,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) } else { - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID(); std::set<LLUUID>::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid); if (it != mPendingUpdateSet.end()) { diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index c0b1a5326a..ed342935ad 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4271,20 +4271,63 @@ S32 LLMeshRepository::update() return static_cast<S32>(size); } -void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) +void LLMeshRepository::unregisterMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail) { - for (auto& lod : mLoadingMeshes) + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + + llassert((mesh_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH); + llassert(mesh_params.getSculptID().notNull()); + auto& lod = mLoadingMeshes[detail]; + auto param_iter = lod.find(mesh_params.getSculptID()); + if (param_iter != lod.end()) { - for (auto& param : lod) + param_iter->second.mVolumes.erase(vobj); + llassert(!param_iter->second.mVolumes.contains(vobj)); + if (param_iter->second.mVolumes.empty()) { - vector_replace_with_last(param.second.mVolumes, vobj); + lod.erase(param_iter); } } +} - for (auto& skin_pair : mLoadingSkins) +void LLMeshRepository::unregisterSkinInfo(const LLUUID& mesh_id, LLVOVolume* vobj) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + + llassert(mesh_id.notNull()); + auto skin_pair_iter = mLoadingSkins.find(mesh_id); + if (skin_pair_iter != mLoadingSkins.end()) + { + skin_pair_iter->second.mVolumes.erase(vobj); + llassert(!skin_pair_iter->second.mVolumes.contains(vobj)); + if (skin_pair_iter->second.mVolumes.empty()) + { + mLoadingSkins.erase(skin_pair_iter); + } + } +} + +// Lots of dead objects make expensive calls to +// LLMeshRepository::unregisterMesh which may delay shutdown. Avoid this by +// preemptively unregistering all meshes. +// We can also do this safely if all objects are confirmed dead for some other +// reason. +void LLMeshRepository::unregisterAllMeshes() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + + // The size of mLoadingMeshes and mLoadingSkins may be large and thus + // expensive to iterate over in LLVOVolume::~LLVOVolume. + // This is unnecessary during shutdown, so we ignore the referenced objects in the + // least expensive way which is still safe: by clearing these containers. + // Clear now and not in LLMeshRepository::shutdown because + // LLMeshRepository::notifyLoadedMeshes could (depending on invocation + // order) reference a pointer to an object after it has been deleted. + for (auto& lod : mLoadingMeshes) { - vector_replace_with_last(skin_pair.second.mVolumes, vobj); + lod.clear(); } + mLoadingSkins.clear(); } S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 new_lod, S32 last_lod) @@ -4306,7 +4349,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para mesh_load_map::iterator iter = mLoadingMeshes[new_lod].find(mesh_id); if (iter != mLoadingMeshes[new_lod].end()) { //request pending for this mesh, append volume id to list - auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), vobj); + auto it = iter->second.mVolumes.find(vobj); if (it == iter->second.mVolumes.end()) { iter->second.addVolume(vobj); } @@ -4804,7 +4847,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOV skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); if (iter != mLoadingSkins.end()) { //request pending for this mesh, append volume id to list - auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), requesting_obj); + auto it = iter->second.mVolumes.find(requesting_obj); if (it == iter->second.mVolumes.end()) { iter->second.addVolume(requesting_obj); } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 01b51e753e..56ad8297c7 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -290,7 +290,7 @@ private: class MeshLoadData { public: - MeshLoadData() {} + MeshLoadData() = default; ~MeshLoadData() { if (std::shared_ptr<PendingRequestBase> request = mRequest.lock()) @@ -300,19 +300,19 @@ public: } void initData(LLVOVolume* vol, std::shared_ptr<PendingRequestBase>& request) { - mVolumes.push_back(vol); + mVolumes.insert(vol); request->trackData(this); mRequest = request; } void addVolume(LLVOVolume* vol) { - mVolumes.push_back(vol); + mVolumes.insert(vol); if (std::shared_ptr<PendingRequestBase> request = mRequest.lock()) { request->setScoreDirty(); } } - std::vector<LLVOVolume*> mVolumes; + std::unordered_set<LLVOVolume*> mVolumes; private: std::weak_ptr<PendingRequestBase> mRequest; }; @@ -862,10 +862,12 @@ public: LLMeshRepository(); void init(); + void unregisterAllMeshes(); void shutdown(); S32 update(); - void unregisterMesh(LLVOVolume* volume); + void unregisterMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail); + void unregisterSkinInfo(const LLUUID& mesh_id, LLVOVolume* vobj); //mesh management functions S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 new_lod = 0, S32 last_lod = -1); diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 6b1fbdce4c..b2e21bea1c 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -3461,7 +3461,7 @@ bool LLModelPreview::render() LLViewerCamera::getInstance()->setAspect(aspect); - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); + LLViewerCamera::getInstance()->setViewNoBroadcast(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); LLVector3 offset = mCameraOffset; LLVector3 target_pos = mPreviewTarget + offset; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 18721b9b7b..353e4b0ae4 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1201,7 +1201,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) // See if that's been overridden by a material setting for same... // - LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha); + LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode); // it is invalid to have any alpha mode other than blend if transparency is greater than zero ... // Want masking? Want emissive? Tough! You get BLEND! @@ -1211,6 +1211,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; mComboAlphaMode->getSelectionInterface()->selectNthItem(alpha_mode); + mComboAlphaMode->setTentative(!identical_alpha_mode); + if (!identical_alpha_mode) + { + std::string multiple = LLTrans::getString("multiple_textures"); + mComboAlphaMode->setLabel(multiple); + } updateAlphaControls(); mExcludeWater &= (LLMaterial::DIFFUSE_ALPHA_MODE_BLEND == alpha_mode); @@ -5484,32 +5490,40 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool& identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats); } -void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha) +void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical) { struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor<U8> { - LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {} - LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {} + LLSelectedTEGetDiffuseAlphaMode() {} virtual ~LLSelectedTEGetDiffuseAlphaMode() {} U8 get(LLViewerObject* object, S32 face) { - U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - LLTextureEntry* tep = object->getTE(face); if (tep) { LLMaterial* mat = tep->getMaterialParams().get(); if (mat) { - diffuse_mode = mat->getDiffuseAlphaMode(); + return mat->getDiffuseAlphaMode(); + } + } + + bool has_alpha = false; + LLViewerTexture* image = object->getTEImage(face); + if (image) + { + LLGLenum format = image->getPrimaryFormat(); + if (format == GL_RGBA || format == GL_ALPHA) + { + has_alpha = true; } } + U8 diffuse_mode = has_alpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; return diffuse_mode; } - bool _isAlpha; // whether or not the diffuse texture selected contains alpha information - } get_diff_mode(diffuse_texture_has_alpha); + } get_diff_mode; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode); } diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 63fee6bab8..82790ac54b 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -652,7 +652,7 @@ public: static void getCurrent(LLMaterialPtr& material_ptr, bool& identical_material); static void getMaxSpecularRepeats(F32& repeats, bool& identical); static void getMaxNormalRepeats(F32& repeats, bool& identical); - static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha); + static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical); static void selectionNormalScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter); static void selectionSpecularScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index ecb66f9cea..ad65293b98 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -191,6 +191,13 @@ bool LLPanelGroup::postBuild() mButtonJoin->setCommitCallback(boost::bind(&LLPanelGroup::onBtnJoin,this)); mJoinText = panel_general->getChild<LLUICtrl>("join_cost_text"); + + mButtonActivate = panel_general->getChild<LLButton>("btn_activate"); + mButtonActivate->setVisible(false); + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + mButtonActivate->setCommitCallback(boost::bind(&LLPanelGroup::onBtnActivate, this)); + + gAgent.addListener(this, "new group"); } LLVoiceClient::addObserver(this); @@ -267,6 +274,7 @@ void LLPanelGroup::onBtnJoin() if (LLGroupActions::isInGroup(mID)) { LLGroupActions::leave(mID); + mButtonActivate->setVisible(false); } else { @@ -275,6 +283,12 @@ void LLPanelGroup::onBtnJoin() } } +void LLPanelGroup::onBtnActivate() +{ + LLGroupActions::activate(mID); + mButtonActivate->setEnabled(false); +} + void LLPanelGroup::changed(LLGroupChange gc) { for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it) @@ -312,6 +326,8 @@ void LLPanelGroup::update(LLGroupChange gc) bool join_btn_visible = is_member || gdatap->mOpenEnrollment; mButtonJoin->setVisible(join_btn_visible); + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + mButtonActivate->setVisible(is_member); mJoinText->setVisible(join_btn_visible); if (is_member) @@ -384,6 +400,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(mButtonJoin) mButtonJoin->setVisible(false); + if (mButtonActivate) + mButtonActivate->setVisible(false); if(is_null_group_id)//creating new group @@ -598,4 +616,20 @@ void LLPanelGroup::showNotice(const std::string& subject, } +bool LLPanelGroup::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + if (event->desc() == "new group") + { + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + return true; + } + + if (event->desc() == "value_changed") + { + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + return true; + } + + return false; +} diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index b43a93bc40..d3550264a0 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -26,6 +26,7 @@ #ifndef LL_LLPANELGROUP_H #define LL_LLPANELGROUP_H +#include "llevent.h" #include "llgroupmgr.h" #include "llpanel.h" #include "lltimer.h" @@ -44,7 +45,8 @@ class LLAgent; class LLPanelGroup : public LLPanel, public LLGroupMgrObserver, - public LLVoiceClientStatusObserver + public LLVoiceClientStatusObserver, + public LLOldEvents::LLSimpleListener { public: LLPanelGroup(); @@ -94,6 +96,7 @@ protected: void onBackBtnClick(); void onBtnJoin(); + void onBtnActivate(); static void onBtnApply(void*); static void onBtnRefresh(void*); @@ -120,11 +123,15 @@ protected: LLUICtrl* mGroupNameCtrl = nullptr; LLButton* mButtonJoin = nullptr; + LLButton* mButtonActivate = nullptr; LLButton* mButtonApply = nullptr; LLButton* mButtonCall = nullptr; LLButton* mButtonChat = nullptr; LLButton* mButtonRefresh = nullptr; LLUICtrl* mJoinText; + +private: + bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // for agent group list changes }; class LLPanelGroupTab : public LLPanel diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index fe9145bf71..868e02f28b 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -188,7 +188,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, mUsernameLength(0), mPasswordLength(0), mLocationLength(0), - mShowFavorites(false) + mShowFavorites(false), + mAlertNotif(false) { setBackgroundVisible(false); setBackgroundOpaque(true); @@ -219,6 +220,11 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, // STEAM-14: When user presses Enter with this field in focus, initiate login password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, false)); + childSetAction("connect_btn", onClickConnect, this); + + mLoginBtn = getChild<LLButton>("connect_btn"); + setDefaultBtn(mLoginBtn); + // change z sort of clickable text to be behind buttons sendChildToBack(getChildView("forgot_password_text")); sendChildToBack(getChildView("sign_up_text")); @@ -295,11 +301,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, onUpdateStartSLURL(start_slurl); // updates grid if needed } - childSetAction("connect_btn", onClickConnect, this); - - LLButton* def_btn = getChild<LLButton>("connect_btn"); - setDefaultBtn(def_btn); - std::string channel = LLVersionInfo::instance().getChannel(); std::string version = stringize(LLVersionInfo::instance().getShortVersion(), " (", LLVersionInfo::instance().getBuild(), ')'); @@ -327,6 +328,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name"); remember_name->setCommitCallback(boost::bind(&LLPanelLogin::onRememberUserCheck, this)); getChild<LLCheckBoxCtrl>("remember_password")->setCommitCallback(boost::bind(&LLPanelLogin::onRememberPasswordCheck, this)); + + mAlertListener = LLNotifications::instance().getChannel("Alerts")->connectChanged([this](const LLSD& notify){ return onUpdateNotification(notify); }); } void LLPanelLogin::addFavoritesToStartLocation() @@ -409,7 +412,7 @@ void LLPanelLogin::addFavoritesToStartLocation() gSavedSettings.setBOOL("RememberPassword", save_password); if (!save_password) { - getChild<LLButton>("connect_btn")->setEnabled(false); + mLoginBtn->setEnabled(false); } update_password_setting = false; } @@ -936,7 +939,7 @@ void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev // static void LLPanelLogin::onClickConnect(bool commit_fields) { - if (sInstance && sInstance->mCallback) + if (sInstance && sInstance->mCallback && !sInstance->mAlertNotif) { if (commit_fields) { @@ -1193,9 +1196,7 @@ void LLPanelLogin::updateServer() void LLPanelLogin::updateLoginButtons() { - LLButton* login_btn = getChild<LLButton>("connect_btn"); - - login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0); + mLoginBtn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0 && !mAlertNotif); if (!mFirstLoginThisInstall) { @@ -1367,3 +1368,22 @@ std::string LLPanelLogin::getUserName(LLPointer<LLCredential> &cred) return "unknown"; } +bool LLPanelLogin::onUpdateNotification(const LLSD& notify) +{ + // disable Login button while alert notification is displayed + LLNotificationPtr notifyp = LLNotifications::instance().find(notify["id"].asUUID()); + if (notifyp && notifyp->getName() == "PromptOptionalUpdate") + { + std::string sigtype = notify["sigtype"].asString(); + if (sigtype == "add") + { + mAlertNotif = true; + } + else if (sigtype == "delete") + { + mAlertNotif = false; + } + updateLoginButtons(); + } + return false; +} diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index a1bf25fb05..f527aa53ac 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -105,8 +105,11 @@ private: static void onRememberPasswordCheck(void*); static void onPassKey(LLLineEditor* caller, void* user_data); + bool onUpdateNotification(const LLSD& notify); + private: std::unique_ptr<LLPanelLoginListener> mListener; + LLTempBoundListener mAlertListener; void updateLoginButtons(); void populateUserList(LLPointer<LLCredential> credential); @@ -126,6 +129,9 @@ private: unsigned int mUsernameLength; unsigned int mPasswordLength; unsigned int mLocationLength; + + bool mAlertNotif; + LLButton* mLoginBtn; }; #endif diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 23e6a9fbcf..69be65d9c9 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -625,7 +625,7 @@ void LLPanelObject::getState( ) } - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + if (objectp->getSculptParams()) { selected_item = MI_SCULPT; //LLFirstUse::useSculptedPrim(); @@ -1078,7 +1078,7 @@ void LLPanelObject::getState( ) LLUUID id; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) // if we have a legal sculpt param block for this object: @@ -1246,13 +1246,13 @@ void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata ) if (selected_type == MI_SCULPT) { self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, true, true); - LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = self->mObject->getSculptParams(); if (sculpt_params) volume_params.setSculptID(sculpt_params->getSculptTexture(), sculpt_params->getSculptType()); } else { - LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = self->mObject->getSculptParams(); if (sculpt_params) self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true); } @@ -2264,24 +2264,21 @@ void LLPanelObject::onCopyParams() mClipboardParams["volume_params"] = params.asLLSD(); // Sculpted Prim - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + LLSculptParams *sculpt_params = objectp->getSculptParams(); + if (sculpt_params) { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (get_can_copy_texture(texture_id)) { - LLUUID texture_id = sculpt_params->getSculptTexture(); - if (get_can_copy_texture(texture_id)) - { - LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; - mClipboardParams["sculpt"]["id"] = texture_id; - } - else - { - mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; - } - - mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; + mClipboardParams["sculpt"]["id"] = texture_id; } + else + { + mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; + } + + mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); } } @@ -2304,7 +2301,7 @@ void LLPanelObject::onPasteParams() } else { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) { objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true); diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 87f05f2028..c380b6860f 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -517,7 +517,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, std::string parcel_owner = LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString(); mParcelOwner->setText(parcel_owner); - LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); mRegionGroupText->setText( getString("none_text")); } @@ -548,7 +548,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID(); if(auth_buyer_id.notNull()) { - LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); + mAvatarNameCacheConnection = LLAvatarNameCache::get(auth_buyer_id, boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mSaleToText)); // Show sales info to a specific person or a group he belongs to. if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id)) diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index f562be0f5d..0c161198f8 100644 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -118,6 +118,8 @@ private: LLTextEditor* mResaleText; LLTextBox* mSaleToText; LLAccordionCtrl* mAccordionCtrl; + + boost::signals2::scoped_connection mAvatarNameCacheConnection; }; #endif // LL_LLPANELPLACEPROFILE_H diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index b81b891685..7396f079b0 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -110,7 +110,11 @@ void LLPanelSnapshotInventory::updateControls(const LLSD& info) void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) { - bool current_window_selected = (getChild<LLComboBox>(getImageSizeComboName())->getCurrentIndex() == 3); + LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); + // Current window likely won't ever change position from being the penultimate item + // Custom window is last item + S32 curent_window_index = combo->getItemCount() - 2; + bool current_window_selected = (combo->getCurrentIndex() == curent_window_index); getChild<LLSpinCtrl>(getWidthSpinnerName())->setVisible(!current_window_selected); getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected); } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 5916163f60..94864797d5 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -532,7 +532,7 @@ void LLPanelVolume::getState( ) getChildView("FlexForceY")->setEnabled(true); getChildView("FlexForceZ")->setEnabled(true); - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); getChild<LLUICtrl>("FlexNumSections")->setValue((F32)attributes->getSimulateLOD()); getChild<LLUICtrl>("FlexGravity")->setValue(attributes->getGravity()); @@ -643,7 +643,7 @@ void LLPanelVolume::getState( ) mComboPhysicsShapeType->add(getString("None"), LLSD(1)); bool isMesh = false; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) { U8 sculpt_type = sculpt_params->getSculptType(); @@ -1043,7 +1043,7 @@ void LLPanelVolume::onCopyFeatures() // Flexi Prim if (volobjp && volobjp->isFlexible()) { - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { clipboard["flex"]["lod"] = attributes->getSimulateLOD(); @@ -1141,7 +1141,7 @@ void LLPanelVolume::onPasteFeatures() objectp->setClickAction(CLICK_ACTION_NONE); } - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { LLFlexibleObjectData new_attributes; @@ -1568,7 +1568,7 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) return; } - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { LLFlexibleObjectData new_attributes; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 4762fc555d..415e6cfa72 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6193,6 +6193,15 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use node->mCategory = category; node->mName.assign(name); node->mDescription.assign(desc); + + LLViewerObject* obj = node->getObject(); + if (obj && LLViewerObject::isObjectInPendingUpdate(owner_id, obj)) + { + // current response doesn't return modify permissions flags, + // so we should request it separately if needed + obj->requestObjectUpdate(); + } + } dialog_refresh_all(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f3cfbd9565..4326bd549c 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -135,9 +135,10 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } -bool LLSpatialGroup::isHUDGroup() +bool LLSpatialGroup::isHUDGroup() const { - return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; + LLSpatialPartition* part = (LLSpatialPartition*)mSpatialPartition; + return part && part->isHUDPartition(); } void LLSpatialGroup::validate() diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index d8a94c8835..4b312b1597 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -264,7 +264,7 @@ public: LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); - bool isHUDGroup() ; + bool isHUDGroup() const; void clearDrawMap(); void validate(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index f78ff2226c..5e2d91d31e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -775,7 +775,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, bool drop, if (!handled) { // Disallow drag and drop to 3D from the marketplace - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 5ccda7d4eb..3bd459f5b0 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -55,17 +55,17 @@ LLToolSelect::LLToolSelect( LLToolComposite* composite ) : LLTool( std::string("Select"), composite ), mIgnoreGroup( false ) { - } +} // True if you selected an object. bool LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) { // do immediate pick query bool pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); - bool pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects"); - bool pick_reflection_probe = gSavedSettings.getBOOL("SelectReflectionProbes"); + static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects"); + static LLCachedControl<bool> select_reflection_probes(gSavedSettings, "SelectReflectionProbes"); - mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged, false, true, pick_reflection_probe); + mPick = gViewerWindow->pickImmediate(x, y, select_invisible_objects, pick_rigged, false, true, select_reflection_probes); // Pass mousedown to agent LLTool::handleMouseDown(x, y, mask); @@ -73,7 +73,6 @@ bool LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) return mPick.getObject().notNull(); } - // static LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, bool ignore_group, bool temp_select, bool select_root) { diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 141f370ecb..fd462fb225 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -42,6 +42,7 @@ #include "llcoproceduremanager.h" #include "lleventcoro.h" #include "llsdutil.h" +#include "llstartup.h" #include "llworld.h" ///---------------------------------------------------------------------------- @@ -460,28 +461,78 @@ void LLViewerAssetStorage::assetRequestCoro( if (!gAgent.getRegion()) { - LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; - result_code = LL_ERR_ASSET_REQUEST_FAILED; - ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); - return; + if (STATE_WORLD_INIT <= LLStartUp::getStartupState()) + { + // Viewer isn't ready, wait for region to become available + LL_INFOS_ONCE("ViewerAsset") << "Waiting for agent region to be set" << LL_ENDL; + + LLEventStream region_init("waitForRegion", true); + std::string pump_name = region_init.getName(); + + boost::signals2::connection region_conn = + gAgent.addRegionChangedCallback([pump_name]() + { + LLEventPumps::instance().obtain(pump_name).post(LLSD()); + }); + F32Seconds timeout_seconds(LL_ASSET_STORAGE_TIMEOUT); + llcoro::suspendUntilEventOnWithTimeout(region_init, timeout_seconds, LLSDMap("timeout", LLSD::Boolean(true))); + gAgent.removeRegionChangedCallback(region_conn); + region_conn.disconnect(); + + if (LLApp::isExiting() || !gAssetStorage) + { + return; + } + + // recheck region whether suspend ended on timeout or not + if (!gAgent.getRegion()) + { + LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: timeout reached while waiting for region" << LL_ENDL; + result_code = LL_ERR_NO_CAP; + ext_status = LLExtStat::NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); + return; + } + } + else + { + LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; + result_code = LL_ERR_NO_CAP; + ext_status = LLExtStat::NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); + return; + } } - else if (!gAgent.getRegion()->capabilitiesReceived()) + + if (!gAgent.getRegion()->capabilitiesReceived()) { LL_WARNS_ONCE("ViewerAsset") << "Waiting for capabilities" << LL_ENDL; LLEventStream capsRecv("waitForCaps", true); - gAgent.getRegion()->setCapabilitiesReceivedCallback( - boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName())); + boost::signals2::connection caps_conn = + gAgent.getRegion()->setCapabilitiesReceivedCallback( + boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName())); - llcoro::suspendUntilEventOn(capsRecv); + F32Seconds timeout_seconds(LL_ASSET_STORAGE_TIMEOUT); // from minutes to seconds, by default 5 minutes + LLSD result = llcoro::suspendUntilEventOnWithTimeout(capsRecv, timeout_seconds, LLSDMap("timeout", LLSD::Boolean(true))); + caps_conn.disconnect(); if (LLApp::isExiting() || !gAssetStorage) { return; } + if (result.has("timeout")) + { + // Caps failed to arrive in 5 minutes + LL_WARNS_ONCE("ViewerAsset") << "Asset " << uuid << " request fails : capabilities took too long to arrive" << LL_ENDL; + result_code = LL_ERR_NO_CAP; + ext_status = LLExtStat::NONE; + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); + return; + } + LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL; LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL; } @@ -492,7 +543,7 @@ void LLViewerAssetStorage::assetRequestCoro( if (mViewerAssetUrl.empty()) { LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL; - result_code = LL_ERR_ASSET_REQUEST_FAILED; + result_code = LL_ERR_NO_CAP; ext_status = LLExtStat::NONE; removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index aa0cbac91f..a7441febd9 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -398,18 +398,12 @@ void init_audio() void audio_update_volume(bool force_update) { - F32 master_volume = gSavedSettings.getF32("AudioLevelMaster"); - bool mute_audio = gSavedSettings.getBOOL("MuteAudio"); - - LLProgressView* progress = gViewerWindow->getProgressView(); - bool progress_view_visible = false; - - if (progress) - { - progress_view_visible = progress->getVisible(); - } + static LLCachedControl<F32> master_volume(gSavedSettings, "AudioLevelMaster"); + static LLCachedControl<bool> mute_audio_setting(gSavedSettings, "MuteAudio"); + static LLCachedControl<bool> mute_when_minimized(gSavedSettings, "MuteWhenMinimized"); + bool mute_audio = mute_audio_setting(); - if (!gViewerWindow->getActive() && gSavedSettings.getBOOL("MuteWhenMinimized")) + if (!gViewerWindow->getActive() && mute_when_minimized()) { mute_audio = true; } @@ -419,7 +413,7 @@ void audio_update_volume(bool force_update) { // Sound Effects - gAudiop->setMasterGain ( master_volume ); + gAudiop->setMasterGain (master_volume()); const F32 AUDIO_LEVEL_DOPPLER = 1.f; gAudiop->setDopplerFactor(AUDIO_LEVEL_DOPPLER); @@ -435,6 +429,7 @@ void audio_update_volume(bool force_update) gAudiop->setRolloffFactor(AUDIO_LEVEL_UNDERWATER_ROLLOFF); } + bool progress_view_visible = gViewerWindow->getShowProgress(); gAudiop->setMuted(mute_audio || progress_view_visible); //Play any deferred sounds when unmuted @@ -448,13 +443,21 @@ void audio_update_volume(bool force_update) audio_update_wind(true); } + static LLCachedControl<bool> mute_sounds(gSavedSettings, "MuteSounds"); + static LLCachedControl<bool> mute_ui(gSavedSettings, "MuteUI"); + static LLCachedControl<bool> mute_ambient(gSavedSettings, "MuteAmbient"); + static LLCachedControl<bool> mute_music(gSavedSettings, "MuteMusic"); + static LLCachedControl<F32> al_sfx(gSavedSettings, "AudioLevelSFX"); + static LLCachedControl<F32> al_ui(gSavedSettings, "AudioLevelUI"); + static LLCachedControl<F32> al_ambient(gSavedSettings, "AudioLevelAmbient"); + static LLCachedControl<F32> al_music(gSavedSettings, "AudioLevelMusic"); // handle secondary gains gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_SFX, - gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX")); + mute_sounds() ? 0.f : al_sfx()); gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_UI, - gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI")); + mute_ui() ? 0.f : al_ui()); gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT, - gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient")); + mute_ambient() ? 0.f : al_ambient()); // Streaming Music @@ -464,31 +467,29 @@ void audio_update_volume(bool force_update) LLViewerAudio::getInstance()->setForcedTeleportFade(false); } - F32 music_volume = gSavedSettings.getF32("AudioLevelMusic"); - bool music_muted = gSavedSettings.getBOOL("MuteMusic"); F32 fade_volume = LLViewerAudio::getInstance()->getFadeVolume(); - music_volume = mute_volume * master_volume * music_volume * fade_volume; - gAudiop->setInternetStreamGain (music_muted ? 0.f : music_volume); + F32 music_volume = mute_volume * master_volume * al_music() * fade_volume; + gAudiop->setInternetStreamGain (mute_music() ? 0.f : music_volume); } // Streaming Media - F32 media_volume = gSavedSettings.getF32("AudioLevelMedia"); - bool media_muted = gSavedSettings.getBOOL("MuteMedia"); - media_volume = mute_volume * master_volume * media_volume; - LLViewerMedia::getInstance()->setVolume( media_muted ? 0.0f : media_volume ); + static LLCachedControl<bool> media_muted(gSavedSettings, "MuteMedia"); + static LLCachedControl<F32> media_volume(gSavedSettings, "AudioLevelMedia"); + LLViewerMedia::getInstance()->setVolume( media_muted() ? 0.0f : (mute_volume * master_volume() * media_volume())); // Voice, this is parametric singleton, it gets initialized when ready if (LLVoiceClient::instanceExists()) { - F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice"); - voice_volume = mute_volume * master_volume * voice_volume; - bool voice_mute = gSavedSettings.getBOOL("MuteVoice"); + static LLCachedControl<bool> voice_mute(gSavedSettings, "MuteVoice"); + static LLCachedControl<F32> voice_volume_setting(gSavedSettings, "AudioLevelVoice"); + static LLCachedControl<F32> voice_mic_setting(gSavedSettings, "AudioLevelMic"); + F32 voice_volume = mute_volume * master_volume() * voice_volume_setting(); LLVoiceClient *voice_inst = LLVoiceClient::getInstance(); - voice_inst->setVoiceVolume(voice_mute ? 0.f : voice_volume); - voice_inst->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic")); + voice_inst->setVoiceVolume(voice_mute() ? 0.f : voice_volume); + voice_inst->setMicGain(voice_mute() ? 0.f : voice_mic_setting()); - if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized"))) + if (!gViewerWindow->getActive() && mute_when_minimized()) { voice_inst->setMuteMic(true); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index bb956d455f..a77b9f6103 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -663,9 +663,10 @@ void LLViewerMedia::updateMedia(void *dummy_arg) LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE); llassert(!gCubeSnapshot); + static LLCachedControl<bool> use_read_thread(gSavedSettings, "PluginUseReadThread", true); // Enable/disable the plugin read thread - LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); + LLPluginProcessParent::setUseReadThread(use_read_thread()); // SL-16418 We can't call LLViewerMediaImpl->update() if we are in the state of shutting down. if(LLApp::isExiting()) @@ -2189,16 +2190,19 @@ void LLViewerMediaImpl::updateVolume() if (mProximityCamera > 0) { - if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMax")) + static LLCachedControl<F32> media_rolloff_min(gSavedSettings, "MediaRollOffMin"); + static LLCachedControl<F32> media_rolloff_max(gSavedSettings, "MediaRollOffMax"); + static LLCachedControl<F32> media_rolloff_rate(gSavedSettings, "MediaRollOffRate"); + if (mProximityCamera > media_rolloff_max()) { volume = 0; } - else if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMin")) + else if (mProximityCamera > media_rolloff_min()) { // attenuated_volume = 1 / (roll_off_rate * (d - min))^2 // the +1 is there so that for distance 0 the volume stays the same - F64 adjusted_distance = mProximityCamera - gSavedSettings.getF32("MediaRollOffMin"); - F64 attenuation = 1.0 + (gSavedSettings.getF32("MediaRollOffRate") * adjusted_distance); + F64 adjusted_distance = mProximityCamera - media_rolloff_min(); + F64 attenuation = 1.0 + (media_rolloff_rate() * adjusted_distance); attenuation = 1.0 / (attenuation * attenuation); // the attenuation multiplier should never be more than one since that would increase volume volume = volume * (F32)llmin(1.0, attenuation); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index abaf813530..f29760c824 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -425,7 +425,7 @@ void LLSLMMenuUpdater::setMerchantMenu() LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); gToolBarView->enableCommand(command->id(), true); - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.isNull()) { U32 mkt_status = LLMarketplaceData::instance().getSLMStatus(); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1675c44c5c..dfb0521167 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -130,6 +130,7 @@ F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motio F64Seconds LLViewerObject::sMaxRegionCrossingInterpolationTime(1.0);// For motion interpolation: don't interpolate over this time on region crossing std::map<std::string, U32> LLViewerObject::sObjectDataMap; +std::unordered_map<LLUUID, std::vector<LLViewerObject*>> LLViewerObject::sPendingUpdatesByOwner; // The maximum size of an object extra parameters binary (packed) block #define MAX_OBJECT_PARAMS_SIZE 1024 @@ -310,6 +311,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mAttachmentItemID(LLUUID::null), mLastUpdateType(OUT_UNKNOWN), mLastUpdateCached(false), + mExtraParameterList(LLNetworkData::PARAMS_MAX >> 4), mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), mRiggedAttachedWarned(false) @@ -367,15 +369,6 @@ LLViewerObject::~LLViewerObject() } // Delete memory associated with extra parameters. - std::unordered_map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if(iter->second != NULL) - { - delete iter->second->data; - delete iter->second; - } - } mExtraParameterList.clear(); for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; @@ -529,6 +522,8 @@ void LLViewerObject::markDead() mReflectionProbe = nullptr; } + removeObjectFromPendingUpdate(this); + sNumZombieObjects++; } } @@ -1508,10 +1503,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, unpackParticleSource(block_num, owner_id); // Mark all extra parameters not used - std::unordered_map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (auto& entry : mExtraParameterList) { - iter->second->in_use = false; + if (entry.in_use) *entry.in_use = false; } // Unpack extra parameters @@ -1543,12 +1537,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, delete[] buffer; } - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (size_t i = 0; i < mExtraParameterList.size(); ++i) { - if (!iter->second->in_use) + auto& entry = mExtraParameterList[i]; + if (entry.in_use && !*entry.in_use) { // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, false, false); + parameterChanged(((U16)i + 1) << 4, entry.data, false, false); } } @@ -1850,10 +1845,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } // Mark all extra parameters not used - std::unordered_map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (auto& entry : mExtraParameterList) { - iter->second->in_use = false; + if (entry.in_use) *entry.in_use = false; } // Unpack extra params @@ -1871,12 +1865,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, unpackParameterEntry(param_type, &dp2); } - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (size_t i = 0; i < mExtraParameterList.size(); ++i) { - if (!iter->second->in_use) + auto& entry = mExtraParameterList[i]; + if (entry.in_use && !*entry.in_use) { // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, false, false); + parameterChanged(((U16)i + 1) << 4, entry.data, false, false); } } @@ -4183,7 +4178,7 @@ void LLViewerObject::boostTexturePriority(bool boost_children /* = true */) if (isSculpted() && !isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { LLUUID sculpt_id = sculpt_params->getSculptTexture(); @@ -6494,7 +6489,7 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) if (param) { param->data->unpack(*dp); - param->in_use = true; + *param->in_use = true; parameterChanged(param_type, param->data, true, false); return true; } @@ -6506,108 +6501,79 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type) { - LLNetworkData* new_block = NULL; + LLNetworkData* new_block = nullptr; + bool* in_use = NULL; switch (param_type) { case LLNetworkData::PARAMS_FLEXIBLE: { - new_block = new LLFlexibleObjectData(); + mFlexibleObjectData = std::make_unique<LLFlexibleObjectData>(); + new_block = mFlexibleObjectData.get(); + in_use = &mFlexibleObjectDataInUse; break; } case LLNetworkData::PARAMS_LIGHT: { - new_block = new LLLightParams(); + mLightParams = std::make_unique<LLLightParams>(); + new_block = mLightParams.get(); + in_use = &mLightParamsInUse; break; } case LLNetworkData::PARAMS_SCULPT: { - new_block = new LLSculptParams(); + mSculptParams = std::make_unique<LLSculptParams>(); + new_block = mSculptParams.get(); + in_use = &mSculptParamsInUse; break; } case LLNetworkData::PARAMS_LIGHT_IMAGE: { - new_block = new LLLightImageParams(); + mLightImageParams = std::make_unique<LLLightImageParams>(); + new_block = mLightImageParams.get(); + in_use = &mLightImageParamsInUse; break; } case LLNetworkData::PARAMS_EXTENDED_MESH: { - new_block = new LLExtendedMeshParams(); + mExtendedMeshParams = std::make_unique<LLExtendedMeshParams>(); + new_block = mExtendedMeshParams.get(); + in_use = &mExtendedMeshParamsInUse; break; } case LLNetworkData::PARAMS_RENDER_MATERIAL: { - new_block = new LLRenderMaterialParams(); + mRenderMaterialParams = std::make_unique<LLRenderMaterialParams>(); + new_block = mRenderMaterialParams.get(); + in_use = &mRenderMaterialParamsInUse; break; } case LLNetworkData::PARAMS_REFLECTION_PROBE: { - new_block = new LLReflectionProbeParams(); + mReflectionProbeParams = std::make_unique<LLReflectionProbeParams>(); + new_block = mReflectionProbeParams.get(); + in_use = &mReflectionProbeParamsInUse; break; } default: { - LL_INFOS_ONCE() << "Unknown param type: " << param_type << LL_ENDL; + LL_INFOS_ONCE() << "Unknown param type. (" << llformat("0x%2x", param_type) << ")" << LL_ENDL; break; } }; + ExtraParameter& entry = mExtraParameterList[U32(param_type >> 4) - 1]; if (new_block) { - ExtraParameter* new_entry = new ExtraParameter; - new_entry->data = new_block; - new_entry->in_use = false; // not in use yet - llassert(mExtraParameterList[param_type] == nullptr); // leak -- redundantly allocated parameter entry - mExtraParameterList[param_type] = new_entry; - return new_entry; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VIEWER; - std::unordered_map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type); - if (itor != mExtraParameterList.end()) - { - return itor->second; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type) -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (!param) - { - param = createNewParameterEntry(param_type); - } - return param; -} - -LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->data; + entry.in_use = in_use; + *entry.in_use = false; // not in use yet + entry.data = new_block; + return &entry; } else { - return NULL; - } -} - -bool LLViewerObject::getParameterEntryInUse(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->in_use; - } - else - { - return false; + entry.is_invalid = true; } + return nullptr; } bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin) @@ -6615,11 +6581,11 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ ExtraParameter* param = getExtraParameterEntryCreate(param_type); if (param) { - if (param->in_use && new_value == *(param->data)) + if (*(param->in_use) && new_value == *(param->data)) { return false; } - param->in_use = true; + *param->in_use = true; param->data->copy(new_value); parameterChanged(param_type, param->data, true, local_origin); return true; @@ -6635,22 +6601,28 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ // Should always return true. bool LLViewerObject::setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin) { - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param && param->in_use != in_use) + if (param_type <= LLNetworkData::PARAMS_MAX) { - param->in_use = in_use; - parameterChanged(param_type, param->data, in_use, local_origin); - return true; + ExtraParameter* param = (in_use ? getExtraParameterEntryCreate(param_type) : &getExtraParameterEntry(param_type)); + if (param && param->data && *param->in_use != in_use) + { + *param->in_use = in_use; + parameterChanged(param_type, param->data, in_use, local_origin); + return true; + } } return false; } void LLViewerObject::parameterChanged(U16 param_type, bool local_origin) { - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) + if (param_type <= LLNetworkData::PARAMS_MAX) { - parameterChanged(param_type, param->data, param->in_use, local_origin); + const ExtraParameter& param = getExtraParameterEntry(param_type); + if (param.data) + { + parameterChanged(param_type, param.data, *param.in_use, local_origin); + } } } @@ -6698,7 +6670,7 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, bool { if (param_type == LLNetworkData::PARAMS_RENDER_MATERIAL) { - const LLRenderMaterialParams* params = in_use ? (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL) : nullptr; + const LLRenderMaterialParams* params = in_use ? getRenderMaterialParams() : nullptr; setRenderMaterialIDs(params, local_origin); } } @@ -7469,9 +7441,10 @@ const std::string& LLViewerObject::getAttachmentItemName() const LLVOAvatar* LLViewerObject::getAvatar() const { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (getControlAvatar()) + LLControlAvatar* ca = getControlAvatar(); + if (ca) { - return getControlAvatar(); + return ca; } if (isAttachment()) { @@ -7490,7 +7463,7 @@ LLVOAvatar* LLViewerObject::getAvatar() const bool LLViewerObject::hasRenderMaterialParams() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL); + return mRenderMaterialParamsInUse; } void LLViewerObject::setHasRenderMaterialParams(bool has_materials) @@ -7512,7 +7485,7 @@ void LLViewerObject::setHasRenderMaterialParams(bool has_materials) const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const { - LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); + const LLRenderMaterialParams* param_block = getRenderMaterialParams(); if (param_block) { return param_block->getMaterial(te); @@ -7553,7 +7526,7 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat start_idx = llmax(start_idx, 0); end_idx = llmin(end_idx, (S32) getNumTEs()); - LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); + LLRenderMaterialParams* param_block = getRenderMaterialParams(); if (!param_block && id.notNull()) { // block doesn't exist, but it will need to param_block = (LLRenderMaterialParams*)createNewParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL)->data; @@ -7781,6 +7754,61 @@ bool LLViewerObject::isReachable() return false; } +void LLViewerObject::markObjectsForUpdate(const LLUUID& owner_id) +{ + sPendingUpdatesByOwner.erase(owner_id); + for (S32 i = 0; i < gObjectList.getNumObjects(); ++i) + { + LLViewerObject* obj = gObjectList.getObject(i); + if (!obj || obj->isDead() || obj->isAvatar() || obj->permYouOwner()) + { + continue; + } + sPendingUpdatesByOwner[owner_id].push_back(obj); + } +} + +void LLViewerObject::removeObjectFromPendingUpdate(LLViewerObject* obj) +{ + for (auto& [owner_id, objects] : sPendingUpdatesByOwner) + { + objects.erase(std::remove(objects.begin(), objects.end(), obj), objects.end()); + } +} + +bool LLViewerObject::isObjectInPendingUpdate(const LLUUID& owner_id, LLViewerObject* obj) +{ + if (!obj) + { + return false; + } + auto it = sPendingUpdatesByOwner.find(owner_id); + if (it != sPendingUpdatesByOwner.end()) + { + const auto& objects = it->second; + return std::find(objects.begin(), objects.end(), obj) != objects.end(); + } + return false; +} + +void LLViewerObject::requestObjectUpdate() +{ + if (LLViewerRegion* regionp = getRegion()) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, 0); + msg->addU32Fast(_PREHASH_ID, getLocalID()); + msg->sendReliable(regionp->getHost()); + + removeObjectFromPendingUpdate(this); + } +} + class ObjectPhysicsProperties : public LLHTTPNode { public: diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index a9c2db60e4..465e221ae4 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -126,13 +126,15 @@ class LLViewerObject protected: virtual ~LLViewerObject(); // use unref() +private: // TomY: Provide for a list of extra parameter structures, mapped by structure name struct ExtraParameter { - bool in_use; - LLNetworkData *data; + bool is_invalid = false; + bool* in_use = nullptr; + LLNetworkData* data = nullptr; }; - std::unordered_map<U16, ExtraParameter*> mExtraParameterList; + std::vector<ExtraParameter> mExtraParameterList; public: typedef std::list<LLPointer<LLViewerObject> > child_list_t; @@ -620,6 +622,11 @@ public: void setPhysicsDensity(F32 density); void setPhysicsRestitution(F32 restitution); + static void markObjectsForUpdate(const LLUUID& owner_id); + static void removeObjectFromPendingUpdate(LLViewerObject* obj); + static bool isObjectInPendingUpdate(const LLUUID& owner_id, LLViewerObject* obj); + void requestObjectUpdate(); + virtual void dump() const; static U32 getNumZombieObjects() { return sNumZombieObjects; } @@ -630,10 +637,16 @@ public: void dirtySpatialGroup() const; virtual void dirtyMesh(); - virtual LLNetworkData* getParameterEntry(U16 param_type) const; - virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); - virtual bool getParameterEntryInUse(U16 param_type) const; - virtual bool setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin); + LLFlexibleObjectData* getFlexibleObjectData() const { return mFlexibleObjectDataInUse ? mFlexibleObjectData.get() : nullptr; } + LLLightParams* getLightParams() const { return mLightParamsInUse ? mLightParams.get() : nullptr; } + LLSculptParams* getSculptParams() const { return mSculptParamsInUse ? mSculptParams.get() : nullptr; } + LLLightImageParams* getLightImageParams() const { return mLightImageParamsInUse ? mLightImageParams.get() : nullptr; } + LLExtendedMeshParams* getExtendedMeshParams() const { return mExtendedMeshParamsInUse ? mExtendedMeshParams.get() : nullptr; } + LLRenderMaterialParams* getRenderMaterialParams() const { return mRenderMaterialParamsInUse ? mRenderMaterialParams.get() : nullptr; } + LLReflectionProbeParams* getReflectionProbeParams() const { return mReflectionProbeParamsInUse ? mReflectionProbeParams.get() : nullptr; } + + bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); + bool setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin); // Called when a parameter is changed virtual void parameterChanged(U16 param_type, bool local_origin); virtual void parameterChanged(U16 param_type, LLNetworkData* data, bool in_use, bool local_origin); @@ -675,8 +688,31 @@ private: bool isAssetInInventory(LLViewerInventoryItem* item, LLAssetType::EType type); ExtraParameter* createNewParameterEntry(U16 param_type); - ExtraParameter* getExtraParameterEntry(U16 param_type) const; - ExtraParameter* getExtraParameterEntryCreate(U16 param_type); + const ExtraParameter& getExtraParameterEntry(U16 param_type) const + { + return mExtraParameterList[U32(param_type >> 4) - 1]; + } + ExtraParameter& getExtraParameterEntry(U16 param_type) + { + return mExtraParameterList[U32(param_type >> 4) - 1]; + } + ExtraParameter* getExtraParameterEntryCreate(U16 param_type) + { + if (param_type <= LLNetworkData::PARAMS_MAX) + { + ExtraParameter& param = getExtraParameterEntry(param_type); + if (!param.is_invalid) + { + if (!param.data) + { + ExtraParameter* new_entry = createNewParameterEntry(param_type); + return new_entry; + } + return ¶m; + } + } + return nullptr; + } bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); // This function checks to see if the given media URL has changed its version @@ -749,7 +785,23 @@ private: // Grabbed from UPDATE_FLAGS U32 mFlags; + bool mFlexibleObjectDataInUse = false, + mLightParamsInUse = false, + mSculptParamsInUse = false, + mLightImageParamsInUse = false, + mExtendedMeshParamsInUse = false, + mRenderMaterialParamsInUse = false, + mReflectionProbeParamsInUse = false; + std::unique_ptr<LLFlexibleObjectData> mFlexibleObjectData; + std::unique_ptr<LLLightParams> mLightParams; + std::unique_ptr<LLSculptParams> mSculptParams; + std::unique_ptr<LLLightImageParams> mLightImageParams; + std::unique_ptr<LLExtendedMeshParams> mExtendedMeshParams; + std::unique_ptr<LLRenderMaterialParams> mRenderMaterialParams; + std::unique_ptr<LLReflectionProbeParams> mReflectionProbeParams; + static std::map<std::string, U32> sObjectDataMap; + static std::unordered_map<LLUUID, std::vector<LLViewerObject*>> sPendingUpdatesByOwner; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 1b38fed3bb..50edb408c7 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -65,6 +65,7 @@ #include "lltoolmgr.h" #include "lltoolpie.h" #include "llkeyboard.h" +#include "llmeshrepository.h" #include "u64.h" #include "llviewertexturelist.h" #include "lldatapacker.h" @@ -1398,6 +1399,8 @@ void LLViewerObjectList::killAllObjects() llassert((objectp == gAgentAvatarp) || objectp->isDead()); } + gMeshRepo.unregisterAllMeshes(); + cleanDeadObjects(false); if(!mObjects.empty()) diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index 60e17a6f58..adfe709b04 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -316,7 +316,6 @@ public: //virtual bool isRecentlyVisible() const; - LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;} bool isAnyRecentlyVisible() const; static U32 getNewOcclusionQueryObjectName(); diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 432da2e990..6a029645fb 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -881,7 +881,8 @@ LLParcel* LLViewerParcelMgr::getCollisionParcel() const void LLViewerParcelMgr::render() { - if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection") && !gDisconnected) + static LLCachedControl<bool> render_parcel_selection(gSavedSettings, "RenderParcelSelection"); + if (mSelected && mRenderSelection && render_parcel_selection() && !gDisconnected) { // Rendering is done in agent-coordinates, so need to supply // an appropriate offset to the render code. diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index e36ad0e722..e023dffc03 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -63,9 +63,9 @@ LLUIColor LLViewerParcelOverlay::sForSaleColor; LLUIColor LLViewerParcelOverlay::sAuctionColor; LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters) -: mRegion( region ), - mParcelGridsPerEdge( S32( region_width_meters / PARCEL_GRID_STEP_METERS ) ), - mDirty( false ), +: mRegion(region), + mParcelGridsPerEdge(S32(region_width_meters / PARCEL_GRID_STEP_METERS)), + mDirty(false), mTimeSinceLastUpdate(), mOverlayTextureIdx(-1) { @@ -467,9 +467,9 @@ void LLViewerParcelOverlay::updatePropertyLines() { for (S32 col = 0; col < GRIDS_PER_EDGE; col++) { - U8 overlay = mOwnership[row*GRIDS_PER_EDGE+col]; + U8 overlay = mOwnership[row * GRIDS_PER_EDGE + col]; S32 colorIndex = overlay & PARCEL_COLOR_MASK; - switch(colorIndex) + switch (colorIndex) { case PARCEL_SELF: case PARCEL_GROUP: @@ -483,11 +483,11 @@ void LLViewerParcelOverlay::updatePropertyLines() const LLColor4U& color = colors[colorIndex]; - F32 left = col*GRID_STEP; - F32 right = left+GRID_STEP; + F32 left = col * GRID_STEP; + F32 right = left + GRID_STEP; - F32 bottom = row*GRID_STEP; - F32 top = bottom+GRID_STEP; + F32 bottom = row * GRID_STEP; + F32 top = bottom + GRID_STEP; // West edge if (overlay & PARCEL_WEST_LINE) @@ -528,99 +528,121 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 Edge& edge = mEdges.back(); edge.color = color; + // Detailized rendering vertices: + // A B C D E F G + // *-*------*--------*--------*------*-* : 'outside' vertices are placed right on the border + // *------*--------*--------*------* : 'inside' vertices are shifted on LINE_WIDTH inside + + // Simplified rendering vertices: + // A G + // *-----------------------------------* + // *-----------------------------------* + F32 outside_x = start_x; F32 outside_y = start_y; - F32 outside_z = 0.f; - F32 inside_x = start_x + tick_dx; - F32 inside_y = start_y + tick_dy; - F32 inside_z = 0.f; + F32 outside_z = land.resolveHeightRegion(outside_x, outside_y); + F32 inside_x = start_x + tick_dx; + F32 inside_y = start_y + tick_dy; + F32 inside_z = land.resolveHeightRegion(inside_x, inside_y); + + auto move = [&](F32 distance) + { + outside_x += dx * distance; + outside_y += dy * distance; + outside_z = land.resolveHeightRegion(outside_x, outside_y); + inside_x += dx * distance; + inside_y += dy * distance; + inside_z = land.resolveHeightRegion(inside_x, inside_y); + }; - auto split = [&](const LLVector3& start, F32 x, F32 y, F32 z, F32 part) + auto split = [&](U32 lod, const LLVector4a& start, F32 x, F32 y, F32 z, F32 part) { - F32 new_x = start.mV[VX] + (x - start.mV[VX]) * part; - F32 new_y = start.mV[VY] + (y - start.mV[VY]) * part; - F32 new_z = start.mV[VZ] + (z - start.mV[VZ]) * part; - edge.vertices.emplace_back(new_x, new_y, new_z); + F32 new_x = start[VX] + (x - start[VX]) * part; + F32 new_y = start[VY] + (y - start[VY]) * part; + edge.pushVertex(lod, new_x, new_y, water_z, 0); }; - auto checkForSplit = [&]() + auto checkForSplit = [&](U32 lod) { - const LLVector3& last_outside = edge.vertices.back(); - F32 z0 = last_outside.mV[VZ]; + const std::vector<LLVector4a>& vertices = edge.verticesUnderWater[lod]; + const LLVector4a& last_outside = vertices.back(); + F32 z0 = last_outside[VZ]; F32 z1 = outside_z; if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z)) return; F32 part = (water_z - z0) / (z1 - z0); - const LLVector3& last_inside = edge.vertices[edge.vertices.size() - 2]; - split(last_inside, inside_x, inside_y, inside_z, part); - split(last_outside, outside_x, outside_y, outside_z, part); + const LLVector4a& last_inside = vertices[vertices.size() - 2]; + split(lod, last_inside, inside_x, inside_y, inside_z, part); + split(lod, last_outside, outside_x, outside_y, outside_z, part); }; - // First part, only one vertex - outside_z = land.resolveHeightRegion( outside_x, outside_y ); - - edge.vertices.emplace_back(outside_x, outside_y, outside_z); - - inside_x += dx * LINE_WIDTH; - inside_y += dy * LINE_WIDTH; - - outside_x += dx * LINE_WIDTH; - outside_y += dy * LINE_WIDTH; - - // Then the "actual edge" - inside_z = land.resolveHeightRegion( inside_x, inside_y ); - outside_z = land.resolveHeightRegion( outside_x, outside_y ); + auto pushTwoVertices = [&](U32 lod) + { + LLVector3 out(outside_x, outside_y, outside_z); + LLVector3 in(inside_x, inside_y, inside_z); + if (fabs(inside_z - outside_z) < LINE_WIDTH / 5) + { + edge.pushVertex(lod, inside_x, inside_y, inside_z, water_z); + } + else + { + // Make the line thinner if heights differ too much + LLVector3 dist(in - out); + F32 coef = dist.length() / LINE_WIDTH; + LLVector3 new_in(out + dist / coef); + edge.pushVertex(lod, new_in[VX], new_in[VY], new_in[VZ], water_z); + } + edge.pushVertex(lod, outside_x, outside_y, outside_z, water_z); + }; - edge.vertices.emplace_back(inside_x, inside_y, inside_z); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); + // Point A simplified (first two vertices) + pushTwoVertices(1); - inside_x += dx * (dx - LINE_WIDTH); - inside_y += dy * (dy - LINE_WIDTH); + // Point A detailized (only one vertex) + edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); - outside_x += dx * (dx - LINE_WIDTH); - outside_y += dy * (dy - LINE_WIDTH); + // Point B (two vertices) + move(LINE_WIDTH); + pushTwoVertices(0); - // Middle part, full width + // Points C, D, E + F32 distance = 1.f - LINE_WIDTH; constexpr S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS; - for (S32 i = 1; i < GRID_STEP; i++) + for (U32 i = 1; i < GRID_STEP; ++i) { - inside_z = land.resolveHeightRegion( inside_x, inside_y ); - outside_z = land.resolveHeightRegion( outside_x, outside_y ); - - checkForSplit(); - - edge.vertices.emplace_back(inside_x, inside_y, inside_z); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); - - inside_x += dx; - inside_y += dy; - - outside_x += dx; - outside_y += dy; + move(distance); + checkForSplit(0); + pushTwoVertices(0); + distance = 1.f; } - // Extra buffer for edge - inside_x -= dx * LINE_WIDTH; - inside_y -= dy * LINE_WIDTH; - - outside_x -= dx * LINE_WIDTH; - outside_y -= dy * LINE_WIDTH; - - inside_z = land.resolveHeightRegion( inside_x, inside_y ); - outside_z = land.resolveHeightRegion( outside_x, outside_y ); - - checkForSplit(); + // Point F (two vertices) + move(1.f - LINE_WIDTH); + checkForSplit(0); + pushTwoVertices(0); - edge.vertices.emplace_back(inside_x, inside_y, inside_z); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); + // Point G simplified (last two vertices) + move(LINE_WIDTH); + pushTwoVertices(1); - outside_x += dx * LINE_WIDTH; - outside_y += dy * LINE_WIDTH; + // Point G detailized (only one vertex) + edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); +} - // Last edge is not drawn to the edge - outside_z = land.resolveHeightRegion( outside_x, outside_y ); +void LLViewerParcelOverlay::Edge::pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z) +{ + verticesUnderWater[lod].emplace_back(x, y, z); + gGL.transform(verticesUnderWater[lod].back()); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); + if (z >= water_z) + { + verticesAboveWater[lod].push_back(verticesUnderWater[lod].back()); + } + else + { + verticesAboveWater[lod].emplace_back(x, y, water_z); + gGL.transform(verticesAboveWater[lod].back()); + } } void LLViewerParcelOverlay::setDirty() @@ -665,6 +687,9 @@ void LLViewerParcelOverlay::renderPropertyLines() if (!show) return; + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_GPU_ZONE("Property Lines"); + LLSurface& land = mRegion->getLand(); bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); @@ -702,6 +727,8 @@ void LLViewerParcelOverlay::renderPropertyLines() // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgentCamera.getCameraPositionGlobal() ); + bool draw_underwater = camera_region.mV[VZ] < water_z || + !gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); // Set up a cull plane 2 * PARCEL_GRID_STEP_METERS behind // the camera. The cull plane normal is the camera's at axis. @@ -709,15 +736,23 @@ void LLViewerParcelOverlay::renderPropertyLines() cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS; cull_plane_point += camera_region; - bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); + bool render_hidden = !draw_underwater && + LLSelectMgr::sRenderHiddenSelections && + LLFloaterReg::instanceVisible("build"); constexpr F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; + const F32 PROPERTY_LINE_LOD0_DIST_SQUARED = PROPERTY_LINE_CLIP_DIST_SQUARED / 25; for (const Edge& edge : mEdges) { - LLVector3 center = edge.vertices[edge.vertices.size() >> 1]; + const std::vector<LLVector4a>& vertices0 = edge.verticesAboveWater[0]; + const F32* first = vertices0.front().getF32ptr(); + const F32* last = vertices0.back().getF32ptr(); + LLVector3 center((first[VX] + last[VX]) / 2, (first[VY] + last[VY]) / 2, (first[VZ] + last[VZ]) / 2); + gGL.untransform(center); - if (dist_vec_squared2D(center, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) + F32 dist_squared = dist_vec_squared(center, camera_region); + if (dist_squared > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } @@ -731,43 +766,33 @@ void LLViewerParcelOverlay::renderPropertyLines() continue; } + U32 lod = dist_squared < PROPERTY_LINE_LOD0_DIST_SQUARED ? 0 : 1; + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.color4ubv(edge.color.mV); - for (const LLVector3& vertex : edge.vertices) + if (draw_underwater) { - if (render_hidden || camera_z < water_z || vertex.mV[2] >= water_z) - { - gGL.vertex3fv(vertex.mV); - } - else - { - LLVector3 visible = vertex; - visible.mV[VZ] = water_z; - gGL.vertex3fv(visible.mV); - } + gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); } - - gGL.end(); - - if (render_hidden) + else { - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.vertexBatchPreTransformed(edge.verticesAboveWater[lod]); - gGL.begin(LLRender::TRIANGLE_STRIP); + if (render_hidden) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - LLColor4U color = edge.color; - color.mV[VALPHA] /= 4; - gGL.color4ubv(color.mV); + LLColor4U color = edge.color; + color.mV[VALPHA] /= 4; + gGL.color4ubv(color.mV); - for (const LLVector3& vertex : edge.vertices) - { - gGL.vertex3fv(vertex.mV); + gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); } - - gGL.end(); } + + gGL.end(); } gGL.popMatrix(); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 50bef02ddf..7271c85701 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -116,7 +116,10 @@ private: struct Edge { - std::vector<LLVector3> vertices; + void pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z); + // LOD: 0 - detailized, 1 - simplified + std::vector<LLVector4a> verticesAboveWater[2]; + std::vector<LLVector4a> verticesUnderWater[2]; LLColor4U color; }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 187cfc9792..ee7b1fb693 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -34,7 +34,6 @@ #include <fstream> #include <algorithm> #include <boost/filesystem.hpp> -#include <boost/lambda/core.hpp> #include <boost/regex.hpp> #include "llagent.h" @@ -1336,7 +1335,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi // Check the whitelist, if there's media (otherwise just show it) if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) { - if ( obj != mDragHoveredObject.get()) + if (obj != mDragHoveredObject) { // Highlight the dragged object LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); @@ -3330,7 +3329,7 @@ void LLViewerWindow::clearPopups() void LLViewerWindow::moveCursorToCenter() { bool mouse_warp = false; - LLCachedControl<S32> mouse_warp_mode(gSavedSettings, "MouseWarpMode", 1); + static LLCachedControl<S32> mouse_warp_mode(gSavedSettings, "MouseWarpMode", 1); switch (mouse_warp_mode()) { @@ -3403,13 +3402,11 @@ void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params) } } -static LLTrace::BlockTimerStatHandle ftm("Update UI"); - // Update UI based on stored mouse position from mouse-move // event processing. void LLViewerWindow::updateUI() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm); + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; static std::string last_handle_msg; @@ -3427,12 +3424,15 @@ void LLViewerWindow::updateUI() } } - LLConsole::updateClass(); + { + LL_PROFILE_ZONE_NAMED("UI updateClass"); + LLConsole::updateClass(); - // execute postponed arrange calls - LLAccordionCtrl::updateClass(); - // animate layout stacks so we have up to date rect for world view - LLLayoutStack::updateClass(); + // execute postponed arrange calls + LLAccordionCtrl::updateClass(); + // animate layout stacks so we have up to date rect for world view + LLLayoutStack::updateClass(); + } // use full window for world view when not rendering UI bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); @@ -3861,6 +3861,7 @@ void LLViewerWindow::updateUI() void LLViewerWindow::updateLayout() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); if (gFloaterTools != NULL && tool != NULL @@ -4340,15 +4341,15 @@ void LLViewerWindow::pickAsync( S32 x, bool pick_unselectable, bool pick_reflection_probes) { + static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects"); // "Show Debug Alpha" means no object actually transparent bool in_build_mode = LLFloaterReg::instanceVisible("build"); - if (LLDrawPoolAlpha::sShowDebugAlpha - || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects"))) + if (LLDrawPoolAlpha::sShowDebugAlpha || (in_build_mode && select_invisible_objects)) { pick_transparent = true; } - LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, pick_unselectable, true, callback); + LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, true, pick_unselectable, callback); schedulePick(pick_info); } @@ -4372,7 +4373,6 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) mWindow->delayInputProcessing(); } - void LLViewerWindow::performPick() { if (!mPicks.empty()) @@ -4406,8 +4406,9 @@ void LLViewerWindow::returnEmptyPicks() // Performs the GL object/land pick. LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, bool pick_transparent, bool pick_rigged, bool pick_particle, bool pick_unselectable, bool pick_reflection_probe) { + static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects"); bool in_build_mode = LLFloaterReg::instanceVisible("build"); - if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha) + if ((in_build_mode && select_invisible_objects) || LLDrawPoolAlpha::sShowDebugAlpha) { // build mode allows interaction with all transparent objects // "Show Debug Alpha" means no object actually transparent @@ -4415,7 +4416,7 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, bool pick_transp } // shortcut queueing in mPicks and just update mLastPick in place - MASK key_mask = gKeyboard->currentMask(true); + MASK key_mask = gKeyboard->currentMask(true); mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, true, false, NULL); mLastPick.fetchResults(); @@ -6154,14 +6155,14 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, bool pick_rigged, bool pick_particle, bool pick_reflection_probe, - bool pick_uv_coords, + bool pick_surface_info, bool pick_unselectable, void (*pick_callback)(const LLPickInfo& pick_info)) : mMousePt(mouse_pos), mKeyMask(keyboard_mask), mPickCallback(pick_callback), mPickType(PICK_INVALID), - mWantSurfaceInfo(pick_uv_coords), + mWantSurfaceInfo(pick_surface_info), mObjectFace(-1), mUVCoords(-1.f, -1.f), mSTCoords(-1.f, -1.f), diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 3efcd763e3..3a700423b3 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2496,17 +2496,18 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection) // callback from llwebrtc void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp) { + connectionPtr_t connection = shared_from_this(); LL::WorkQueue::postMaybe(mMainQueue, - [=, this] { - if (mShutDown) + [=] { + if (connection->mShutDown) { return; } LL_DEBUGS("Voice") << "On Offer Available." << LL_ENDL; - mChannelSDP = sdp; - if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START) + connection->mChannelSDP = sdp; + if (connection->mVoiceConnectionState == VOICE_STATE_WAIT_FOR_SESSION_START) { - mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION; + connection->mVoiceConnectionState = VOICE_STATE_REQUEST_CONNECTION; } }); } @@ -2523,16 +2524,17 @@ void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp) // callback from llwebrtc void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface* audio_interface) { + connectionPtr_t connection = shared_from_this(); LL::WorkQueue::postMaybe(mMainQueue, - [=, this] { - if (mShutDown) + [=] { + if (connection->mShutDown) { return; } LL_DEBUGS("Voice") << "On AudioEstablished." << LL_ENDL; - mWebRTCAudioInterface = audio_interface; - mWebRTCAudioInterface->setMute(true); // mute will be set appropriately later when we finish setting up. - setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED); + connection->mWebRTCAudioInterface = audio_interface; + connection->mWebRTCAudioInterface->setMute(true); // mute will be set appropriately later when we finish setting up. + connection->setVoiceConnectionState(VOICE_STATE_SESSION_ESTABLISHED); }); } @@ -2549,10 +2551,7 @@ void LLVoiceWebRTCConnection::OnRenegotiationNeeded() LL::WorkQueue::postMaybe(mMainQueue, [=, this] { LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL; - if (!mShutDown) - { - setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); - } + setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); mCurrentStatus = LLVoiceClientStatusObserver::ERROR_UNKNOWN; }); } @@ -2898,9 +2897,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() // this connection. // For spatial this connection will come up as muted, but will be set to the appropriate // value later on when we determine the regions we connect to. - if (!isSpatial()) + if (isSpatial()) { - mWebRTCAudioInterface->setMute(mMuted); + // we'll determine primary state later and set mute accordinly + mPrimary = false; } mWebRTCAudioInterface->setReceiveVolume(mSpeakerVolume); LLWebRTCVoiceClient::getInstance()->OnConnectionEstablished(mChannelID, mRegionID); @@ -2924,6 +2924,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() LLWebRTCVoiceClient::getInstance()->updatePosition(); LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true); } + else + { + mWebRTCAudioInterface->setMute(mMuted); + } } break; } @@ -3205,17 +3209,18 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b // llwebrtc callback void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) { + connectionPtr_t connection = shared_from_this(); LL::WorkQueue::postMaybe(mMainQueue, - [=, this] { - if (mShutDown) + [=] { + if (connection->mShutDown) { return; } if (data_interface) { - mWebRTCDataInterface = data_interface; - mWebRTCDataInterface->setDataObserver(this); + connection->mWebRTCDataInterface = data_interface; + connection->mWebRTCDataInterface->setDataObserver(connection.get()); } }); } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9c0f4baf28..b328d3a414 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -250,10 +250,12 @@ LLVOVolume::~LLVOVolume() delete mVolumeImpl; mVolumeImpl = NULL; - gMeshRepo.unregisterMesh(this); + unregisterOldMeshAndSkin(); if(!mMediaImplList.empty()) { + LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("delete volume media list"); + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) { if(mMediaImplList[i].notNull()) @@ -351,7 +353,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, U8 sculpt_type = 0; if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { sculpt_id = sculpt_params->getSculptTexture(); @@ -924,7 +926,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (getLightTextureID().notNull()) { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* params = getLightImageParams(); LLUUID id = params->getLightTexture(); mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE); if (mLightTexture.notNull()) @@ -1048,6 +1050,28 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) return mDrawable; } +// Inverse of gMeshRepo.loadMesh and gMeshRepo.getSkinInfo, combined into one function +// Assume a Collada mesh never changes after being set. +void LLVOVolume::unregisterOldMeshAndSkin() +{ + if (mVolumep) + { + const LLVolumeParams& params = mVolumep->getParams(); + if ((params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + // object is being deleted, so it will no longer need to request + // meshes. + for (S32 lod = 0; lod != LLVolumeLODGroup::NUM_LODS; ++lod) + { + gMeshRepo.unregisterMesh(this, params, lod); + } + // This volume may or may not have a skin + gMeshRepo.unregisterSkinInfo(params.getSculptID(), this); + } + } +} + + bool LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; @@ -1082,7 +1106,7 @@ bool LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, true, false); if (!mVolumeImpl) { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData* data = getFlexibleObjectData(); mVolumeImpl = new LLVolumeImplFlexible(this, data); } } @@ -1193,7 +1217,7 @@ void LLVOVolume::updateSculptTexture() if (isSculpted() && !isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { LLUUID id = sculpt_params->getSculptTexture(); @@ -3053,7 +3077,7 @@ void LLVOVolume::setLightTextureID(LLUUID id) { old_texturep->removeVolume(LLRender::LIGHT_TEX, this); } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* param_block = getLightImageParams(); if (param_block && param_block->getLightTexture() != id) { param_block->setLightTexture(id); @@ -3083,7 +3107,7 @@ void LLVOVolume::setLightTextureID(LLUUID id) void LLVOVolume::setSpotLightParams(LLVector3 params) { - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* param_block = getLightImageParams(); if (param_block && param_block->getParams() != params) { param_block->setParams(params); @@ -3125,7 +3149,7 @@ void LLVOVolume::setLightSRGBColor(const LLColor3& color) void LLVOVolume::setLightLinearColor(const LLColor3& color) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getLinearColor() != color) @@ -3140,7 +3164,7 @@ void LLVOVolume::setLightLinearColor(const LLColor3& color) void LLVOVolume::setLightIntensity(F32 intensity) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getLinearColor().mV[3] != intensity) @@ -3153,7 +3177,7 @@ void LLVOVolume::setLightIntensity(F32 intensity) void LLVOVolume::setLightRadius(F32 radius) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getRadius() != radius) @@ -3166,7 +3190,7 @@ void LLVOVolume::setLightRadius(F32 radius) void LLVOVolume::setLightFalloff(F32 falloff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getFalloff() != falloff) @@ -3179,7 +3203,7 @@ void LLVOVolume::setLightFalloff(F32 falloff) void LLVOVolume::setLightCutoff(F32 cutoff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getCutoff() != cutoff) @@ -3194,7 +3218,7 @@ void LLVOVolume::setLightCutoff(F32 cutoff) bool LLVOVolume::getIsLight() const { - mIsLight = getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); + mIsLight = getLightParams() != nullptr; return mIsLight; } @@ -3210,7 +3234,7 @@ LLColor3 LLVOVolume::getLightSRGBBaseColor() const LLColor3 LLVOVolume::getLightLinearBaseColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return LLColor3(param_block->getLinearColor()); @@ -3223,7 +3247,7 @@ LLColor3 LLVOVolume::getLightLinearBaseColor() const LLColor3 LLVOVolume::getLightLinearColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return LLColor3(param_block->getLinearColor()) * param_block->getLinearColor().mV[3]; @@ -3241,33 +3265,27 @@ LLColor3 LLVOVolume::getLightSRGBColor() const return ret; } -LLUUID LLVOVolume::getLightTextureID() const +const LLUUID& LLVOVolume::getLightTextureID() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + const LLLightImageParams *param_block = getLightImageParams(); + if (param_block) { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } + return param_block->getLightTexture(); } return LLUUID::null; } -LLVector3 LLVOVolume::getSpotLightParams() const +const LLVector3& LLVOVolume::getSpotLightParams() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + const LLLightImageParams *param_block = getLightImageParams(); + if (param_block) { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } + return param_block->getParams(); } - return LLVector3(); + return LLVector3::zero; } F32 LLVOVolume::getSpotLightPriority() const @@ -3304,8 +3322,8 @@ void LLVOVolume::updateSpotLightPriority() bool LLVOVolume::isLightSpotlight() const { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + const LLLightImageParams* params = getLightImageParams(); + if (params) { return params->isLightSpotlight(); } @@ -3315,7 +3333,7 @@ bool LLVOVolume::isLightSpotlight() const LLViewerTexture* LLVOVolume::getLightTexture() { - LLUUID id = getLightTextureID(); + const LLUUID& id = getLightTextureID(); if (id.notNull()) { @@ -3326,7 +3344,7 @@ LLViewerTexture* LLVOVolume::getLightTexture() } else { - mLightTexture = NULL; + mLightTexture = nullptr; } return mLightTexture; @@ -3334,7 +3352,7 @@ LLViewerTexture* LLVOVolume::getLightTexture() F32 LLVOVolume::getLightIntensity() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getLinearColor().mV[3]; @@ -3347,7 +3365,7 @@ F32 LLVOVolume::getLightIntensity() const F32 LLVOVolume::getLightRadius() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getRadius(); @@ -3360,7 +3378,7 @@ F32 LLVOVolume::getLightRadius() const F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getFalloff() * fudge_factor; @@ -3373,7 +3391,7 @@ F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const F32 LLVOVolume::getLightCutoff() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getCutoff(); @@ -3386,7 +3404,7 @@ F32 LLVOVolume::getLightCutoff() const bool LLVOVolume::isReflectionProbe() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); + return getReflectionProbeParams() != nullptr; } bool LLVOVolume::setIsReflectionProbe(bool is_probe) @@ -3411,7 +3429,7 @@ bool LLVOVolume::setIsReflectionProbe(bool is_probe) bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getAmbiance() != ambiance) @@ -3427,7 +3445,7 @@ bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance) bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getClipDistance() != near_clip) @@ -3443,7 +3461,7 @@ bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip) bool LLVOVolume::setReflectionProbeIsBox(bool is_box) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getIsBox() != is_box) @@ -3459,7 +3477,7 @@ bool LLVOVolume::setReflectionProbeIsBox(bool is_box) bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getIsDynamic() != is_dynamic) @@ -3475,7 +3493,7 @@ bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) { - LLReflectionProbeParams *param_block = (LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getIsMirror() != is_mirror) @@ -3498,7 +3516,7 @@ bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) F32 LLVOVolume::getReflectionProbeAmbiance() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getAmbiance(); @@ -3511,7 +3529,7 @@ F32 LLVOVolume::getReflectionProbeAmbiance() const F32 LLVOVolume::getReflectionProbeNearClip() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getClipDistance(); @@ -3524,7 +3542,7 @@ F32 LLVOVolume::getReflectionProbeNearClip() const bool LLVOVolume::getReflectionProbeIsBox() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getIsBox(); @@ -3535,7 +3553,7 @@ bool LLVOVolume::getReflectionProbeIsBox() const bool LLVOVolume::getReflectionProbeIsDynamic() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getIsDynamic(); @@ -3546,8 +3564,7 @@ bool LLVOVolume::getReflectionProbeIsDynamic() const bool LLVOVolume::getReflectionProbeIsMirror() const { - const LLReflectionProbeParams *param_block = - (const LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getIsMirror(); @@ -3568,7 +3585,7 @@ U32 LLVOVolume::getVolumeInterfaceID() const bool LLVOVolume::isFlexible() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) + if (getFlexibleObjectData()) { LLVolume* volume = getVolume(); if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) @@ -3587,7 +3604,7 @@ bool LLVOVolume::isFlexible() const bool LLVOVolume::isSculpted() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + if (getSculptParams()) { return true; } @@ -3599,7 +3616,7 @@ bool LLVOVolume::isMesh() const { if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { U8 sculpt_type = sculpt_params->getSculptType(); @@ -3617,7 +3634,7 @@ bool LLVOVolume::isMesh() const bool LLVOVolume::hasLightTexture() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + if (getLightImageParams()) { return true; } @@ -3737,8 +3754,7 @@ bool LLVOVolume::isRiggedMesh() const //---------------------------------------------------------------------------- U32 LLVOVolume::getExtendedMeshFlags() const { - const LLExtendedMeshParams *param_block = - (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); + const LLExtendedMeshParams *param_block = getExtendedMeshParams(); if (param_block) { return param_block->getFlags(); @@ -3783,8 +3799,7 @@ void LLVOVolume::setExtendedMeshFlags(U32 flags) { bool in_use = true; setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); - LLExtendedMeshParams *param_block = - (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); + LLExtendedMeshParams *param_block = (LLExtendedMeshParams *)getExtendedMeshParams(); if (param_block) { param_block->setFlags(flags); @@ -3842,11 +3857,12 @@ void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_pare } if (old_volp && old_volp->isAnimatedObject()) { - if (old_volp->getControlAvatar()) + LLControlAvatar* cav = old_volp->getControlAvatar(); + if (cav) { // We have been removed from an animated object, need to do cleanup. - old_volp->getControlAvatar()->updateAttachmentOverrides(); - old_volp->getControlAvatar()->updateAnimations(); + cav->updateAttachmentOverrides(); + cav->updateAnimations(); } } } @@ -5131,7 +5147,7 @@ U32 LLVOVolume::getPartitionType() const { return LLViewerRegion::PARTITION_HUD; } - if (isAnimatedObject() && getControlAvatar()) + if (isAnimatedObjectFast() && getControlAvatar()) { return LLViewerRegion::PARTITION_CONTROL_AV; } @@ -5757,11 +5773,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } // Standard rigged mesh attachments: - bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); + bool is_animated = vobj->isAnimatedObject(); + bool rigged = !is_animated && skinInfo && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to // exclude static objects in animated object linksets. - rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && - vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); + if (!rigged && is_animated && vobj->isRiggedMesh()) + { + LLControlAvatar* cav = vobj->getControlAvatar(); + if (cav) + { + rigged = cav->mPlaying; + } + } bool any_rigged_face = false; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 97a5131260..b6044bc319 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -227,6 +227,7 @@ public: void setTexture(const S32 face); S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];} + void unregisterOldMeshAndSkin(); /*virtual*/ bool setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override; void updateSculptTexture(); void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;} @@ -283,9 +284,9 @@ public: // Get the light color in sRGB color space scaled by intensity. LLColor3 getLightSRGBColor() const; - LLUUID getLightTextureID() const; + const LLUUID& getLightTextureID() const; bool isLightSpotlight() const; - LLVector3 getSpotLightParams() const; + const LLVector3& getSpotLightParams() const; void updateSpotLightPriority(); F32 getSpotLightPriority() const; diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index a319aa00bc..f603274335 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -34,6 +34,7 @@ #include "llagent.h" #include "llappviewer.h" +#include "llfloatermarketplace.h" #include "llfloaterwebcontent.h" #include "llfloaterreg.h" #include "lllogininstance.h" @@ -74,12 +75,20 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std } // static -// Explicitly open a Web URL using the Web content floater +// Explicitly open a Web URL using the Web content floater or Marketplace floater void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode) { LLFloaterWebContent::Params p; p.url(url).target(target).id(uuid).dev_mode(dev_mode); - LLFloaterReg::showInstance("web_content", p); + + if (LLFloaterMarketplace::isMarketplaceURL(url)) + { + LLFloaterReg::showInstance("marketplace", p); + } + else + { + LLFloaterReg::showInstance("web_content", p); + } } // static diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 153bee3aef..1db36649fa 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -118,6 +118,7 @@ LLVector3d LLSimInfo::getGlobalOrigin() const { return from_region_handle(mHandle); } + LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const { LLVector3d sim_origin = from_region_handle(mHandle); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 6b2bd3e6fb..1be6a6cfff 100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -517,26 +517,38 @@ void LLWorldMapView::draw() // Draw the region name in the lower left corner if (mMapScale >= DRAW_TEXT_THRESHOLD) { - std::string mesg; + static LLCachedControl<bool> print_coords(gSavedSettings, "MapShowGridCoords"); + static LLFontGL* font = LLFontGL::getFontSansSerifSmallBold(); + + auto print = [&](std::string text, F32 x, F32 y, bool use_ellipses) + { + font->renderUTF8(text, 0, + (F32)llfloor(left + x), (F32)llfloor(bottom + y), + LLColor4::white, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, + S32_MAX, //max_chars + (S32)mMapScale, //max_pixels + NULL, + use_ellipses); + }; + + std::string grid_name = info->getName(); if (info->isDown()) { - mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); + grid_name += " (" + sStringsMap["offline"] + ")"; } - else + + if (print_coords) { - mesg = info->getName(); + print(grid_name, 3, 14, true); + // Obtain and print the grid map coordinates + LLVector3d region_pos = info->getGlobalOrigin(); + std::string grid_coords = llformat("[%.0f, %.0f]", region_pos[VX] / 256, region_pos[VY] / 256); + print(grid_coords, 3, 2, false); } - if (!mesg.empty()) + else { - LLFontGL::getFontSansSerifSmallBold()->renderUTF8( - mesg, 0, - (F32)llfloor(left + 3), (F32)llfloor(bottom + 2), - LLColor4::white, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, - S32_MAX, //max_chars - (S32)mMapScale, //max_pixels - NULL, - /*use_ellipses*/true); + print(grid_name, 3, 2, true); } } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d2aebfbce5..d1ea8c2ee5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5525,7 +5525,7 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_ if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) { // moving lights get a little higher priority (too much causes artifacts) - dist = llmax(dist - light->getLightRadius()*0.25f, 0.f); + dist = llmax(dist - radius * 0.25f, 0.f); } return dist; } diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml index 4211d624ac..0d75685223 100644 --- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml @@ -155,4 +155,36 @@ name="item3" value="tx" /> </combo_box> + <text + type="string" + length="1" + height="16" + layout="topleft" + left_delta="0" + top_pad="24" + width="200"> + Multiple columns: + </text> + <combo_box + name="multi_column_combo" + layout="topleft" + height="20" + width="150" + left_delta="0" + top_pad="4"> + <combo_item name="combo_item1" value="0"> + <column width="40" name="label" label="|Abc|" /> + <column name="longtext" label="Match full text" /> + </combo_item> + + <combo_item name="combo_item2" value="1"> + <column name="label" label="*Abc*" /> + <column name="longtext" label="Match substring" /> + </combo_item> + + <combo_item name="combo_item3" value="2"> + <column name="label" label="/ *. /" /> + <column name="longtext" label="Match regular expression" /> + </combo_item> + </combo_box> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 0ce64b7a83..b0635a2229 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -109,7 +109,7 @@ </panel> <panel follows="right|top" - height="126" + height="150" top_pad="4" width="238" left="1" @@ -285,6 +285,30 @@ by owner </text> + <check_box + name="grid_coords_chk" + control_name="MapShowGridCoords" + layout="topleft" + follows="top|right" + top_pad="2" + left="3" + height="16" + width="22" + /> + <text + name="grid_coords_label" + type="string" + layout="topleft" + follows="top|right" + top_delta="2" + left_pad="3" + height="16" + width="220" + halign="left" + length="1" > + Show grid map coordinates + </text> + <button follows="top|right" height="22" @@ -455,7 +479,7 @@ <panel follows="right|top|bottom" - height="235" + height="220" top_pad="0" width="238" name="layout_panel_4"> @@ -573,7 +597,7 @@ draw_stripes="false" bg_writeable_color="MouseGray" follows="all" - height="145" + height="130" layout="topleft" left="28" name="search_results" diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml index 6345394b46..f82f705fb7 100644 --- a/indra/newview/skins/default/xui/en/menu_favorites.xml +++ b/indra/newview/skins/default/xui/en/menu_favorites.xml @@ -35,6 +35,9 @@ <menu_item_call.on_click function="Favorites.DoToSelected" parameter="show_on_map" /> + <menu_item_call.on_enable + function="Favorites.EnableSelected" + parameter="show_on_map" /> </menu_item_call> <menu_item_call label="Copy SLurl" @@ -43,6 +46,9 @@ <menu_item_call.on_click function="Favorites.DoToSelected" parameter="copy_slurl" /> + <menu_item_call.on_enable + function="Favorites.EnableSelected" + parameter="copy_slurl" /> </menu_item_call> <menu_item_call label="Create Pick" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dbd513afe8..e8da8a6322 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2466,6 +2466,17 @@ You already have a landmark for this location. </notification> <notification + icon="alert.tga" + name="LandmarkLocationUnknown" + type="alert"> +Viewer wasn't able to get region's location. Region might be temporarily unavailable, was removed or landmark failed to load. + <usetemplate + name="okbutton" + yestext="OK"/> + <tag>fail</tag> + </notification> + + <notification icon="alertmodal.tga" name="CannotCreateLandmarkNotOwner" type="alertmodal"> @@ -4425,9 +4436,9 @@ Click OK to install. </notification> <notification - icon="alertmodal.tga" + icon="alert.tga" name="PromptOptionalUpdate" - type="alertmodal"> + type="alert"> Version [VERSION] has been downloaded and is ready to install. Release notes: [URL] diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 7290cbb5c6..74bc7736f9 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -86,6 +86,15 @@ Hover your mouse over the options for more help. name="btn_join" visible="true" width="120" /> + <button + follows="left|top" + left_pad="6" + top_delta="0" + height="23" + label="Activate" + name="btn_activate" + visible="true" + width="120" /> </panel> <text_editor type="string" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index ddddb4855f..aa641a35f7 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -113,7 +113,7 @@ width="70"> <combo_box.item enabled="true" - label="1:00 AM" + label="1:00 PM" name="12H" value="0" /> <combo_box.item diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 6ef1b6e44a..47e1e669d1 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -33,6 +33,28 @@ unknown </text> <text + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + right="-100" + name="estate_id_lbl" + width="80"> + Estate ID: + </text> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + name="estate_id" + enabled="false" + right="-10" + initial_value="unknown" + width="85" /> + <text follows="left|top" font="SansSerif" height="20" @@ -55,6 +77,39 @@ unknown </text> <text + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + right="-100" + name="grid_position_lbl" + width="80"> + Grid Position: + </text> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + right="-55" + name="grid_position_x" + enabled="false" + top_delta="0" + default_text="n/a" + width="40" /> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + right="-10" + name="grid_position_y" + enabled="false" + top_delta="0" + default_text="n/a" + width="40" /> + <text follows="left|top" font="SansSerif" height="20" diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 94d234686a..109f00c9ae 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -259,9 +259,10 @@ class ViewerManifest(LLManifest): global CHANNEL_VENDOR_BASE channel_type=self.channel_type() if channel_type == 'release': - return CHANNEL_VENDOR_BASE + app_suffix='Viewer' else: - return CHANNEL_VENDOR_BASE + ' ' + self.channel_variant() + app_suffix=self.channel_variant() + return CHANNEL_VENDOR_BASE + ' ' + app_suffix def exec_name(self): return "SecondLifeViewer" |
