summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMnikolenko Productengine <mnikolenko@productengine.com>2026-01-15 21:49:17 +0200
committerMnikolenko Productengine <mnikolenko@productengine.com>2026-01-15 21:54:48 +0200
commite4a079e14dea60d48342473fecb7762c29ad0456 (patch)
treea3499be0247d2c8b559882c3d8348b150e2ae0f9
parenta377ec310848657ca6f4b76bdf74aca9cfc6f9da (diff)
parent106556538c6d7f4098bd204fcb87860f8e2bff6c (diff)
Merge branch 'develop' into project/flat-ui-fonts-update
-rw-r--r--.github/workflows/build.yaml26
-rw-r--r--.github/workflows/cla.yaml2
-rw-r--r--.github/workflows/pre-commit.yaml2
-rw-r--r--autobuild.xml138
-rw-r--r--indra/cmake/Boost.cmake38
-rw-r--r--indra/llappearance/lltexlayer.cpp18
-rw-r--r--indra/llcharacter/CMakeLists.txt4
-rw-r--r--indra/llcharacter/llkeyframemotionparam.cpp436
-rw-r--r--indra/llcharacter/llkeyframemotionparam.h169
-rw-r--r--indra/llcharacter/llmotioncontroller.h1
-rw-r--r--indra/llcharacter/llstatemachine.cpp384
-rw-r--r--indra/llcharacter/llstatemachine.h147
-rw-r--r--indra/llcommon/CMakeLists.txt3
-rw-r--r--indra/llcommon/llapp.cpp1
-rw-r--r--indra/llcommon/llapp.h2
-rwxr-xr-xindra/llcommon/llpointer.cpp43
-rw-r--r--indra/llcommon/llpointer.h291
-rw-r--r--indra/llcommon/llprocess.cpp13
-rw-r--r--indra/llcommon/llthread.cpp6
-rw-r--r--indra/llcommon/llwatchdog.cpp (renamed from indra/newview/llwatchdog.cpp)37
-rw-r--r--indra/llcommon/llwatchdog.h (renamed from indra/newview/llwatchdog.h)25
-rw-r--r--indra/llcommon/workqueue.cpp29
-rw-r--r--indra/llcommon/workqueue.h6
-rw-r--r--indra/llimage/llimage.cpp16
-rw-r--r--indra/llimage/llimage.h5
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp5
-rw-r--r--indra/llmath/llvolume.cpp29
-rw-r--r--indra/llmath/llvolumemgr.cpp1
-rw-r--r--indra/llmath/v3math.h9
-rw-r--r--indra/llmeshoptimizer/llmeshoptimizer.cpp1
-rw-r--r--indra/llmessage/llassetstorage.cpp3
-rw-r--r--indra/llmessage/llassetstorage.h1
-rw-r--r--indra/llmessage/llexperiencecache.cpp33
-rw-r--r--indra/llmessage/llexperiencecache.h4
-rw-r--r--indra/llprimitive/llprimitive.h9
-rw-r--r--indra/llrender/llrender.cpp63
-rw-r--r--indra/llrender/llrender.h13
-rw-r--r--indra/llrender/lltexturemanagerbridge.cpp2
-rw-r--r--indra/llui/llfolderviewitem.cpp13
-rw-r--r--indra/llui/lllineeditor.cpp1
-rw-r--r--indra/llui/lllineeditor.h2
-rw-r--r--indra/llui/llmenugl.cpp14
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llui/llnotifications.h1
-rw-r--r--indra/llui/llscrolllistctrl.cpp1
-rw-r--r--indra/llui/lltexteditor.cpp2
-rw-r--r--indra/llwebrtc/llwebrtc.cpp3
-rw-r--r--indra/llwindow/llwindow.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp65
-rw-r--r--indra/llwindow/llwindowwin32.h141
-rw-r--r--indra/llxml/llcontrol.cpp29
-rw-r--r--indra/llxml/llcontrol.h2
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/settings.xml15
-rw-r--r--indra/newview/llagentcamera.cpp8
-rw-r--r--indra/newview/llappviewer.cpp64
-rw-r--r--indra/newview/llappviewer.h2
-rw-r--r--indra/newview/llavataractions.cpp2
-rw-r--r--indra/newview/llcallingcard.cpp2
-rw-r--r--indra/newview/lldrawable.cpp8
-rw-r--r--indra/newview/lldrawpoolalpha.cpp2
-rw-r--r--indra/newview/lleventpoll.cpp58
-rw-r--r--indra/newview/llexternaleditor.cpp8
-rw-r--r--indra/newview/llface.cpp6
-rw-r--r--indra/newview/llfavoritesbar.cpp36
-rw-r--r--indra/newview/llfilepicker_mac.mm7
-rw-r--r--indra/newview/llfloatereditenvironmentbase.cpp2
-rw-r--r--indra/newview/llfloatermarketplace.cpp36
-rw-r--r--indra/newview/llfloatermarketplace.h3
-rw-r--r--indra/newview/llfloatermarketplacelistings.cpp24
-rw-r--r--indra/newview/llfloaterobjectweights.cpp2
-rw-r--r--indra/newview/llfloaterpay.cpp2
-rw-r--r--indra/newview/llfloaterpreference.cpp15
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llfloaterregioninfo.cpp15
-rw-r--r--indra/newview/llglsandbox.cpp66
-rw-r--r--indra/newview/llgrouplist.cpp2
-rw-r--r--indra/newview/llhudnametag.cpp2
-rw-r--r--indra/newview/llinventorybridge.cpp22
-rw-r--r--indra/newview/llinventoryfunctions.cpp14
-rw-r--r--indra/newview/llinventorygallery.cpp10
-rw-r--r--indra/newview/llinventorygallerymenu.cpp8
-rw-r--r--indra/newview/llinventorymodel.cpp11
-rw-r--r--indra/newview/llinventorymodel.h4
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp2
-rw-r--r--indra/newview/llinventorypanel.cpp16
-rw-r--r--indra/newview/lllandmarklist.cpp49
-rw-r--r--indra/newview/lllandmarklist.h1
-rw-r--r--indra/newview/lllocalbitmaps.cpp2
-rw-r--r--indra/newview/llmarketplacefunctions.cpp4
-rw-r--r--indra/newview/llmeshrepository.cpp59
-rw-r--r--indra/newview/llmeshrepository.h12
-rw-r--r--indra/newview/llmodelpreview.cpp2
-rw-r--r--indra/newview/llpanelface.cpp32
-rw-r--r--indra/newview/llpanelface.h2
-rw-r--r--indra/newview/llpanelgroup.cpp34
-rw-r--r--indra/newview/llpanelgroup.h9
-rw-r--r--indra/newview/llpanellogin.cpp42
-rw-r--r--indra/newview/llpanellogin.h6
-rw-r--r--indra/newview/llpanelobject.cpp37
-rw-r--r--indra/newview/llpanelplaceprofile.cpp4
-rw-r--r--indra/newview/llpanelplaceprofile.h2
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp6
-rw-r--r--indra/newview/llpanelvolume.cpp10
-rw-r--r--indra/newview/llselectmgr.cpp9
-rw-r--r--indra/newview/llspatialpartition.cpp5
-rw-r--r--indra/newview/llspatialpartition.h2
-rw-r--r--indra/newview/lltooldraganddrop.cpp2
-rw-r--r--indra/newview/lltoolselect.cpp9
-rw-r--r--indra/newview/llviewerassetstorage.cpp71
-rw-r--r--indra/newview/llvieweraudio.cpp59
-rw-r--r--indra/newview/llviewermedia.cpp14
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llviewerobject.cpp226
-rw-r--r--indra/newview/llviewerobject.h70
-rw-r--r--indra/newview/llviewerobjectlist.cpp3
-rw-r--r--indra/newview/llvieweroctree.h1
-rw-r--r--indra/newview/llviewerparcelmgr.cpp3
-rwxr-xr-xindra/newview/llviewerparceloverlay.cpp235
-rw-r--r--indra/newview/llviewerparceloverlay.h5
-rw-r--r--indra/newview/llviewerwindow.cpp39
-rw-r--r--indra/newview/llvoicewebrtc.cpp45
-rw-r--r--indra/newview/llvovolume.cpp153
-rw-r--r--indra/newview/llvovolume.h5
-rw-r--r--indra/newview/llweb.cpp13
-rw-r--r--indra/newview/llworldmap.cpp1
-rwxr-xr-xindra/newview/llworldmapview.cpp40
-rw-r--r--indra/newview/pipeline.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_combobox.xml32
-rw-r--r--indra/newview/skins/default/xui/en/floater_world_map.xml30
-rw-r--r--indra/newview/skins/default/xui/en/menu_favorites.xml6
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_general.xml9
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general.xml55
-rwxr-xr-xindra/newview/viewer_manifest.py5
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 = &paramMotion;
- }
- 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 = &paramMotion;
- }
- //...or, if we've seen no other motion so far, make sure we blend to this only
- else if (!firstMotion)
- {
- firstMotion = &paramMotion;
- secondMotion = &paramMotion;
- }
- }
- }
-
- 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 &current_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 &current_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 &current_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 &current_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 &current_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 &current_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 &param;
+ }
+ }
+ 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 &params_in, const S32 detail, bool unique_volume)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
@@ -1082,7 +1106,7 @@ bool LLVOVolume::setVolume(const LLVolumeParams &params_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"